Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Capitual payment method #5501

Merged
merged 8 commits into from
Jul 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions core/src/main/java/bisq/core/locale/CurrencyUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,15 @@ public static List<TradeCurrency> getAllAmazonGiftCardCurrencies() {
return currencies;
}

public static List<TradeCurrency> getAllCapitualCurrencies() {
return new ArrayList<>(Arrays.asList(
new FiatCurrency("BRL"),
new FiatCurrency("EUR"),
new FiatCurrency("GBP"),
new FiatCurrency("USD")
));
}

// https://www.revolut.com/help/getting-started/exchanging-currencies/what-fiat-currencies-are-supported-for-holding-and-exchange
public static List<TradeCurrency> getAllRevolutCurrencies() {
ArrayList<TradeCurrency> currencies = new ArrayList<>(Arrays.asList(
Expand Down
46 changes: 46 additions & 0 deletions core/src/main/java/bisq/core/payment/CapitualAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.locale.CurrencyUtil;
import bisq.core.payment.payload.CapitualAccountPayload;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(callSuper = true)
public final class CapitualAccount extends PaymentAccount {
public CapitualAccount() {
super(PaymentMethod.CAPITUAL);
tradeCurrencies.addAll(CurrencyUtil.getAllCapitualCurrencies());
}

@Override
protected PaymentAccountPayload createPayload() {
return new CapitualAccountPayload(paymentMethod.getId(), id);
}

public void setAccountNr(String accountNr) {
((CapitualAccountPayload) paymentAccountPayload).setAccountNr(accountNr);
}

public String getAccountNr() {
return ((CapitualAccountPayload) paymentAccountPayload).getAccountNr();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new AmazonGiftCardAccount();
case PaymentMethod.BLOCK_CHAINS_INSTANT_ID:
return new InstantCryptoCurrencyAccount();
case PaymentMethod.CAPITUAL_ID:
return new CapitualAccount();

// Cannot be deleted as it would break old trade history entries
case PaymentMethod.OK_PAY_ID:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* 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.payload;

import bisq.core.locale.Res;

import com.google.protobuf.Message;

import java.nio.charset.StandardCharsets;

import java.util.HashMap;
import java.util.Map;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

@EqualsAndHashCode(callSuper = true)
@ToString
@Setter
@Getter
@Slf4j
public final class CapitualAccountPayload extends PaymentAccountPayload {
private String accountNr = "";

public CapitualAccountPayload(String paymentMethod, String id) {
super(paymentMethod, id);
}


///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////

private CapitualAccountPayload(String paymentMethod,
String id,
String accountNr,
long maxTradePeriod,
Map<String, String> excludeFromJsonDataMap) {
super(paymentMethod,
id,
maxTradePeriod,
excludeFromJsonDataMap);

this.accountNr = accountNr;
}

@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
.setCapitualAccountPayload(protobuf.CapitualAccountPayload.newBuilder()
.setAccountNr(accountNr))
.build();
}

public static CapitualAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new CapitualAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getCapitualAccountPayload().getAccountNr(),
proto.getMaxTradePeriod(),
new HashMap<>(proto.getExcludeFromJsonDataMap()));
}

///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////

@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.capitual.cap") + " " + accountNr;
}

@Override
public String getPaymentDetailsForTradePopup() {
return getPaymentDetails();
}

@Override
public byte[] getAgeWitnessInputData() {
return super.getAgeWitnessInputData(accountNr.getBytes(StandardCharsets.UTF_8));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static final String AMAZON_GIFT_CARD_ID = "AMAZON_GIFT_CARD";
public static final String BLOCK_CHAINS_INSTANT_ID = "BLOCK_CHAINS_INSTANT";
public static final String CASH_BY_MAIL_ID = "CASH_BY_MAIL";
public static final String CAPITUAL_ID = "CAPITUAL";

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -140,6 +141,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static PaymentMethod AMAZON_GIFT_CARD;
public static PaymentMethod BLOCK_CHAINS_INSTANT;
public static PaymentMethod CASH_BY_MAIL;
public static PaymentMethod CAPITUAL;

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -191,6 +193,8 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),
ADVANCED_CASH = new PaymentMethod(ADVANCED_CASH_ID, DAY, DEFAULT_TRADE_LIMIT_VERY_LOW_RISK),
TRANSFERWISE = new PaymentMethod(TRANSFERWISE_ID, 4 * DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
CAPITUAL = new PaymentMethod(CAPITUAL_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),


// Japan
JAPAN_BANK = new PaymentMethod(JAPAN_BANK_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/bisq/core/proto/CoreProtoResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import bisq.core.payment.payload.AliPayAccountPayload;
import bisq.core.payment.payload.AmazonGiftCardAccountPayload;
import bisq.core.payment.payload.AustraliaPayidPayload;
import bisq.core.payment.payload.CapitualAccountPayload;
import bisq.core.payment.payload.CashAppAccountPayload;
import bisq.core.payment.payload.CashByMailAccountPayload;
import bisq.core.payment.payload.CashDepositAccountPayload;
Expand Down Expand Up @@ -159,6 +160,8 @@ public PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return AmazonGiftCardAccountPayload.fromProto(proto);
case INSTANT_CRYPTO_CURRENCY_ACCOUNT_PAYLOAD:
return InstantCryptoCurrencyPayload.fromProto(proto);
case CAPITUAL_ACCOUNT_PAYLOAD:
return CapitualAccountPayload.fromProto(proto);

// Cannot be deleted as it would break old trade history entries
case O_K_PAY_ACCOUNT_PAYLOAD:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ private enum PaymentMethodMapper {
BLOCK_CHAINS_INSTANT,
TRANSFERWISE,
AMAZON_GIFT_CARD,
CASH_BY_MAIL
CASH_BY_MAIL,
CAPITUAL
}

@Getter
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3268,6 +3268,7 @@ payment.select.altcoin=Select or search Altcoin
payment.secret=Secret question
payment.answer=Answer
payment.wallet=Wallet ID
payment.capitual.cap=CAP Code
payment.amazon.site=Buy giftcard at
payment.ask=Ask in Trader Chat
payment.uphold.accountId=Username or email or phone no.
Expand Down Expand Up @@ -3481,7 +3482,6 @@ payment.amazonGiftCard.info=To pay with Amazon eGift Card, you will need to send
to tell your trading peer the reference text you picked so they can verify your payment)\n\
- Amazon eGift Cards can only be redeemed on the Amazon website they were purchased on (e.g., a gift card purchased on amazon.it can only be redeemed on amazon.it)


# We use constants from the code so we do not use our normal naming convention
# dynamic values are not recognized by IntelliJ

Expand Down Expand Up @@ -3564,6 +3564,8 @@ TRANSFERWISE=TransferWise
AMAZON_GIFT_CARD=Amazon eGift Card
# suppress inspection "UnusedProperty"
BLOCK_CHAINS_INSTANT=Altcoins Instant
# suppress inspection "UnusedProperty"
CAPITUAL=Capitual

# Deprecated: Cannot be deleted as it would break old trade history entries
# suppress inspection "UnusedProperty"
Expand Down Expand Up @@ -3616,6 +3618,8 @@ TRANSFERWISE_SHORT=TransferWise
AMAZON_GIFT_CARD_SHORT=Amazon eGift Card
# suppress inspection "UnusedProperty"
BLOCK_CHAINS_INSTANT_SHORT=Altcoins Instant
# suppress inspection "UnusedProperty"
CAPITUAL_SHORT=Capitual

# Deprecated: Cannot be deleted as it would break old trade history entries
# suppress inspection "UnusedProperty"
Expand Down Expand Up @@ -3706,3 +3710,4 @@ validation.phone.tooManyDigits=There are too many digits in {0} to be a valid ph
validation.phone.invalidDialingCode=Country dialing code for number {0} is invalid for country {1}. \
The correct dialing code is {2}.
validation.invalidAddressList=Must be comma separated list of valid addresses
validation.capitual.invalidFormat=Must be a valid CAP code of format: CAP-XXXXXX (6 alphanumeric characters)
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* 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.desktop.components.paymentmethods;

import bisq.desktop.components.InputTextField;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.Layout;
import bisq.desktop.util.validation.CapitualValidator;

import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.payment.CapitualAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.CapitualAccountPayload;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.validation.InputValidator;

import bisq.common.util.Tuple2;

import org.apache.commons.lang3.StringUtils;

import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;

import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextField;
import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextFieldWithCopyIcon;
import static bisq.desktop.util.FormBuilder.addTopLabelFlowPane;

public class CapitualForm extends PaymentMethodForm {
private final CapitualAccount capitualAccount;
private final CapitualValidator capitualValidator;
private InputTextField accountNrInputTextField;

public static int addFormForBuyer(GridPane gridPane, int gridRow,
PaymentAccountPayload paymentAccountPayload) {
addCompactTopLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.capitual.cap"),
((CapitualAccountPayload) paymentAccountPayload).getAccountNr());
return gridRow;
}

public CapitualForm(PaymentAccount paymentAccount,
AccountAgeWitnessService accountAgeWitnessService,
CapitualValidator capitualValidator,
InputValidator inputValidator,
GridPane gridPane,
int gridRow,
CoinFormatter formatter) {
super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter);
this.capitualAccount = (CapitualAccount) paymentAccount;
this.capitualValidator = capitualValidator;
}

@Override
public void addFormForAddAccount() {
gridRowFrom = gridRow + 1;

accountNrInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.capitual.cap"));
accountNrInputTextField.setValidator(capitualValidator);
accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
capitualAccount.setAccountNr(newValue);
updateFromInputs();
});

addCurrenciesGrid(true);
addLimitations(false);
addAccountNameTextFieldWithAutoFillToggleButton();
}

