diff --git a/core/src/main/java/bisq/core/payment/NequiAccount.java b/core/src/main/java/bisq/core/payment/NequiAccount.java new file mode 100644 index 00000000000..d623ccf78ff --- /dev/null +++ b/core/src/main/java/bisq/core/payment/NequiAccount.java @@ -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 . + */ + +package bisq.core.payment; + +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.payment.payload.PaymentMethod; +import bisq.core.payment.payload.NequiAccountPayload; + +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class NequiAccount extends CountryBasedPaymentAccount { + public NequiAccount() { + super(PaymentMethod.NEQUI); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new NequiAccountPayload(paymentMethod.getId(), id); + } + + public void setMobileNr(String mobileNr) { + ((NequiAccountPayload) paymentAccountPayload).setMobileNr(mobileNr); + } + + public String getMobileNr() { + return ((NequiAccountPayload) paymentAccountPayload).getMobileNr(); + } + + public String getMessageForBuyer() { + return "payment.nequi.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.nequi.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.nequi.info.account"; + } +} diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java index b5a69eac8e7..e4028727bfb 100644 --- a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java +++ b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java @@ -96,6 +96,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) { return new UpiAccount(); case PaymentMethod.PAYTM_ID: return new PaytmAccount(); + case PaymentMethod.NEQUI_ID: + return new NequiAccount(); case PaymentMethod.AMAZON_GIFT_CARD_ID: return new AmazonGiftCardAccount(); case PaymentMethod.BLOCK_CHAINS_INSTANT_ID: diff --git a/core/src/main/java/bisq/core/payment/payload/NequiAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/NequiAccountPayload.java new file mode 100644 index 00000000000..7b1f9e627ca --- /dev/null +++ b/core/src/main/java/bisq/core/payment/payload/NequiAccountPayload.java @@ -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 . + */ + +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 NequiAccountPayload extends CountryBasedPaymentAccountPayload { + private String mobileNr = ""; + + public NequiAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + private NequiAccountPayload(String paymentMethod, + String id, + String countryCode, + String mobileNr, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + countryCode, + maxTradePeriod, + excludeFromJsonDataMap); + + this.mobileNr = mobileNr; + } + + @Override + public Message toProtoMessage() { + protobuf.NequiAccountPayload.Builder builder = protobuf.NequiAccountPayload.newBuilder() + .setMobileNr(mobileNr); + final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setNequiAccountPayload(builder); + return getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayload) + .build(); + } + + public static NequiAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { + protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload(); + protobuf.NequiAccountPayload paytmAccountPayloadPB = countryBasedPaymentAccountPayload.getNequiAccountPayload(); + return new NequiAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + countryBasedPaymentAccountPayload.getCountryCode(), + paytmAccountPayloadPB.getMobileNr(), + proto.getMaxTradePeriod(), + new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.mobile") + " " + mobileNr; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(mobileNr.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java index f4ad3b8fe9d..e05a0c2f65f 100644 --- a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java +++ b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java @@ -103,6 +103,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable. + */ + +package bisq.desktop.components.paymentmethods; + +import bisq.desktop.components.InputTextField; +import bisq.desktop.util.FormBuilder; +import bisq.desktop.util.Layout; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.locale.CountryUtil; +import bisq.core.locale.FiatCurrency; +import bisq.core.locale.Res; +import bisq.core.payment.PaymentAccount; +import bisq.core.payment.NequiAccount; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.payment.payload.NequiAccountPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.validation.InputValidator; + +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; + +import static bisq.desktop.util.FormBuilder.addCompactTopLabelTextField; +import static bisq.desktop.util.FormBuilder.addTopLabelTextField; +import static bisq.desktop.util.FormBuilder.addTopLabelTextFieldWithCopyIcon; + +public class NequiForm extends PaymentMethodForm { + private final NequiAccount account; + private InputTextField mobileNrInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + addTopLabelTextFieldWithCopyIcon(gridPane, gridRow, 1, Res.get("payment.mobile"), + ((NequiAccountPayload) paymentAccountPayload).getMobileNr(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE); + return gridRow; + } + + public NequiForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, + InputValidator inputValidator, GridPane gridPane, + int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (NequiAccount) paymentAccount; + } + + @Override + public void addFormForAddAccount() { + // this payment method is only for Columbia/COP + account.setSingleTradeCurrency(new FiatCurrency("COP")); + CountryUtil.findCountryByCode("CO").ifPresent(c -> account.setCountry(c)); + + gridRowFrom = gridRow + 1; + + mobileNrInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.mobile")); + mobileNrInputTextField.setValidator(inputValidator); + mobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setMobileNr(newValue.trim()); + updateFromInputs(); + }); + + addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), account.getSingleTradeCurrency().getNameAndCode()); + addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), account.getCountry().name); + addLimitations(false); + addAccountNameTextFieldWithAutoFillToggleButton(); + } + + @Override + protected void autoFillNameTextField() { + setAccountNameWithString(mobileNrInputTextField.getText()); + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addTopLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), + account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.paymentMethod"), + Res.get(account.getPaymentMethod().getId())); + TextField field = addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.mobile"), + account.getMobileNr()).second; + field.setMouseTransparent(false); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), account.getSingleTradeCurrency().getNameAndCode()); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), account.getCountry().name); + addLimitations(true); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && inputValidator.validate(account.getMobileNr()).isValid); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java index 8e614d2562a..c07f8b1418d 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java @@ -39,6 +39,7 @@ import bisq.desktop.components.paymentmethods.MoneyGramForm; import bisq.desktop.components.paymentmethods.NationalBankForm; import bisq.desktop.components.paymentmethods.NeftForm; +import bisq.desktop.components.paymentmethods.NequiForm; import bisq.desktop.components.paymentmethods.PaymentMethodForm; import bisq.desktop.components.paymentmethods.PaytmForm; import bisq.desktop.components.paymentmethods.PerfectMoneyForm; @@ -562,6 +563,8 @@ private PaymentMethodForm getPaymentMethodForm(PaymentMethod paymentMethod, Paym return new UpiForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); case PaymentMethod.PAYTM_ID: return new PaytmForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); + case PaymentMethod.NEQUI_ID: + return new NequiForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); case PaymentMethod.AMAZON_GIFT_CARD_ID: return new AmazonGiftCardForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); case PaymentMethod.CAPITUAL_ID: diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index a91ff0208f6..0aed94c7c3c 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -41,6 +41,7 @@ import bisq.desktop.components.paymentmethods.MoneyGramForm; import bisq.desktop.components.paymentmethods.NationalBankForm; import bisq.desktop.components.paymentmethods.NeftForm; +import bisq.desktop.components.paymentmethods.NequiForm; import bisq.desktop.components.paymentmethods.PaxumForm; import bisq.desktop.components.paymentmethods.PayseraForm; import bisq.desktop.components.paymentmethods.PaytmForm; @@ -352,6 +353,9 @@ protected void addContent() { case PaymentMethod.PAYTM_ID: gridRow = PaytmForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); break; + case PaymentMethod.NEQUI_ID: + gridRow = NequiForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; case PaymentMethod.AMAZON_GIFT_CARD_ID: gridRow = AmazonGiftCardForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); break; diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index f274d08362e..9ab43bd25ae 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1035,6 +1035,7 @@ message CountryBasedPaymentAccountPayload { UpiAccountPayload upi_account_payload = 9; PaytmAccountPayload paytm_account_payload = 10; IfscBasedAccountPayload ifsc_based_account_payload = 11; + NequiAccountPayload nequi_account_payload = 12; } } @@ -1269,6 +1270,10 @@ message CelPayAccountPayload { string email = 1; } +message NequiAccountPayload { + string mobile_nr = 1; +} + message SwiftAccountPayload { string beneficiary_name = 1; string beneficiary_account_nr = 2;