diff --git a/core/src/main/java/bisq/core/payment/AchTransferAccount.java b/core/src/main/java/bisq/core/payment/AchTransferAccount.java
new file mode 100644
index 00000000000..386e9f2a798
--- /dev/null
+++ b/core/src/main/java/bisq/core/payment/AchTransferAccount.java
@@ -0,0 +1,63 @@
+/*
+ * 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.BankAccountPayload;
+import bisq.core.payment.payload.AchTransferAccountPayload;
+import bisq.core.payment.payload.PaymentAccountPayload;
+import bisq.core.payment.payload.PaymentMethod;
+
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+public final class AchTransferAccount extends CountryBasedPaymentAccount implements SameCountryRestrictedBankAccount {
+ public AchTransferAccount() {
+ super(PaymentMethod.ACH_TRANSFER);
+ }
+
+ @Override
+ protected PaymentAccountPayload createPayload() {
+ return new AchTransferAccountPayload(paymentMethod.getId(), id);
+ }
+
+ @Override
+ public String getBankId() {
+ return ((BankAccountPayload) paymentAccountPayload).getBankId();
+ }
+
+ @Override
+ public String getCountryCode() {
+ return getCountry() != null ? getCountry().code : "";
+ }
+
+ public AchTransferAccountPayload getPayload() {
+ return (AchTransferAccountPayload) paymentAccountPayload;
+ }
+
+ public String getMessageForBuyer() {
+ return "payment.achTransfer.info.buyer";
+ }
+
+ public String getMessageForSeller() {
+ return "payment.achTransfer.info.seller";
+ }
+
+ public String getMessageForAccountCreation() {
+ return "payment.achTransfer.info.account";
+ }
+}
diff --git a/core/src/main/java/bisq/core/payment/DomesticWireTransferAccount.java b/core/src/main/java/bisq/core/payment/DomesticWireTransferAccount.java
new file mode 100644
index 00000000000..4844211c335
--- /dev/null
+++ b/core/src/main/java/bisq/core/payment/DomesticWireTransferAccount.java
@@ -0,0 +1,63 @@
+/*
+ * 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.BankAccountPayload;
+import bisq.core.payment.payload.DomesticWireTransferAccountPayload;
+import bisq.core.payment.payload.PaymentAccountPayload;
+import bisq.core.payment.payload.PaymentMethod;
+
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+public final class DomesticWireTransferAccount extends CountryBasedPaymentAccount implements SameCountryRestrictedBankAccount {
+ public DomesticWireTransferAccount() {
+ super(PaymentMethod.DOMESTIC_WIRE_TRANSFER);
+ }
+
+ @Override
+ protected PaymentAccountPayload createPayload() {
+ return new DomesticWireTransferAccountPayload(paymentMethod.getId(), id);
+ }
+
+ @Override
+ public String getBankId() {
+ return ((BankAccountPayload) paymentAccountPayload).getBankId();
+ }
+
+ @Override
+ public String getCountryCode() {
+ return getCountry() != null ? getCountry().code : "";
+ }
+
+ public DomesticWireTransferAccountPayload getPayload() {
+ return (DomesticWireTransferAccountPayload) paymentAccountPayload;
+ }
+
+ public String getMessageForBuyer() {
+ return "payment.domesticWire.info.buyer";
+ }
+
+ public String getMessageForSeller() {
+ return "payment.domesticWire.info.seller";
+ }
+
+ public String getMessageForAccountCreation() {
+ return "payment.domesticWire.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 c570d749bef..8e3c1e74a36 100644
--- a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java
+++ b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java
@@ -124,6 +124,10 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new StrikeAccount();
case PaymentMethod.SWIFT_ID:
return new SwiftAccount();
+ case PaymentMethod.ACH_TRANSFER_ID:
+ return new AchTransferAccount();
+ case PaymentMethod.DOMESTIC_WIRE_TRANSFER_ID:
+ return new DomesticWireTransferAccount();
case PaymentMethod.BSQ_SWAP_ID:
return new BsqSwapAccount();
diff --git a/core/src/main/java/bisq/core/payment/payload/AchTransferAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/AchTransferAccountPayload.java
new file mode 100644
index 00000000000..7c438bb078b
--- /dev/null
+++ b/core/src/main/java/bisq/core/payment/payload/AchTransferAccountPayload.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.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
+@Getter
+@Setter
+@Slf4j
+public final class AchTransferAccountPayload extends BankAccountPayload {
+ private String holderAddress = "";
+
+ public AchTransferAccountPayload(String paymentMethod, String id) {
+ super(paymentMethod, id);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PROTO BUFFER
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private AchTransferAccountPayload(String paymentMethodName,
+ String id,
+ String countryCode,
+ String holderName,
+ String bankName,
+ String branchId,
+ String accountNr,
+ String accountType,
+ String holderAddress,
+ long maxTradePeriod,
+ Map excludeFromJsonDataMap) {
+ super(paymentMethodName,
+ id,
+ countryCode,
+ holderName,
+ bankName,
+ branchId,
+ accountNr,
+ accountType,
+ null, // holderTaxId not used
+ null, // bankId not used
+ null, // nationalAccountId not used
+ maxTradePeriod,
+ excludeFromJsonDataMap);
+
+ this.holderAddress = holderAddress;
+ }
+
+ @Override
+ public Message toProtoMessage() {
+ protobuf.AchTransferAccountPayload.Builder builder = protobuf.AchTransferAccountPayload.newBuilder()
+ .setHolderAddress(holderAddress);
+ protobuf.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ .getCountryBasedPaymentAccountPayloadBuilder()
+ .getBankAccountPayloadBuilder()
+ .setAchTransferAccountPayload(builder);
+ protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ .getCountryBasedPaymentAccountPayloadBuilder()
+ .setBankAccountPayload(bankAccountPayloadBuilder);
+ return getPaymentAccountPayloadBuilder()
+ .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayloadBuilder)
+ .build();
+ }
+
+ public static AchTransferAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.BankAccountPayload bankAccountPayloadPB = countryBasedPaymentAccountPayload.getBankAccountPayload();
+ protobuf.AchTransferAccountPayload accountPayloadPB = bankAccountPayloadPB.getAchTransferAccountPayload();
+ return new AchTransferAccountPayload(proto.getPaymentMethodId(),
+ proto.getId(),
+ countryBasedPaymentAccountPayload.getCountryCode(),
+ bankAccountPayloadPB.getHolderName(),
+ bankAccountPayloadPB.getBankName().isEmpty() ? null : bankAccountPayloadPB.getBankName(),
+ bankAccountPayloadPB.getBranchId().isEmpty() ? null : bankAccountPayloadPB.getBranchId(),
+ bankAccountPayloadPB.getAccountNr().isEmpty() ? null : bankAccountPayloadPB.getAccountNr(),
+ bankAccountPayloadPB.getAccountType().isEmpty() ? null : bankAccountPayloadPB.getAccountType(),
+ accountPayloadPB.getHolderAddress().isEmpty() ? null : accountPayloadPB.getHolderAddress(),
+ proto.getMaxTradePeriod(),
+ new HashMap<>(proto.getExcludeFromJsonDataMap()));
+ }
+
+ @Override
+ public String getPaymentDetails() {
+ return Res.get(paymentMethodId) + " - " + getPaymentDetailsForTradePopup().replace("\n", ", ");
+ }
+}
diff --git a/core/src/main/java/bisq/core/payment/payload/DomesticWireTransferAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/DomesticWireTransferAccountPayload.java
new file mode 100644
index 00000000000..f3bba3223e6
--- /dev/null
+++ b/core/src/main/java/bisq/core/payment/payload/DomesticWireTransferAccountPayload.java
@@ -0,0 +1,119 @@
+/*
+ * 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.BankUtil;
+import bisq.core.locale.Res;
+
+import com.google.protobuf.Message;
+
+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
+@Getter
+@Setter
+@Slf4j
+public final class DomesticWireTransferAccountPayload extends BankAccountPayload {
+ private String holderAddress = "";
+
+ public DomesticWireTransferAccountPayload(String paymentMethod, String id) {
+ super(paymentMethod, id);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PROTO BUFFER
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private DomesticWireTransferAccountPayload(String paymentMethodName,
+ String id,
+ String countryCode,
+ String holderName,
+ String bankName,
+ String branchId,
+ String accountNr,
+ String holderAddress,
+ long maxTradePeriod,
+ Map excludeFromJsonDataMap) {
+ super(paymentMethodName,
+ id,
+ countryCode,
+ holderName,
+ bankName,
+ branchId,
+ accountNr,
+ null,
+ null, // holderTaxId not used
+ null, // bankId not used
+ null, // nationalAccountId not used
+ maxTradePeriod,
+ excludeFromJsonDataMap);
+
+ this.holderAddress = holderAddress;
+ }
+
+ @Override
+ public Message toProtoMessage() {
+ protobuf.DomesticWireTransferAccountPayload.Builder builder = protobuf.DomesticWireTransferAccountPayload.newBuilder()
+ .setHolderAddress(holderAddress);
+ protobuf.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ .getCountryBasedPaymentAccountPayloadBuilder()
+ .getBankAccountPayloadBuilder()
+ .setDomesticWireTransferAccountPayload(builder);
+ protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ .getCountryBasedPaymentAccountPayloadBuilder()
+ .setBankAccountPayload(bankAccountPayloadBuilder);
+ return getPaymentAccountPayloadBuilder()
+ .setCountryBasedPaymentAccountPayload(countryBasedPaymentAccountPayloadBuilder)
+ .build();
+ }
+
+ public static DomesticWireTransferAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.BankAccountPayload bankAccountPayloadPB = countryBasedPaymentAccountPayload.getBankAccountPayload();
+ protobuf.DomesticWireTransferAccountPayload accountPayloadPB = bankAccountPayloadPB.getDomesticWireTransferAccountPayload();
+ return new DomesticWireTransferAccountPayload(proto.getPaymentMethodId(),
+ proto.getId(),
+ countryBasedPaymentAccountPayload.getCountryCode(),
+ bankAccountPayloadPB.getHolderName(),
+ bankAccountPayloadPB.getBankName().isEmpty() ? null : bankAccountPayloadPB.getBankName(),
+ bankAccountPayloadPB.getBranchId().isEmpty() ? null : bankAccountPayloadPB.getBranchId(),
+ bankAccountPayloadPB.getAccountNr().isEmpty() ? null : bankAccountPayloadPB.getAccountNr(),
+ accountPayloadPB.getHolderAddress().isEmpty() ? null : accountPayloadPB.getHolderAddress(),
+ proto.getMaxTradePeriod(),
+ new HashMap<>(proto.getExcludeFromJsonDataMap()));
+ }
+
+ @Override
+ public String getPaymentDetails() {
+ String paymentDetails = (Res.get(paymentMethodId) + " - " +
+ Res.getWithCol("payment.account.owner") + " " + holderName + ", " +
+ BankUtil.getBankNameLabel(countryCode) + ": " + this.bankName + ", " +
+ BankUtil.getBranchIdLabel(countryCode) + ": " + this.branchId + ", " +
+ BankUtil.getAccountNrLabel(countryCode) + ": " + this.accountNr);
+ return paymentDetails;
+ }
+}
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 59f76e04a82..9850aac2e9c 100644
--- a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java
+++ b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java
@@ -118,6 +118,8 @@ public final class PaymentMethod implements PersistablePayload, Comparable.
+ */
+
+package bisq.desktop.components.paymentmethods;
+
+import bisq.core.account.witness.AccountAgeWitnessService;
+import bisq.core.locale.BankUtil;
+import bisq.core.locale.Country;
+import bisq.core.locale.Res;
+import bisq.core.payment.AchTransferAccount;
+import bisq.core.payment.CountryBasedPaymentAccount;
+import bisq.core.payment.PaymentAccount;
+import bisq.core.payment.payload.AchTransferAccountPayload;
+import bisq.core.payment.payload.BankAccountPayload;
+import bisq.core.payment.payload.PaymentAccountPayload;
+import bisq.core.util.coin.CoinFormatter;
+import bisq.core.util.validation.InputValidator;
+
+import javafx.scene.control.ComboBox;
+import javafx.scene.layout.GridPane;
+
+import javafx.collections.FXCollections;
+
+import static bisq.desktop.util.FormBuilder.*;
+
+public class AchTransferForm extends GeneralUsBankForm {
+
+ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) {
+ AchTransferAccountPayload achTransferAccountPayload = (AchTransferAccountPayload) paymentAccountPayload;
+ return addFormForBuyer(gridPane, gridRow, paymentAccountPayload, achTransferAccountPayload.getAccountType(), achTransferAccountPayload.getHolderAddress());
+ }
+
+ private final AchTransferAccount achTransferAccount;
+
+ public AchTransferForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator,
+ GridPane gridPane, int gridRow, CoinFormatter formatter) {
+ super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter);
+ this.achTransferAccount = (AchTransferAccount) paymentAccount;
+ }
+
+ @Override
+ public void addFormForDisplayAccount() {
+ addFormForDisplayAccount(achTransferAccount.getPayload(), achTransferAccount.getPayload().getHolderAddress());
+ }
+
+ @Override
+ public void addFormForAddAccount() {
+ addFormForAddAccountInternal(achTransferAccount.getPayload(), achTransferAccount.getPayload().getHolderAddress());
+ }
+
+ @Override
+ protected void setHolderAddress(String holderAddress) {
+ achTransferAccount.getPayload().setHolderAddress(holderAddress);
+ }
+
+ @Override
+ protected void maybeAddAccountTypeCombo(BankAccountPayload bankAccountPayload, Country country) {
+ ComboBox accountTypeComboBox = addComboBox(gridPane, ++gridRow, Res.get("payment.select.account"));
+ accountTypeComboBox.setItems(FXCollections.observableArrayList(BankUtil.getAccountTypeValues(country.code)));
+ accountTypeComboBox.setOnAction(e -> {
+ if (BankUtil.isAccountTypeRequired(country.code)) {
+ bankAccountPayload.setAccountType(accountTypeComboBox.getSelectionModel().getSelectedItem());
+ updateFromInputs();
+ }
+ });
+ }
+
+ @Override
+ public void updateAllInputsValid() {
+ AchTransferAccountPayload achTransferAccountPayload = achTransferAccount.getPayload();
+ boolean result = isAccountNameValid()
+ && paymentAccount.getSingleTradeCurrency() != null
+ && ((CountryBasedPaymentAccount) this.paymentAccount).getCountry() != null
+ && inputValidator.validate(achTransferAccountPayload.getHolderName()).isValid
+ && inputValidator.validate(achTransferAccountPayload.getHolderAddress()).isValid;
+
+ result = getValidationResult(result,
+ achTransferAccountPayload.getCountryCode(),
+ achTransferAccountPayload.getBankName(),
+ achTransferAccountPayload.getBankId(),
+ achTransferAccountPayload.getBranchId(),
+ achTransferAccountPayload.getAccountNr(),
+ achTransferAccountPayload.getAccountType(),
+ achTransferAccountPayload.getHolderTaxId(),
+ achTransferAccountPayload.getNationalAccountId());
+ allInputsValid.set(result);
+ }
+}
diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/DomesticWireTransferForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/DomesticWireTransferForm.java
new file mode 100644
index 00000000000..a4c3f920340
--- /dev/null
+++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/DomesticWireTransferForm.java
@@ -0,0 +1,89 @@
+/*
+ * 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.locale.Country;
+import bisq.core.payment.DomesticWireTransferAccount;
+import bisq.core.payment.CountryBasedPaymentAccount;
+import bisq.core.payment.PaymentAccount;
+import bisq.core.payment.payload.BankAccountPayload;
+import bisq.core.payment.payload.DomesticWireTransferAccountPayload;
+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 DomesticWireTransferForm extends GeneralUsBankForm {
+
+ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) {
+ DomesticWireTransferAccountPayload domesticWireTransferAccountPayload = (DomesticWireTransferAccountPayload) paymentAccountPayload;
+ return addFormForBuyer(gridPane, gridRow, paymentAccountPayload, null,
+ domesticWireTransferAccountPayload.getHolderAddress());
+ }
+
+ private final DomesticWireTransferAccount domesticWireTransferAccount;
+
+ public DomesticWireTransferForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator,
+ GridPane gridPane, int gridRow, CoinFormatter formatter) {
+ super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter);
+ this.domesticWireTransferAccount = (DomesticWireTransferAccount) paymentAccount;
+ }
+
+ @Override
+ public void addFormForDisplayAccount() {
+ addFormForDisplayAccount(domesticWireTransferAccount.getPayload(), domesticWireTransferAccount.getPayload().getHolderAddress());
+ }
+
+ @Override
+ public void addFormForAddAccount() {
+ addFormForAddAccountInternal(domesticWireTransferAccount.getPayload(), domesticWireTransferAccount.getPayload().getHolderAddress());
+ }
+
+ @Override
+ protected void setHolderAddress(String holderAddress) {
+ domesticWireTransferAccount.getPayload().setHolderAddress(holderAddress);
+ }
+
+ @Override
+ protected void maybeAddAccountTypeCombo(BankAccountPayload bankAccountPayload, Country country) {
+ // DomesticWireTransfer does not use the account type combo
+ }
+
+ @Override
+ public void updateAllInputsValid() {
+ DomesticWireTransferAccountPayload domesticWireTransferAccountPayload = domesticWireTransferAccount.getPayload();
+ boolean result = isAccountNameValid()
+ && paymentAccount.getSingleTradeCurrency() != null
+ && ((CountryBasedPaymentAccount) this.paymentAccount).getCountry() != null
+ && inputValidator.validate(domesticWireTransferAccountPayload.getHolderName()).isValid
+ && inputValidator.validate(domesticWireTransferAccountPayload.getHolderAddress()).isValid;
+
+ result = getValidationResult(result,
+ domesticWireTransferAccountPayload.getCountryCode(),
+ domesticWireTransferAccountPayload.getBankName(),
+ domesticWireTransferAccountPayload.getBankId(),
+ domesticWireTransferAccountPayload.getBranchId(),
+ domesticWireTransferAccountPayload.getAccountNr(),
+ domesticWireTransferAccountPayload.getAccountNr(),
+ domesticWireTransferAccountPayload.getHolderTaxId(),
+ domesticWireTransferAccountPayload.getNationalAccountId());
+ allInputsValid.set(result);
+ }
+}
diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralUsBankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralUsBankForm.java
new file mode 100644
index 00000000000..74d196a4a96
--- /dev/null
+++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralUsBankForm.java
@@ -0,0 +1,171 @@
+/*
+ * 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.Layout;
+
+import bisq.core.account.witness.AccountAgeWitnessService;
+import bisq.core.locale.BankUtil;
+import bisq.core.locale.Country;
+import bisq.core.locale.CountryUtil;
+import bisq.core.locale.CurrencyUtil;
+import bisq.core.locale.Res;
+import bisq.core.locale.TradeCurrency;
+import bisq.core.payment.CountryBasedPaymentAccount;
+import bisq.core.payment.PaymentAccount;
+import bisq.core.payment.payload.BankAccountPayload;
+import bisq.core.payment.payload.CountryBasedPaymentAccountPayload;
+import bisq.core.payment.payload.PaymentAccountPayload;
+import bisq.core.util.coin.CoinFormatter;
+import bisq.core.util.validation.InputValidator;
+
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.GridPane;
+
+import javax.annotation.Nullable;
+
+import static bisq.common.util.Utilities.cleanString;
+import static bisq.desktop.util.FormBuilder.*;
+
+public abstract class GeneralUsBankForm extends GeneralBankForm {
+
+ protected static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload,
+ @Nullable String accountType,
+ String holderAddress) {
+ BankAccountPayload bankAccountPayload = (BankAccountPayload) paymentAccountPayload;
+ String countryCode = bankAccountPayload.getCountryCode();
+ int colIndex = 1;
+
+ addTopLabelTextFieldWithCopyIcon(gridPane, getIndexOfColumn(colIndex) == 0 ? ++gridRow : gridRow, getIndexOfColumn(colIndex++),
+ Res.get("payment.account.owner"), bankAccountPayload.getHolderName(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE);
+
+ String branchIdLabel = BankUtil.getBranchIdLabel(countryCode);
+ String accountNrLabel = BankUtil.getAccountNrLabel(countryCode);
+ addCompactTopLabelTextFieldWithCopyIcon(gridPane, getIndexOfColumn(colIndex) == 0 ? ++gridRow : gridRow, getIndexOfColumn(colIndex++),
+ branchIdLabel + " / " + accountNrLabel,
+ bankAccountPayload.getBranchId() + " / " + bankAccountPayload.getAccountNr());
+
+ String bankNameLabel = BankUtil.getBankNameLabel(countryCode);
+ String accountTypeLabel = accountType == null ? "" : " / " + BankUtil.getAccountTypeLabel(countryCode);
+ addCompactTopLabelTextFieldWithCopyIcon(gridPane, getIndexOfColumn(colIndex) == 0 ? ++gridRow : gridRow, getIndexOfColumn(colIndex++),
+ bankNameLabel + accountTypeLabel,
+ accountType == null ? bankAccountPayload.getBankName() : bankAccountPayload.getBankName() + " / " + accountType);
+
+ if (holderAddress.length() > 0) {
+ TextArea textAddress = addCompactTopLabelTextArea(gridPane, getIndexOfColumn(colIndex) == 0 ? ++gridRow : gridRow, getIndexOfColumn(colIndex++),
+ Res.get("payment.account.address"), "").second;
+ textAddress.setMinHeight(70);
+ textAddress.setEditable(false);
+ textAddress.setText(holderAddress);
+ }
+ return gridRow;
+ }
+
+ public GeneralUsBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator,
+ GridPane gridPane, int gridRow, CoinFormatter formatter) {
+ super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter);
+ }
+
+ protected void addFormForDisplayAccount(BankAccountPayload bankAccountPayload, String holderAddress) {
+ Country country = ((CountryBasedPaymentAccount) paymentAccount).getCountry();
+ 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"), bankAccountPayload.getHolderName());
+ addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.account.owner.address"), cleanString(holderAddress));
+ addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.bank.name"), bankAccountPayload.getBankName());
+ addCompactTopLabelTextField(gridPane, ++gridRow, BankUtil.getBranchIdLabel(country.code), bankAccountPayload.getBranchId());
+ addCompactTopLabelTextField(gridPane, ++gridRow, BankUtil.getAccountNrLabel(country.code), bankAccountPayload.getAccountNr());
+ if (bankAccountPayload.getAccountType() != null) {
+ addCompactTopLabelTextField(gridPane, ++gridRow, BankUtil.getAccountTypeLabel(country.code), bankAccountPayload.getAccountType());
+ }
+ addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), paymentAccount.getSingleTradeCurrency().getNameAndCode());
+ addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), country.name);
+ addLimitations(true);
+ }
+
+ protected void addFormForAddAccountInternal(BankAccountPayload bankAccountPayload, String holderAddress) {
+ // this payment method is only for United States/USD
+ CountryUtil.findCountryByCode("US").ifPresent(c -> onCountrySelected(c));
+ Country country = ((CountryBasedPaymentAccount) paymentAccount).getCountry();
+
+ InputTextField holderNameInputTextField = addInputTextField(gridPane, ++gridRow, Res.get("payment.account.owner"));
+ holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
+ bankAccountPayload.setHolderName(newValue);
+ updateFromInputs();
+ });
+ holderNameInputTextField.setValidator(inputValidator);
+
+ TextArea addressTextArea = addTopLabelTextArea(gridPane, ++gridRow,
+ Res.get("payment.account.owner.address"), Res.get("payment.account.owner.address")).second;
+ addressTextArea.setMinHeight(70);
+ addressTextArea.textProperty().addListener((ov, oldValue, newValue) -> {
+ setHolderAddress(newValue.trim());
+ updateFromInputs();
+ });
+
+ bankNameInputTextField = addInputTextField(gridPane, ++gridRow, Res.get("payment.bank.name"));
+ bankNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
+ bankAccountPayload.setBankName(newValue);
+ updateFromInputs();
+ });
+ bankNameInputTextField.setValidator(inputValidator);
+
+ branchIdInputTextField = addInputTextField(gridPane, ++gridRow, BankUtil.getBranchIdLabel(country.code));
+ branchIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
+ bankAccountPayload.setBranchId(newValue);
+ updateFromInputs();
+ });
+ branchIdInputTextField.setValidator(inputValidator);
+
+ accountNrInputTextField = addInputTextField(gridPane, ++gridRow, BankUtil.getAccountNrLabel(country.code));
+ accountNrInputTextField.textProperty().addListener((ov, oldValue, newValue) -> {
+ bankAccountPayload.setAccountNr(newValue);
+ updateFromInputs();
+ });
+ accountNrInputTextField.setValidator(inputValidator);
+
+ maybeAddAccountTypeCombo(bankAccountPayload, country);
+
+ addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.currency"), paymentAccount.getSingleTradeCurrency().getNameAndCode());
+ addTopLabelTextField(gridPane, ++gridRow, Res.get("shared.country"), country.name);
+ addLimitations(false);
+ addAccountNameTextFieldWithAutoFillToggleButton();
+ this.validatorsApplied = true;
+ }
+
+ abstract protected void setHolderAddress(String holderAddress);
+
+ abstract protected void maybeAddAccountTypeCombo(BankAccountPayload bankAccountPayload, Country country);
+
+ protected void onCountrySelected(Country country) {
+ if (country != null) {
+ ((CountryBasedPaymentAccount) this.paymentAccount).setCountry(country);
+ String countryCode = country.code;
+ TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(countryCode);
+ paymentAccount.setSingleTradeCurrency(currency);
+ }
+ }
+
+ @Override
+ protected void autoFillNameTextField() {
+ autoFillAccountTextFields((CountryBasedPaymentAccountPayload) paymentAccount.getPaymentAccountPayload());
+ }
+}
diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/TransferwiseUsdForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/TransferwiseUsdForm.java
index 69a5e9183e6..359afaff8ff 100644
--- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/TransferwiseUsdForm.java
+++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/TransferwiseUsdForm.java
@@ -94,7 +94,8 @@ public void addFormForAddAccount() {
updateFromInputs();
});
- TextArea addressTextArea = addTopLabelTextArea(gridPane, ++gridRow, Res.get("payment.transferwiseUsd.address"), Res.get("payment.transferwiseUsd.address")).second;
+ String addressLabel = Res.get("payment.account.owner.address") + Res.get("payment.transferwiseUsd.address");
+ TextArea addressTextArea = addTopLabelTextArea(gridPane, ++gridRow, addressLabel, addressLabel).second;
addressTextArea.setMinHeight(70);
addressTextArea.textProperty().addListener((ov, oldValue, newValue) -> {
account.setBeneficiaryAddress(newValue.trim());
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 178c63084bd..bad77df7d83 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
@@ -19,6 +19,7 @@
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.TitledGroupBg;
+import bisq.desktop.components.paymentmethods.AchTransferForm;
import bisq.desktop.components.paymentmethods.AdvancedCashForm;
import bisq.desktop.components.paymentmethods.AliPayForm;
import bisq.desktop.components.paymentmethods.AmazonGiftCardForm;
@@ -30,6 +31,7 @@
import bisq.desktop.components.paymentmethods.CelPayForm;
import bisq.desktop.components.paymentmethods.ChaseQuickPayForm;
import bisq.desktop.components.paymentmethods.ClearXchangeForm;
+import bisq.desktop.components.paymentmethods.DomesticWireTransferForm;
import bisq.desktop.components.paymentmethods.F2FForm;
import bisq.desktop.components.paymentmethods.FasterPaymentsForm;
import bisq.desktop.components.paymentmethods.HalCashForm;
@@ -597,6 +599,10 @@ private PaymentMethodForm getPaymentMethodForm(PaymentMethod paymentMethod, Paym
return new StrikeForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
case PaymentMethod.SWIFT_ID:
return new SwiftForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
+ case PaymentMethod.ACH_TRANSFER_ID:
+ return new AchTransferForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
+ case PaymentMethod.DOMESTIC_WIRE_TRANSFER_ID:
+ return new DomesticWireTransferForm(paymentAccount, accountAgeWitnessService, inputValidator, root, gridRow, formatter);
default:
log.error("Not supported PaymentMethod: " + paymentMethod);
return null;
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 a2ee010eec7..304b2a48a29 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
@@ -21,6 +21,7 @@
import bisq.desktop.components.BusyAnimation;
import bisq.desktop.components.TextFieldWithCopyIcon;
import bisq.desktop.components.TitledGroupBg;
+import bisq.desktop.components.paymentmethods.AchTransferForm;
import bisq.desktop.components.paymentmethods.AdvancedCashForm;
import bisq.desktop.components.paymentmethods.AliPayForm;
import bisq.desktop.components.paymentmethods.AmazonGiftCardForm;
@@ -32,6 +33,7 @@
import bisq.desktop.components.paymentmethods.CelPayForm;
import bisq.desktop.components.paymentmethods.ChaseQuickPayForm;
import bisq.desktop.components.paymentmethods.ClearXchangeForm;
+import bisq.desktop.components.paymentmethods.DomesticWireTransferForm;
import bisq.desktop.components.paymentmethods.F2FForm;
import bisq.desktop.components.paymentmethods.FasterPaymentsForm;
import bisq.desktop.components.paymentmethods.HalCashForm;
@@ -400,6 +402,12 @@ protected void addContent() {
case PaymentMethod.SWIFT_ID:
gridRow = SwiftForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload, trade);
break;
+ case PaymentMethod.ACH_TRANSFER_ID:
+ gridRow = AchTransferForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload);
+ break;
+ case PaymentMethod.DOMESTIC_WIRE_TRANSFER_ID:
+ gridRow = DomesticWireTransferForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload);
+ break;
default:
log.error("Not supported PaymentMethod: " + paymentMethodId);
}
diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto
index 255cc52c3aa..e305174798c 100644
--- a/proto/src/main/proto/pb.proto
+++ b/proto/src/main/proto/pb.proto
@@ -1151,10 +1151,20 @@ message BankAccountPayload {
NationalBankAccountPayload national_bank_account_payload = 9;
SameBankAccountPayload same_bank_accont_payload = 10;
SpecificBanksAccountPayload specific_banks_account_payload = 11;
+ AchTransferAccountPayload ach_transfer_account_payload = 13;
+ DomesticWireTransferAccountPayload domestic_wire_transfer_account_payload = 14;
}
string national_account_id = 12;
}
+message AchTransferAccountPayload {
+ string holder_address = 1;
+}
+
+message DomesticWireTransferAccountPayload {
+ string holder_address = 1;
+}
+
message NationalBankAccountPayload {
}