mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Merge pull request #2801 from ManfredKarrer/restrict-new-accounts
Add check for account age to apply restrictions
This commit is contained in:
commit
7523fc5628
@ -82,6 +82,7 @@ public class Version {
|
||||
|
||||
// The version no. of the current protocol. The offer holds that version.
|
||||
// A taker will check the version of the offers to see if his version is compatible.
|
||||
// Offers created with the old version will become invalid and have to be canceled.
|
||||
// VERSION = 0.5.0 -> TRADE_PROTOCOL_VERSION = 1
|
||||
public static final int TRADE_PROTOCOL_VERSION = 1;
|
||||
private static int p2pMessageVersion;
|
||||
|
@ -649,11 +649,28 @@ public class BisqSetup {
|
||||
filterManager.onAllServicesInitialized();
|
||||
filterManager.addListener(filter -> {
|
||||
if (filter != null && filterWarningHandler != null) {
|
||||
if (filter.getSeedNodes() != null && !filter.getSeedNodes().isEmpty())
|
||||
filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.seed")));
|
||||
if (filter.getSeedNodes() != null && !filter.getSeedNodes().isEmpty()) {
|
||||
log.warn(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.seed")));
|
||||
// Lets keep that more silent. Might be used in case a node is unstable and we don't want to confuse users.
|
||||
// filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.seed")));
|
||||
}
|
||||
|
||||
if (filter.getPriceRelayNodes() != null && !filter.getPriceRelayNodes().isEmpty())
|
||||
filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.priceRelay")));
|
||||
if (filter.getPriceRelayNodes() != null && !filter.getPriceRelayNodes().isEmpty()) {
|
||||
log.warn(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.priceRelay")));
|
||||
// Lets keep that more silent. Might be used in case a node is unstable and we don't want to confuse users.
|
||||
// filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.priceRelay")));
|
||||
}
|
||||
|
||||
if (filterManager.requireUpdateToNewVersionForTrading()) {
|
||||
filterWarningHandler.accept(Res.get("popup.warning.mandatoryUpdate.trading"));
|
||||
}
|
||||
|
||||
if (filterManager.requireUpdateToNewVersionForDAO()) {
|
||||
filterWarningHandler.accept(Res.get("popup.warning.mandatoryUpdate.dao"));
|
||||
}
|
||||
if (filter.isDisableDao()) {
|
||||
filterWarningHandler.accept(Res.get("popup.warning.disable.dao"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -878,10 +878,9 @@ public class DisputeManager implements PersistedDataHost {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Dispute dispute = disputeOptional.get();
|
||||
try {
|
||||
cleanupRetryMap(uid);
|
||||
Dispute dispute = disputeOptional.get();
|
||||
arbitratorsPubKeyRing = dispute.getArbitratorPubKeyRing();
|
||||
DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage();
|
||||
if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
|
||||
@ -997,7 +996,24 @@ public class DisputeManager implements PersistedDataHost {
|
||||
|
||||
success = true;
|
||||
}
|
||||
} catch (AddressFormatException | WalletException | TransactionVerificationException e) {
|
||||
} catch (TransactionVerificationException e) {
|
||||
e.printStackTrace();
|
||||
errorMessage = "Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString();
|
||||
log.error(errorMessage);
|
||||
success = false;
|
||||
|
||||
// We prefer to close the dispute in that case. If there was no deposit tx and a random tx was used
|
||||
// we get a TransactionVerificationException. No reason to keep that dispute open...
|
||||
if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
|
||||
tradeManager.closeDisputedTrade(dispute.getTradeId());
|
||||
else {
|
||||
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
|
||||
openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer()));
|
||||
}
|
||||
dispute.setIsClosed(true);
|
||||
|
||||
throw new RuntimeException(errorMessage);
|
||||
} catch (AddressFormatException | WalletException e) {
|
||||
e.printStackTrace();
|
||||
errorMessage = "Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString();
|
||||
log.error(errorMessage);
|
||||
|
@ -350,7 +350,7 @@ public class FilterManager {
|
||||
.anyMatch(e -> e.equals(nodeAddress.getFullAddress()));
|
||||
}
|
||||
|
||||
public boolean requireUpdateToNewVersion() {
|
||||
public boolean requireUpdateToNewVersionForTrading() {
|
||||
if (getFilter() == null) {
|
||||
return false;
|
||||
}
|
||||
@ -364,6 +364,20 @@ public class FilterManager {
|
||||
return requireUpdateToNewVersion;
|
||||
}
|
||||
|
||||
public boolean requireUpdateToNewVersionForDAO() {
|
||||
if (getFilter() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean requireUpdateToNewVersion = false;
|
||||
String disableDaoBelowVersion = getFilter().getDisableDaoBelowVersion();
|
||||
if (disableDaoBelowVersion != null && !disableDaoBelowVersion.isEmpty()) {
|
||||
requireUpdateToNewVersion = Version.isNewVersion(disableDaoBelowVersion);
|
||||
}
|
||||
|
||||
return requireUpdateToNewVersion;
|
||||
}
|
||||
|
||||
public boolean isPeersPaymentAccountDataAreBanned(PaymentAccountPayload paymentAccountPayload,
|
||||
PaymentAccountFilter[] appliedPaymentAccountFilter) {
|
||||
return getFilter() != null &&
|
||||
|
@ -18,6 +18,8 @@
|
||||
package bisq.core.offer;
|
||||
|
||||
import bisq.core.app.AppOptionKeys;
|
||||
import bisq.core.filter.FilterManager;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.provider.price.PriceFeedService;
|
||||
|
||||
import bisq.network.p2p.BootstrapListener;
|
||||
@ -63,6 +65,7 @@ public class OfferBookService {
|
||||
private final P2PService p2PService;
|
||||
private final PriceFeedService priceFeedService;
|
||||
private final List<OfferBookChangedListener> offerBookChangedListeners = new LinkedList<>();
|
||||
private final FilterManager filterManager;
|
||||
private final JsonFileManager jsonFileManager;
|
||||
|
||||
|
||||
@ -73,10 +76,12 @@ public class OfferBookService {
|
||||
@Inject
|
||||
public OfferBookService(P2PService p2PService,
|
||||
PriceFeedService priceFeedService,
|
||||
FilterManager filterManager,
|
||||
@Named(Storage.STORAGE_DIR) File storageDir,
|
||||
@Named(AppOptionKeys.DUMP_STATISTICS) boolean dumpStatistics) {
|
||||
this.p2PService = p2PService;
|
||||
this.priceFeedService = priceFeedService;
|
||||
this.filterManager = filterManager;
|
||||
jsonFileManager = new JsonFileManager(storageDir);
|
||||
|
||||
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
|
||||
@ -132,6 +137,11 @@ public class OfferBookService {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
if (filterManager.requireUpdateToNewVersionForTrading()) {
|
||||
errorMessageHandler.handleErrorMessage(Res.get("popup.warning.mandatoryUpdate.trading"));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean result = p2PService.addProtectedStorageEntry(offer.getOfferPayload(), true);
|
||||
if (result) {
|
||||
resultHandler.handleResult();
|
||||
@ -141,6 +151,11 @@ public class OfferBookService {
|
||||
}
|
||||
|
||||
public void refreshTTL(OfferPayload offerPayload, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
if (filterManager.requireUpdateToNewVersionForTrading()) {
|
||||
errorMessageHandler.handleErrorMessage(Res.get("popup.warning.mandatoryUpdate.trading"));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean result = p2PService.refreshTTL(offerPayload, true);
|
||||
if (result) {
|
||||
resultHandler.handleResult();
|
||||
|
59
core/src/main/java/bisq/core/offer/OfferRestrictions.java
Normal file
59
core/src/main/java/bisq/core/offer/OfferRestrictions.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq 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 Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.offer;
|
||||
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
import bisq.core.trade.Trade;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
public class OfferRestrictions {
|
||||
public static Coin TOLERATED_SMALL_TRADE_AMOUNT = Coin.parseCoin("0.01");
|
||||
|
||||
public static boolean isOfferRisky(Offer offer) {
|
||||
return offer != null &&
|
||||
offer.isBuyOffer() &&
|
||||
PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) &&
|
||||
isMinTradeAmountRisky(offer);
|
||||
}
|
||||
|
||||
public static boolean isSellOfferRisky(Offer offer) {
|
||||
return offer != null &&
|
||||
PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) &&
|
||||
isMinTradeAmountRisky(offer);
|
||||
}
|
||||
|
||||
public static boolean isTradeRisky(Trade trade) {
|
||||
if (trade == null)
|
||||
return false;
|
||||
|
||||
Offer offer = trade.getOffer();
|
||||
return offer != null &&
|
||||
PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) &&
|
||||
trade.getTradeAmount() != null &&
|
||||
isAmountRisky(trade.getTradeAmount());
|
||||
}
|
||||
|
||||
public static boolean isMinTradeAmountRisky(Offer offer) {
|
||||
return isAmountRisky(offer.getMinAmount());
|
||||
}
|
||||
|
||||
public static boolean isAmountRisky(Coin amount) {
|
||||
return amount.isGreaterThan(TOLERATED_SMALL_TRADE_AMOUNT);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq 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 Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.payment;
|
||||
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OfferRestrictions;
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
import bisq.core.trade.Trade;
|
||||
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class AccountAgeRestrictions {
|
||||
public static final long SAFE_ACCOUNT_AGE_DATE = Utilities.getUTCDate(2019, GregorianCalendar.MARCH, 15).getTime();
|
||||
|
||||
public static boolean isMakersAccountAgeImmature(AccountAgeWitnessService accountAgeWitnessService, Offer offer) {
|
||||
long accountCreationDate = new Date().getTime() - accountAgeWitnessService.getMakersAccountAge(offer, new Date());
|
||||
return accountCreationDate > SAFE_ACCOUNT_AGE_DATE;
|
||||
}
|
||||
|
||||
public static boolean isTradePeersAccountAgeImmature(AccountAgeWitnessService accountAgeWitnessService, Trade trade) {
|
||||
long accountCreationDate = new Date().getTime() - accountAgeWitnessService.getTradingPeersAccountAge(trade);
|
||||
return accountCreationDate > SAFE_ACCOUNT_AGE_DATE;
|
||||
}
|
||||
|
||||
public static boolean isMyAccountAgeImmature(AccountAgeWitnessService accountAgeWitnessService, PaymentAccount myPaymentAccount) {
|
||||
long accountCreationDate = new Date().getTime() - accountAgeWitnessService.getMyAccountAge(myPaymentAccount.getPaymentAccountPayload());
|
||||
return accountCreationDate > SAFE_ACCOUNT_AGE_DATE;
|
||||
}
|
||||
|
||||
public static long getMyTradeLimitAtCreateOffer(AccountAgeWitnessService accountAgeWitnessService,
|
||||
PaymentAccount paymentAccount,
|
||||
String currencyCode,
|
||||
OfferPayload.Direction direction) {
|
||||
if (direction == OfferPayload.Direction.BUY &&
|
||||
PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod()) &&
|
||||
AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, paymentAccount)) {
|
||||
return OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value;
|
||||
} else {
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, currencyCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static long getMyTradeLimitAtTakeOffer(AccountAgeWitnessService accountAgeWitnessService,
|
||||
PaymentAccount paymentAccount,
|
||||
Offer offer,
|
||||
String currencyCode,
|
||||
OfferPayload.Direction direction) {
|
||||
if (direction == OfferPayload.Direction.BUY && PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod()) &&
|
||||
AccountAgeRestrictions.isMakersAccountAgeImmature(accountAgeWitnessService, offer)) {
|
||||
// Taker is seller
|
||||
return OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value;
|
||||
} else if (direction == OfferPayload.Direction.SELL && PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod()) &&
|
||||
AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, paymentAccount)) {
|
||||
// Taker is buyer
|
||||
return OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value;
|
||||
} else {
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, currencyCode);
|
||||
}
|
||||
}
|
||||
}
|
@ -63,6 +63,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
public class AccountAgeWitnessService {
|
||||
private static final Date RELEASE = Utilities.getUTCDate(2017, GregorianCalendar.NOVEMBER, 11);
|
||||
public static final Date FULL_ACTIVATION = Utilities.getUTCDate(2018, GregorianCalendar.FEBRUARY, 15);
|
||||
public static final long SAFE_ACCOUNT_AGE_DATE = Utilities.getUTCDate(2019, GregorianCalendar.MARCH, 15).getTime();
|
||||
|
||||
public enum AccountAge {
|
||||
LESS_ONE_MONTH,
|
||||
|
@ -19,6 +19,7 @@ package bisq.core.payment;
|
||||
|
||||
import bisq.core.locale.Country;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferRestrictions;
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
@ -37,18 +38,65 @@ import javax.annotation.Nullable;
|
||||
|
||||
@Slf4j
|
||||
public class PaymentAccountUtil {
|
||||
public static boolean isAnyPaymentAccountValidForOffer(Offer offer, Collection<PaymentAccount> paymentAccounts) {
|
||||
for (PaymentAccount paymentAccount : paymentAccounts) {
|
||||
if (isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
|
||||
public static boolean isRiskyBuyOfferWithImmatureAccountAge(Offer offer, AccountAgeWitnessService accountAgeWitnessService) {
|
||||
return OfferRestrictions.isOfferRisky(offer) &&
|
||||
AccountAgeRestrictions.isMakersAccountAgeImmature(accountAgeWitnessService, offer);
|
||||
}
|
||||
|
||||
public static boolean isSellOfferAndAnyTakerPaymentAccountForOfferMature(Offer offer,
|
||||
Collection<PaymentAccount> takerPaymentAccounts,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
if (!OfferRestrictions.isSellOfferRisky(offer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (PaymentAccount takerPaymentAccount : takerPaymentAccounts) {
|
||||
if (isTakerAccountForOfferMature(offer, takerPaymentAccount, accountAgeWitnessService))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ObservableList<PaymentAccount> getPossiblePaymentAccounts(Offer offer, Set<PaymentAccount> paymentAccounts) {
|
||||
private static boolean isTakerAccountForOfferMature(Offer offer,
|
||||
PaymentAccount takerPaymentAccount,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
return !PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) ||
|
||||
!OfferRestrictions.isMinTradeAmountRisky(offer) ||
|
||||
(isTakerPaymentAccountValidForOffer(offer, takerPaymentAccount) &&
|
||||
!AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, takerPaymentAccount));
|
||||
}
|
||||
|
||||
public static boolean hasMakerAnyMatureAccountForBuyOffer(Collection<PaymentAccount> makerPaymentAccounts,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
for (PaymentAccount makerPaymentAccount : makerPaymentAccounts) {
|
||||
if (hasMyMatureAccountForBuyOffer(makerPaymentAccount, accountAgeWitnessService))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasMyMatureAccountForBuyOffer(PaymentAccount myPaymentAccount,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
return !PaymentMethod.hasChargebackRisk(myPaymentAccount.getPaymentMethod()) ||
|
||||
!AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, myPaymentAccount);
|
||||
}
|
||||
|
||||
public static boolean isAnyTakerPaymentAccountValidForOffer(Offer offer, Collection<PaymentAccount> takerPaymentAccounts) {
|
||||
for (PaymentAccount takerPaymentAccount : takerPaymentAccounts) {
|
||||
if (isTakerPaymentAccountValidForOffer(offer, takerPaymentAccount))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ObservableList<PaymentAccount> getPossiblePaymentAccounts(Offer offer,
|
||||
Set<PaymentAccount> paymentAccounts,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
ObservableList<PaymentAccount> result = FXCollections.observableArrayList();
|
||||
result.addAll(paymentAccounts.stream()
|
||||
.filter(paymentAccount -> isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.filter(paymentAccount -> isTakerPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.filter(paymentAccount -> isTakerAccountForOfferMature(offer, paymentAccount, accountAgeWitnessService))
|
||||
.collect(Collectors.toList()));
|
||||
return result;
|
||||
}
|
||||
@ -61,7 +109,7 @@ public class PaymentAccountUtil {
|
||||
"Payment method from offer: " + offer.getPaymentMethod().toString();
|
||||
}
|
||||
|
||||
public static boolean isPaymentAccountValidForOffer(Offer offer, PaymentAccount paymentAccount) {
|
||||
public static boolean isTakerPaymentAccountValidForOffer(Offer offer, PaymentAccount paymentAccount) {
|
||||
return new ReceiptValidator(offer, paymentAccount).isValid();
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ class PaymentAccounts {
|
||||
private final BiFunction<Offer, PaymentAccount, Boolean> validator;
|
||||
|
||||
PaymentAccounts(Set<PaymentAccount> accounts, AccountAgeWitnessService service) {
|
||||
this(accounts, service, PaymentAccountUtil::isPaymentAccountValidForOffer);
|
||||
this(accounts, service, PaymentAccountUtil::isTakerPaymentAccountValidForOffer);
|
||||
}
|
||||
|
||||
PaymentAccounts(Set<PaymentAccount> accounts, AccountAgeWitnessService service,
|
||||
|
@ -316,4 +316,23 @@ public final class PaymentMethod implements PersistablePayload, Comparable {
|
||||
public boolean isAsset() {
|
||||
return this.equals(BLOCK_CHAINS_INSTANT) || this.equals(BLOCK_CHAINS);
|
||||
}
|
||||
|
||||
public static boolean hasChargebackRisk(PaymentMethod paymentMethod) {
|
||||
if (paymentMethod == null)
|
||||
return false;
|
||||
|
||||
String id = paymentMethod.getId();
|
||||
return id.equals(PaymentMethod.SEPA_ID) ||
|
||||
id.equals(PaymentMethod.SEPA_INSTANT_ID) ||
|
||||
id.equals(PaymentMethod.INTERAC_E_TRANSFER_ID) ||
|
||||
id.equals(PaymentMethod.CLEAR_X_CHANGE_ID) ||
|
||||
id.equals(PaymentMethod.REVOLUT_ID) ||
|
||||
id.equals(PaymentMethod.NATIONAL_BANK_ID) ||
|
||||
id.equals(PaymentMethod.SAME_BANK_ID) ||
|
||||
id.equals(PaymentMethod.SPECIFIC_BANKS_ID) ||
|
||||
id.equals(PaymentMethod.CHASE_QUICK_PAY_ID) ||
|
||||
id.equals(PaymentMethod.POPMONEY_ID) ||
|
||||
id.equals(PaymentMethod.MONEY_BEAM_ID) ||
|
||||
id.equals(PaymentMethod.UPHOLD_ID);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import bisq.core.trade.messages.DepositTxPublishedMessage;
|
||||
import bisq.core.trade.messages.PayDepositRequest;
|
||||
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
||||
import bisq.core.trade.messages.TradeMessage;
|
||||
import bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
|
||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage;
|
||||
@ -129,7 +129,7 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
});
|
||||
taskRunner.addTasks(
|
||||
MakerProcessPayDepositRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
VerifyPeersAccountAgeWitness.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
@ -186,7 +186,7 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
handleTaskRunnerFault(errorMessage);
|
||||
});
|
||||
taskRunner.addTasks(
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
BuyerAsMakerSignPayoutTx.class,
|
||||
|
@ -23,7 +23,7 @@ import bisq.core.trade.Trade;
|
||||
import bisq.core.trade.messages.PayoutTxPublishedMessage;
|
||||
import bisq.core.trade.messages.PublishDepositTxRequest;
|
||||
import bisq.core.trade.messages.TradeMessage;
|
||||
import bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
|
||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage;
|
||||
@ -145,7 +145,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage));
|
||||
taskRunner.addTasks(
|
||||
TakerProcessPublishDepositTxRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
VerifyPeersAccountAgeWitness.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
@ -179,7 +179,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
handleTaskRunnerFault(errorMessage);
|
||||
});
|
||||
taskRunner.addTasks(
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
BuyerAsMakerSignPayoutTx.class,
|
||||
|
@ -24,7 +24,7 @@ import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage;
|
||||
import bisq.core.trade.messages.DepositTxPublishedMessage;
|
||||
import bisq.core.trade.messages.PayDepositRequest;
|
||||
import bisq.core.trade.messages.TradeMessage;
|
||||
import bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
|
||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||
import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract;
|
||||
@ -38,6 +38,7 @@ import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerVerifiesPeersAccountAge;
|
||||
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerCreatesAndSignsDepositTx;
|
||||
import bisq.core.util.Validator;
|
||||
|
||||
@ -124,9 +125,10 @@ public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
|
||||
taskRunner.addTasks(
|
||||
MakerProcessPayDepositRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
VerifyPeersAccountAgeWitness.class,
|
||||
SellerVerifiesPeersAccountAge.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
MakerCreateAndSignContract.class,
|
||||
SellerAsMakerCreatesAndSignsDepositTx.class,
|
||||
@ -205,7 +207,7 @@ public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
});
|
||||
|
||||
taskRunner.addTasks(
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
SellerSignAndFinalizePayoutTx.class,
|
||||
@ -230,7 +232,7 @@ public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
});
|
||||
|
||||
taskRunner.addTasks(
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
SellerSendPayoutTxPublishedMessage.class
|
||||
|
@ -23,13 +23,14 @@ import bisq.core.trade.Trade;
|
||||
import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage;
|
||||
import bisq.core.trade.messages.PublishDepositTxRequest;
|
||||
import bisq.core.trade.messages.TradeMessage;
|
||||
import bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
|
||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx;
|
||||
import bisq.core.trade.protocol.tasks.seller.SellerVerifiesPeersAccountAge;
|
||||
import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerCreatesDepositTxInputs;
|
||||
import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignAndPublishDepositTx;
|
||||
import bisq.core.trade.protocol.tasks.taker.CreateTakerFeeTx;
|
||||
@ -137,9 +138,10 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
|
||||
taskRunner.addTasks(
|
||||
TakerProcessPublishDepositTxRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
VerifyPeersAccountAgeWitness.class,
|
||||
SellerVerifiesPeersAccountAge.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
TakerVerifyAndSignContract.class,
|
||||
TakerPublishFeeTx.class,
|
||||
@ -192,7 +194,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
});
|
||||
|
||||
taskRunner.addTasks(
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
SellerSignAndFinalizePayoutTx.class,
|
||||
@ -217,7 +219,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
});
|
||||
|
||||
taskRunner.addTasks(
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
SellerSendPayoutTxPublishedMessage.class
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package bisq.core.trade.protocol.tasks;
|
||||
|
||||
import bisq.core.filter.FilterManager;
|
||||
import bisq.core.filter.PaymentAccountFilter;
|
||||
import bisq.core.payment.payload.PaymentAccountPayload;
|
||||
import bisq.core.trade.Trade;
|
||||
@ -30,9 +31,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
public class CheckIfPeerIsBanned extends TradeTask {
|
||||
public class ApplyFilter extends TradeTask {
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public CheckIfPeerIsBanned(TaskRunner taskHandler, Trade trade) {
|
||||
public ApplyFilter(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@ -45,23 +46,24 @@ public class CheckIfPeerIsBanned extends TradeTask {
|
||||
PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getTradingPeer().getPaymentAccountPayload());
|
||||
final PaymentAccountFilter[] appliedPaymentAccountFilter = new PaymentAccountFilter[1];
|
||||
|
||||
if (nodeAddress != null && processModel.getFilterManager().isNodeAddressBanned(nodeAddress)) {
|
||||
FilterManager filterManager = processModel.getFilterManager();
|
||||
if (nodeAddress != null && filterManager.isNodeAddressBanned(nodeAddress)) {
|
||||
failed("Other trader is banned by his node address.\n" +
|
||||
"tradingPeerNodeAddress=" + nodeAddress);
|
||||
} else if (processModel.getFilterManager().isOfferIdBanned(trade.getId())) {
|
||||
} else if (filterManager.isOfferIdBanned(trade.getId())) {
|
||||
failed("Offer ID is banned.\n" +
|
||||
"Offer ID=" + trade.getId());
|
||||
} else if (processModel.getFilterManager().isCurrencyBanned(trade.getOffer().getCurrencyCode())) {
|
||||
} else if (trade.getOffer() != null && filterManager.isCurrencyBanned(trade.getOffer().getCurrencyCode())) {
|
||||
failed("Currency is banned.\n" +
|
||||
"Currency code=" + trade.getOffer().getCurrencyCode());
|
||||
} else if (processModel.getFilterManager().isPaymentMethodBanned(trade.getOffer().getPaymentMethod())) {
|
||||
} else if (filterManager.isPaymentMethodBanned(trade.getOffer().getPaymentMethod())) {
|
||||
failed("Payment method is banned.\n" +
|
||||
"Payment method=" + trade.getOffer().getPaymentMethod().getId());
|
||||
} else if (processModel.getFilterManager().isPeersPaymentAccountDataAreBanned(paymentAccountPayload, appliedPaymentAccountFilter)) {
|
||||
} else if (filterManager.isPeersPaymentAccountDataAreBanned(paymentAccountPayload, appliedPaymentAccountFilter)) {
|
||||
failed("Other trader is banned by his trading account data.\n" +
|
||||
"paymentAccountPayload=" + paymentAccountPayload.getPaymentDetails() + "\n" +
|
||||
"banFilter=" + appliedPaymentAccountFilter[0].toString());
|
||||
} else if (processModel.getFilterManager().requireUpdateToNewVersion()) {
|
||||
} else if (filterManager.requireUpdateToNewVersionForTrading()) {
|
||||
failed("Your version of Bisq is not compatible for trading anymore. " +
|
||||
"Please update to the latest Bisq version at https://bisq.network/downloads.");
|
||||
} else {
|
@ -45,7 +45,7 @@ public class VerifyPeersAccountAgeWitness extends TradeTask {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
if (CurrencyUtil.isFiatCurrency(trade.getOffer().getCurrencyCode())) {
|
||||
if (trade.getOffer() != null && CurrencyUtil.isFiatCurrency(trade.getOffer().getCurrencyCode())) {
|
||||
final AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService();
|
||||
final TradingPeer tradingPeer = processModel.getTradingPeer();
|
||||
final PaymentAccountPayload peersPaymentAccountPayload = checkNotNull(tradingPeer.getPaymentAccountPayload(),
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq 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 Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.core.trade.protocol.tasks.seller;
|
||||
|
||||
import bisq.core.offer.OfferRestrictions;
|
||||
import bisq.core.payment.AccountAgeRestrictions;
|
||||
import bisq.core.trade.Trade;
|
||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
||||
|
||||
import bisq.common.taskrunner.TaskRunner;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class SellerVerifiesPeersAccountAge extends TradeTask {
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public SellerVerifiesPeersAccountAge(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
log.error("SellerVerifiesPeersAccountAge isOfferRisky={} isTradePeersAccountAgeImmature={}", OfferRestrictions.isTradeRisky(trade), AccountAgeRestrictions.isTradePeersAccountAgeImmature(processModel.getAccountAgeWitnessService(), trade));
|
||||
if (OfferRestrictions.isTradeRisky(trade) &&
|
||||
AccountAgeRestrictions.isTradePeersAccountAgeImmature(processModel.getAccountAgeWitnessService(), trade)) {
|
||||
failed("Violation of security restrictions:\n" +
|
||||
" - The peer's account was created after March 15th 2019\n" +
|
||||
" - The trade amount is above 0.01 BTC\n" +
|
||||
" - The payment method for that offer is considered risky for bank chargebacks\n");
|
||||
} else {
|
||||
complete();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
@ -343,7 +343,28 @@ offerbook.withdrawFundsHint=You can withdraw the funds you paid in from the {0}
|
||||
offerbook.warning.noTradingAccountForCurrency.headline=No trading account for selected currency
|
||||
offerbook.warning.noTradingAccountForCurrency.msg=You don't have a trading account for the selected currency.\nDo you want to create an offer with one of your existing trading accounts?
|
||||
offerbook.warning.noMatchingAccount.headline=No matching trading account.
|
||||
offerbook.warning.noMatchingAccount.msg=You don't have a trading account with the payment method required for that offer.\nYou need to setup a trading account with that payment method if you want to take this offer.\nDo you want to do this now?
|
||||
offerbook.warning.noMatchingAccount.msg=To take this offer, you will need to set up a payment account using this payment method.\n\nWould you like to do this now?
|
||||
|
||||
offerbook.warning.riskyBuyOfferWithImmatureAccountAge=This offer cannot be taken because of security restrictions based on the following criteria:\n\
|
||||
- The maker''s payment account was created after March 15th 2019\n\
|
||||
- The minimum trade amount is above 0.01 BTC\n\
|
||||
- The payment method for the offer is considered risky for bank chargebacks\n\n{0}
|
||||
|
||||
offerbook.warning.sellOfferAndAnyTakerPaymentAccountForOfferMature=This offer cannot be taken because of security restrictions based on the following criteria:\n\
|
||||
- Your payment account was created after March 15th 2019\n\
|
||||
- The minimum trade amount is above 0.01 BTC\n\
|
||||
- The payment method for this offer is considered risky for bank chargebacks\n\n{0}
|
||||
|
||||
offerbook.warning.newVersionAnnouncement=We needed to deploy this restriction as a short-term measure for enhanced security.\n\n\
|
||||
The next software release will provide more robust protection tools so that offers with this risk profile can be traded again.
|
||||
|
||||
popup.warning.tradeLimitDueAccountAgeRestriction.seller=The allowed trade amount is limited to 0.01 BTC because of security restrictions based on the following criteria:\n\
|
||||
- The buyers account was created after March 15th 2019\n\
|
||||
- The payment method for this offer is considered risky for bank chargebacks\n\n{0}
|
||||
popup.warning.tradeLimitDueAccountAgeRestriction.buyer=The allowed trade amount is limited to 0.01 BTC because of security restrictions based on the following criteria:\n\
|
||||
- Your payment account was created after March 15th 2019\n\
|
||||
- The payment method for this offer is considered risky for bank chargebacks\n\n{0}
|
||||
|
||||
offerbook.warning.wrongTradeProtocol=That offer requires a different protocol version as the one used in your version of the software.\n\nPlease check if you have the latest version installed, otherwise the user who created the offer has used an older version.\n\nUsers cannot trade with an incompatible trade protocol version.
|
||||
offerbook.warning.userIgnored=You have added that user's onion address to your ignore list.
|
||||
offerbook.warning.offerBlocked=That offer was blocked by the Bisq developers.\nProbably there is an unhandled bug causing issues when taking that offer.
|
||||
@ -479,7 +500,7 @@ takeOffer.failed.offererOffline=You cannot take that offer because the maker is
|
||||
takeOffer.warning.connectionToPeerLost=You lost connection to the maker.\nHe might have gone offline or has closed the connection to you because of too many open connections.\n\nIf you can still see his offer in the offerbook you can try to take the offer again.
|
||||
|
||||
takeOffer.error.noFundsLost=\n\nNo funds have left your wallet yet.\nPlease try to restart your application and check your network connection to see if you can resolve the issue.
|
||||
takeOffer.error.feePaid=\n\nThe taker fee is already paid. In the worst case you have lost that fee.\nPlease try to restart your application and check your network connection to see if you can resolve the issue.
|
||||
takeOffer.error.feePaid=\n\nPlease try to restart your application and check your network connection to see if you can resolve the issue.
|
||||
takeOffer.error.depositPublished=\n\nThe deposit transaction is already published.\nPlease try to restart your application and check your network connection to see if you can resolve the issue.\nIf the problem still remains please contact the developers for support.
|
||||
takeOffer.error.payoutPublished=\n\nThe payout transaction is already published.\nPlease try to restart your application and check your network connection to see if you can resolve the issue.\nIf the problem still remains please contact the developers for support.
|
||||
takeOffer.tac=With taking this offer I agree to the trade conditions as defined in this screen.
|
||||
@ -2272,7 +2293,14 @@ popup.warning.lockedUpFunds=You have locked up funds from a failed trade.\n\
|
||||
popup.warning.nodeBanned=One of the {0} nodes got banned. Please restart your application to be sure to not be connected to the banned node.
|
||||
popup.warning.priceRelay=price relay
|
||||
popup.warning.seed=seed
|
||||
|
||||
popup.warning.mandatoryUpdate.trading=Please update to the latest Bisq version. \
|
||||
A mandatory update was released which disables trading for old versions. \
|
||||
Please check out the Bisq Forum for more information.
|
||||
popup.warning.mandatoryUpdate.dao=Please update to the latest Bisq version. \
|
||||
A mandatory update was released which disables the Bisq DAO and BSQ for old versions. \
|
||||
Please check out the Bisq Forum for more information.
|
||||
popup.warning.disable.dao=The Bisq DAO and BSQ are temporary disabled. \
|
||||
Please check out the Bisq Forum for more information.
|
||||
popup.warning.burnBTC=This transaction is not possible, as the mining fees of {0} would exceed the amount to transfer of {1}. \
|
||||
Please wait until the mining fees are low again or until you''ve accumulated more BTC to transfer.
|
||||
|
||||
|
@ -378,6 +378,9 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupCompleteList
|
||||
bisqSetup.getBtcSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress());
|
||||
daoPresentation.getBsqSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress());
|
||||
|
||||
bisqSetup.setFilterWarningHandler(warning -> {
|
||||
new Popup<>().warning(warning).show();
|
||||
});
|
||||
}
|
||||
|
||||
private void setupP2PNumPeersWatcher() {
|
||||
|
@ -26,7 +26,7 @@ import bisq.core.offer.availability.tasks.SendOfferAvailabilityRequest;
|
||||
import bisq.core.offer.placeoffer.tasks.AddToOfferBook;
|
||||
import bisq.core.offer.placeoffer.tasks.CreateMakerFeeTx;
|
||||
import bisq.core.offer.placeoffer.tasks.ValidateOffer;
|
||||
import bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
|
||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||
import bisq.core.trade.protocol.tasks.PublishTradeStatistics;
|
||||
import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage;
|
||||
import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener;
|
||||
@ -107,7 +107,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
addGroup("BuyerAsMakerProtocol",
|
||||
FXCollections.observableArrayList(Arrays.asList(
|
||||
MakerProcessPayDepositRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
MakerCreateAndSignContract.class,
|
||||
@ -120,7 +120,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
PublishTradeStatistics.class,
|
||||
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
BuyerAsMakerSignPayoutTx.class,
|
||||
@ -137,7 +137,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
TakerSendPayDepositRequest.class,
|
||||
|
||||
TakerProcessPublishDepositTxRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
TakerVerifyAndSignContract.class,
|
||||
@ -148,7 +148,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
SellerSignAndFinalizePayoutTx.class,
|
||||
@ -164,14 +164,14 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
TakerSendPayDepositRequest.class,
|
||||
|
||||
TakerProcessPublishDepositTxRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
TakerVerifyAndSignContract.class,
|
||||
BuyerAsTakerSignAndPublishDepositTx.class,
|
||||
TakerSendDepositTxPublishedMessage.class,
|
||||
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
BuyerAsMakerSignPayoutTx.class,
|
||||
@ -181,7 +181,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
addGroup("SellerAsMakerProtocol",
|
||||
FXCollections.observableArrayList(Arrays.asList(
|
||||
MakerProcessPayDepositRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
MakerCreateAndSignContract.class,
|
||||
@ -198,7 +198,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
|
||||
CheckIfPeerIsBanned.class,
|
||||
ApplyFilter.class,
|
||||
MakerVerifyTakerAccount.class,
|
||||
MakerVerifyTakerFeePayment.class,
|
||||
SellerSignAndFinalizePayoutTx.class,
|
||||
|
@ -35,6 +35,7 @@ import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OfferUtil;
|
||||
import bisq.core.offer.OpenOfferManager;
|
||||
import bisq.core.payment.AccountAgeRestrictions;
|
||||
import bisq.core.payment.AccountAgeWitnessService;
|
||||
import bisq.core.payment.HalCashAccount;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
@ -438,9 +439,8 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
|
||||
|
||||
buyerSecurityDeposit.set(preferences.getBuyerSecurityDepositAsPercent(getPaymentAccount()));
|
||||
|
||||
long myLimit = accountAgeWitnessService.getMyTradeLimit(paymentAccount, tradeCurrencyCode.get());
|
||||
if (amount.get() != null)
|
||||
this.amount.set(Coin.valueOf(Math.min(amount.get().value, myLimit)));
|
||||
this.amount.set(Coin.valueOf(Math.min(amount.get().value, getMaxTradeLimit())));
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,7 +581,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
|
||||
|
||||
long getMaxTradeLimit() {
|
||||
if (paymentAccount != null)
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, tradeCurrencyCode.get());
|
||||
return AccountAgeRestrictions.getMyTradeLimitAtCreateOffer(accountAgeWitnessService, paymentAccount, tradeCurrencyCode.get(), direction);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ import bisq.core.monetary.Price;
|
||||
import bisq.core.monetary.Volume;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OfferRestrictions;
|
||||
import bisq.core.offer.OfferUtil;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
import bisq.core.provider.price.MarketPrice;
|
||||
@ -728,6 +729,11 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
if (minAmount.get() != null)
|
||||
minAmountValidationResult.set(isBtcInputValid(minAmount.get()));
|
||||
} else if (amount.get() != null && btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().value == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) {
|
||||
new Popup<>().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.buyer",
|
||||
Res.get("offerbook.warning.newVersionAnnouncement")))
|
||||
.width(900)
|
||||
.show();
|
||||
}
|
||||
// We want to trigger a recalculation of the volume
|
||||
UserThread.execute(() -> {
|
||||
|
@ -435,6 +435,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
|
||||
private void onShowInfo(Offer offer,
|
||||
boolean isPaymentAccountValidForOffer,
|
||||
boolean isRiskyBuyOfferWithImmatureAccountAge,
|
||||
boolean isSellOfferAndAnyTakerPaymentAccountForOfferMature,
|
||||
boolean hasSameProtocolVersion,
|
||||
boolean isIgnored,
|
||||
boolean isOfferBanned,
|
||||
@ -448,6 +450,12 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
Res.get("offerbook.warning.noMatchingAccount.msg"),
|
||||
FiatAccountsView.class,
|
||||
"navigation.account");
|
||||
} else if (isRiskyBuyOfferWithImmatureAccountAge) {
|
||||
new Popup<>().warning(Res.get("offerbook.warning.riskyBuyOfferWithImmatureAccountAge",
|
||||
Res.get("offerbook.warning.newVersionAnnouncement"))).show();
|
||||
} else if (!isSellOfferAndAnyTakerPaymentAccountForOfferMature) {
|
||||
new Popup<>().warning(Res.get("offerbook.warning.sellOfferAndAnyTakerPaymentAccountForOfferMature",
|
||||
Res.get("offerbook.warning.newVersionAnnouncement"))).show();
|
||||
} else if (!hasSameProtocolVersion) {
|
||||
new Popup<>().warning(Res.get("offerbook.warning.wrongTradeProtocol")).show();
|
||||
} else if (isIgnored) {
|
||||
@ -812,7 +820,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
return new TableCell<>() {
|
||||
final ImageView iconView = new ImageView();
|
||||
final AutoTooltipButton button = new AutoTooltipButton();
|
||||
boolean isTradable, isPaymentAccountValidForOffer,
|
||||
boolean isTradable, isPaymentAccountValidForOffer, isRiskyBuyOfferWithImmatureAccountAge,
|
||||
isSellOfferAndAnyTakerPaymentAccountForOfferMature,
|
||||
hasSameProtocolVersion, isIgnored, isOfferBanned, isCurrencyBanned,
|
||||
isPaymentMethodBanned, isNodeAddressBanned, isInsufficientTradeLimit,
|
||||
requireUpdateToNewVersion;
|
||||
@ -834,6 +843,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
boolean myOffer = model.isMyOffer(offer);
|
||||
if (tableRow != null) {
|
||||
isPaymentAccountValidForOffer = model.isAnyPaymentAccountValidForOffer(offer);
|
||||
isRiskyBuyOfferWithImmatureAccountAge = model.isRiskyBuyOfferWithImmatureAccountAge(offer);
|
||||
isSellOfferAndAnyTakerPaymentAccountForOfferMature = model.isSellOfferAndAnyTakerPaymentAccountForOfferMature(offer);
|
||||
hasSameProtocolVersion = model.hasSameProtocolVersion(offer);
|
||||
isIgnored = model.isIgnored(offer);
|
||||
isOfferBanned = model.isOfferBanned(offer);
|
||||
@ -843,6 +854,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
requireUpdateToNewVersion = model.requireUpdateToNewVersion();
|
||||
isInsufficientTradeLimit = model.isInsufficientTradeLimit(offer);
|
||||
isTradable = isPaymentAccountValidForOffer &&
|
||||
!isRiskyBuyOfferWithImmatureAccountAge &&
|
||||
isSellOfferAndAnyTakerPaymentAccountForOfferMature &&
|
||||
hasSameProtocolVersion &&
|
||||
!isIgnored &&
|
||||
!isOfferBanned &&
|
||||
@ -865,6 +878,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
if (!(e.getTarget() instanceof ImageView || e.getTarget() instanceof Canvas))
|
||||
onShowInfo(offer,
|
||||
isPaymentAccountValidForOffer,
|
||||
isRiskyBuyOfferWithImmatureAccountAge,
|
||||
isSellOfferAndAnyTakerPaymentAccountForOfferMature,
|
||||
hasSameProtocolVersion,
|
||||
isIgnored,
|
||||
isOfferBanned,
|
||||
@ -905,6 +920,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
if (!myOffer && !isTradable)
|
||||
button.setOnAction(e -> onShowInfo(offer,
|
||||
isPaymentAccountValidForOffer,
|
||||
isRiskyBuyOfferWithImmatureAccountAge,
|
||||
isSellOfferAndAnyTakerPaymentAccountForOfferMature,
|
||||
hasSameProtocolVersion,
|
||||
isIgnored,
|
||||
isOfferBanned,
|
||||
|
@ -505,7 +505,17 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
boolean isAnyPaymentAccountValidForOffer(Offer offer) {
|
||||
return user.getPaymentAccounts() != null && PaymentAccountUtil.isAnyPaymentAccountValidForOffer(offer, user.getPaymentAccounts());
|
||||
return user.getPaymentAccounts() != null &&
|
||||
PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(offer, user.getPaymentAccounts());
|
||||
}
|
||||
|
||||
boolean isSellOfferAndAnyTakerPaymentAccountForOfferMature(Offer offer) {
|
||||
return user.getPaymentAccounts() != null &&
|
||||
PaymentAccountUtil.isSellOfferAndAnyTakerPaymentAccountForOfferMature(offer, user.getPaymentAccounts(), accountAgeWitnessService);
|
||||
}
|
||||
|
||||
boolean isRiskyBuyOfferWithImmatureAccountAge(Offer offer) {
|
||||
return PaymentAccountUtil.isRiskyBuyOfferWithImmatureAccountAge(offer, accountAgeWitnessService);
|
||||
}
|
||||
|
||||
boolean hasPaymentAccountForCurrency() {
|
||||
@ -515,6 +525,12 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
user.hasPaymentAccountForCurrency(selectedTradeCurrency);
|
||||
}
|
||||
|
||||
boolean hasMakerAnyMatureAccountForBuyOffer() {
|
||||
return direction == OfferPayload.Direction.SELL ||
|
||||
(user.getPaymentAccounts() != null &&
|
||||
PaymentAccountUtil.hasMakerAnyMatureAccountForBuyOffer(user.getPaymentAccounts(), accountAgeWitnessService));
|
||||
}
|
||||
|
||||
boolean hasAcceptedArbitrators() {
|
||||
return user.getAcceptedArbitrators() != null && !user.getAcceptedArbitrators().isEmpty();
|
||||
}
|
||||
@ -558,7 +574,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
boolean requireUpdateToNewVersion() {
|
||||
return filterManager.requireUpdateToNewVersion();
|
||||
return filterManager.requireUpdateToNewVersionForTrading();
|
||||
}
|
||||
|
||||
boolean isInsufficientTradeLimit(Offer offer) {
|
||||
|
@ -35,6 +35,7 @@ import bisq.core.monetary.Volume;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OfferUtil;
|
||||
import bisq.core.payment.AccountAgeRestrictions;
|
||||
import bisq.core.payment.AccountAgeWitnessService;
|
||||
import bisq.core.payment.HalCashAccount;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
@ -185,8 +186,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
checkArgument(!possiblePaymentAccounts.isEmpty(), "possiblePaymentAccounts.isEmpty()");
|
||||
paymentAccount = getLastSelectedPaymentAccount();
|
||||
|
||||
long myLimit = accountAgeWitnessService.getMyTradeLimit(paymentAccount, getCurrencyCode());
|
||||
this.amount.set(Coin.valueOf(Math.min(offer.getAmount().value, myLimit)));
|
||||
this.amount.set(Coin.valueOf(Math.min(offer.getAmount().value, getMaxTradeLimit())));
|
||||
|
||||
securityDeposit = offer.getDirection() == OfferPayload.Direction.SELL ?
|
||||
getBuyerSecurityDeposit() :
|
||||
@ -304,7 +304,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
new Popup<>().warning(Res.get("offerbook.warning.offerBlocked")).show();
|
||||
} else if (filterManager.isNodeAddressBanned(offer.getMakerNodeAddress())) {
|
||||
new Popup<>().warning(Res.get("offerbook.warning.nodeBlocked")).show();
|
||||
} else if (filterManager.requireUpdateToNewVersion()) {
|
||||
} else if (filterManager.requireUpdateToNewVersionForTrading()) {
|
||||
new Popup<>().warning(Res.get("offerbook.warning.requireUpdateToNewVersion")).show();
|
||||
} else {
|
||||
tradeManager.onTakeOffer(amount.get(),
|
||||
@ -373,7 +373,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
if (paymentAccount != null) {
|
||||
this.paymentAccount = paymentAccount;
|
||||
|
||||
long myLimit = accountAgeWitnessService.getMyTradeLimit(paymentAccount, getCurrencyCode());
|
||||
long myLimit = getMaxTradeLimit();
|
||||
this.amount.set(Coin.valueOf(Math.max(offer.getMinAmount().value, Math.min(amount.get().value, myLimit))));
|
||||
|
||||
preferences.setTakeOfferSelectedPaymentAccountId(paymentAccount.getId());
|
||||
@ -405,7 +405,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
ObservableList<PaymentAccount> getPossiblePaymentAccounts() {
|
||||
Set<PaymentAccount> paymentAccounts = user.getPaymentAccounts();
|
||||
checkNotNull(paymentAccounts, "paymentAccounts must not be null");
|
||||
return PaymentAccountUtil.getPossiblePaymentAccounts(offer, paymentAccounts);
|
||||
return PaymentAccountUtil.getPossiblePaymentAccounts(offer, paymentAccounts, accountAgeWitnessService);
|
||||
}
|
||||
|
||||
public PaymentAccount getLastSelectedPaymentAccount() {
|
||||
@ -430,11 +430,12 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
|
||||
long getMaxTradeLimit() {
|
||||
if (paymentAccount != null)
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, getCurrencyCode());
|
||||
return AccountAgeRestrictions.getMyTradeLimitAtTakeOffer(accountAgeWitnessService, paymentAccount, offer, getCurrencyCode(), getDirection());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Bindings, listeners
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -447,6 +448,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
btcWalletService.removeBalanceListener(balanceListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -468,8 +470,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
}
|
||||
|
||||
void applyAmount(Coin amount) {
|
||||
long myLimit = accountAgeWitnessService.getMyTradeLimit(paymentAccount, getCurrencyCode());
|
||||
this.amount.set(Coin.valueOf(Math.min(amount.value, myLimit)));
|
||||
this.amount.set(Coin.valueOf(Math.min(amount.value, getMaxTradeLimit())));
|
||||
|
||||
calculateTotalToPay();
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import bisq.core.monetary.Price;
|
||||
import bisq.core.monetary.Volume;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.offer.OfferRestrictions;
|
||||
import bisq.core.offer.OfferUtil;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
@ -371,6 +372,19 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
if (dataModel.wouldCreateDustForMaker())
|
||||
amountValidationResult.set(new InputValidator.ValidationResult(false,
|
||||
Res.get("takeOffer.validation.amountLargerThanOfferAmountMinusFee")));
|
||||
} else if (btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().value == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) {
|
||||
if (dataModel.getDirection() == OfferPayload.Direction.BUY) {
|
||||
new Popup<>().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.seller",
|
||||
Res.get("offerbook.warning.newVersionAnnouncement")))
|
||||
.width(900)
|
||||
.show();
|
||||
} else {
|
||||
new Popup<>().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.buyer",
|
||||
Res.get("offerbook.warning.newVersionAnnouncement")))
|
||||
.width(900)
|
||||
.show();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,14 +40,10 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addMultilineLabel;
|
||||
|
||||
//TODO might be removed, but leave it for now until sure we will not use it anymore.
|
||||
public class SelectDepositTxWindow extends Overlay<SelectDepositTxWindow> {
|
||||
private static final Logger log = LoggerFactory.getLogger(SelectDepositTxWindow.class);
|
||||
|
||||
private ComboBox<Transaction> transactionsComboBox;
|
||||
private List<Transaction> transactions;
|
||||
private Optional<Consumer<Transaction>> selectHandlerOptional;
|
||||
|
@ -23,7 +23,6 @@ import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.disputes.DisputesView;
|
||||
import bisq.desktop.main.overlays.notifications.NotificationCenter;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.SelectDepositTxWindow;
|
||||
import bisq.desktop.main.overlays.windows.WalletPasswordWindow;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
@ -35,6 +34,7 @@ import bisq.core.btc.wallet.BtcWalletService;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.payment.AccountAgeWitnessService;
|
||||
import bisq.core.payment.payload.PaymentAccountPayload;
|
||||
import bisq.core.trade.BuyerTrade;
|
||||
import bisq.core.trade.SellerTrade;
|
||||
@ -71,6 +71,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
@ -83,6 +85,8 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
public final DisputeManager disputeManager;
|
||||
private final P2PService p2PService;
|
||||
private final WalletsSetup walletsSetup;
|
||||
@Getter
|
||||
private final AccountAgeWitnessService accountAgeWitnessService;
|
||||
public final Navigation navigation;
|
||||
public final WalletPasswordWindow walletPasswordWindow;
|
||||
private final NotificationCenter notificationCenter;
|
||||
@ -110,6 +114,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
Preferences preferences,
|
||||
P2PService p2PService,
|
||||
WalletsSetup walletsSetup,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
Navigation navigation,
|
||||
WalletPasswordWindow walletPasswordWindow,
|
||||
NotificationCenter notificationCenter) {
|
||||
@ -120,6 +125,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
this.preferences = preferences;
|
||||
this.p2PService = p2PService;
|
||||
this.walletsSetup = walletsSetup;
|
||||
this.accountAgeWitnessService = accountAgeWitnessService;
|
||||
this.navigation = navigation;
|
||||
this.walletPasswordWindow = walletPasswordWindow;
|
||||
this.notificationCenter = notificationCenter;
|
||||
@ -418,15 +424,22 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
}
|
||||
});
|
||||
|
||||
if (candidates.size() == 1)
|
||||
if (candidates.size() > 0) {
|
||||
log.error("Trade.depositTx is null. We take the first possible MultiSig tx just to be able to open a dispute. " +
|
||||
"candidates={}", candidates);
|
||||
doOpenDispute(isSupportTicket, candidates.get(0));
|
||||
else if (candidates.size() > 1)
|
||||
}/* else if (candidates.size() > 1) {
|
||||
// Let remove that as it confused users and was from little help
|
||||
new SelectDepositTxWindow().transactions(candidates)
|
||||
.onSelect(transaction -> doOpenDispute(isSupportTicket, transaction))
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.show();
|
||||
else
|
||||
log.error("Trade.depositTx is null and we did not find any MultiSig transaction.");
|
||||
}*/ else if (transactions.size() > 0) {
|
||||
doOpenDispute(isSupportTicket, transactions.get(0));
|
||||
log.error("Trade.depositTx is null and we did not find any MultiSig transaction. We take any random tx just to be able to open a dispute");
|
||||
} else {
|
||||
log.error("Trade.depositTx is null and we did not find any transaction.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("Trade is null");
|
||||
|
@ -301,7 +301,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||
if (trade != null && model.getUser().getPaymentAccounts() != null) {
|
||||
Offer offer = trade.getOffer();
|
||||
List<PaymentAccount> possiblePaymentAccounts = PaymentAccountUtil.getPossiblePaymentAccounts(offer,
|
||||
model.getUser().getPaymentAccounts());
|
||||
model.getUser().getPaymentAccounts(), model.dataModel.getAccountAgeWitnessService());
|
||||
PaymentAccountPayload buyersPaymentAccountPayload = model.dataModel.getBuyersPaymentAccountPayload();
|
||||
if (buyersPaymentAccountPayload != null && possiblePaymentAccounts.size() > 1) {
|
||||
String id = buyersPaymentAccountPayload.getId();
|
||||
|
@ -27,6 +27,7 @@ import javax.inject.Inject;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -45,6 +46,7 @@ public class BtcValidator extends NumberValidator {
|
||||
|
||||
@Nullable
|
||||
@Setter
|
||||
@Getter
|
||||
protected Coin maxTradeLimit;
|
||||
|
||||
@Inject
|
||||
|
@ -99,46 +99,46 @@ public class OfferBookViewModelTest {
|
||||
Collection<PaymentAccount> paymentAccounts;
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSepaAccount("EUR", "DE", "1212324",
|
||||
new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
// empty paymentAccounts
|
||||
paymentAccounts = new ArrayList<>();
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(getSEPAPaymentMethod("EUR", "AT",
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(getSEPAPaymentMethod("EUR", "AT",
|
||||
new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// simple cases: same payment methods
|
||||
|
||||
// offer: alipay paymentAccount: alipay - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getAliPayAccount("CNY")));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getAliPayPaymentMethod("EUR"), paymentAccounts));
|
||||
|
||||
// offer: ether paymentAccount: ether - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getCryptoAccount("ETH")));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getBlockChainsPaymentMethod("ETH"), paymentAccounts));
|
||||
|
||||
// offer: sepa paymentAccount: sepa - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSepaAccount("EUR", "AT", "1212324",
|
||||
new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// offer: nationalBank paymentAccount: nationalBank - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getNationalBankAccount("EUR", "AT", "PSK")));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// offer: SameBank paymentAccount: SameBank - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSameBankAccount("EUR", "AT", "PSK")));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSameBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// offer: sepa paymentAccount: sepa - diff. country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSepaAccount("EUR", "DE", "1212324", new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
@ -146,79 +146,79 @@ public class OfferBookViewModelTest {
|
||||
|
||||
// offer: sepa paymentAccount: sepa - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSepaAccount("EUR", "AT", "1212324", new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
// offer: sepa paymentAccount: nationalBank - same country, same currency
|
||||
// wrong method
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getNationalBankAccount("EUR", "AT", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// wrong currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getNationalBankAccount("USD", "US", "XXX")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// wrong country
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getNationalBankAccount("EUR", "FR", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// sepa wrong country
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getNationalBankAccount("EUR", "CH", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// sepa wrong currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getNationalBankAccount("CHF", "DE", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
// same bank
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSameBankAccount("EUR", "AT", "PSK")));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// not same bank
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSameBankAccount("EUR", "AT", "Raika")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// same bank, wrong country
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSameBankAccount("EUR", "DE", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// same bank, wrong currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSameBankAccount("USD", "AT", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSpecificBanksAccount("EUR", "AT", "PSK",
|
||||
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank, missing bank
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSpecificBanksAccount("EUR", "AT", "PSK",
|
||||
new ArrayList<>(Collections.singletonList("Raika")))));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank, wrong country
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSpecificBanksAccount("EUR", "FR", "PSK",
|
||||
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank, wrong currency
|
||||
paymentAccounts = new ArrayList<>(Collections.singletonList(getSpecificBanksAccount("USD", "AT", "PSK",
|
||||
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
//TODO add more tests
|
||||
|
Loading…
Reference in New Issue
Block a user