diff --git a/core/src/main/java/bisq/core/payment/ImpsAccount.java b/core/src/main/java/bisq/core/payment/ImpsAccount.java new file mode 100644 index 00000000000..f16349e8ad5 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/ImpsAccount.java @@ -0,0 +1,48 @@ +/* + * 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.ImpsAccountPayload; + +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class ImpsAccount extends CountryBasedPaymentAccount { + public ImpsAccount() { + super(PaymentMethod.IMPS); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new ImpsAccountPayload(paymentMethod.getId(), id); + } + + public String getMessageForBuyer() { + return "payment.imps.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.imps.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.imps.info.account"; + } +} diff --git a/core/src/main/java/bisq/core/payment/NeftAccount.java b/core/src/main/java/bisq/core/payment/NeftAccount.java new file mode 100644 index 00000000000..cb954d8d872 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/NeftAccount.java @@ -0,0 +1,48 @@ +/* + * 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.NeftAccountPayload; + +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class NeftAccount extends CountryBasedPaymentAccount { + public NeftAccount() { + super(PaymentMethod.NEFT); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new NeftAccountPayload(paymentMethod.getId(), id); + } + + public String getMessageForBuyer() { + return "payment.neft.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.neft.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.neft.info.account"; + } +} diff --git a/core/src/main/java/bisq/core/payment/PaymentAccount.java b/core/src/main/java/bisq/core/payment/PaymentAccount.java index 686dc7d972f..631f3ba915b 100644 --- a/core/src/main/java/bisq/core/payment/PaymentAccount.java +++ b/core/src/main/java/bisq/core/payment/PaymentAccount.java @@ -225,4 +225,27 @@ public void onAddToUser() { // We are in the process to get added to the user. This is called just before saving the account and the // last moment we could apply some special handling if needed (e.g. as it happens for Revolut) } + + public String getPreTradeMessage(boolean isBuyer) { + if (isBuyer) { + return getMessageForBuyer(); + } else { + return getMessageForSeller(); + } + } + + // will be overridden by specific account when necessary + public String getMessageForBuyer() { + return null; + } + + // will be overridden by specific account when necessary + public String getMessageForSeller() { + return null; + } + + // will be overridden by specific account when necessary + public String getMessageForAccountCreation() { + return null; + } } diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java index f6c528a8ae5..fc3c3f391d0 100644 --- a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java +++ b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java @@ -86,6 +86,16 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) { return new PayseraAccount(); case PaymentMethod.PAXUM_ID: return new PaxumAccount(); + case PaymentMethod.NEFT_ID: + return new NeftAccount(); + case PaymentMethod.RTGS_ID: + return new RtgsAccount(); + case PaymentMethod.IMPS_ID: + return new ImpsAccount(); + case PaymentMethod.UPI_ID: + return new UpiAccount(); + case PaymentMethod.PAYTM_ID: + return new PaytmAccount(); 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/PaytmAccount.java b/core/src/main/java/bisq/core/payment/PaytmAccount.java new file mode 100644 index 00000000000..d2b27c7b478 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/PaytmAccount.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.PaytmAccountPayload; + +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class PaytmAccount extends CountryBasedPaymentAccount { + public PaytmAccount() { + super(PaymentMethod.PAYTM); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new PaytmAccountPayload(paymentMethod.getId(), id); + } + + public void setEmailOrMobileNr(String emailOrMobileNr) { + ((PaytmAccountPayload) paymentAccountPayload).setEmailOrMobileNr(emailOrMobileNr); + } + + public String getEmailOrMobileNr() { + return ((PaytmAccountPayload) paymentAccountPayload).getEmailOrMobileNr(); + } + + public String getMessageForBuyer() { + return "payment.paytm.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.paytm.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.paytm.info.account"; + } +} diff --git a/core/src/main/java/bisq/core/payment/RtgsAccount.java b/core/src/main/java/bisq/core/payment/RtgsAccount.java new file mode 100644 index 00000000000..0b9b2156faf --- /dev/null +++ b/core/src/main/java/bisq/core/payment/RtgsAccount.java @@ -0,0 +1,48 @@ +/* + * 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.RtgsAccountPayload; + +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class RtgsAccount extends CountryBasedPaymentAccount { + public RtgsAccount() { + super(PaymentMethod.RTGS); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new RtgsAccountPayload(paymentMethod.getId(), id); + } + + public String getMessageForBuyer() { + return "payment.rtgs.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.rtgs.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.rtgs.info.account"; + } +} diff --git a/core/src/main/java/bisq/core/payment/SwiftAccount.java b/core/src/main/java/bisq/core/payment/SwiftAccount.java index dd932622b4f..d43a4ef836d 100644 --- a/core/src/main/java/bisq/core/payment/SwiftAccount.java +++ b/core/src/main/java/bisq/core/payment/SwiftAccount.java @@ -51,4 +51,16 @@ public void selectAllTradeCurrencies() { .collect(Collectors.toList()); tradeCurrencies.addAll(currencyCodesSorted); } + + public String getMessageForBuyer() { + return "payment.swift.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.swift.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.swift.info.account"; + } } diff --git a/core/src/main/java/bisq/core/payment/UpiAccount.java b/core/src/main/java/bisq/core/payment/UpiAccount.java new file mode 100644 index 00000000000..8dbce84fc28 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/UpiAccount.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.UpiAccountPayload; + +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class UpiAccount extends CountryBasedPaymentAccount { + public UpiAccount() { + super(PaymentMethod.UPI); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new UpiAccountPayload(paymentMethod.getId(), id); + } + + public void setVirtualPaymentAddress(String virtualPaymentAddress) { + ((UpiAccountPayload) paymentAccountPayload).setVirtualPaymentAddress(virtualPaymentAddress); + } + + public String getVirtualPaymentAddress() { + return ((UpiAccountPayload) paymentAccountPayload).getVirtualPaymentAddress(); + } + + public String getMessageForBuyer() { + return "payment.upi.info.buyer"; + } + + public String getMessageForSeller() { + return "payment.upi.info.seller"; + } + + public String getMessageForAccountCreation() { + return "payment.upi.info.account"; + } +} diff --git a/core/src/main/java/bisq/core/payment/payload/IfscBasedAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/IfscBasedAccountPayload.java new file mode 100644 index 00000000000..12945c335fd --- /dev/null +++ b/core/src/main/java/bisq/core/payment/payload/IfscBasedAccountPayload.java @@ -0,0 +1,96 @@ +package bisq.core.payment.payload; + + +import bisq.core.locale.BankUtil; +import bisq.core.locale.CountryUtil; +import bisq.core.locale.Res; + +import java.nio.charset.StandardCharsets; + +import java.util.Map; +import java.util.Optional; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@EqualsAndHashCode(callSuper = true) +@Setter +@Getter +@ToString +@Slf4j +public abstract class IfscBasedAccountPayload extends CountryBasedPaymentAccountPayload implements PayloadWithHolderName { + protected String holderName = ""; + protected String ifsc = ""; + protected String accountNr = ""; + + protected IfscBasedAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + protected IfscBasedAccountPayload(String paymentMethodName, + String id, + String countryCode, + String holderName, + String accountNr, + String ifsc, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethodName, + id, + countryCode, + maxTradePeriod, + excludeFromJsonDataMap); + + this.holderName = holderName; + this.accountNr = accountNr; + this.ifsc = ifsc; + } + + @Override + public protobuf.PaymentAccountPayload.Builder getPaymentAccountPayloadBuilder() { + protobuf.IfscBasedAccountPayload.Builder builder = + protobuf.IfscBasedAccountPayload.newBuilder() + .setHolderName(holderName); + Optional.ofNullable(ifsc).ifPresent(builder::setIfsc); + Optional.ofNullable(accountNr).ifPresent(builder::setAccountNr); + final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = + super.getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setIfscBasedAccountPayload(builder); + return super.getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayloadBuilder); + } + + @Override + public String getPaymentDetails() { + return "Ifsc account transfer - " + getPaymentDetailsForTradePopup().replace("\n", ", "); + } + + @Override + public String getPaymentDetailsForTradePopup() { + return Res.getWithCol("payment.account.owner") + " " + holderName + "\n" + + BankUtil.getAccountNrLabel(countryCode) + ": " + accountNr + "\n" + + BankUtil.getBankIdLabel(countryCode) + ": " + ifsc + "\n" + + Res.getWithCol("payment.bank.country") + " " + CountryUtil.getNameByCode(countryCode); + } + + @Override + public byte[] getAgeWitnessInputData() { + // We don't add holderName because we don't want to break age validation if the user recreates an account with + // slight changes in holder name (e.g. add or remove middle name) + String all = accountNr + ifsc; + return super.getAgeWitnessInputData(all.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public String getOwnerId() { + return holderName; + } +} diff --git a/core/src/main/java/bisq/core/payment/payload/ImpsAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/ImpsAccountPayload.java new file mode 100644 index 00000000000..6edf10b3295 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/payload/ImpsAccountPayload.java @@ -0,0 +1,115 @@ +/* + * 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 ImpsAccountPayload extends IfscBasedAccountPayload { + + public ImpsAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + private ImpsAccountPayload(String paymentMethod, + String id, + String countryCode, + String holderName, + String accountNr, + String ifsc, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + countryCode, + holderName, + accountNr, + ifsc, + maxTradePeriod, + excludeFromJsonDataMap); + } + + @Override + public Message toProtoMessage() { + protobuf.IfscBasedAccountPayload.Builder ifscBasedAccountPayloadBuilder = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .getIfscBasedAccountPayloadBuilder() + .setImpsAccountPayload(protobuf.ImpsAccountPayload.newBuilder()); + + protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setIfscBasedAccountPayload(ifscBasedAccountPayloadBuilder); + + return getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayloadBuilder) + .build(); + } + + public static ImpsAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { + protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload(); + protobuf.IfscBasedAccountPayload ifscBasedAccountPayloadPB = countryBasedPaymentAccountPayload.getIfscBasedAccountPayload(); + return new ImpsAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + countryBasedPaymentAccountPayload.getCountryCode(), + ifscBasedAccountPayloadPB.getHolderName(), + ifscBasedAccountPayloadPB.getAccountNr(), + ifscBasedAccountPayloadPB.getIfsc(), + proto.getMaxTradePeriod(), + new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account.owner") + " " + holderName + ", " + + Res.getWithCol("payment.account.no") + " " + accountNr + + Res.getWithCol("payment.ifsc") + " " + ifsc; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + String accountNr = this.accountNr == null ? "" : this.accountNr; + return super.getAgeWitnessInputData(accountNr.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public String getHolderName() { + return getOwnerId(); + } +} diff --git a/core/src/main/java/bisq/core/payment/payload/NeftAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/NeftAccountPayload.java new file mode 100644 index 00000000000..ab2b9a3daef --- /dev/null +++ b/core/src/main/java/bisq/core/payment/payload/NeftAccountPayload.java @@ -0,0 +1,115 @@ +/* + * 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 NeftAccountPayload extends IfscBasedAccountPayload { + + public NeftAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + private NeftAccountPayload(String paymentMethod, + String id, + String countryCode, + String holderName, + String accountNr, + String ifsc, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + countryCode, + holderName, + accountNr, + ifsc, + maxTradePeriod, + excludeFromJsonDataMap); + } + + @Override + public Message toProtoMessage() { + protobuf.IfscBasedAccountPayload.Builder ifscBasedAccountPayloadBuilder = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .getIfscBasedAccountPayloadBuilder() + .setNeftAccountPayload(protobuf.NeftAccountPayload.newBuilder()); + + protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setIfscBasedAccountPayload(ifscBasedAccountPayloadBuilder); + + return getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayloadBuilder) + .build(); + } + + public static NeftAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { + protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload(); + protobuf.IfscBasedAccountPayload ifscBasedAccountPayloadPB = countryBasedPaymentAccountPayload.getIfscBasedAccountPayload(); + return new NeftAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + countryBasedPaymentAccountPayload.getCountryCode(), + ifscBasedAccountPayloadPB.getHolderName(), + ifscBasedAccountPayloadPB.getAccountNr(), + ifscBasedAccountPayloadPB.getIfsc(), + proto.getMaxTradePeriod(), + new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account.owner") + " " + holderName + ", " + + Res.getWithCol("payment.account.no") + " " + accountNr + + Res.getWithCol("payment.ifsc") + " " + ifsc; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + String accountNr = this.accountNr == null ? "" : this.accountNr; + return super.getAgeWitnessInputData(accountNr.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public String getHolderName() { + return getOwnerId(); + } +} 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 91721e06562..634e0c0f83d 100644 --- a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java +++ b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java @@ -98,6 +98,11 @@ public final class PaymentMethod implements PersistablePayload, Comparable. + */ + +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 PaytmAccountPayload extends CountryBasedPaymentAccountPayload { + private String emailOrMobileNr = ""; + + public PaytmAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + private PaytmAccountPayload(String paymentMethod, + String id, + String countryCode, + String emailOrMobileNr, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + countryCode, + maxTradePeriod, + excludeFromJsonDataMap); + + this.emailOrMobileNr = emailOrMobileNr; + } + + @Override + public Message toProtoMessage() { + protobuf.PaytmAccountPayload.Builder builder = protobuf.PaytmAccountPayload.newBuilder() + .setEmailOrMobileNr(emailOrMobileNr); + final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setPaytmAccountPayload(builder); + return getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayload) + .build(); + } + + public static PaytmAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { + protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload(); + protobuf.PaytmAccountPayload paytmAccountPayloadPB = countryBasedPaymentAccountPayload.getPaytmAccountPayload(); + return new PaytmAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + countryBasedPaymentAccountPayload.getCountryCode(), + paytmAccountPayloadPB.getEmailOrMobileNr(), + proto.getMaxTradePeriod(), + new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.email.mobile") + " " + emailOrMobileNr; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(emailOrMobileNr.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/core/src/main/java/bisq/core/payment/payload/RtgsAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/RtgsAccountPayload.java new file mode 100644 index 00000000000..4f1c1335d45 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/payload/RtgsAccountPayload.java @@ -0,0 +1,115 @@ +/* + * 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 RtgsAccountPayload extends IfscBasedAccountPayload { + + public RtgsAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + private RtgsAccountPayload(String paymentMethod, + String id, + String countryCode, + String holderName, + String accountNr, + String ifsc, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + countryCode, + holderName, + accountNr, + ifsc, + maxTradePeriod, + excludeFromJsonDataMap); + } + + @Override + public Message toProtoMessage() { + protobuf.IfscBasedAccountPayload.Builder ifscBasedAccountPayloadBuilder = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .getIfscBasedAccountPayloadBuilder() + .setRtgsAccountPayload(protobuf.RtgsAccountPayload.newBuilder()); + + protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setIfscBasedAccountPayload(ifscBasedAccountPayloadBuilder); + + return getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayloadBuilder) + .build(); + } + + public static RtgsAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { + protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload(); + protobuf.IfscBasedAccountPayload ifscBasedAccountPayloadPB = countryBasedPaymentAccountPayload.getIfscBasedAccountPayload(); + return new RtgsAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + countryBasedPaymentAccountPayload.getCountryCode(), + ifscBasedAccountPayloadPB.getHolderName(), + ifscBasedAccountPayloadPB.getAccountNr(), + ifscBasedAccountPayloadPB.getIfsc(), + proto.getMaxTradePeriod(), + new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account.owner") + " " + holderName + ", " + + Res.getWithCol("payment.account.no") + " " + accountNr + + Res.getWithCol("payment.ifsc") + " " + ifsc; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + String accountNr = this.accountNr == null ? "" : this.accountNr; + return super.getAgeWitnessInputData(accountNr.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public String getHolderName() { + return getOwnerId(); + } +} diff --git a/core/src/main/java/bisq/core/payment/payload/UpiAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/UpiAccountPayload.java new file mode 100644 index 00000000000..5b8aaba8078 --- /dev/null +++ b/core/src/main/java/bisq/core/payment/payload/UpiAccountPayload.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 UpiAccountPayload extends CountryBasedPaymentAccountPayload { + private String virtualPaymentAddress = ""; + + public UpiAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + private UpiAccountPayload(String paymentMethod, + String id, + String countryCode, + String virtualPaymentAddress, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + countryCode, + maxTradePeriod, + excludeFromJsonDataMap); + + this.virtualPaymentAddress = virtualPaymentAddress; + } + + @Override + public Message toProtoMessage() { + protobuf.UpiAccountPayload.Builder builder = protobuf.UpiAccountPayload.newBuilder() + .setVirtualPaymentAddress(virtualPaymentAddress); + final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder() + .getCountryBasedPaymentAccountPayloadBuilder() + .setUpiAccountPayload(builder); + return getPaymentAccountPayloadBuilder() + .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayload) + .build(); + } + + public static UpiAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { + protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload(); + protobuf.UpiAccountPayload upiAccountPayloadPB = countryBasedPaymentAccountPayload.getUpiAccountPayload(); + return new UpiAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + countryBasedPaymentAccountPayload.getCountryCode(), + upiAccountPayloadPB.getVirtualPaymentAddress(), + proto.getMaxTradePeriod(), + new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.upi.virtualPaymentAddress") + " " + virtualPaymentAddress; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(virtualPaymentAddress.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/core/src/main/java/bisq/core/proto/CoreProtoResolver.java b/core/src/main/java/bisq/core/proto/CoreProtoResolver.java index 2c70420c4e9..f285b83b31a 100644 --- a/core/src/main/java/bisq/core/proto/CoreProtoResolver.java +++ b/core/src/main/java/bisq/core/proto/CoreProtoResolver.java @@ -35,20 +35,24 @@ import bisq.core.payment.payload.F2FAccountPayload; import bisq.core.payment.payload.FasterPaymentsAccountPayload; import bisq.core.payment.payload.HalCashAccountPayload; +import bisq.core.payment.payload.ImpsAccountPayload; import bisq.core.payment.payload.InstantCryptoCurrencyPayload; import bisq.core.payment.payload.InteracETransferAccountPayload; import bisq.core.payment.payload.JapanBankAccountPayload; import bisq.core.payment.payload.MoneyBeamAccountPayload; import bisq.core.payment.payload.MoneyGramAccountPayload; import bisq.core.payment.payload.NationalBankAccountPayload; +import bisq.core.payment.payload.NeftAccountPayload; import bisq.core.payment.payload.OKPayAccountPayload; import bisq.core.payment.payload.PaxumAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.PayseraAccountPayload; +import bisq.core.payment.payload.PaytmAccountPayload; import bisq.core.payment.payload.PerfectMoneyAccountPayload; import bisq.core.payment.payload.PopmoneyAccountPayload; import bisq.core.payment.payload.PromptPayAccountPayload; import bisq.core.payment.payload.RevolutAccountPayload; +import bisq.core.payment.payload.RtgsAccountPayload; import bisq.core.payment.payload.SameBankAccountPayload; import bisq.core.payment.payload.SepaAccountPayload; import bisq.core.payment.payload.SepaInstantAccountPayload; @@ -58,6 +62,7 @@ import bisq.core.payment.payload.TransferwiseAccountPayload; import bisq.core.payment.payload.USPostalMoneyOrderAccountPayload; import bisq.core.payment.payload.UpholdAccountPayload; +import bisq.core.payment.payload.UpiAccountPayload; import bisq.core.payment.payload.VenmoAccountPayload; import bisq.core.payment.payload.WeChatPayAccountPayload; import bisq.core.payment.payload.WesternUnionAccountPayload; @@ -118,6 +123,24 @@ public PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) { return SepaInstantAccountPayload.fromProto(proto); case F2F_ACCOUNT_PAYLOAD: return F2FAccountPayload.fromProto(proto); + case UPI_ACCOUNT_PAYLOAD: + return UpiAccountPayload.fromProto(proto); + case PAYTM_ACCOUNT_PAYLOAD: + return PaytmAccountPayload.fromProto(proto); + case IFSC_BASED_ACCOUNT_PAYLOAD: + final protobuf.IfscBasedAccountPayload.MessageCase messageCaseIfsc = proto.getCountryBasedPaymentAccountPayload().getIfscBasedAccountPayload().getMessageCase(); + switch (messageCaseIfsc) { + case NEFT_ACCOUNT_PAYLOAD: + return NeftAccountPayload.fromProto(proto); + case RTGS_ACCOUNT_PAYLOAD: + return RtgsAccountPayload.fromProto(proto); + case IMPS_ACCOUNT_PAYLOAD: + return ImpsAccountPayload.fromProto(proto); + default: + throw new ProtobufferRuntimeException("Unknown proto message case" + + "(PB.PaymentAccountPayload.CountryBasedPaymentAccountPayload.IfscBasedPaymentAccount). " + + "messageCase=" + messageCaseIfsc); + } default: throw new ProtobufferRuntimeException("Unknown proto message case" + "(PB.PaymentAccountPayload.CountryBasedPaymentAccountPayload)." + diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics3.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics3.java index 6f381b2d6ed..92371b5aee2 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics3.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics3.java @@ -156,7 +156,12 @@ private enum PaymentMethodMapper { CAPITUAL, PAYSERA, PAXUM, - SWIFT + SWIFT, + NEFT, + RTGS, + IMPS, + UPI, + PAYTM } @Getter diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 345be309ae9..28b6c329dd2 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -3288,6 +3288,7 @@ payment.secret=Secret question payment.answer=Answer payment.wallet=Wallet ID payment.capitual.cap=CAP Code +payment.upi.virtualPaymentAddress=Virtual Payment Address # suppress inspection "UnusedProperty" payment.swift.headline=International SWIFT Wire Transfer @@ -3440,7 +3441,7 @@ payment.account.amazonGiftCard.addCountryInfo={0}\n\ This will not affect your account age status. payment.amazonGiftCard.upgrade.headLine=Update Amazon Gift Card account -payment.swift.info=Carefully review the core guidelines for using SWIFT on Bisq:\n\ +payment.swift.info.account=Carefully review the core guidelines for using SWIFT on Bisq:\n\ \n\ - fill all fields completely and accurately \n\ - buyer must send payment in currency specified by the offer maker \n\ @@ -3462,6 +3463,73 @@ If you receive a SWIFT payment that does not use SHA, open a mediation ticket.\n \n\ Please review further guidance on the wiki to avoid penalties and ensure smooth trades [HYPERLINK:https://bisq.wiki/SWIFT]. +payment.imps.info.account=Please make sure to include your:\n\n\ + ● Account owner full name\n\ + ● Account number\n\ + ● IFSC number\n\n\ +These details should match your bank account that you will use for sending / receiving payments.\n\n\ +Please be aware there is a maximum of Rs. 200,000 that can be sent per transaction. If you are trading over this amount multiple transactions will be needed. However be aware their is a maximum limit of Rs. 1,000,000 that can be sent per day.\n\n\ +Some banks have different limits for their customers. +payment.imps.info.buyer=Please send payment only to the account details provided in Bisq.\n\n\ +The maximum trade size is Rs. 200,000 per transaction.\n\n\ +If your trade is over Rs. 200,000 you will have to make multiple transfers. However be aware their is a maximum limit of Rs. 1,000,000 that can be sent per day.\n\n\ +Please note some banks have different limits for their customers. +payment.imps.info.seller=If you intend to receive over Rs. 200,000 per trade you should expect the buyer to have to make multiple transfers. However be aware there is a maximum limit of Rs. 1,000,000 that can be sent per day.\n\n\ +Please note some banks have different limits for their customers. + +payment.neft.info.account=Please make sure to include your:\n\n\ + ● Account owner full name\n\ + ● Account number\n\ + ● IFSC number\n\n\ +These details should match your bank account that you will use for sending / receiving payments.\n\n\ +Please be aware there is a maximum of Rs. 50,000 that can be sent per transaction. If you are trading over this amount multiple transactions will be needed.\n\n\ +Please note some banks have different limits for their customers. +payment.neft.info.buyer=Please send payment only to the account details provided in Bisq.\n\n\ +The maximum trade size is Rs. 50,000 per transaction.\n\n\ +If your trade is over Rs. 50,000 you will have to make multiple transfers.\n\n\ +Please note some banks have different limits for their customers. +payment.neft.info.seller=If you intend to receive over Rs. 50,000 per trade you should expect the buyer to have to make multiple transfers.\n\n\ +Please note some banks have different limits for their customers. + +payment.paytm.info.account=Please make sure to include your email or phone number that matches your email or phone number in your PayTM account. \n\n\ +When users set up a PayTM account with No KYC users are limited to: \n\n\ + ● Maximum of Rs. 5,000 can be sent per transaction.\n\ + ● Maximum of Rs. 10,000 can be held in someone's PayTM wallet.\n\n\ +If you intend to trade amount of over 5,000 per trade you will need to complete KYC with PayTM. With KYC users are limited to:\n\n\ + ● Maximum of Rs. 100,000 can be sent per transaction.\n\ + ● Maximum of Rs. 100,000 can be held in someone's PayTM wallet.\n\n\ +Users should also be aware of account limits. Trades above PayTM account limits will likely have to take place over more than one day, or, be cancelled. +payment.paytm.info.buyer=Please send payment only to the email address or phone number provided.\n\n\ +If you intend to trade amount of over Rs. 5,000 per trade you will need to complete KYC with PayTM.\n\n\ +With No KYC Rs. 5,000 can be sent per transaction.\n\n\ +With KYC users Rs. 100,000 can be sent per transaction. +payment.paytm.info.seller=If you intend to trade amount of over Rs. 5,000 per trade you will need to complete KYC with PayTM. With KYC users are limited to:\n\n\ + ● Maximum of Rs. 100,000 can be sent per transaction.\n\ + ● Maximum of Rs. 100,000 can be held in your PayTM wallet .\n\n\ +Users should also be aware of account limits. As a maximum of Rs. 100,000 can be held in your PayTM wallet please make sure you transfer out your rupees regularly. + +payment.rtgs.info.account=RTGS is for payments of large trades of Rs. 200,000 or over.\n\n\ +When setting up your RTGS payment account please make sure to include your:\n\n\ + ● Account owner full name\n\ + ● Account number\n\ + ● IFSC number\n\n\ +These details should match your bank account that you will use for sending / receiving payments.\n\n\ +Please be aware there is a minimum trade amount of Rs. 200,000 that can be sent per transaction. If you are trading under this amount either the trade would get cancelled or both traders would have to agree on another payment method (eg IMPS or UPI). +payment.rtgs.info.buyer=Please send payment only to the account details provided in Bisq.\n\n\ +Please be aware there is a minimum trade amount of Rs. 200,000 that can be sent per transaction. If you are trading under this amount either the trade would get cancelled or both traders would have to agree on another payment method (eg IMPS or UPI). +payment.rtgs.info.seller=Please be aware there is a minimum trade amount of Rs. 200,000 that can be sent per transaction. If you are trading under this amount either the trade would get cancelled or both traders would have to agree on another payment method (eg IMPS or UPI). + +payment.upi.info.account=Please make sure to include your Virtual Payment Address (VPA) also called your UPI ID. The format for this is like an email ID: with the sign “@” in the middle. For example, your UPI ID could be “receiver’s_name@bank_name” or “phone_number@bank_name.” \n\n\ +For UPI there is a maximum limit of Rs. 100,000 that can be sent per transaction. \n\n\ +If you intend to trade amount of over Rs. 100,000 per trade it is likely trades will have to take place over multiple transfers. \n\n\ +Please note some banks have different limits for their customers. +payment.upi.info.buyer=Please send payment only to the VPA / UPI ID provided in Bisq. \n\n\ +The maximum trade size is Rs. 100,000 per transaction. \n\n\ +If your trade is over Rs. 100,000 you will have to make multiple transfers. \n\n\ +Please note some banks have different limits for their customers. +payment.upi.info.seller=If you intend to receive over Rs. 100,000 per trade you should expect the buyer to have to make multiple transfers. \n\n\ +Please note some banks have different limits for their customers. + payment.usPostalMoneyOrder.info=Trading using US Postal Money Orders (USPMO) on Bisq requires that you understand the following:\n\ \n\ - BTC buyers must write the BTC Seller’s name in both the Payer and the Payee’s fields & take a high-resolution photo of the USPMO and envelope with proof of tracking before sending.\n\ @@ -3525,6 +3593,8 @@ payment.f2f.info='Face to Face' trades have different rules and come with differ payment.f2f.info.openURL=Open web page payment.f2f.offerbook.tooltip.countryAndCity=Country and city: {0} / {1} payment.f2f.offerbook.tooltip.extra=Additional information: {0} +payment.ifsc=IFS Code +payment.ifsc.validation=IFSC format: XXXX0999999 payment.japan.bank=Bank payment.japan.branch=Branch @@ -3627,6 +3697,16 @@ PAYSERA=Paysera # suppress inspection "UnusedProperty" PAXUM=Paxum # suppress inspection "UnusedProperty" +NEFT=India/NEFT +# suppress inspection "UnusedProperty" +RTGS=India/RTGS +# suppress inspection "UnusedProperty" +IMPS=India/IMPS +# suppress inspection "UnusedProperty" +UPI=India/UPI +# suppress inspection "UnusedProperty" +PAYTM=India/PayTM +# suppress inspection "UnusedProperty" AMAZON_GIFT_CARD=Amazon eGift Card # suppress inspection "UnusedProperty" BLOCK_CHAINS_INSTANT=Altcoins Instant @@ -3687,6 +3767,16 @@ PAYSERA_SHORT=Paysera # suppress inspection "UnusedProperty" PAXUM_SHORT=Paxum # suppress inspection "UnusedProperty" +NEFT_SHORT=NEFT +# suppress inspection "UnusedProperty" +RTGS_SHORT=RTGS +# suppress inspection "UnusedProperty" +IMPS_SHORT=IMPS +# suppress inspection "UnusedProperty" +UPI_SHORT=UPI +# suppress inspection "UnusedProperty" +PAYTM_SHORT=PayTM +# suppress inspection "UnusedProperty" AMAZON_GIFT_CARD_SHORT=Amazon eGift Card # suppress inspection "UnusedProperty" BLOCK_CHAINS_INSTANT_SHORT=Altcoins Instant diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/IfscBankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/IfscBankForm.java new file mode 100644 index 00000000000..1a29428c211 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/IfscBankForm.java @@ -0,0 +1,132 @@ +/* + * 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.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.payload.IfscBasedAccountPayload; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.validation.InputValidator; +import bisq.core.util.validation.RegexValidator; + +import javafx.scene.control.TextField; +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.addTopLabelTextField; +import static bisq.desktop.util.FormBuilder.addTopLabelTextFieldWithCopyIcon; + +public class IfscBankForm extends PaymentMethodForm { + private final IfscBasedAccountPayload ifscBasedAccountPayload; + private InputTextField holderNameInputTextField, accountNrInputTextField, ifscInputTextField; + private RegexValidator ifscValidator; // https://en.wikipedia.org/wiki/Indian_Financial_System_Code + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + IfscBasedAccountPayload ifscAccountPayload = (IfscBasedAccountPayload) paymentAccountPayload; + addTopLabelTextFieldWithCopyIcon(gridPane, gridRow, 1, Res.get("payment.account.owner"), ifscAccountPayload.getHolderName(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE); + addCompactTopLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.accountNr"), ifscAccountPayload.getAccountNr()); + addCompactTopLabelTextFieldWithCopyIcon(gridPane, gridRow, 1, Res.get("payment.ifsc"), ifscAccountPayload.getIfsc()); + return gridRow; + } + + public IfscBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, + InputValidator inputValidator, GridPane gridPane, + int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.ifscBasedAccountPayload = (IfscBasedAccountPayload) paymentAccount.paymentAccountPayload; + ifscValidator = new RegexValidator(); + ifscValidator.setPattern("[A-Z]{4}0[0-9]{6}"); + ifscValidator.setErrorMessage(Res.get("payment.ifsc.validation")); + } + + @Override + public void addFormForAddAccount() { + // this payment method is only for India/INR + paymentAccount.setSingleTradeCurrency(new FiatCurrency("INR")); + CountryUtil.findCountryByCode("IN").ifPresent(c -> ifscBasedAccountPayload.setCountryCode(c.code)); + + gridRowFrom = gridRow + 1; + + holderNameInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, + Res.get("payment.account.owner")); + holderNameInputTextField.setValidator(inputValidator); + holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + ifscBasedAccountPayload.setHolderName(newValue.trim()); + updateFromInputs(); + }); + + accountNrInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.accountNr")); + accountNrInputTextField.setValidator(inputValidator); + accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + ifscBasedAccountPayload.setAccountNr(newValue.trim()); + updateFromInputs(); + }); + + ifscInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.ifsc")); + ifscInputTextField.setText("XXXX0999999"); + ifscInputTextField.setValidator(ifscValidator); + ifscInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + ifscBasedAccountPayload.setIfsc(newValue.trim()); + updateFromInputs(); + }); + + addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), paymentAccount.getSingleTradeCurrency().getNameAndCode()); + addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), CountryUtil.getNameByCode(ifscBasedAccountPayload.getCountryCode())); + addLimitations(false); + addAccountNameTextFieldWithAutoFillToggleButton(); + } + + @Override + protected void autoFillNameTextField() { + setAccountNameWithString(holderNameInputTextField.getText()); + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addTopLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), paymentAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.paymentMethod"), Res.get(paymentAccount.getPaymentMethod().getId())); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.account.owner"), + ifscBasedAccountPayload.getHolderName()); + TextField field = addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.accountNr"), ifscBasedAccountPayload.getAccountNr()).second; + field.setMouseTransparent(false); + TextField fieldIfsc = addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.ifsc"), ifscBasedAccountPayload.getIfsc()).second; + fieldIfsc.setMouseTransparent(false); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), paymentAccount.getSingleTradeCurrency().getNameAndCode()); + addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), CountryUtil.getNameByCode(ifscBasedAccountPayload.getCountryCode())); + addLimitations(true); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && inputValidator.validate(ifscBasedAccountPayload.getHolderName()).isValid + && inputValidator.validate(ifscBasedAccountPayload.getAccountNr()).isValid + && ifscValidator.validate(ifscBasedAccountPayload.getIfsc()).isValid); + } +} diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/ImpsForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/ImpsForm.java new file mode 100644 index 00000000000..0601f2e77dd --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/ImpsForm.java @@ -0,0 +1,38 @@ +/* + * 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.desktop.components.paymentmethods; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.payment.PaymentAccount; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.validation.InputValidator; + +import javafx.scene.layout.GridPane; + +public class ImpsForm extends IfscBankForm { + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + return IfscBankForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + } + + public ImpsForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, + GridPane gridPane, int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + } +} diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/NeftForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/NeftForm.java new file mode 100644 index 00000000000..40232cc30b4 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/NeftForm.java @@ -0,0 +1,38 @@ +/* + * 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.desktop.components.paymentmethods; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.payment.PaymentAccount; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.validation.InputValidator; + +import javafx.scene.layout.GridPane; + +public class NeftForm extends IfscBankForm { + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + return IfscBankForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + } + + public NeftForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, + GridPane gridPane, int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + } +} diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaytmForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaytmForm.java new file mode 100644 index 00000000000..30c08275ecd --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaytmForm.java @@ -0,0 +1,106 @@ +/* + * 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.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.PaytmAccount; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.payment.payload.PaytmAccountPayload; +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 PaytmForm extends PaymentMethodForm { + private final PaytmAccount account; + private InputTextField emailOrMobileNrInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + addTopLabelTextFieldWithCopyIcon(gridPane, gridRow, 1, Res.get("payment.email.mobile"), + ((PaytmAccountPayload) paymentAccountPayload).getEmailOrMobileNr(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE); + return gridRow; + } + + public PaytmForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, + InputValidator inputValidator, GridPane gridPane, + int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (PaytmAccount) paymentAccount; + } + + @Override + public void addFormForAddAccount() { + // this payment method is only for India/INR + account.setSingleTradeCurrency(new FiatCurrency("INR")); + CountryUtil.findCountryByCode("IN").ifPresent(c -> account.setCountry(c)); + + gridRowFrom = gridRow + 1; + + emailOrMobileNrInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.email.mobile")); + emailOrMobileNrInputTextField.setValidator(inputValidator); + emailOrMobileNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setEmailOrMobileNr(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(emailOrMobileNrInputTextField.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.email.mobile"), + account.getEmailOrMobileNr()).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.getEmailOrMobileNr()).isValid); + } +} diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/RtgsForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/RtgsForm.java new file mode 100644 index 00000000000..624bb881b29 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/RtgsForm.java @@ -0,0 +1,38 @@ +/* + * 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.desktop.components.paymentmethods; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.payment.PaymentAccount; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.validation.InputValidator; + +import javafx.scene.layout.GridPane; + +public class RtgsForm extends IfscBankForm { + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + return IfscBankForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + } + + public RtgsForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, + GridPane gridPane, int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + } +} diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwiftForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwiftForm.java index 45d6d838f0a..769cf10dd15 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwiftForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwiftForm.java @@ -76,10 +76,6 @@ public SwiftForm(PaymentAccount paymentAccount, @Override public void addFormForAddAccount() { ((SwiftAccount) paymentAccount).selectAllTradeCurrencies(); - new Popup().information(Res.get("payment.swift.info")) - .width(900) - .closeButtonText(Res.get("shared.iUnderstand")) - .show(); gridRowFrom = gridRow + 1; addFieldsForBankEdit(true, this::setBankSwiftCode, this::setBankName, this::setBankBranch, this::setBankAddress); addFieldsForBankEdit(false, this::setIntermediarySwiftCode, this::setIntermediaryName, this::setIntermediaryBranch, this::setIntermediaryAddress); diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpiForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpiForm.java new file mode 100644 index 00000000000..88361c2dfd0 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpiForm.java @@ -0,0 +1,106 @@ +/* + * 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.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.UpiAccount; +import bisq.core.payment.payload.PaymentAccountPayload; +import bisq.core.payment.payload.UpiAccountPayload; +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.addCompactTopLabelTextFieldWithCopyIcon; +import static bisq.desktop.util.FormBuilder.addTopLabelTextField; + +public class UpiForm extends PaymentMethodForm { + private final UpiAccount account; + private InputTextField virtualPaymentAddressInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + addCompactTopLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.upi.virtualPaymentAddress"), + ((UpiAccountPayload) paymentAccountPayload).getVirtualPaymentAddress()); + return gridRow; + } + + public UpiForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, + InputValidator inputValidator, GridPane gridPane, + int gridRow, CoinFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (UpiAccount) paymentAccount; + } + + @Override + public void addFormForAddAccount() { + // this payment method is only for India/INR + account.setSingleTradeCurrency(new FiatCurrency("INR")); + CountryUtil.findCountryByCode("IN").ifPresent(c -> account.setCountry(c)); + + gridRowFrom = gridRow + 1; + + virtualPaymentAddressInputTextField = FormBuilder.addInputTextField(gridPane, ++gridRow, Res.get("payment.upi.virtualPaymentAddress")); + virtualPaymentAddressInputTextField.setValidator(inputValidator); + virtualPaymentAddressInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setVirtualPaymentAddress(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(virtualPaymentAddressInputTextField.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.upi.virtualPaymentAddress"), + account.getVirtualPaymentAddress()).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.getVirtualPaymentAddress()).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 09e3cb37b22..9a6e127e919 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 @@ -31,16 +31,20 @@ import bisq.desktop.components.paymentmethods.F2FForm; import bisq.desktop.components.paymentmethods.FasterPaymentsForm; import bisq.desktop.components.paymentmethods.HalCashForm; +import bisq.desktop.components.paymentmethods.ImpsForm; import bisq.desktop.components.paymentmethods.InteracETransferForm; import bisq.desktop.components.paymentmethods.JapanBankTransferForm; import bisq.desktop.components.paymentmethods.MoneyBeamForm; import bisq.desktop.components.paymentmethods.MoneyGramForm; import bisq.desktop.components.paymentmethods.NationalBankForm; +import bisq.desktop.components.paymentmethods.NeftForm; import bisq.desktop.components.paymentmethods.PaymentMethodForm; +import bisq.desktop.components.paymentmethods.PaytmForm; import bisq.desktop.components.paymentmethods.PerfectMoneyForm; import bisq.desktop.components.paymentmethods.PopmoneyForm; import bisq.desktop.components.paymentmethods.PromptPayForm; import bisq.desktop.components.paymentmethods.RevolutForm; +import bisq.desktop.components.paymentmethods.RtgsForm; import bisq.desktop.components.paymentmethods.SameBankForm; import bisq.desktop.components.paymentmethods.SepaForm; import bisq.desktop.components.paymentmethods.SepaInstantForm; @@ -52,6 +56,7 @@ import bisq.desktop.components.paymentmethods.PaxumForm; import bisq.desktop.components.paymentmethods.USPostalMoneyOrderForm; import bisq.desktop.components.paymentmethods.UpholdForm; +import bisq.desktop.components.paymentmethods.UpiForm; import bisq.desktop.components.paymentmethods.WeChatPayForm; import bisq.desktop.components.paymentmethods.WesternUnionForm; import bisq.desktop.main.account.content.PaymentAccountsView; @@ -428,6 +433,12 @@ public PaymentMethod fromString(String s) { gridRow = 2; paymentMethodForm = getPaymentMethodForm(paymentMethodComboBox.getSelectionModel().getSelectedItem()); if (paymentMethodForm != null) { + if (paymentMethodForm.getPaymentAccount().getMessageForAccountCreation() != null) { + new Popup().information(Res.get(paymentMethodForm.getPaymentAccount().getMessageForAccountCreation())) + .width(900) + .closeButtonText(Res.get("shared.iUnderstand")) + .show(); + } paymentMethodForm.addFormForAddAccount(); gridRow = paymentMethodForm.getGridRow(); Tuple2 tuple2 = add2ButtonsAfterGroup(root, ++gridRow, Res.get("shared.saveNewAccount"), Res.get("shared.cancel")); @@ -540,6 +551,16 @@ private PaymentMethodForm getPaymentMethodForm(PaymentMethod paymentMethod, Paym return new PayseraForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); case PaymentMethod.PAXUM_ID: return new PaxumForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); + case PaymentMethod.NEFT_ID: + return new NeftForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); + case PaymentMethod.RTGS_ID: + return new RtgsForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); + case PaymentMethod.IMPS_ID: + return new ImpsForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); + case PaymentMethod.UPI_ID: + return new UpiForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter); + case PaymentMethod.PAYTM_ID: + return new PaytmForm(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/offer/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java index 938e8dd5dc2..f0f42d5e5d1 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java @@ -112,6 +112,7 @@ import java.io.ByteArrayInputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.concurrent.TimeUnit; @@ -169,7 +170,8 @@ public abstract class MutableOfferView> exten protected int gridRow = 0; private final List editOfferElements = new ArrayList<>(); - private boolean clearXchangeWarningDisplayed, fasterPaymentsWarningDisplayed, swiftWarningDisplayed, isActivated; + private HashMap paymentAccountWarningDisplayed = new HashMap<>(); + private boolean clearXchangeWarningDisplayed, fasterPaymentsWarningDisplayed, isActivated; private InfoInputTextField marketBasedPriceInfoInputTextField, volumeInfoInputTextField, buyerSecurityDepositInfoInputTextField, triggerPriceInfoInputTextField; private AutoTooltipSlideToggleButton tradeFeeInBtcToggle, tradeFeeInBsqToggle; @@ -500,17 +502,19 @@ private void maybeShowFasterPaymentsWarning(PaymentAccount paymentAccount) { } } - private void maybeShowSwiftWarning(PaymentAccount paymentAccount) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.SWIFT_ID) && !swiftWarningDisplayed) { - swiftWarningDisplayed = true; - UserThread.runAfter(() -> { - if (model.getDataModel().isBuyOffer()) { - GUIUtil.showSwiftWarningToBuyer(); - } else { - GUIUtil.showSwiftWarningToSeller(); - } - }, 500, TimeUnit.MILLISECONDS); + private void maybeShowAccountWarning(PaymentAccount paymentAccount, boolean isBuyer) { + String msgKey = paymentAccount.getPreTradeMessage(isBuyer); + if (msgKey == null || paymentAccountWarningDisplayed.getOrDefault(msgKey, false)) { + return; } + paymentAccountWarningDisplayed.put(msgKey, true); + UserThread.runAfter(() -> { + new Popup().information(Res.get(msgKey)) + .width(900) + .closeButtonText(Res.get("shared.iConfirm")) + .dontShowAgainId(msgKey) + .show(); + }, 500, TimeUnit.MILLISECONDS); } protected void onPaymentAccountsComboBoxSelected() { @@ -522,7 +526,7 @@ protected void onPaymentAccountsComboBoxSelected() { if (paymentAccount != null) { maybeShowClearXchangeWarning(paymentAccount); maybeShowFasterPaymentsWarning(paymentAccount); - maybeShowSwiftWarning(paymentAccount); + maybeShowAccountWarning(paymentAccount, model.getDataModel().isBuyOffer()); currencySelection.setVisible(paymentAccount.hasMultipleCurrencies()); currencySelection.setManaged(paymentAccount.hasMultipleCurrencies()); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index c8af97a49ea..caeab48c27c 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -113,6 +113,7 @@ import java.io.ByteArrayInputStream; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.NotNull; @@ -162,8 +163,9 @@ public class TakeOfferView extends ActivatableViewAndModel paymentAccountWarningDisplayed = new HashMap<>(); private boolean offerDetailsWindowDisplayed, clearXchangeWarningDisplayed, fasterPaymentsWarningDisplayed, - swiftWarningDisplayed, takeOfferFromUnsignedAccountWarningDisplayed, cashByMailWarningDisplayed; + takeOfferFromUnsignedAccountWarningDisplayed, cashByMailWarningDisplayed; private SimpleBooleanProperty errorPopupDisplayed; private ChangeListener amountFocusedListener, getShowWalletFundedNotificationListener; @@ -309,7 +311,7 @@ protected void activate() { maybeShowTakeOfferFromUnsignedAccountWarning(model.dataModel.getOffer()); maybeShowClearXchangeWarning(lastPaymentAccount); maybeShowFasterPaymentsWarning(lastPaymentAccount); - maybeShowSwiftWarning(lastPaymentAccount); + maybeShowAccountWarning(lastPaymentAccount, model.dataModel.isBuyOffer()); maybeShowCashByMailWarning(lastPaymentAccount, model.dataModel.getOffer()); if (!DevEnv.isDaoActivated() && !model.isRange()) { @@ -832,7 +834,7 @@ private void addPaymentGroup() { if (paymentAccount != null) { maybeShowClearXchangeWarning(paymentAccount); maybeShowFasterPaymentsWarning(paymentAccount); - maybeShowSwiftWarning(paymentAccount); + maybeShowAccountWarning(paymentAccount, model.dataModel.isBuyOffer()); } model.onPaymentAccountSelected(paymentAccount); }); @@ -1274,17 +1276,19 @@ private void maybeShowFasterPaymentsWarning(PaymentAccount paymentAccount) { } } - private void maybeShowSwiftWarning(PaymentAccount paymentAccount) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.SWIFT_ID) && !swiftWarningDisplayed) { - swiftWarningDisplayed = true; - UserThread.runAfter(() -> { - if (model.getOffer().getDirection() == OfferPayload.Direction.BUY) { - GUIUtil.showSwiftWarningToSeller(); // taking an offer to buy, we are the seller - } else { - GUIUtil.showSwiftWarningToBuyer(); // taking an offer to sell, we are the buyer - } - }, 500, TimeUnit.MILLISECONDS); + private void maybeShowAccountWarning(PaymentAccount paymentAccount, boolean isBuyer) { + String msgKey = paymentAccount.getPreTradeMessage(!isBuyer); + if (msgKey == null || paymentAccountWarningDisplayed.getOrDefault(msgKey, false)) { + return; } + paymentAccountWarningDisplayed.put(msgKey, true); + UserThread.runAfter(() -> { + new Popup().information(Res.get(msgKey)) + .width(900) + .closeButtonText(Res.get("shared.iConfirm")) + .dontShowAgainId(msgKey) + .show(); + }, 500, TimeUnit.MILLISECONDS); } private void maybeShowCashByMailWarning(PaymentAccount paymentAccount, Offer offer) { 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 278de94f84a..07876d79a3f 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 @@ -33,17 +33,21 @@ import bisq.desktop.components.paymentmethods.F2FForm; import bisq.desktop.components.paymentmethods.FasterPaymentsForm; import bisq.desktop.components.paymentmethods.HalCashForm; +import bisq.desktop.components.paymentmethods.ImpsForm; import bisq.desktop.components.paymentmethods.InteracETransferForm; import bisq.desktop.components.paymentmethods.JapanBankTransferForm; import bisq.desktop.components.paymentmethods.MoneyBeamForm; import bisq.desktop.components.paymentmethods.MoneyGramForm; import bisq.desktop.components.paymentmethods.NationalBankForm; +import bisq.desktop.components.paymentmethods.NeftForm; import bisq.desktop.components.paymentmethods.PaxumForm; import bisq.desktop.components.paymentmethods.PayseraForm; +import bisq.desktop.components.paymentmethods.PaytmForm; import bisq.desktop.components.paymentmethods.PerfectMoneyForm; import bisq.desktop.components.paymentmethods.PopmoneyForm; import bisq.desktop.components.paymentmethods.PromptPayForm; import bisq.desktop.components.paymentmethods.RevolutForm; +import bisq.desktop.components.paymentmethods.RtgsForm; import bisq.desktop.components.paymentmethods.SameBankForm; import bisq.desktop.components.paymentmethods.SepaForm; import bisq.desktop.components.paymentmethods.SepaInstantForm; @@ -53,6 +57,7 @@ import bisq.desktop.components.paymentmethods.TransferwiseForm; import bisq.desktop.components.paymentmethods.USPostalMoneyOrderForm; import bisq.desktop.components.paymentmethods.UpholdForm; +import bisq.desktop.components.paymentmethods.UpiForm; import bisq.desktop.components.paymentmethods.WeChatPayForm; import bisq.desktop.components.paymentmethods.WesternUnionForm; import bisq.desktop.main.MainView; @@ -331,6 +336,21 @@ protected void addContent() { case PaymentMethod.PAXUM_ID: gridRow = PaxumForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); break; + case PaymentMethod.NEFT_ID: + gridRow = NeftForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.RTGS_ID: + gridRow = RtgsForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.IMPS_ID: + gridRow = ImpsForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.UPI_ID: + gridRow = UpiForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.PAYTM_ID: + gridRow = PaytmForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; case PaymentMethod.AMAZON_GIFT_CARD_ID: gridRow = AmazonGiftCardForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); break; diff --git a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java index f5177b3a154..6160a860cae 100644 --- a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java @@ -778,24 +778,6 @@ public static void showFasterPaymentsWarning(Navigation navigation) { .show(); } - public static void showSwiftWarningToBuyer() { - String key = "confirmSwiftRequirementsBuyer"; - new Popup().information(Res.get("payment.swift.info.buyer")) - .width(900) - .closeButtonText(Res.get("shared.iConfirm")) - .dontShowAgainId(key) - .show(); - } - - public static void showSwiftWarningToSeller() { - String key = "confirmSwiftRequirementsSeller"; - new Popup().information(Res.get("payment.swift.info.seller")) - .width(900) - .closeButtonText(Res.get("shared.iConfirm")) - .dontShowAgainId(key) - .show(); - } - public static String getBitcoinURI(String address, Coin amount, String label) { return address != null ? BitcoinURI.convertToBitcoinURI(Address.fromString(Config.baseCurrencyNetworkParameters(), diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index b268b65c8c5..48fd69af4b3 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1031,6 +1031,9 @@ message CountryBasedPaymentAccountPayload { WesternUnionAccountPayload western_union_account_payload = 5; SepaInstantAccountPayload sepa_instant_account_payload = 6; F2FAccountPayload f2f_account_payload = 7; + UpiAccountPayload upi_account_payload = 9; + PaytmAccountPayload paytm_account_payload = 10; + IfscBasedAccountPayload ifsc_based_account_payload = 11; } } @@ -1203,6 +1206,34 @@ message F2FAccountPayload { string extra_info = 3; } +message IfscBasedAccountPayload { + string holder_name = 1; + string account_nr = 2; + string ifsc = 3; + oneof message { + NeftAccountPayload neft_account_payload = 4; + RtgsAccountPayload rtgs_account_payload = 5; + ImpsAccountPayload imps_account_payload = 6; + } +} + +message NeftAccountPayload { +} + +message RtgsAccountPayload { +} + +message ImpsAccountPayload { +} + +message UpiAccountPayload { + string virtual_payment_address = 1; +} + +message PaytmAccountPayload { + string email_or_mobile_nr = 1; +} + message CashByMailAccountPayload { string postal_address = 1; string contact = 2;