diff --git a/apitest/src/test/java/bisq/apitest/method/payment/AbstractPaymentAccountTest.java b/apitest/src/test/java/bisq/apitest/method/payment/AbstractPaymentAccountTest.java index 433898731e5..92b8e8309ca 100644 --- a/apitest/src/test/java/bisq/apitest/method/payment/AbstractPaymentAccountTest.java +++ b/apitest/src/test/java/bisq/apitest/method/payment/AbstractPaymentAccountTest.java @@ -1,6 +1,7 @@ package bisq.apitest.method.payment; import bisq.core.api.model.PaymentAccountForm; +import bisq.core.locale.FiatCurrency; import bisq.core.locale.Res; import bisq.core.locale.TradeCurrency; import bisq.core.payment.PaymentAccount; @@ -17,10 +18,13 @@ import java.io.OutputStreamWriter; import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -57,14 +61,23 @@ public class AbstractPaymentAccountTest extends MethodTest { static final String PROPERTY_NAME_BANK_ACCOUNT_NAME = "bankAccountName"; static final String PROPERTY_NAME_BANK_ACCOUNT_NUMBER = "bankAccountNumber"; static final String PROPERTY_NAME_BANK_ACCOUNT_TYPE = "bankAccountType"; + static final String PROPERTY_NAME_BANK_ADDRESS = "bankAddress"; + static final String PROPERTY_NAME_BANK_BRANCH = "bankBranch"; static final String PROPERTY_NAME_BANK_BRANCH_CODE = "bankBranchCode"; static final String PROPERTY_NAME_BANK_BRANCH_NAME = "bankBranchName"; static final String PROPERTY_NAME_BANK_CODE = "bankCode"; + static final String PROPERTY_NAME_BANK_COUNTRY_CODE = "bankCountryCode"; @SuppressWarnings("unused") static final String PROPERTY_NAME_BANK_ID = "bankId"; static final String PROPERTY_NAME_BANK_NAME = "bankName"; + static final String PROPERTY_NAME_BANK_SWIFT_CODE = "bankSwiftCode"; static final String PROPERTY_NAME_BRANCH_ID = "branchId"; static final String PROPERTY_NAME_BIC = "bic"; + static final String PROPERTY_NAME_BENEFICIARY_NAME = "beneficiaryName"; + static final String PROPERTY_NAME_BENEFICIARY_ACCOUNT_NR = "beneficiaryAccountNr"; + static final String PROPERTY_NAME_BENEFICIARY_ADDRESS = "beneficiaryAddress"; + static final String PROPERTY_NAME_BENEFICIARY_CITY = "beneficiaryCity"; + static final String PROPERTY_NAME_BENEFICIARY_PHONE = "beneficiaryPhone"; static final String PROPERTY_NAME_COUNTRY = "country"; static final String PROPERTY_NAME_CITY = "city"; static final String PROPERTY_NAME_CONTACT = "contact"; @@ -75,6 +88,11 @@ public class AbstractPaymentAccountTest extends MethodTest { static final String PROPERTY_NAME_HOLDER_NAME = "holderName"; static final String PROPERTY_NAME_HOLDER_TAX_ID = "holderTaxId"; static final String PROPERTY_NAME_IBAN = "iban"; + static final String PROPERTY_NAME_INTERMEDIARY_ADDRESS = "intermediaryAddress"; + static final String PROPERTY_NAME_INTERMEDIARY_BRANCH = "intermediaryBranch"; + static final String PROPERTY_NAME_INTERMEDIARY_COUNTRY_CODE = "intermediaryCountryCode"; + static final String PROPERTY_NAME_INTERMEDIARY_NAME = "intermediaryName"; + static final String PROPERTY_NAME_INTERMEDIARY_SWIFT_CODE = "intermediarySwiftCode"; static final String PROPERTY_NAME_MOBILE_NR = "mobileNr"; static final String PROPERTY_NAME_NATIONAL_ACCOUNT_ID = "nationalAccountId"; static final String PROPERTY_NAME_PAY_ID = "payid"; @@ -83,7 +101,9 @@ public class AbstractPaymentAccountTest extends MethodTest { static final String PROPERTY_NAME_QUESTION = "question"; static final String PROPERTY_NAME_REQUIREMENTS = "requirements"; static final String PROPERTY_NAME_SALT = "salt"; + static final String PROPERTY_NAME_SELECTED_TRADE_CURRENCY = "selectedTradeCurrency"; static final String PROPERTY_NAME_SORT_CODE = "sortCode"; + static final String PROPERTY_NAME_SPECIAL_INSTRUCTIONS = "specialInstructions"; static final String PROPERTY_NAME_STATE = "state"; static final String PROPERTY_NAME_TRADE_CURRENCIES = "tradeCurrencies"; static final String PROPERTY_NAME_USERNAME = "userName"; @@ -110,7 +130,7 @@ protected final File getEmptyForm(TestInfo testInfo, String paymentMethodId) { COMPLETED_FORM_MAP.clear(); File emptyForm = getPaymentAccountForm(aliceClient, paymentMethodId); - // A short cut over the API: + // A shortcut over the API: // File emptyForm = PAYMENT_ACCOUNT_FORM.getPaymentAccountForm(paymentMethodId); log.debug("{} Empty form saved to {}", testName(testInfo), @@ -125,7 +145,14 @@ protected final void verifyEmptyForm(File jsonForm, String paymentMethodId, Stri PAYMENT_ACCOUNT_FORM.toJsonString(jsonForm), Object.class); assertNotNull(emptyForm); - assertEquals(PROPERTY_VALUE_JSON_COMMENTS, emptyForm.get(PROPERTY_NAME_JSON_COMMENTS)); + + // TODO remove 'false' condition to enable creation of SWIFT accounts in future PR. + if (false && paymentMethodId.equals("SWIFT_ID")) { + assertEquals(getSwiftFormComments(), emptyForm.get(PROPERTY_NAME_JSON_COMMENTS)); + } else { + assertEquals(PROPERTY_VALUE_JSON_COMMENTS, emptyForm.get(PROPERTY_NAME_JSON_COMMENTS)); + } + assertEquals(paymentMethodId, emptyForm.get(PROPERTY_NAME_PAYMENT_METHOD_ID)); assertEquals("your accountname", emptyForm.get(PROPERTY_NAME_ACCOUNT_NAME)); for (String field : fields) { @@ -149,6 +176,15 @@ protected final void verifyAccountSingleTradeCurrency(String expectedCurrencyCod assertEquals(expectedCurrencyCode, paymentAccount.getSingleTradeCurrency().getCode()); } + protected final void verifyAccountTradeCurrencies(Collection expectedFiatCurrencies, + PaymentAccount paymentAccount) { + assertNotNull(paymentAccount.getTradeCurrencies()); + List expectedTradeCurrencies = new ArrayList<>() {{ + addAll(expectedFiatCurrencies); + }}; + assertArrayEquals(expectedTradeCurrencies.toArray(), paymentAccount.getTradeCurrencies().toArray()); + } + protected final void verifyAccountTradeCurrencies(List expectedTradeCurrencies, PaymentAccount paymentAccount) { assertNotNull(paymentAccount.getTradeCurrencies()); @@ -164,14 +200,44 @@ protected final void verifyUserPayloadHasPaymentAccountWithId(GrpcClient grpcCli assertTrue(paymentAccount.isPresent()); } + protected final String getCompletedFormAsJsonString(List comments) { + File completedForm = fillPaymentAccountForm(comments); + String jsonString = PAYMENT_ACCOUNT_FORM.toJsonString(completedForm); + log.debug("Completed form: {}", jsonString); + return jsonString; + } + protected final String getCompletedFormAsJsonString() { - File completedForm = fillPaymentAccountForm(); + File completedForm = fillPaymentAccountForm(PROPERTY_VALUE_JSON_COMMENTS); String jsonString = PAYMENT_ACCOUNT_FORM.toJsonString(completedForm); log.debug("Completed form: {}", jsonString); return jsonString; } - private File fillPaymentAccountForm() { + protected final String getCommaDelimitedFiatCurrencyCodes(Collection fiatCurrencies) { + return fiatCurrencies.stream() + .sorted(TradeCurrency::compareTo) // note: sorted by ccy name, not ccy code + .map(c -> c.getCurrency().getCurrencyCode()) + .collect(Collectors.joining(",")); + } + + protected final String getCommaDelimitedTradeCurrencyCodes(List tradeCurrencies) { + return tradeCurrencies.stream() + .sorted(Comparator.comparing(TradeCurrency::getCode)) // sorted by code + .map(c -> c.getCode()) + .collect(Collectors.joining(",")); + } + + protected final List getSwiftFormComments() { + List comments = new ArrayList<>(); + comments.addAll(PROPERTY_VALUE_JSON_COMMENTS); + // List wrappedSwiftComments = Res.getWrappedAsList("payment.swift.info", 110); + // comments.addAll(wrappedSwiftComments); + // comments.add("See https://bisq.wiki/SWIFT"); + return comments; + } + + private File fillPaymentAccountForm(List comments) { File tmpJsonForm = null; try { tmpJsonForm = File.createTempFile("temp_acct_form_", @@ -182,7 +248,7 @@ private File fillPaymentAccountForm() { writer.name(PROPERTY_NAME_JSON_COMMENTS); writer.beginArray(); - for (String s : PROPERTY_VALUE_JSON_COMMENTS) { + for (String s : comments) { writer.value(s); } writer.endArray(); diff --git a/apitest/src/test/java/bisq/apitest/method/payment/CreatePaymentAccountTest.java b/apitest/src/test/java/bisq/apitest/method/payment/CreatePaymentAccountTest.java index b7eb7f7ebb7..26e2030c844 100644 --- a/apitest/src/test/java/bisq/apitest/method/payment/CreatePaymentAccountTest.java +++ b/apitest/src/test/java/bisq/apitest/method/payment/CreatePaymentAccountTest.java @@ -21,6 +21,7 @@ import bisq.core.payment.AdvancedCashAccount; import bisq.core.payment.AliPayAccount; import bisq.core.payment.AustraliaPayid; +import bisq.core.payment.CapitualAccount; import bisq.core.payment.CashDepositAccount; import bisq.core.payment.ClearXchangeAccount; import bisq.core.payment.F2FAccount; @@ -31,7 +32,9 @@ import bisq.core.payment.MoneyBeamAccount; import bisq.core.payment.MoneyGramAccount; import bisq.core.payment.NationalBankAccount; +import bisq.core.payment.PaxumAccount; import bisq.core.payment.PaymentAccount; +import bisq.core.payment.PayseraAccount; import bisq.core.payment.PerfectMoneyAccount; import bisq.core.payment.PopmoneyAccount; import bisq.core.payment.PromptPayAccount; @@ -58,6 +61,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -103,11 +107,18 @@ public void testCreateAdvancedCashAccount(TestInfo testInfo) { COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, ADVANCED_CASH_ID); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Advanced Cash Acct"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NR, "0000 1111 2222"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllAdvancedCashCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "RUB"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, encodeToHex("Restored Advanced Cash Acct Salt")); String jsonString = getCompletedFormAsJsonString(); AdvancedCashAccount paymentAccount = (AdvancedCashAccount) createPaymentAccount(aliceClient, jsonString); verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); verifyAccountTradeCurrencies(getAllAdvancedCashCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); verifyCommonFormEntries(paymentAccount); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr()); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex()); @@ -155,6 +166,33 @@ public void testCreateAustraliaPayidAccount(TestInfo testInfo) { print(paymentAccount); } + @Test + public void testCreateCapitualAccount(TestInfo testInfo) { + File emptyForm = getEmptyForm(testInfo, CAPITUAL_ID); + verifyEmptyForm(emptyForm, + CAPITUAL_ID, + PROPERTY_NAME_ACCOUNT_NR); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, CAPITUAL_ID); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Capitual Acct"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NR, "1111 2222 3333-4"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllCapitualCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "BRL"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, encodeToHex("Restored Capitual Acct Salt")); + String jsonString = getCompletedFormAsJsonString(); + CapitualAccount paymentAccount = (CapitualAccount) createPaymentAccount(aliceClient, jsonString); + verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); + verifyAccountTradeCurrencies(getAllCapitualCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); + verifyCommonFormEntries(paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex()); + print(paymentAccount); + } + @Test public void testCreateCashDepositAccount(TestInfo testInfo) { File emptyForm = getEmptyForm(testInfo, CASH_DEPOSIT_ID); @@ -443,6 +481,11 @@ public void testCreateMoneyGramAccount(TestInfo testInfo) { PROPERTY_NAME_STATE); COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, MONEY_GRAM_ID); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Money Gram Acct"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllMoneyGramCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "INR"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_HOLDER_NAME, "John Doe"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "john@doe.info"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_COUNTRY, "US"); @@ -452,6 +495,8 @@ public void testCreateMoneyGramAccount(TestInfo testInfo) { MoneyGramAccount paymentAccount = (MoneyGramAccount) createPaymentAccount(aliceClient, jsonString); verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); verifyAccountTradeCurrencies(getAllMoneyGramCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); verifyCommonFormEntries(paymentAccount); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), paymentAccount.getFullName()); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail()); @@ -481,6 +526,58 @@ public void testCreatePerfectMoneyAccount(TestInfo testInfo) { print(paymentAccount); } + @Test + public void testCreatePaxumAccount(TestInfo testInfo) { + File emptyForm = getEmptyForm(testInfo, PAXUM_ID); + verifyEmptyForm(emptyForm, + PAXUM_ID, + PROPERTY_NAME_EMAIL); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, PAXUM_ID); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Paxum Acct"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllPaxumCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "SEK"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.net"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, ""); + String jsonString = getCompletedFormAsJsonString(); + PaxumAccount paymentAccount = (PaxumAccount) createPaymentAccount(aliceClient, jsonString); + verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); + verifyAccountTradeCurrencies(getAllPaxumCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); + verifyCommonFormEntries(paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail()); + print(paymentAccount); + } + + @Test + public void testCreatePayseraAccount(TestInfo testInfo) { + File emptyForm = getEmptyForm(testInfo, PAYSERA_ID); + verifyEmptyForm(emptyForm, + PAYSERA_ID, + PROPERTY_NAME_EMAIL); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, PAYSERA_ID); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Paysera Acct"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllPayseraCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "ZAR"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.net"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, ""); + String jsonString = getCompletedFormAsJsonString(); + PayseraAccount paymentAccount = (PayseraAccount) createPaymentAccount(aliceClient, jsonString); + verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); + verifyAccountTradeCurrencies(getAllPayseraCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); + verifyCommonFormEntries(paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail()); + print(paymentAccount); + } + @Test public void testCreatePopmoneyAccount(TestInfo testInfo) { File emptyForm = getEmptyForm(testInfo, POPMONEY_ID); @@ -531,12 +628,19 @@ public void testCreateRevolutAccount(TestInfo testInfo) { PROPERTY_NAME_USERNAME); COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, REVOLUT_ID); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Revolut Acct"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllRevolutCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "QAR"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_USERNAME, "revolut123"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, ""); String jsonString = getCompletedFormAsJsonString(); RevolutAccount paymentAccount = (RevolutAccount) createPaymentAccount(aliceClient, jsonString); verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); verifyAccountTradeCurrencies(getAllRevolutCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); verifyCommonFormEntries(paymentAccount); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_USERNAME), paymentAccount.getUserName()); print(paymentAccount); @@ -697,6 +801,65 @@ public void testCreateSpecificBanksAccount(TestInfo testInfo) { print(paymentAccount); } + /* + @Test + public void testCreateSwiftAccount(TestInfo testInfo) { + // https://www.theswiftcodes.com + File emptyForm = getEmptyForm(testInfo, SWIFT_ID); + verifyEmptyForm(emptyForm, + SWIFT_ID, + PROPERTY_NAME_BANK_SWIFT_CODE); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, SWIFT_ID); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "IT Swift Acct w/ DE Intermediary"); + String allFiatCodes = getCommaDelimitedFiatCurrencyCodes(getAllSortedFiatCurrencies()); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, allFiatCodes); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "EUR"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BANK_SWIFT_CODE, "PASCITMMFIR"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BANK_COUNTRY_CODE, "IT"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BANK_NAME, "BANCA MONTE DEI PASCHI DI SIENA S.P.A."); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BANK_BRANCH, "SUCC. DI FIRENZE"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BANK_ADDRESS, "Via dei Pecori, 8, 50123 Firenze FI, Italy"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BENEFICIARY_NAME, "Vito de' Medici"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BENEFICIARY_ACCOUNT_NR, "0000 1111 2222 3333"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BENEFICIARY_ADDRESS, "Via dei Pecori, 1, 50123 Firenze FI, Italy"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BENEFICIARY_CITY, "Firenze"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_BENEFICIARY_PHONE, "+39 055 222222"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SPECIAL_INSTRUCTIONS, "N/A"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_INTERMEDIARY_SWIFT_CODE, "DEUTDEFFXXX"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_INTERMEDIARY_COUNTRY_CODE, "DE"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_INTERMEDIARY_NAME, "Kosmo Krump"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_INTERMEDIARY_ADDRESS, "TAUNUSANLAGE 12, FRANKFURT AM MAIN, 60262"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_INTERMEDIARY_BRANCH, "Deutsche Bank Frankfurt F"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, encodeToHex("Restored Swift Acct Salt")); + String jsonString = getCompletedFormAsJsonString(getSwiftFormComments()); + SwiftAccount paymentAccount = (SwiftAccount) createPaymentAccount(aliceClient, jsonString); + verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); + verifyAccountTradeCurrencies(getAllSortedFiatCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); + verifyCommonFormEntries(paymentAccount); + SwiftAccountPayload payload = (SwiftAccountPayload) paymentAccount.getPaymentAccountPayload(); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_SWIFT_CODE), payload.getBankSwiftCode()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_COUNTRY_CODE), payload.getBankCountryCode()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_NAME), payload.getBankName()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_BRANCH), payload.getBankBranch()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_ADDRESS), payload.getBankAddress()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BENEFICIARY_NAME), payload.getBeneficiaryName()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BENEFICIARY_ACCOUNT_NR), payload.getBeneficiaryAccountNr()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BENEFICIARY_ADDRESS), payload.getBeneficiaryAddress()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BENEFICIARY_CITY), payload.getBeneficiaryCity()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BENEFICIARY_PHONE), payload.getBeneficiaryPhone()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SPECIAL_INSTRUCTIONS), payload.getSpecialInstructions()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_INTERMEDIARY_SWIFT_CODE), payload.getIntermediarySwiftCode()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_INTERMEDIARY_COUNTRY_CODE), payload.getIntermediaryCountryCode()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_INTERMEDIARY_NAME), payload.getIntermediaryName()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_INTERMEDIARY_BRANCH), payload.getIntermediaryBranch()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_INTERMEDIARY_ADDRESS), payload.getIntermediaryAddress()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex()); + print(paymentAccount); + } + */ + @Test public void testCreateSwishAccount(TestInfo testInfo) { File emptyForm = getEmptyForm(testInfo, SWISH_ID); @@ -728,17 +891,16 @@ public void testCreateTransferwiseAccountWith1TradeCurrency(TestInfo testInfo) { PROPERTY_NAME_EMAIL); COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, TRANSFERWISE_ID); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Transferwise Acct"); - COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, "eur"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, "NZD"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "NZD"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.info"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, ""); String jsonString = getCompletedFormAsJsonString(); TransferwiseAccount paymentAccount = (TransferwiseAccount) createPaymentAccount(aliceClient, jsonString); verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); assertEquals(1, paymentAccount.getTradeCurrencies().size()); - TradeCurrency expectedCurrency = getTradeCurrency("EUR").get(); - assertEquals(expectedCurrency, paymentAccount.getSelectedTradeCurrency()); - List expectedTradeCurrencies = singletonList(expectedCurrency); - verifyAccountTradeCurrencies(expectedTradeCurrencies, paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); verifyCommonFormEntries(paymentAccount); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail()); print(paymentAccount); @@ -752,7 +914,8 @@ public void testCreateTransferwiseAccountWith10TradeCurrencies(TestInfo testInfo PROPERTY_NAME_EMAIL); COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, TRANSFERWISE_ID); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Transferwise Acct"); - COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, "ars, cad, hrk, czk, eur, hkd, idr, jpy, chf, nzd"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, "ARS,CAD,HRK,CZK,EUR,HKD,IDR,JPY,CHF,NZD"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "CHF"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.info"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, ""); String jsonString = getCompletedFormAsJsonString(); @@ -772,8 +935,34 @@ public void testCreateTransferwiseAccountWith10TradeCurrencies(TestInfo testInfo add(getTradeCurrency("NZD").get()); }}; verifyAccountTradeCurrencies(expectedTradeCurrencies, paymentAccount); - TradeCurrency expectedSelectedCurrency = expectedTradeCurrencies.get(0); - assertEquals(expectedSelectedCurrency, paymentAccount.getSelectedTradeCurrency()); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); + verifyCommonFormEntries(paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail()); + print(paymentAccount); + } + + @Test + public void testCreateTransferwiseAccountWithSupportedTradeCurrencies(TestInfo testInfo) { + File emptyForm = getEmptyForm(testInfo, TRANSFERWISE_ID); + verifyEmptyForm(emptyForm, + TRANSFERWISE_ID, + PROPERTY_NAME_EMAIL); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, TRANSFERWISE_ID); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Transferwise Acct"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllTransferwiseCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "AUD"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.info"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, ""); + String jsonString = getCompletedFormAsJsonString(); + TransferwiseAccount paymentAccount = (TransferwiseAccount) createPaymentAccount(aliceClient, jsonString); + verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); + verifyAccountTradeCurrencies(getAllTransferwiseCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); verifyCommonFormEntries(paymentAccount); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail()); print(paymentAccount); @@ -813,7 +1002,7 @@ public void testCreateTransferwiseAccountWithoutTradeCurrenciesShouldThrowExcept Throwable exception = assertThrows(StatusRuntimeException.class, () -> createPaymentAccount(aliceClient, jsonString)); - assertEquals("INVALID_ARGUMENT: no trade currencies defined for transferwise payment account", + assertEquals("INVALID_ARGUMENT: no trade currency defined for transferwise payment account", exception.getMessage()); } @@ -826,11 +1015,18 @@ public void testCreateUpholdAccount(TestInfo testInfo) { COMPLETED_FORM_MAP.put(PROPERTY_NAME_PAYMENT_METHOD_ID, UPHOLD_ID); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_NAME, "Uphold Acct"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_ACCOUNT_ID, "UA 9876"); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, getAllUpholdCurrencies() + .stream() + .map(TradeCurrency::getCode) + .collect(Collectors.joining(","))); + COMPLETED_FORM_MAP.put(PROPERTY_NAME_SELECTED_TRADE_CURRENCY, "MXN"); COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, encodeToHex("Restored Uphold Acct Salt")); String jsonString = getCompletedFormAsJsonString(); UpholdAccount paymentAccount = (UpholdAccount) createPaymentAccount(aliceClient, jsonString); verifyUserPayloadHasPaymentAccountWithId(aliceClient, paymentAccount.getId()); verifyAccountTradeCurrencies(getAllUpholdCurrencies(), paymentAccount); + assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SELECTED_TRADE_CURRENCY), + paymentAccount.getSelectedTradeCurrency().getCode()); verifyCommonFormEntries(paymentAccount); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_ID), paymentAccount.getAccountId()); assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex()); diff --git a/apitest/src/test/java/bisq/apitest/scenario/PaymentAccountTest.java b/apitest/src/test/java/bisq/apitest/scenario/PaymentAccountTest.java index 1aaf553c857..8d03b7dd470 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/PaymentAccountTest.java +++ b/apitest/src/test/java/bisq/apitest/scenario/PaymentAccountTest.java @@ -49,6 +49,7 @@ public void testCreatePaymentAccount(TestInfo testInfo) { test.testCreateAdvancedCashAccount(testInfo); test.testCreateAliPayAccount(testInfo); test.testCreateAustraliaPayidAccount(testInfo); + test.testCreateCapitualAccount(testInfo); test.testCreateCashDepositAccount(testInfo); test.testCreateBrazilNationalBankAccount(testInfo); test.testCreateClearXChangeAccount(testInfo); @@ -60,6 +61,8 @@ public void testCreatePaymentAccount(TestInfo testInfo) { test.testCreateMoneyBeamAccount(testInfo); test.testCreateMoneyGramAccount(testInfo); test.testCreatePerfectMoneyAccount(testInfo); + test.testCreatePaxumAccount(testInfo); + test.testCreatePayseraAccount(testInfo); test.testCreatePopmoneyAccount(testInfo); test.testCreatePromptPayAccount(testInfo); test.testCreateRevolutAccount(testInfo); @@ -67,12 +70,12 @@ public void testCreatePaymentAccount(TestInfo testInfo) { test.testCreateSepaInstantAccount(testInfo); test.testCreateSepaAccount(testInfo); test.testCreateSpecificBanksAccount(testInfo); + // test.testCreateSwiftAccount(testInfo); test.testCreateSwishAccount(testInfo); - // TransferwiseAccount is only PaymentAccount with a - // tradeCurrencies field in the json form. test.testCreateTransferwiseAccountWith1TradeCurrency(testInfo); test.testCreateTransferwiseAccountWith10TradeCurrencies(testInfo); + test.testCreateTransferwiseAccountWithSupportedTradeCurrencies(testInfo); test.testCreateTransferwiseAccountWithInvalidBrlTradeCurrencyShouldThrowException(testInfo); test.testCreateTransferwiseAccountWithoutTradeCurrenciesShouldThrowException(testInfo); diff --git a/apitest/src/test/resources/logback.xml b/apitest/src/test/resources/logback.xml new file mode 100644 index 00000000000..28279faa118 --- /dev/null +++ b/apitest/src/test/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + + %highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{30}: %msg %xEx%n) + + + + + + + + + diff --git a/common/src/main/java/bisq/common/util/Utilities.java b/common/src/main/java/bisq/common/util/Utilities.java index 3d530b918d2..30e247b2980 100644 --- a/common/src/main/java/bisq/common/util/Utilities.java +++ b/common/src/main/java/bisq/common/util/Utilities.java @@ -52,9 +52,11 @@ import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; @@ -337,12 +339,12 @@ public static boolean isCorrectOSArchitecture() { public static void openURI(URI uri) throws IOException { if (!DesktopUtil.browse(uri)) - throw new IOException("Failed to open URI: " + uri.toString()); + throw new IOException("Failed to open URI: " + uri); } public static void openFile(File file) throws IOException { if (!DesktopUtil.open(file)) - throw new IOException("Failed to open file: " + file.toString()); + throw new IOException("Failed to open file: " + file); } public static String getDownloadOfHomeDir() { @@ -480,6 +482,16 @@ public static String toTruncatedString(Object message, int maxLength, boolean re } + public static List toListOfWrappedStrings(String s, int wrapLength) { + StringBuilder sb = new StringBuilder(s); + int i = 0; + while (i + wrapLength < sb.length() && (i = sb.lastIndexOf(" ", i + wrapLength)) != -1) { + sb.replace(i, i + 1, "\n"); + } + String[] splitLine = sb.toString().split("\n"); + return Arrays.asList(splitLine); + } + public static String getRandomPrefix(int minLength, int maxLength) { int length = minLength + new Random().nextInt(maxLength - minLength + 1); String result; diff --git a/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java b/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java index 220205fbee3..416dde6531b 100644 --- a/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java +++ b/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java @@ -138,9 +138,8 @@ List getCryptoCurrencyPaymentMethods() { } private void verifyPaymentAccountHasRequiredFields(PaymentAccount paymentAccount) { - // Do checks here to make sure required fields are populated. - if (paymentAccount.isTransferwiseAccount() && paymentAccount.getTradeCurrencies().isEmpty()) - throw new IllegalArgumentException(format("no trade currencies defined for %s payment account", + if (!paymentAccount.hasMultipleCurrencies() && paymentAccount.getSingleTradeCurrency() == null) + throw new IllegalArgumentException(format("no trade currency defined for %s payment account", paymentAccount.getPaymentMethod().getDisplayString().toLowerCase())); } } diff --git a/core/src/main/java/bisq/core/api/model/PaymentAccountForm.java b/core/src/main/java/bisq/core/api/model/PaymentAccountForm.java index eb3a6cd3bac..5de59e7c0f0 100644 --- a/core/src/main/java/bisq/core/api/model/PaymentAccountForm.java +++ b/core/src/main/java/bisq/core/api/model/PaymentAccountForm.java @@ -134,11 +134,11 @@ public class PaymentAccountForm { "maxTradePeriod", "paymentAccountPayload", "paymentMethod", - "paymentMethodId", // This field will be included, but handled differently. - "selectedTradeCurrency", - "tradeCurrencies", // This field may be included, but handled differently. + "paymentMethodId", // Will be included, but handled differently. + "selectedTradeCurrency", // May be included, but handled differently. + "tradeCurrencies", // May be included, but handled differently. "HOLDER_NAME", - "SALT" // This field will be included, but handled differently. + "SALT" // Will be included, but handled differently. }; /** diff --git a/core/src/main/java/bisq/core/api/model/PaymentAccountTypeAdapter.java b/core/src/main/java/bisq/core/api/model/PaymentAccountTypeAdapter.java index 219c3db04c9..00b0654145f 100644 --- a/core/src/main/java/bisq/core/api/model/PaymentAccountTypeAdapter.java +++ b/core/src/main/java/bisq/core/api/model/PaymentAccountTypeAdapter.java @@ -53,10 +53,8 @@ import static bisq.common.util.ReflectionUtils.*; import static bisq.common.util.Utilities.decodeFromHex; import static bisq.core.locale.CountryUtil.findCountryByCode; -import static bisq.core.locale.CurrencyUtil.getAllTransferwiseCurrencies; -import static bisq.core.locale.CurrencyUtil.getCurrencyByCountryCode; -import static bisq.core.locale.CurrencyUtil.getTradeCurrencies; -import static bisq.core.locale.CurrencyUtil.getTradeCurrenciesInList; +import static bisq.core.locale.CurrencyUtil.*; +import static bisq.core.payment.payload.PaymentMethod.*; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; import static java.util.Arrays.stream; @@ -110,13 +108,7 @@ public void write(JsonWriter out, PaymentAccount account) throws IOException { // We're not serializing a real payment account instance here. out.beginObject(); - // All json forms start with immutable _COMMENTS_ and paymentMethodId fields. - out.name("_COMMENTS_"); - out.beginArray(); - for (String s : JSON_COMMENTS) { - out.value(s); - } - out.endArray(); + writeComments(out, account); out.name("paymentMethodId"); out.value(account.getPaymentMethod().getId()); @@ -131,9 +123,32 @@ public void write(JsonWriter out, PaymentAccount account) throws IOException { out.endObject(); } + private void writeComments(JsonWriter out, PaymentAccount account) throws IOException { + // All json forms start with immutable _COMMENTS_ and paymentMethodId fields. + out.name("_COMMENTS_"); + out.beginArray(); + for (String s : JSON_COMMENTS) { + out.value(s); + } + /* + if (account.isSwiftAccount()) { + // Add extra comments for more complex swift account form. + List wrappedSwiftComments = Res.getWrappedAsList("payment.swift.info", 110); + for (String line : wrappedSwiftComments) { + out.value(line); + } + out.value("See https://bisq.wiki/SWIFT"); + } + */ + out.endArray(); + } + + private void writeInnerMutableFields(JsonWriter out, PaymentAccount account) { - if (account.isTransferwiseAccount()) + if (account.hasMultipleCurrencies()) { writeTradeCurrenciesField(out, account); + writeSelectedTradeCurrencyField(out, account); + } fieldSettersMap.forEach((field, value) -> { try { @@ -170,7 +185,7 @@ private void writeTradeCurrenciesField(JsonWriter out, PaymentAccount account) { String fieldName = "tradeCurrencies"; log.debug("Append form with non-settable field: {}", fieldName); out.name(fieldName); - out.value("comma delimited currency code list, e.g., gbp,eur"); + out.value("comma delimited currency code list, e.g., gbp,eur,jpy,usd"); } catch (Exception ex) { String errMsg = format("cannot create a new %s json form", account.getClass().getSimpleName()); @@ -179,6 +194,22 @@ private void writeTradeCurrenciesField(JsonWriter out, PaymentAccount account) { } } + // PaymentAccounts that support multiple 'tradeCurrencies' need to define a + // 'selectedTradeCurrency' field (not simply defaulting to first in list). + // Write this field to the form. + private void writeSelectedTradeCurrencyField(JsonWriter out, PaymentAccount account) { + try { + String fieldName = "selectedTradeCurrency"; + log.debug("Append form with settable field: {}", fieldName); + out.name(fieldName); + out.value("primary trading currency code, e.g., eur"); + } catch (Exception ex) { + String errMsg = format("cannot create a new %s json form", + account.getClass().getSimpleName()); + log.error(StringUtils.capitalize(errMsg) + ".", ex); + throw new IllegalStateException("programmer error: " + errMsg); + } + } @Override public PaymentAccount read(JsonReader in) throws IOException { @@ -187,12 +218,17 @@ public PaymentAccount read(JsonReader in) throws IOException { while (in.hasNext()) { String currentFieldName = in.nextName(); - // The tradeCurrency field is common to all payment account types, + // The tradeCurrencies field is common to all payment account types, // but has no setter. if (didReadTradeCurrenciesField(in, account, currentFieldName)) continue; - // Some of the fields are common to all payment account types. + // The selectedTradeCurrency field is common to all payment account types, + // but is @Nullable, and may not need to be explicitly defined by user. + if (didReadSelectedTradeCurrencyField(in, account, currentFieldName)) + continue; + + // Some fields are common to all payment account types. if (didReadCommonField(in, account, currentFieldName)) continue; @@ -317,37 +353,76 @@ else if (s != null && !s.isEmpty()) private boolean didReadTradeCurrenciesField(JsonReader in, PaymentAccount account, String fieldName) { + if (!fieldName.equals("tradeCurrencies")) + return false; + // The PaymentAccount.tradeCurrencies field is a special case because it has - // no setter, and we add currencies to the List here. Normally, it is an - // excluded field, TransferwiseAccount excepted. - if (fieldName.equals("tradeCurrencies")) { - String fieldValue = nextStringOrNull(in); - List currencyCodes = commaDelimitedCodesToList.apply(fieldValue); - - Optional> tradeCurrencies; - if (account.isTransferwiseAccount()) - tradeCurrencies = getTradeCurrenciesInList(currencyCodes, getAllTransferwiseCurrencies()); - else - tradeCurrencies = getTradeCurrencies(currencyCodes); - - if (tradeCurrencies.isPresent()) { - for (TradeCurrency tradeCurrency : tradeCurrencies.get()) { - account.addCurrency(tradeCurrency); - } - // For api users, define a selected currency. - account.setSelectedTradeCurrency(account.getTradeCurrency().orElse(null)); + // no setter, so we add currencies to the List here if the payment account + // supports multiple trade currencies. + String fieldValue = nextStringOrNull(in); + List currencyCodes = commaDelimitedCodesToList.apply(fieldValue); + Optional> tradeCurrencies = getReconciledTradeCurrencies(currencyCodes, account); + if (tradeCurrencies.isPresent()) { + for (TradeCurrency tradeCurrency : tradeCurrencies.get()) { + account.addCurrency(tradeCurrency); + } + } else { + // Log a warning. We should not throw an exception here because the + // gson library will not pass it up to the calling Bisq object exactly as + // it would be defined here (causing confusion). Do a check in a calling + // class to make sure the tradeCurrencies field is populated in the + // PaymentAccount object, if it is required for the payment account method. + log.warn("No trade currencies were found in the {} account form.", + account.getPaymentMethod().getDisplayString()); + } + return true; + } + + private Optional> getReconciledTradeCurrencies(List currencyCodes, + PaymentAccount account) { + if (account.hasPaymentMethodWithId(ADVANCED_CASH_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllAdvancedCashCurrencies()); + else if (account.hasPaymentMethodWithId(AMAZON_GIFT_CARD_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllAmazonGiftCardCurrencies()); + else if (account.hasPaymentMethodWithId(CAPITUAL_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllCapitualCurrencies()); + else if (account.hasPaymentMethodWithId(MONEY_GRAM_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllMoneyGramCurrencies()); + else if (account.hasPaymentMethodWithId(PAXUM_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllPaxumCurrencies()); + else if (account.hasPaymentMethodWithId(PAYSERA_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllPayseraCurrencies()); + else if (account.hasPaymentMethodWithId(REVOLUT_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllRevolutCurrencies()); + /*else if (account.hasPaymentMethodWithId(SWIFT_ID)) + return getTradeCurrenciesInList(currencyCodes, new ArrayList<>(getAllSortedFiatCurrencies()));*/ + else if (account.hasPaymentMethodWithId(TRANSFERWISE_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllTransferwiseCurrencies()); + else if (account.hasPaymentMethodWithId(UPHOLD_ID)) + return getTradeCurrenciesInList(currencyCodes, getAllUpholdCurrencies()); + else + return Optional.empty(); + } + + private boolean didReadSelectedTradeCurrencyField(JsonReader in, + PaymentAccount account, + String fieldName) { + if (!fieldName.equals("selectedTradeCurrency")) + return false; + + String fieldValue = nextStringOrNull(in); + if (fieldValue != null && !fieldValue.isEmpty()) { + Optional tradeCurrency = getTradeCurrency(fieldValue.toUpperCase()); + if (tradeCurrency.isPresent()) { + account.setSelectedTradeCurrency(tradeCurrency.get()); } else { - // Log a warning. We should not throw an exception here because the - // gson library will not pass it up to the calling Bisq class as it - // would be defined here. Do a check in a calling class to make sure - // the tradeCurrencies field is populated in the PaymentAccount - // object, if it is required for the payment account method. - log.warn("No trade currencies were found in the {} account form.", - account.getPaymentMethod().getDisplayString()); + // Log an error. We should not throw an exception here because the + // gson library will not pass it up to the calling Bisq object exactly as + // it would be defined here (causing confusion). + log.error("{} is not a valid trade currency code.", fieldValue); } - return true; } - return false; + return true; } private boolean didReadCommonField(JsonReader in, @@ -356,8 +431,8 @@ private boolean didReadCommonField(JsonReader in, switch (fieldName) { case "_COMMENTS_": case "paymentMethodId": - // Skip over the the comments and paymentMethodId, which is already - // set on the PaymentAccount instance. + // Skip over comments and paymentMethodId field, which + // are already set on the PaymentAccount instance. in.skipValue(); return true; case "accountName": @@ -388,7 +463,7 @@ private boolean didReadCountryField(JsonReader in, PaymentAccount account, Strin ((CountryBasedPaymentAccount) account).setCountry(country.get()); FiatCurrency fiatCurrency = getCurrencyByCountryCode(checkNotNull(countryCode)); account.setSingleTradeCurrency(fiatCurrency); - } else if (account.isMoneyGramAccount()) { + } else if (account.hasPaymentMethodWithId(MONEY_GRAM_ID)) { ((MoneyGramAccount) account).setCountry(country.get()); } else { String errMsg = format("cannot set the country on a %s", diff --git a/core/src/main/java/bisq/core/locale/Res.java b/core/src/main/java/bisq/core/locale/Res.java index fcf9141c918..cec006aff0d 100644 --- a/core/src/main/java/bisq/core/locale/Res.java +++ b/core/src/main/java/bisq/core/locale/Res.java @@ -33,6 +33,8 @@ import java.io.InputStream; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.PropertyResourceBundle; @@ -42,6 +44,9 @@ import org.jetbrains.annotations.NotNull; +import static bisq.common.util.Utilities.toListOfWrappedStrings; +import static java.nio.charset.StandardCharsets.UTF_8; + @Slf4j public class Res { public static void setup() { @@ -125,13 +130,30 @@ public static String get(String key) { return key; } } + + public static List getWrappedAsList(String key, int wrapLength) { + String[] raw = get(key).split("\n"); + List wrapped = new ArrayList<>(); + for (String s : raw) { + List list = toListOfWrappedStrings(s, wrapLength); + for (String line : list) { + if (!line.isEmpty()) + wrapped.add(line); + } + } + return wrapped; + } } // Adds UTF8 support for property files class UTF8Control extends ResourceBundle.Control { - public ResourceBundle newBundle(String baseName, @NotNull Locale locale, @NotNull String format, ClassLoader loader, boolean reload) - throws IllegalAccessException, InstantiationException, IOException { + public ResourceBundle newBundle(String baseName, + @NotNull Locale locale, + @NotNull String format, + ClassLoader loader, + boolean reload) + throws IOException { // Below is a copy of the default implementation. final String bundleName = toBundleName(baseName, locale); final String resourceName = toResourceName(bundleName, "properties"); @@ -152,7 +174,7 @@ public ResourceBundle newBundle(String baseName, @NotNull Locale locale, @NotNul if (stream != null) { try { // Only this line is changed to make it read properties files as UTF-8. - bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); + bundle = new PropertyResourceBundle(new InputStreamReader(stream, UTF_8)); } finally { stream.close(); } diff --git a/core/src/main/java/bisq/core/offer/CreateOfferService.java b/core/src/main/java/bisq/core/offer/CreateOfferService.java index 733eee1a7f9..9f5f61dd68b 100644 --- a/core/src/main/java/bisq/core/offer/CreateOfferService.java +++ b/core/src/main/java/bisq/core/offer/CreateOfferService.java @@ -54,6 +54,8 @@ import lombok.extern.slf4j.Slf4j; +import static bisq.core.payment.payload.PaymentMethod.HAL_CASH_ID; + @Slf4j @Singleton public class CreateOfferService { @@ -133,7 +135,7 @@ public Offer createAndGetOffer(String offerId, NodeAddress makerAddress = p2PService.getAddress(); boolean useMarketBasedPriceValue = useMarketBasedPrice && isMarketPriceAvailable(currencyCode) && - !paymentAccount.isHalCashAccount(); + !paymentAccount.hasPaymentMethodWithId(HAL_CASH_ID); long priceAsLong = price != null && !useMarketBasedPriceValue ? price.getValue() : 0L; double marketPriceMarginParam = useMarketBasedPriceValue ? marketPriceMargin : 0; diff --git a/core/src/main/java/bisq/core/payment/PaymentAccount.java b/core/src/main/java/bisq/core/payment/PaymentAccount.java index caafed4611f..686dc7d972f 100644 --- a/core/src/main/java/bisq/core/payment/PaymentAccount.java +++ b/core/src/main/java/bisq/core/payment/PaymentAccount.java @@ -41,6 +41,8 @@ import javax.annotation.Nullable; +import static bisq.core.payment.payload.PaymentMethod.TRANSFERWISE_ID; +import static bisq.core.payment.payload.PaymentMethod.getPaymentMethodById; import static com.google.common.base.Preconditions.checkNotNull; @EqualsAndHashCode @@ -104,14 +106,14 @@ public static PaymentAccount fromProto(protobuf.PaymentAccount proto, CoreProtoR // We need to remove NGN for Transferwise Optional ngnTwOptional = tradeCurrencies.stream() - .filter(e -> paymentMethodId.equals(PaymentMethod.TRANSFERWISE_ID)) + .filter(e -> paymentMethodId.equals(TRANSFERWISE_ID)) .filter(e -> e.getCode().equals("NGN")) .findAny(); // We cannot remove it in the stream as it would cause a concurrentModificationException ngnTwOptional.ifPresent(tradeCurrencies::remove); try { - PaymentAccount account = PaymentAccountFactory.getPaymentAccount(PaymentMethod.getPaymentMethodById(paymentMethodId)); + PaymentAccount account = PaymentAccountFactory.getPaymentAccount(getPaymentMethodById(paymentMethodId)); account.getTradeCurrencies().clear(); account.setId(proto.getId()); account.setCreationDate(proto.getCreationDate()); @@ -195,23 +197,15 @@ public boolean isCountryBasedPaymentAccount() { return this instanceof CountryBasedPaymentAccount; } - public boolean isHalCashAccount() { - return this instanceof HalCashAccount; - } - - public boolean isMoneyGramAccount() { - return this instanceof MoneyGramAccount; - } - - public boolean isTransferwiseAccount() { - return this instanceof TransferwiseAccount; + public boolean hasPaymentMethodWithId(String paymentMethodId) { + return this.getPaymentMethod().getId().equals(paymentMethodId); } /** * Return an Optional of the trade currency for this payment account, or * Optional.empty() if none is found. If this payment account has a selected * trade currency, that is returned, else its single trade currency is returned, - * else the first trade currency in the this payment account's tradeCurrencies + * else the first trade currency in this payment account's tradeCurrencies * list is returned. * * @return Optional of the trade currency for the given payment account diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java index b96376d10af..3f2a733168b 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java @@ -92,6 +92,7 @@ import javax.annotation.Nullable; +import static bisq.core.payment.payload.PaymentMethod.HAL_CASH_ID; import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Comparator.comparing; @@ -565,7 +566,7 @@ private Volume calculateVolumeForAmount(ObjectProperty minAmount) { Volume volumeByAmount = price.get().getVolumeByAmount(minAmount.get()); // For HalCash we want multiple of 10 EUR - if (paymentAccount.isHalCashAccount()) + if (isUsingHalCashAccount()) volumeByAmount = VolumeUtil.getAdjustedVolumeForHalCash(volumeByAmount); else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) volumeByAmount = VolumeUtil.getRoundedFiatVolume(volumeByAmount); @@ -576,7 +577,7 @@ void calculateAmount() { if (isNonZeroPrice.test(price) && isNonZeroVolume.test(volume) && allowAmountUpdate) { try { Coin value = DisplayUtils.reduceTo4Decimals(price.get().getAmountByVolume(volume.get()), btcFormatter); - if (paymentAccount.isHalCashAccount()) + if (isUsingHalCashAccount()) value = CoinUtil.getAdjustedAmountForHalCash(value, price.get(), getMaxTradeLimit()); else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) value = CoinUtil.getRoundedFiatAmount(value, price.get(), getMaxTradeLimit()); @@ -647,10 +648,6 @@ protected void setBuyerSecurityDeposit(double value) { this.buyerSecurityDeposit.set(value); } - protected boolean isUseMarketBasedPriceValue() { - return marketPriceAvailable && useMarketBasedPrice.get() && !paymentAccount.isHalCashAccount(); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Getters /////////////////////////////////////////////////////////////////////////////////////////// @@ -782,4 +779,8 @@ public boolean isMinBuyerSecurityDeposit() { public void setTriggerPrice(long triggerPrice) { this.triggerPrice = triggerPrice; } + + public boolean isUsingHalCashAccount() { + return paymentAccount.hasPaymentMethodWithId(HAL_CASH_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 3794dc1b63f..0835919d7c9 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java @@ -117,6 +117,7 @@ import org.jetbrains.annotations.NotNull; +import static bisq.core.payment.payload.PaymentMethod.HAL_CASH_ID; import static bisq.desktop.util.FormBuilder.*; import static javafx.beans.binding.Bindings.createStringBinding; @@ -345,7 +346,7 @@ private void onPlaceOffer() { Offer offer = model.createAndGetOffer(); if (!DevEnv.isDevMode()) { offerDetailsWindow.onPlaceOffer(() -> - model.onPlaceOffer(offer, offerDetailsWindow::hide)) + model.onPlaceOffer(offer, offerDetailsWindow::hide)) .show(offer); } else { balanceSubscription.unsubscribe(); @@ -881,7 +882,7 @@ protected void updatePriceToggle() { int marketPriceAvailableValue = model.marketPriceAvailableProperty.get(); if (marketPriceAvailableValue > -1) { boolean showPriceToggle = marketPriceAvailableValue == 1 && - !model.getDataModel().paymentAccount.isHalCashAccount(); + !model.getDataModel().paymentAccount.hasPaymentMethodWithId(HAL_CASH_ID); percentagePriceBox.setVisible(showPriceToggle); priceTypeToggleButton.setVisible(showPriceToggle); boolean fixedPriceSelected = !model.getDataModel().getUseMarketBasedPrice().get() || !showPriceToggle; diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java index 13912e055c9..952197daea1 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java @@ -122,7 +122,7 @@ public abstract class MutableOfferViewModel ext final StringProperty buyerSecurityDepositInBTC = new SimpleStringProperty(); final StringProperty buyerSecurityDepositLabel = new SimpleStringProperty(); - // Price in the viewModel is always dependent on fiat/altcoin: Fiat Fiat/BTC, for altcoins we use inverted price. + // Price in the viewModel is always dependent on fiat/altcoin: Fiat/BTC, for altcoins we use inverted price. // The domain (dataModel) uses always the same price model (otherCurrencyBTC) // If we would change the price representation in the domain we would not be backward compatible public final StringProperty price = new SimpleStringProperty(); @@ -364,7 +364,7 @@ private void createListeners() { double percentage = ParsingUtils.parsePercentStringToDouble(newValue); if (percentage >= 1 || percentage <= -1) { new Popup().warning(Res.get("popup.warning.tooLargePercentageValue") + "\n" + - Res.get("popup.warning.examplePercentageValue")) + Res.get("popup.warning.examplePercentageValue")) .show(); } else { final String currencyCode = dataModel.getTradeCurrencyCode().get(); @@ -492,11 +492,7 @@ private void createListeners() { } }; - isWalletFundedListener = (ov, oldValue, newValue) -> updateButtonDisableState(); - /* feeFromFundingTxListener = (ov, oldValue, newValue) -> { - updateButtonDisableState(); - };*/ currenciesUpdateListener = (observable, oldValue, newValue) -> { updateMarketPriceAvailable(); @@ -691,8 +687,8 @@ boolean fundFromSavingsWallet() { return true; } else { new Popup().warning(Res.get("shared.notEnoughFunds", - btcFormatter.formatCoinWithCode(dataModel.totalToPayAsCoinProperty().get()), - btcFormatter.formatCoinWithCode(dataModel.getTotalAvailableBalance()))) + btcFormatter.formatCoinWithCode(dataModel.totalToPayAsCoinProperty().get()), + btcFormatter.formatCoinWithCode(dataModel.getTotalAvailableBalance()))) .actionButtonTextWithGoTo("navigation.funds.depositFunds") .onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, DepositView.class)) .show(); @@ -732,8 +728,8 @@ void onFocusOutAmountTextField(boolean oldValue, boolean newValue) { } else if (amount.get() != null && btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().value == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) { amount.set(btcFormatter.formatCoin(btcValidator.getMaxTradeLimit())); new Popup().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.buyer", - btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT), - Res.get("offerbook.warning.newVersionAnnouncement"))) + btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT), + Res.get("offerbook.warning.newVersionAnnouncement"))) .width(900) .show(); } @@ -882,7 +878,7 @@ void onFocusOutVolumeTextField(boolean oldValue, boolean newValue) { Volume volume = dataModel.getVolume().get(); if (volume != null) { // For HalCash we want multiple of 10 EUR - if (dataModel.paymentAccount.isHalCashAccount()) + if (dataModel.isUsingHalCashAccount()) volume = VolumeUtil.getAdjustedVolumeForHalCash(volume); else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) volume = VolumeUtil.getRoundedFiatVolume(volume); @@ -974,7 +970,7 @@ public boolean isPriceInRange() { private void displayPriceOutOfRangePopup() { Popup popup = new Popup(); popup.warning(Res.get("createOffer.priceOutSideOfDeviation", - FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent()))) + FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent()))) .actionButtonText(Res.get("createOffer.changePrice")) .onAction(popup::hide) .closeButtonTextWithGoTo("navigation.settings.preferences") @@ -1161,7 +1157,7 @@ private void setAmountToModel() { long maxTradeLimit = dataModel.getMaxTradeLimit(); Price price = dataModel.getPrice().get(); if (price != null) { - if (dataModel.paymentAccount.isHalCashAccount()) + if (dataModel.isUsingHalCashAccount()) amount = CoinUtil.getAdjustedAmountForHalCash(amount, price, maxTradeLimit); else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) amount = CoinUtil.getRoundedFiatAmount(amount, price, maxTradeLimit); @@ -1185,7 +1181,7 @@ private void setMinAmountToModel() { Price price = dataModel.getPrice().get(); long maxTradeLimit = dataModel.getMaxTradeLimit(); if (price != null) { - if (dataModel.paymentAccount.isHalCashAccount()) + if (dataModel.isUsingHalCashAccount()) minAmount = CoinUtil.getAdjustedAmountForHalCash(minAmount, price, maxTradeLimit); else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) minAmount = CoinUtil.getRoundedFiatAmount(minAmount, price, maxTradeLimit); @@ -1281,11 +1277,6 @@ private void updateSpinnerInfo() { waitingForFundsText.set(""); } else if (dataModel.getIsBtcWalletFunded().get()) { waitingForFundsText.set(""); - /* if (dataModel.isFeeFromFundingTxSufficient.get()) { - spinnerInfoText.set(""); - } else { - spinnerInfoText.set("Check if funding tx miner fee is sufficient..."); - }*/ } else { waitingForFundsText.set(Res.get("shared.waitingForFunds")); } @@ -1325,8 +1316,6 @@ void updateButtonDisableState() { } isNextButtonDisabled.set(!inputDataValid); - // boolean notSufficientFees = dataModel.isWalletFunded.get() && dataModel.isMainNet.get() && !dataModel.isFeeFromFundingTxSufficient.get(); - //isPlaceOfferButtonDisabled.set(createOfferRequested || !inputDataValid || notSufficientFees); isPlaceOfferButtonDisabled.set(createOfferRequested || !inputDataValid || !dataModel.getIsBtcWalletFunded().get()); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 00309dc6f8a..b9d2fdd0e12 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -77,6 +77,7 @@ import javax.annotation.Nullable; +import static bisq.core.payment.payload.PaymentMethod.HAL_CASH_ID; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -678,8 +679,8 @@ public Coin getUsableBsqBalance() { return usableBsqBalance; } - public boolean isHalCashAccount() { - return paymentAccount.isHalCashAccount(); + public boolean isUsingHalCashAccount() { + return paymentAccount.hasPaymentMethodWithId(HAL_CASH_ID); } public boolean isCurrencyForTakerFeeBtc() { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java index 2e20113243f..6c13c24c236 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java @@ -263,8 +263,8 @@ boolean fundFromSavingsWallet() { return true; } else { new Popup().warning(Res.get("shared.notEnoughFunds", - btcFormatter.formatCoinWithCode(dataModel.getTotalToPayAsCoin().get()), - btcFormatter.formatCoinWithCode(dataModel.getTotalAvailableBalance()))) + btcFormatter.formatCoinWithCode(dataModel.getTotalToPayAsCoin().get()), + btcFormatter.formatCoinWithCode(dataModel.getTotalAvailableBalance()))) .actionButtonTextWithGoTo("navigation.funds.depositFunds") .onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, DepositView.class)) .show(); @@ -349,14 +349,14 @@ void onFocusOutAmountTextField(boolean oldValue, boolean newValue, String userIn } else if (btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().value == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) { if (dataModel.getDirection() == OfferPayload.Direction.BUY) { new Popup().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.seller", - btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT), - Res.get("offerbook.warning.newVersionAnnouncement"))) + btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT), + Res.get("offerbook.warning.newVersionAnnouncement"))) .width(900) .show(); } else { new Popup().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.buyer", - btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT), - Res.get("offerbook.warning.newVersionAnnouncement"))) + btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT), + Res.get("offerbook.warning.newVersionAnnouncement"))) .width(900) .show(); } @@ -611,7 +611,7 @@ private void setAmountToModel() { long maxTradeLimit = dataModel.getMaxTradeLimit(); Price price = dataModel.tradePrice; if (price != null) { - if (dataModel.isHalCashAccount()) { + if (dataModel.isUsingHalCashAccount()) { amount = CoinUtil.getAdjustedAmountForHalCash(amount, price, maxTradeLimit); } else if (CurrencyUtil.isFiatCurrency(dataModel.getCurrencyCode()) && !isAmountEqualMinAmount(amount) && !isAmountEqualMaxAmount(amount)) {