private void addCurrenciesGrid(boolean isEditable) {
final Tuple2<Label, FlowPane> labelFlowPaneTuple2 = addTopLabelFlowPane(gridPane, ++gridRow, Res.get("payment.supportedCurrencies"), 0);

FlowPane flowPane = labelFlowPaneTuple2.second;

if (isEditable)
flowPane.setId("flow-pane-checkboxes-bg");
else
flowPane.setId("flow-pane-checkboxes-non-editable-bg");

CurrencyUtil.getAllCapitualCurrencies().forEach(e ->
fillUpFlowPaneWithCurrencies(isEditable, flowPane, e, capitualAccount));
}

@Override
protected void autoFillNameTextField() {
if (useCustomAccountNameToggleButton != null && !useCustomAccountNameToggleButton.isSelected()) {
String accountNr = accountNrInputTextField.getText();
accountNr = StringUtils.abbreviate(accountNr, 9);
String method = Res.get(paymentAccount.getPaymentMethod().getId());
accountNameTextField.setText(method.concat(": ").concat(accountNr));
}
}

@Override
public void addFormForDisplayAccount() {
gridRowFrom = gridRow;
addCompactTopLabelTextField(gridPane, gridRow, Res.get("payment.account.name"),
capitualAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.paymentMethod"),
Res.get(capitualAccount.getPaymentMethod().getId()));
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.capitual.cap"),
capitualAccount.getAccountNr());
addLimitations(true);
addCurrenciesGrid(false);
}

@Override
public void updateAllInputsValid() {
allInputsValid.set(isAccountNameValid()
&& capitualValidator.validate(capitualAccount.getAccountNr()).isValid
&& !capitualAccount.getTradeCurrencies().isEmpty());
}

}
Loading