mirror of
https://github.com/bisq-network/bisq.git
synced 2025-03-04 03:03:48 +01:00
Merge pull request #5284 from ghubstan/07-validate-paymentacct-n-new-offer
Validate offer <-> payment-acct in createoffer
This commit is contained in:
commit
463f87b39e
40 changed files with 674 additions and 226 deletions
|
@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
|
||||
import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAsPercent;
|
||||
import static java.lang.String.format;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
@ -55,4 +56,40 @@ public class ValidateCreateOfferTest extends AbstractOfferTest {
|
|||
assertEquals("UNKNOWN: An error occurred at task: ValidateOffer",
|
||||
exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void testNoMatchingEURPaymentAccountShouldThrowException() {
|
||||
PaymentAccount chfAccount = createDummyF2FAccount(aliceClient, "ch");
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
|
||||
aliceClient.createFixedPricedOffer("buy",
|
||||
"eur",
|
||||
10000000L,
|
||||
10000000L,
|
||||
"40000.0000",
|
||||
getDefaultBuyerSecurityDepositAsPercent(),
|
||||
chfAccount.getId(),
|
||||
"btc"));
|
||||
String expectedError = format("UNKNOWN: cannot create EUR offer with payment account %s", chfAccount.getId());
|
||||
assertEquals(expectedError, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void testNoMatchingCADPaymentAccountShouldThrowException() {
|
||||
PaymentAccount audAccount = createDummyF2FAccount(aliceClient, "au");
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
|
||||
aliceClient.createFixedPricedOffer("buy",
|
||||
"cad",
|
||||
10000000L,
|
||||
10000000L,
|
||||
"63000.0000",
|
||||
getDefaultBuyerSecurityDepositAsPercent(),
|
||||
audAccount.getId(),
|
||||
"btc"));
|
||||
String expectedError = format("UNKNOWN: cannot create CAD offer with payment account %s", audAccount.getId());
|
||||
assertEquals(expectedError, exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ public class AbstractPaymentAccountTest extends MethodTest {
|
|||
static final String PROPERTY_NAME_SALT = "salt";
|
||||
static final String PROPERTY_NAME_SORT_CODE = "sortCode";
|
||||
static final String PROPERTY_NAME_STATE = "state";
|
||||
static final String PROPERTY_NAME_TRADE_CURRENCIES = "tradeCurrencies";
|
||||
static final String PROPERTY_NAME_USERNAME = "userName";
|
||||
|
||||
static final Gson GSON = new GsonBuilder()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package bisq.apitest.method.payment;
|
||||
|
||||
import bisq.core.locale.TradeCurrency;
|
||||
import bisq.core.payment.AdvancedCashAccount;
|
||||
import bisq.core.payment.AliPayAccount;
|
||||
import bisq.core.payment.AustraliaPayid;
|
||||
|
@ -31,6 +32,7 @@ import bisq.core.payment.JapanBankAccount;
|
|||
import bisq.core.payment.MoneyBeamAccount;
|
||||
import bisq.core.payment.MoneyGramAccount;
|
||||
import bisq.core.payment.NationalBankAccount;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
import bisq.core.payment.PerfectMoneyAccount;
|
||||
import bisq.core.payment.PopmoneyAccount;
|
||||
import bisq.core.payment.PromptPayAccount;
|
||||
|
@ -50,8 +52,12 @@ import bisq.core.payment.payload.CashDepositAccountPayload;
|
|||
import bisq.core.payment.payload.SameBankAccountPayload;
|
||||
import bisq.core.payment.payload.SpecificBanksAccountPayload;
|
||||
|
||||
import io.grpc.StatusRuntimeException;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -65,15 +71,16 @@ import org.junit.jupiter.api.TestMethodOrder;
|
|||
|
||||
import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
|
||||
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
|
||||
import static bisq.core.locale.CurrencyUtil.getAllAdvancedCashCurrencies;
|
||||
import static bisq.core.locale.CurrencyUtil.getAllMoneyGramCurrencies;
|
||||
import static bisq.core.locale.CurrencyUtil.getAllRevolutCurrencies;
|
||||
import static bisq.core.locale.CurrencyUtil.getAllUpholdCurrencies;
|
||||
import static bisq.cli.TableFormat.formatPaymentAcctTbl;
|
||||
import static bisq.core.locale.CurrencyUtil.*;
|
||||
import static bisq.core.payment.payload.PaymentMethod.*;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||
|
||||
@SuppressWarnings({"OptionalGetWithoutIsPresent", "ConstantConditions"})
|
||||
@Disabled
|
||||
@Slf4j
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
|
@ -105,7 +112,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -124,7 +131,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyAccountSingleTradeCurrency("CNY", paymentAccount);
|
||||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -146,7 +153,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_PAY_ID), paymentAccount.getPayid());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_ACCOUNT_NAME), paymentAccount.getBankAccountName());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -198,7 +205,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_TAX_ID), payload.getHolderTaxId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_NATIONAL_ACCOUNT_ID), payload.getNationalAccountId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_REQUIREMENTS), payload.getRequirements());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -243,7 +250,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_TAX_ID), payload.getHolderTaxId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_NATIONAL_ACCOUNT_ID), payload.getNationalAccountId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -265,7 +272,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), paymentAccount.getHolderName());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -288,7 +295,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL_OR_MOBILE_NR), paymentAccount.getEmailOrMobileNr());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), paymentAccount.getHolderName());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -317,7 +324,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_CITY), paymentAccount.getCity());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_CONTACT), paymentAccount.getContact());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EXTRA_INFO), paymentAccount.getExtraInfo());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -340,7 +347,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SORT_CODE), paymentAccount.getSortCode());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -359,7 +366,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyAccountSingleTradeCurrency("EUR", paymentAccount);
|
||||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_MOBILE_NR), paymentAccount.getMobileNr());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -388,7 +395,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_QUESTION), paymentAccount.getQuestion());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ANSWER), paymentAccount.getAnswer());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -425,7 +432,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_ACCOUNT_NAME), paymentAccount.getBankAccountName());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_ACCOUNT_TYPE), paymentAccount.getBankAccountType());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BANK_ACCOUNT_NUMBER), paymentAccount.getBankAccountNumber());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -445,7 +452,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_ID), paymentAccount.getAccountId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -474,7 +481,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_COUNTRY),
|
||||
Objects.requireNonNull(paymentAccount.getCountry()).code);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_STATE), paymentAccount.getState());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -494,7 +501,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -516,7 +523,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_ID), paymentAccount.getAccountId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), paymentAccount.getHolderName());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -536,7 +543,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_PROMPT_PAY_ID), paymentAccount.getPromptPayId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -555,7 +562,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyAccountTradeCurrencies(getAllRevolutCurrencies(), paymentAccount);
|
||||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_USERNAME), paymentAccount.getUserName());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -600,7 +607,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_TAX_ID), payload.getHolderTaxId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_NATIONAL_ACCOUNT_ID), payload.getNationalAccountId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -631,7 +638,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BIC), paymentAccount.getBic());
|
||||
// bankId == bic
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BIC), paymentAccount.getBankId());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -663,7 +670,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
// bankId == bic
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_BIC), paymentAccount.getBankId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -710,7 +717,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), payload.getHolderName());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_TAX_ID), payload.getHolderTaxId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_NATIONAL_ACCOUNT_ID), payload.getNationalAccountId());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -733,29 +740,104 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_MOBILE_NR), paymentAccount.getMobileNr());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), paymentAccount.getHolderName());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTransferwiseAccount(TestInfo testInfo) {
|
||||
public void testCreateTransferwiseAccountWith1TradeCurrency(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_EMAIL, "jan@doe.info");
|
||||
COMPLETED_FORM_MAP.put(PROPERTY_NAME_TRADE_CURRENCIES, "eur");
|
||||
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());
|
||||
// As per commit 88f26f93241af698ae689bf081205d0f9dc929fa
|
||||
// Do not autofill all currencies by default but keep all unselected.
|
||||
// verifyAccountTradeCurrencies(getAllTransferwiseCurrencies(), paymentAccount);
|
||||
assertEquals(0, paymentAccount.getTradeCurrencies().size());
|
||||
assertEquals(1, paymentAccount.getTradeCurrencies().size());
|
||||
TradeCurrency expectedCurrency = getTradeCurrency("EUR").get();
|
||||
assertEquals(expectedCurrency, paymentAccount.getSelectedTradeCurrency());
|
||||
List<TradeCurrency> expectedTradeCurrencies = singletonList(expectedCurrency);
|
||||
verifyAccountTradeCurrencies(expectedTradeCurrencies, paymentAccount);
|
||||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTransferwiseAccountWith10TradeCurrencies(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, "ars, cad, hrk, czk, eur, hkd, idr, jpy, chf, 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(10, paymentAccount.getTradeCurrencies().size());
|
||||
List<TradeCurrency> expectedTradeCurrencies = new ArrayList<>() {{
|
||||
add(getTradeCurrency("ARS").get()); // 1st in list = selected ccy
|
||||
add(getTradeCurrency("CAD").get());
|
||||
add(getTradeCurrency("HRK").get());
|
||||
add(getTradeCurrency("CZK").get());
|
||||
add(getTradeCurrency("EUR").get());
|
||||
add(getTradeCurrency("HKD").get());
|
||||
add(getTradeCurrency("IDR").get());
|
||||
add(getTradeCurrency("JPY").get());
|
||||
add(getTradeCurrency("CHF").get());
|
||||
add(getTradeCurrency("NZD").get());
|
||||
}};
|
||||
verifyAccountTradeCurrencies(expectedTradeCurrencies, paymentAccount);
|
||||
TradeCurrency expectedSelectedCurrency = expectedTradeCurrencies.get(0);
|
||||
assertEquals(expectedSelectedCurrency, paymentAccount.getSelectedTradeCurrency());
|
||||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail());
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTransferwiseAccountWithInvalidBrlTradeCurrencyShouldThrowException(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, "eur, hkd, idr, jpy, chf, nzd, brl, gbp");
|
||||
COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.info");
|
||||
COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, "");
|
||||
String jsonString = getCompletedFormAsJsonString();
|
||||
|
||||
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
|
||||
createPaymentAccount(aliceClient, jsonString));
|
||||
assertEquals("INVALID_ARGUMENT: BRL is not a member of valid currencies list",
|
||||
exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTransferwiseAccountWithoutTradeCurrenciesShouldThrowException(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, "");
|
||||
COMPLETED_FORM_MAP.put(PROPERTY_NAME_EMAIL, "jane@doe.info");
|
||||
COMPLETED_FORM_MAP.put(PROPERTY_NAME_SALT, "");
|
||||
String jsonString = getCompletedFormAsJsonString();
|
||||
|
||||
Throwable exception = assertThrows(StatusRuntimeException.class, () ->
|
||||
createPaymentAccount(aliceClient, jsonString));
|
||||
assertEquals("INVALID_ARGUMENT: no trade currencies defined for transferwise payment account",
|
||||
exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -775,7 +857,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_ID), paymentAccount.getAccountId());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -797,7 +879,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_HOLDER_NAME), paymentAccount.getHolderName());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_POSTAL_ADDRESS), paymentAccount.getPostalAddress());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -817,7 +899,7 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
verifyCommonFormEntries(paymentAccount);
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_ACCOUNT_NR), paymentAccount.getAccountNr());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_SALT), paymentAccount.getSaltAsHex());
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -849,11 +931,18 @@ public class CreatePaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_EMAIL), paymentAccount.getEmail());
|
||||
assertEquals(COMPLETED_FORM_MAP.get(PROPERTY_NAME_COUNTRY),
|
||||
Objects.requireNonNull(paymentAccount.getCountry()).code);
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
print(paymentAccount);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void tearDown() {
|
||||
tearDownScaffold();
|
||||
}
|
||||
|
||||
private void print(PaymentAccount paymentAccount) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Deserialized {}: {}", paymentAccount.getClass().getSimpleName(), paymentAccount);
|
||||
log.debug("\n{}", formatPaymentAcctTbl(singletonList(paymentAccount.toProtoMessage())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ public class OfferTest extends AbstractOfferTest {
|
|||
public void testAmtTooLargeShouldThrowException() {
|
||||
ValidateCreateOfferTest test = new ValidateCreateOfferTest();
|
||||
test.testAmtTooLargeShouldThrowException();
|
||||
test.testNoMatchingEURPaymentAccountShouldThrowException();
|
||||
test.testNoMatchingCADPaymentAccountShouldThrowException();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -13,8 +13,6 @@ import org.junit.jupiter.api.TestMethodOrder;
|
|||
import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
|
||||
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
|
||||
import static bisq.apitest.config.BisqAppConfig.seednode;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
|
@ -27,10 +25,6 @@ import bisq.apitest.method.payment.GetPaymentMethodsTest;
|
|||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class PaymentAccountTest extends AbstractPaymentAccountTest {
|
||||
|
||||
// Two dummy (usd +eth) accounts are set up as defaults in regtest / dao mode,
|
||||
// then we add 28 more payment accounts in testCreatePaymentAccount().
|
||||
private static final int EXPECTED_NUM_PAYMENT_ACCOUNTS = 2 + 28;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() {
|
||||
try {
|
||||
|
@ -75,14 +69,18 @@ public class PaymentAccountTest extends AbstractPaymentAccountTest {
|
|||
test.testCreateSepaAccount(testInfo);
|
||||
test.testCreateSpecificBanksAccount(testInfo);
|
||||
test.testCreateSwishAccount(testInfo);
|
||||
test.testCreateTransferwiseAccount(testInfo);
|
||||
|
||||
// TransferwiseAccount is only PaymentAccount with a
|
||||
// tradeCurrencies field in the json form.
|
||||
test.testCreateTransferwiseAccountWith1TradeCurrency(testInfo);
|
||||
test.testCreateTransferwiseAccountWith10TradeCurrencies(testInfo);
|
||||
test.testCreateTransferwiseAccountWithInvalidBrlTradeCurrencyShouldThrowException(testInfo);
|
||||
test.testCreateTransferwiseAccountWithoutTradeCurrenciesShouldThrowException(testInfo);
|
||||
|
||||
test.testCreateUpholdAccount(testInfo);
|
||||
test.testCreateUSPostalMoneyOrderAccount(testInfo);
|
||||
test.testCreateWeChatPayAccount(testInfo);
|
||||
test.testCreateWesternUnionAccount(testInfo);
|
||||
|
||||
var paymentAccounts = requireNonNull(aliceClient).getPaymentAccounts();
|
||||
assertEquals(EXPECTED_NUM_PAYMENT_ACCOUNTS, paymentAccounts.size());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
|
|
11
build.gradle
11
build.gradle
|
@ -378,6 +378,17 @@ configure(project(':cli')) {
|
|||
implementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
|
||||
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
testRuntime "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ public class TableFormat {
|
|||
+ padEnd(COL_HEADER_PAYMENT_METHOD, paymentMethodColWidth, ' ') + COL_HEADER_DELIMITER
|
||||
+ COL_HEADER_UUID + COL_HEADER_DELIMITER + "\n";
|
||||
String colDataFormat = "%-" + nameColWidth + "s" // left justify
|
||||
+ " %" + COL_HEADER_CURRENCY.length() + "s" // right justify
|
||||
+ " %-" + COL_HEADER_CURRENCY.length() + "s" // left justify
|
||||
+ " %-" + paymentMethodColWidth + "s" // left justify
|
||||
+ " %-" + COL_HEADER_UUID.length() + "s"; // left justify
|
||||
return headerLine
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
|
||||
package bisq.cli.opts;
|
||||
|
||||
import joptsimple.OptionException;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import joptsimple.OptionSpec;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
|
@ -48,12 +50,29 @@ abstract class AbstractMethodOptionParser implements MethodOpts {
|
|||
}
|
||||
|
||||
public AbstractMethodOptionParser parse() {
|
||||
options = parser.parse(new ArgumentList(args).getMethodArguments());
|
||||
nonOptionArguments = (List<String>) options.nonOptionArguments();
|
||||
return this;
|
||||
try {
|
||||
options = parser.parse(new ArgumentList(args).getMethodArguments());
|
||||
//noinspection unchecked
|
||||
nonOptionArguments = (List<String>) options.nonOptionArguments();
|
||||
return this;
|
||||
} catch (OptionException ex) {
|
||||
throw new IllegalArgumentException(cliExceptionMessageStyle.apply(ex), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isForHelp() {
|
||||
return options.has(helpOpt);
|
||||
}
|
||||
|
||||
private final Function<OptionException, String> cliExceptionMessageStyle = (ex) -> {
|
||||
if (ex.getMessage() == null)
|
||||
return null;
|
||||
|
||||
var optionToken = "option ";
|
||||
var cliMessage = ex.getMessage().toLowerCase();
|
||||
if (cliMessage.startsWith(optionToken) && cliMessage.length() > optionToken.length()) {
|
||||
cliMessage = cliMessage.substring(cliMessage.indexOf(" ") + 1);
|
||||
}
|
||||
return cliMessage;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,13 +21,11 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_OFFER_ID;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class CancelOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to cancel")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public CancelOfferOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -40,7 +38,7 @@ public class CancelOfferOptionParser extends AbstractMethodOptionParser implemen
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(offerIdOpt))
|
||||
if (!options.has(offerIdOpt) || options.valueOf(offerIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no offer id specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -33,20 +33,16 @@ public class CreateOfferOptionParser extends AbstractMethodOptionParser implemen
|
|||
.defaultsTo(EMPTY);
|
||||
|
||||
final OptionSpec<String> directionOpt = parser.accepts(OPT_DIRECTION, "offer direction (buy|sell)")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> currencyCodeOpt = parser.accepts(OPT_CURRENCY_CODE, "currency code (eur|usd|...)")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> amountOpt = parser.accepts(OPT_AMOUNT, "amount of btc to buy or sell")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> minAmountOpt = parser.accepts(OPT_MIN_AMOUNT, "minimum amount of btc to buy or sell")
|
||||
.withOptionalArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withOptionalArg();
|
||||
|
||||
final OptionSpec<String> mktPriceMarginOpt = parser.accepts(OPT_MKT_PRICE_MARGIN, "market btc price margin (%)")
|
||||
.withOptionalArg()
|
||||
|
@ -54,11 +50,10 @@ public class CreateOfferOptionParser extends AbstractMethodOptionParser implemen
|
|||
|
||||
final OptionSpec<String> fixedPriceOpt = parser.accepts(OPT_FIXED_PRICE, "fixed btc price")
|
||||
.withOptionalArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.defaultsTo("0");
|
||||
|
||||
final OptionSpec<String> securityDepositOpt = parser.accepts(OPT_SECURITY_DEPOSIT, "maker security deposit (%)")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> makerFeeCurrencyCodeOpt = parser.accepts(OPT_FEE_CURRENCY, "maker fee currency code (bsq|btc)")
|
||||
.withOptionalArg()
|
||||
|
@ -75,19 +70,28 @@ public class CreateOfferOptionParser extends AbstractMethodOptionParser implemen
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(paymentAccountIdOpt))
|
||||
if (!options.has(paymentAccountIdOpt) || options.valueOf(paymentAccountIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no payment account id specified");
|
||||
|
||||
if (!options.has(directionOpt))
|
||||
if (!options.has(directionOpt) || options.valueOf(directionOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no direction (buy|sell) specified");
|
||||
|
||||
if (!options.has(amountOpt))
|
||||
if (!options.has(currencyCodeOpt) || options.valueOf(currencyCodeOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no currency code specified");
|
||||
|
||||
if (!options.has(amountOpt) || options.valueOf(amountOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no btc amount specified");
|
||||
|
||||
if (!options.has(mktPriceMarginOpt) && !options.has(fixedPriceOpt))
|
||||
throw new IllegalArgumentException("no market price margin or fixed price specified");
|
||||
|
||||
if (!options.has(securityDepositOpt))
|
||||
if (options.has(mktPriceMarginOpt) && options.valueOf(mktPriceMarginOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no market price margin specified");
|
||||
|
||||
if (options.has(fixedPriceOpt) && options.valueOf(fixedPriceOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no fixed price specified");
|
||||
|
||||
if (!options.has(securityDepositOpt) || options.valueOf(securityDepositOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no security deposit specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -25,14 +25,12 @@ import java.nio.file.Paths;
|
|||
|
||||
import static bisq.cli.opts.OptLabel.OPT_PAYMENT_ACCOUNT_FORM;
|
||||
import static java.lang.String.format;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class CreatePaymentAcctOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> paymentAcctFormPathOpt = parser.accepts(OPT_PAYMENT_ACCOUNT_FORM,
|
||||
"path to json payment account form")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public CreatePaymentAcctOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -45,7 +43,7 @@ public class CreatePaymentAcctOptionParser extends AbstractMethodOptionParser im
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(paymentAcctFormPathOpt))
|
||||
if (!options.has(paymentAcctFormPathOpt) || options.valueOf(paymentAcctFormPathOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no path to json payment account form specified");
|
||||
|
||||
Path path = Paths.get(options.valueOf(paymentAcctFormPathOpt));
|
||||
|
|
|
@ -21,13 +21,11 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_ADDRESS;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetAddressBalanceOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> addressOpt = parser.accepts(OPT_ADDRESS, "wallet btc address")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public GetAddressBalanceOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -40,7 +38,7 @@ public class GetAddressBalanceOptionParser extends AbstractMethodOptionParser im
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(addressOpt))
|
||||
if (!options.has(addressOpt) || options.valueOf(addressOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no address specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -21,13 +21,11 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_CURRENCY_CODE;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetBTCMarketPriceOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> currencyCodeOpt = parser.accepts(OPT_CURRENCY_CODE, "currency-code")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public GetBTCMarketPriceOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -40,7 +38,7 @@ public class GetBTCMarketPriceOptionParser extends AbstractMethodOptionParser im
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(currencyCodeOpt))
|
||||
if (!options.has(currencyCodeOpt) || options.valueOf(currencyCodeOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no currency code specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -21,13 +21,11 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_OFFER_ID;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to get")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public GetOfferOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -40,7 +38,7 @@ public class GetOfferOptionParser extends AbstractMethodOptionParser implements
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(offerIdOpt))
|
||||
if (!options.has(offerIdOpt) || options.valueOf(offerIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no offer id specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -22,17 +22,14 @@ import joptsimple.OptionSpec;
|
|||
|
||||
import static bisq.cli.opts.OptLabel.OPT_CURRENCY_CODE;
|
||||
import static bisq.cli.opts.OptLabel.OPT_DIRECTION;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetOffersOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> directionOpt = parser.accepts(OPT_DIRECTION, "offer direction (buy|sell)")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> currencyCodeOpt = parser.accepts(OPT_CURRENCY_CODE, "currency code (eur|usd|...)")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public GetOffersOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -45,10 +42,10 @@ public class GetOffersOptionParser extends AbstractMethodOptionParser implements
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(directionOpt))
|
||||
if (!options.has(directionOpt) || options.valueOf(directionOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no direction (buy|sell) specified");
|
||||
|
||||
if (!options.has(currencyCodeOpt))
|
||||
if (!options.has(currencyCodeOpt) || options.valueOf(currencyCodeOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no currency code specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -21,14 +21,12 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_PAYMENT_METHOD_ID;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetPaymentAcctFormOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> paymentMethodIdOpt = parser.accepts(OPT_PAYMENT_METHOD_ID,
|
||||
"id of payment method type used by a payment account")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public GetPaymentAcctFormOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -41,7 +39,7 @@ public class GetPaymentAcctFormOptionParser extends AbstractMethodOptionParser i
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(paymentMethodIdOpt))
|
||||
if (!options.has(paymentMethodIdOpt) || options.valueOf(paymentMethodIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no payment method id specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -22,13 +22,11 @@ import joptsimple.OptionSpec;
|
|||
|
||||
import static bisq.cli.opts.OptLabel.OPT_SHOW_CONTRACT;
|
||||
import static bisq.cli.opts.OptLabel.OPT_TRADE_ID;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetTradeOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> tradeIdOpt = parser.accepts(OPT_TRADE_ID, "id of trade")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<Boolean> showContractOpt = parser.accepts(OPT_SHOW_CONTRACT, "show trade's json contract")
|
||||
.withOptionalArg()
|
||||
|
@ -46,7 +44,7 @@ public class GetTradeOptionParser extends AbstractMethodOptionParser implements
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(tradeIdOpt))
|
||||
if (!options.has(tradeIdOpt) || options.valueOf(tradeIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no trade id specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -21,13 +21,11 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_TRANSACTION_ID;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class GetTransactionOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> txIdOpt = parser.accepts(OPT_TRANSACTION_ID, "id of transaction")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public GetTransactionOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -40,7 +38,7 @@ public class GetTransactionOptionParser extends AbstractMethodOptionParser imple
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(txIdOpt))
|
||||
if (!options.has(txIdOpt) || options.valueOf(txIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no tx id specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -22,17 +22,14 @@ import joptsimple.OptionSpec;
|
|||
|
||||
import static bisq.cli.opts.OptLabel.OPT_DISPUTE_AGENT_TYPE;
|
||||
import static bisq.cli.opts.OptLabel.OPT_REGISTRATION_KEY;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class RegisterDisputeAgentOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> disputeAgentTypeOpt = parser.accepts(OPT_DISPUTE_AGENT_TYPE, "dispute agent type")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> registrationKeyOpt = parser.accepts(OPT_REGISTRATION_KEY, "registration key")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public RegisterDisputeAgentOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -45,10 +42,10 @@ public class RegisterDisputeAgentOptionParser extends AbstractMethodOptionParser
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(disputeAgentTypeOpt))
|
||||
if (!options.has(disputeAgentTypeOpt) || options.valueOf(disputeAgentTypeOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no dispute agent type specified");
|
||||
|
||||
if (!options.has(registrationKeyOpt))
|
||||
if (!options.has(registrationKeyOpt) || options.valueOf(registrationKeyOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no registration key specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -21,13 +21,11 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_WALLET_PASSWORD;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class RemoveWalletPasswordOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> passwordOpt = parser.accepts(OPT_WALLET_PASSWORD, "bisq wallet password")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public RemoveWalletPasswordOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -40,7 +38,7 @@ public class RemoveWalletPasswordOptionParser extends AbstractMethodOptionParser
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(passwordOpt))
|
||||
if (!options.has(passwordOpt) || options.valueOf(passwordOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no password specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -28,12 +28,10 @@ import static joptsimple.internal.Strings.EMPTY;
|
|||
public class SendBsqOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> addressOpt = parser.accepts(OPT_ADDRESS, "destination bsq address")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> amountOpt = parser.accepts(OPT_AMOUNT, "amount of bsq to send")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> feeRateOpt = parser.accepts(OPT_TX_FEE_RATE, "optional tx fee rate (sats/byte)")
|
||||
.withOptionalArg()
|
||||
|
@ -50,10 +48,10 @@ public class SendBsqOptionParser extends AbstractMethodOptionParser implements M
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(addressOpt))
|
||||
if (!options.has(addressOpt) || options.valueOf(addressOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no bsq address specified");
|
||||
|
||||
if (!options.has(amountOpt))
|
||||
if (!options.has(amountOpt) || options.valueOf(amountOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no bsq amount specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -29,12 +29,10 @@ import static joptsimple.internal.Strings.EMPTY;
|
|||
public class SendBtcOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> addressOpt = parser.accepts(OPT_ADDRESS, "destination btc address")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> amountOpt = parser.accepts(OPT_AMOUNT, "amount of btc to send")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> feeRateOpt = parser.accepts(OPT_TX_FEE_RATE, "optional tx fee rate (sats/byte)")
|
||||
.withOptionalArg()
|
||||
|
@ -55,10 +53,10 @@ public class SendBtcOptionParser extends AbstractMethodOptionParser implements M
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(addressOpt))
|
||||
if (!options.has(addressOpt) || options.valueOf(addressOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no btc address specified");
|
||||
|
||||
if (!options.has(amountOpt))
|
||||
if (!options.has(amountOpt) || options.valueOf(amountOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no btc amount specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -21,14 +21,12 @@ package bisq.cli.opts;
|
|||
import joptsimple.OptionSpec;
|
||||
|
||||
import static bisq.cli.opts.OptLabel.OPT_TX_FEE_RATE;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class SetTxFeeRateOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> feeRateOpt = parser.accepts(OPT_TX_FEE_RATE,
|
||||
"tx fee rate preference (sats/byte)")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
public SetTxFeeRateOptionParser(String[] args) {
|
||||
super(args);
|
||||
|
@ -41,7 +39,7 @@ public class SetTxFeeRateOptionParser extends AbstractMethodOptionParser impleme
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(feeRateOpt))
|
||||
if (!options.has(feeRateOpt) || options.valueOf(feeRateOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no tx fee rate specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -27,8 +27,7 @@ import static joptsimple.internal.Strings.EMPTY;
|
|||
public class SetWalletPasswordOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> passwordOpt = parser.accepts(OPT_WALLET_PASSWORD, "bisq wallet password")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> newPasswordOpt = parser.accepts(OPT_NEW_WALLET_PASSWORD, "new bisq wallet password")
|
||||
.withOptionalArg()
|
||||
|
@ -45,7 +44,7 @@ public class SetWalletPasswordOptionParser extends AbstractMethodOptionParser im
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(passwordOpt))
|
||||
if (!options.has(passwordOpt) || options.valueOf(passwordOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no password specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -23,17 +23,14 @@ import joptsimple.OptionSpec;
|
|||
import static bisq.cli.opts.OptLabel.OPT_FEE_CURRENCY;
|
||||
import static bisq.cli.opts.OptLabel.OPT_OFFER_ID;
|
||||
import static bisq.cli.opts.OptLabel.OPT_PAYMENT_ACCOUNT;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class TakeOfferOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> offerIdOpt = parser.accepts(OPT_OFFER_ID, "id of offer to take")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> paymentAccountIdOpt = parser.accepts(OPT_PAYMENT_ACCOUNT, "id of payment account used for trade")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> takerFeeCurrencyCodeOpt = parser.accepts(OPT_FEE_CURRENCY, "taker fee currency code (bsq|btc)")
|
||||
.withOptionalArg()
|
||||
|
@ -50,10 +47,10 @@ public class TakeOfferOptionParser extends AbstractMethodOptionParser implements
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(offerIdOpt))
|
||||
if (!options.has(offerIdOpt) || options.valueOf(offerIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no offer id specified");
|
||||
|
||||
if (!options.has(paymentAccountIdOpt))
|
||||
if (!options.has(paymentAccountIdOpt) || options.valueOf(paymentAccountIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no payment account id specified");
|
||||
|
||||
return this;
|
||||
|
|
|
@ -22,13 +22,11 @@ import joptsimple.OptionSpec;
|
|||
|
||||
import static bisq.cli.opts.OptLabel.OPT_TIMEOUT;
|
||||
import static bisq.cli.opts.OptLabel.OPT_WALLET_PASSWORD;
|
||||
import static joptsimple.internal.Strings.EMPTY;
|
||||
|
||||
public class UnlockWalletOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> passwordOpt = parser.accepts(OPT_WALLET_PASSWORD, "bisq wallet password")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<Long> unlockTimeoutOpt = parser.accepts(OPT_TIMEOUT, "wallet unlock timeout (s)")
|
||||
.withRequiredArg()
|
||||
|
@ -46,7 +44,7 @@ public class UnlockWalletOptionParser extends AbstractMethodOptionParser impleme
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(passwordOpt))
|
||||
if (!options.has(passwordOpt) || options.valueOf(passwordOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no password specified");
|
||||
|
||||
if (!options.has(unlockTimeoutOpt) || options.valueOf(unlockTimeoutOpt) <= 0)
|
||||
|
|
|
@ -28,12 +28,10 @@ import static joptsimple.internal.Strings.EMPTY;
|
|||
public class WithdrawFundsOptionParser extends AbstractMethodOptionParser implements MethodOpts {
|
||||
|
||||
final OptionSpec<String> tradeIdOpt = parser.accepts(OPT_TRADE_ID, "id of trade")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> addressOpt = parser.accepts(OPT_ADDRESS, "destination btc address")
|
||||
.withRequiredArg()
|
||||
.defaultsTo(EMPTY);
|
||||
.withRequiredArg();
|
||||
|
||||
final OptionSpec<String> memoOpt = parser.accepts(OPT_MEMO, "optional tx memo")
|
||||
.withOptionalArg()
|
||||
|
@ -50,9 +48,12 @@ public class WithdrawFundsOptionParser extends AbstractMethodOptionParser implem
|
|||
if (options.has(helpOpt))
|
||||
return this;
|
||||
|
||||
if (!options.has(tradeIdOpt))
|
||||
if (!options.has(tradeIdOpt) || options.valueOf(tradeIdOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no trade id specified");
|
||||
|
||||
if (!options.has(addressOpt) || options.valueOf(addressOpt).isEmpty())
|
||||
throw new IllegalArgumentException("no destination address specified");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,24 +16,24 @@ public class GetOffersSmokeTest {
|
|||
public static void main(String[] args) {
|
||||
|
||||
out.println(">>> getoffers buy usd");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "buy", "usd"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=buy", "--currency-code=usd"});
|
||||
out.println(">>> getoffers sell usd");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "sell", "usd"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=sell", "--currency-code=usd"});
|
||||
|
||||
out.println(">>> getoffers buy eur");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "buy", "eur"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=buy", "--currency-code=eur"});
|
||||
out.println(">>> getoffers sell eur");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "sell", "eur"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=sell", "--currency-code=eur"});
|
||||
|
||||
out.println(">>> getoffers buy gbp");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "buy", "gbp"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=buy", "--currency-code=gbp"});
|
||||
out.println(">>> getoffers sell gbp");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "sell", "gbp"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=sell", "--currency-code=gbp"});
|
||||
|
||||
out.println(">>> getoffers buy brl");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "buy", "brl"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=buy", "--currency-code=brl"});
|
||||
out.println(">>> getoffers sell brl");
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "sell", "brl"});
|
||||
CliMain.main(new String[]{"--password=xyz", "getoffers", "--direction=sell", "--currency-code=brl"});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
180
cli/src/test/java/bisq/cli/opt/OptionParsersTest.java
Normal file
180
cli/src/test/java/bisq/cli/opt/OptionParsersTest.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package bisq.cli.opt;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static bisq.cli.Method.canceloffer;
|
||||
import static bisq.cli.Method.createoffer;
|
||||
import static bisq.cli.Method.createpaymentacct;
|
||||
import static bisq.cli.opts.OptLabel.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
|
||||
import bisq.cli.opts.CancelOfferOptionParser;
|
||||
import bisq.cli.opts.CreateOfferOptionParser;
|
||||
import bisq.cli.opts.CreatePaymentAcctOptionParser;
|
||||
|
||||
|
||||
public class OptionParsersTest {
|
||||
|
||||
private static final String PASSWORD_OPT = "--" + OPT_PASSWORD + "=" + "xyz";
|
||||
|
||||
// CancelOffer opt parsing tests
|
||||
|
||||
@Test
|
||||
public void testCancelOfferWithMissingOfferIdOptShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
canceloffer.name()
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CancelOfferOptionParser(args).parse());
|
||||
assertEquals("no offer id specified", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelOfferWithEmptyOfferIdOptShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
canceloffer.name(),
|
||||
"--" + OPT_OFFER_ID + "=" // missing opt value
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CancelOfferOptionParser(args).parse());
|
||||
assertEquals("no offer id specified", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelOfferWithMissingOfferIdValueShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
canceloffer.name(),
|
||||
"--" + OPT_OFFER_ID // missing equals sign & opt value
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CancelOfferOptionParser(args).parse());
|
||||
assertEquals("offer-id requires an argument", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidCancelOfferOpts() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
canceloffer.name(),
|
||||
"--" + OPT_OFFER_ID + "=" + "ABC-OFFER-ID"
|
||||
};
|
||||
new CancelOfferOptionParser(args).parse();
|
||||
}
|
||||
|
||||
// CreateOffer opt parsing tests
|
||||
|
||||
@Test
|
||||
public void testCreateOfferOptParserWithMissingPaymentAccountIdOptShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createoffer.name()
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreateOfferOptionParser(args).parse());
|
||||
assertEquals("no payment account id specified", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateOfferOptParserWithEmptyPaymentAccountIdOptShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createoffer.name(),
|
||||
"--" + OPT_PAYMENT_ACCOUNT
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreateOfferOptionParser(args).parse());
|
||||
assertEquals("payment-account requires an argument", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateOfferOptParserWithMissingDirectionOptShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createoffer.name(),
|
||||
"--" + OPT_PAYMENT_ACCOUNT + "=" + "abc-payment-acct-id-123"
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreateOfferOptionParser(args).parse());
|
||||
assertEquals("no direction (buy|sell) specified", exception.getMessage());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateOfferOptParserWithMissingDirectionOptValueShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createoffer.name(),
|
||||
"--" + OPT_PAYMENT_ACCOUNT + "=" + "abc-payment-acct-id-123",
|
||||
"--" + OPT_DIRECTION + "=" + ""
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreateOfferOptionParser(args).parse());
|
||||
assertEquals("no direction (buy|sell) specified", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidCreateOfferOpts() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createoffer.name(),
|
||||
"--" + OPT_PAYMENT_ACCOUNT + "=" + "abc-payment-acct-id-123",
|
||||
"--" + OPT_DIRECTION + "=" + "BUY",
|
||||
"--" + OPT_CURRENCY_CODE + "=" + "EUR",
|
||||
"--" + OPT_AMOUNT + "=" + "0.125",
|
||||
"--" + OPT_MKT_PRICE_MARGIN + "=" + "0.0",
|
||||
"--" + OPT_SECURITY_DEPOSIT + "=" + "25.0"
|
||||
};
|
||||
CreateOfferOptionParser parser = new CreateOfferOptionParser(args).parse();
|
||||
assertEquals("abc-payment-acct-id-123", parser.getPaymentAccountId());
|
||||
assertEquals("BUY", parser.getDirection());
|
||||
assertEquals("EUR", parser.getCurrencyCode());
|
||||
assertEquals("0.125", parser.getAmount());
|
||||
assertEquals("0.0", parser.getMktPriceMargin());
|
||||
assertEquals("25.0", parser.getSecurityDeposit());
|
||||
}
|
||||
|
||||
// CreatePaymentAcct opt parser tests
|
||||
|
||||
@Test
|
||||
public void testCreatePaymentAcctOptParserWithMissingPaymentFormOptShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createpaymentacct.name()
|
||||
// OPT_PAYMENT_ACCOUNT_FORM
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreatePaymentAcctOptionParser(args).parse());
|
||||
assertEquals("no path to json payment account form specified", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePaymentAcctOptParserWithMissingPaymentFormOptValueShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createpaymentacct.name(),
|
||||
"--" + OPT_PAYMENT_ACCOUNT_FORM + "="
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreatePaymentAcctOptionParser(args).parse());
|
||||
assertEquals("no path to json payment account form specified", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePaymentAcctOptParserWithInvalidPaymentFormOptValueShouldThrowException() {
|
||||
String[] args = new String[]{
|
||||
PASSWORD_OPT,
|
||||
createpaymentacct.name(),
|
||||
"--" + OPT_PAYMENT_ACCOUNT_FORM + "=" + "/tmp/milkyway/solarsystem/mars"
|
||||
};
|
||||
Throwable exception = assertThrows(RuntimeException.class, () ->
|
||||
new CreatePaymentAcctOptionParser(args).parse());
|
||||
assertEquals("json payment account form '/tmp/milkyway/solarsystem/mars' could not be found",
|
||||
exception.getMessage());
|
||||
}
|
||||
}
|
|
@ -28,9 +28,13 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Arrays.stream;
|
||||
import static org.apache.commons.lang3.StringUtils.capitalize;
|
||||
|
||||
@Slf4j
|
||||
public class ReflectionUtils {
|
||||
|
||||
/**
|
||||
|
@ -105,4 +109,32 @@ public class ReflectionUtils {
|
|||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
public static Field getField(String name, Class<?> clazz) {
|
||||
Optional<Field> field = stream(clazz.getDeclaredFields())
|
||||
.filter(f -> f.getName().equals(name)).findFirst();
|
||||
return field.orElseThrow(() ->
|
||||
new IllegalArgumentException(format("field %s not found in class %s",
|
||||
name,
|
||||
clazz.getSimpleName())));
|
||||
}
|
||||
|
||||
public static Method getMethod(String name, Class<?> clazz) {
|
||||
Optional<Method> method = stream(clazz.getDeclaredMethods())
|
||||
.filter(m -> m.getName().equals(name)).findFirst();
|
||||
return method.orElseThrow(() ->
|
||||
new IllegalArgumentException(format("method %s not found in class %s",
|
||||
name,
|
||||
clazz.getSimpleName())));
|
||||
}
|
||||
|
||||
public static void handleSetFieldValueError(Object object,
|
||||
Field field,
|
||||
ReflectiveOperationException ex) {
|
||||
String errMsg = format("cannot set value of field %s, on class %s",
|
||||
field.getName(),
|
||||
object.getClass().getSimpleName());
|
||||
log.error(capitalize(errMsg) + ".", ex);
|
||||
throw new IllegalStateException("programmer error: " + errMsg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import static bisq.common.util.MathUtils.scaleUpByPowerOf10;
|
|||
import static bisq.core.locale.CurrencyUtil.isCryptoCurrency;
|
||||
import static bisq.core.offer.OfferPayload.Direction;
|
||||
import static bisq.core.offer.OfferPayload.Direction.BUY;
|
||||
import static bisq.core.payment.PaymentAccountUtil.isPaymentAccountValidForOffer;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Comparator.comparing;
|
||||
|
||||
|
@ -101,6 +102,7 @@ class CoreOffersService {
|
|||
Offer getOffer(String id) {
|
||||
return offerBookService.getOffers().stream()
|
||||
.filter(o -> o.getId().equals(id))
|
||||
.filter(o -> !o.isMyOffer(keyRing))
|
||||
.filter(o -> offerFilter.canTakeOffer(o, isApiUser).isValid())
|
||||
.findAny().orElseThrow(() ->
|
||||
new IllegalStateException(format("offer with id '%s' not found", id)));
|
||||
|
@ -116,6 +118,7 @@ class CoreOffersService {
|
|||
|
||||
List<Offer> getOffers(String direction, String currencyCode) {
|
||||
return offerBookService.getOffers().stream()
|
||||
.filter(o -> !o.isMyOffer(keyRing))
|
||||
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
|
||||
.filter(o -> offerFilter.canTakeOffer(o, isApiUser).isValid())
|
||||
.sorted(priceComparator(direction))
|
||||
|
@ -174,6 +177,8 @@ class CoreOffersService {
|
|||
buyerSecurityDeposit,
|
||||
paymentAccount);
|
||||
|
||||
verifyPaymentAccountIsValidForNewOffer(offer, paymentAccount);
|
||||
|
||||
// We don't support atm funding from external wallet to keep it simple.
|
||||
boolean useSavingsWallet = true;
|
||||
//noinspection ConstantConditions
|
||||
|
@ -210,7 +215,7 @@ class CoreOffersService {
|
|||
}
|
||||
|
||||
void cancelOffer(String id) {
|
||||
Offer offer = getOffer(id);
|
||||
Offer offer = getMyOffer(id);
|
||||
openOfferManager.removeOffer(offer,
|
||||
() -> {
|
||||
},
|
||||
|
@ -219,6 +224,15 @@ class CoreOffersService {
|
|||
});
|
||||
}
|
||||
|
||||
private void verifyPaymentAccountIsValidForNewOffer(Offer offer, PaymentAccount paymentAccount) {
|
||||
if (!isPaymentAccountValidForOffer(offer, paymentAccount)) {
|
||||
String error = format("cannot create %s offer with payment account %s",
|
||||
offer.getOfferPayload().getCounterCurrencyCode(),
|
||||
paymentAccount.getId());
|
||||
throw new IllegalStateException(error);
|
||||
}
|
||||
}
|
||||
|
||||
private void placeOffer(Offer offer,
|
||||
double buyerSecurityDeposit,
|
||||
long triggerPrice,
|
||||
|
|
|
@ -35,6 +35,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
class CorePaymentAccountsService {
|
||||
|
@ -54,6 +56,7 @@ class CorePaymentAccountsService {
|
|||
|
||||
PaymentAccount createPaymentAccount(String jsonString) {
|
||||
PaymentAccount paymentAccount = paymentAccountForm.toPaymentAccount(jsonString);
|
||||
verifyPaymentAccountHasRequiredFields(paymentAccount);
|
||||
user.addPaymentAccountIfNotExists(paymentAccount);
|
||||
accountAgeWitnessService.publishMyAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
||||
log.info("Saved payment account with id {} and payment method {}.",
|
||||
|
@ -82,4 +85,11 @@ class CorePaymentAccountsService {
|
|||
File getPaymentAccountForm(String paymentMethodId) {
|
||||
return paymentAccountForm.getPaymentAccountForm(paymentMethodId);
|
||||
}
|
||||
|
||||
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",
|
||||
paymentAccount.getPaymentMethod().getDisplayString().toLowerCase()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ public class PaymentAccountForm {
|
|||
"paymentMethod",
|
||||
"paymentMethodId", // This field will be included, but handled differently.
|
||||
"selectedTradeCurrency",
|
||||
"tradeCurrencies",
|
||||
"tradeCurrencies", // This field may be included, but handled differently.
|
||||
"HOLDER_NAME",
|
||||
"SALT" // This field will be included, but handled differently.
|
||||
};
|
||||
|
|
|
@ -20,6 +20,7 @@ package bisq.core.api.model;
|
|||
|
||||
import bisq.core.locale.Country;
|
||||
import bisq.core.locale.FiatCurrency;
|
||||
import bisq.core.locale.TradeCurrency;
|
||||
import bisq.core.payment.CountryBasedPaymentAccount;
|
||||
import bisq.core.payment.MoneyGramAccount;
|
||||
import bisq.core.payment.PaymentAccount;
|
||||
|
@ -35,12 +36,11 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
@ -50,16 +50,20 @@ import java.lang.reflect.Method;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.common.util.ReflectionUtils.getSetterMethodForFieldInClassHierarchy;
|
||||
import static bisq.common.util.ReflectionUtils.getVisibilityModifierAsString;
|
||||
import static bisq.common.util.ReflectionUtils.isSetterOnClass;
|
||||
import static bisq.common.util.ReflectionUtils.loadFieldListForClassHierarchy;
|
||||
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 com.google.common.base.Preconditions.checkNotNull;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static java.util.Comparator.comparing;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@Slf4j
|
||||
class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
||||
|
@ -96,7 +100,7 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
public PaymentAccountTypeAdapter(Class<? extends PaymentAccount> paymentAccountType, String[] excludedFields) {
|
||||
this.paymentAccountType = paymentAccountType;
|
||||
this.paymentAccountPayloadType = getPaymentAccountPayloadType();
|
||||
this.isExcludedField = (f) -> Arrays.stream(excludedFields).anyMatch(e -> e.equals(f.getName()));
|
||||
this.isExcludedField = (f) -> stream(excludedFields).anyMatch(e -> e.equals(f.getName()));
|
||||
this.fieldSettersMap = getFieldSetterMap();
|
||||
}
|
||||
|
||||
|
@ -128,6 +132,9 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
}
|
||||
|
||||
private void writeInnerMutableFields(JsonWriter out, PaymentAccount account) {
|
||||
if (account.isTransferwiseAccount())
|
||||
writeTradeCurrenciesField(out, account);
|
||||
|
||||
fieldSettersMap.forEach((field, value) -> {
|
||||
try {
|
||||
// Write out a json element if there is a @Setter for this field.
|
||||
|
@ -151,6 +158,25 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
});
|
||||
}
|
||||
|
||||
// In some cases (TransferwiseAccount), we need to include a 'tradeCurrencies'
|
||||
// field in the json form, though the 'tradeCurrencies' field has no setter method in
|
||||
// the PaymentAccount class hierarchy. At of time of this change, TransferwiseAccount
|
||||
// is the only known exception to the rule.
|
||||
private void writeTradeCurrenciesField(JsonWriter out, PaymentAccount account) {
|
||||
try {
|
||||
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");
|
||||
} 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 {
|
||||
PaymentAccount account = initNewPaymentAccount();
|
||||
|
@ -158,6 +184,11 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
while (in.hasNext()) {
|
||||
String currentFieldName = in.nextName();
|
||||
|
||||
// The tradeCurrency 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.
|
||||
if (didReadCommonField(in, account, currentFieldName))
|
||||
continue;
|
||||
|
@ -199,17 +230,13 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
account.getClass().getSimpleName());
|
||||
throw new IllegalStateException(errMsg);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
String errMsg = format("cannot set field value for %s on %s",
|
||||
field.getName(),
|
||||
account.getClass().getSimpleName());
|
||||
log.error(StringUtils.capitalize(errMsg) + ".", ex);
|
||||
throw new IllegalStateException("programmer error: " + errMsg);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
handleSetFieldValueError(account, field, ex);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
format("programmer error: cannot de-serialize json to a '%s' "
|
||||
+ " because there is no setter method for field %s.",
|
||||
+ " because field value cannot be set %s.",
|
||||
account.getClass().getSimpleName(),
|
||||
field.getName()));
|
||||
}
|
||||
|
@ -232,7 +259,7 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
.or(() -> getSetterMethodForFieldInClassHierarchy(field, paymentAccountPayloadType));
|
||||
map.put(field, setter);
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
return unmodifiableMap(map);
|
||||
}
|
||||
|
||||
private List<Field> getOrderedFields() {
|
||||
|
@ -274,6 +301,52 @@ class PaymentAccountTypeAdapter extends TypeAdapter<PaymentAccount> {
|
|||
}
|
||||
}
|
||||
|
||||
private final Predicate<String> isCommaDelimitedCurrencyList = (s) -> s != null && s.contains(",");
|
||||
private final Function<String, List<String>> commaDelimitedCodesToList = (s) -> {
|
||||
if (isCommaDelimitedCurrencyList.test(s))
|
||||
return stream(s.split(",")).map(a -> a.trim().toUpperCase()).collect(toList());
|
||||
else if (s != null && !s.isEmpty())
|
||||
return singletonList(s.trim().toUpperCase());
|
||||
else
|
||||
return new ArrayList<>();
|
||||
};
|
||||
|
||||
private boolean didReadTradeCurrenciesField(JsonReader in,
|
||||
PaymentAccount account,
|
||||
String fieldName) {
|
||||
// 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<String> currencyCodes = commaDelimitedCodesToList.apply(fieldValue);
|
||||
|
||||
Optional<List<TradeCurrency>> 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));
|
||||
} 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());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean didReadCommonField(JsonReader in,
|
||||
PaymentAccount account,
|
||||
String fieldName) throws IOException {
|
||||
|
|
|
@ -43,6 +43,7 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -51,6 +52,7 @@ import java.util.stream.Stream;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.lang.String.format;
|
||||
|
||||
@Slf4j
|
||||
public class CurrencyUtil {
|
||||
|
@ -486,6 +488,32 @@ public class CurrencyUtil {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static Optional<List<TradeCurrency>> getTradeCurrencies(List<String> currencyCodes) {
|
||||
List<TradeCurrency> tradeCurrencies = new ArrayList<>();
|
||||
currencyCodes.stream().forEachOrdered(c ->
|
||||
tradeCurrencies.add(getTradeCurrency(c).orElseThrow(() ->
|
||||
new IllegalArgumentException(format("%s is not a valid trade currency code", c)))));
|
||||
return tradeCurrencies.isEmpty()
|
||||
? Optional.empty()
|
||||
: Optional.of(tradeCurrencies);
|
||||
}
|
||||
|
||||
public static Optional<List<TradeCurrency>> getTradeCurrenciesInList(List<String> currencyCodes,
|
||||
List<TradeCurrency> validCurrencies) {
|
||||
Optional<List<TradeCurrency>> tradeCurrencies = getTradeCurrencies(currencyCodes);
|
||||
Consumer<List<TradeCurrency>> validateCandidateCurrencies = (list) -> {
|
||||
for (TradeCurrency tradeCurrency : list) {
|
||||
if (!validCurrencies.contains(tradeCurrency)) {
|
||||
throw new IllegalArgumentException(
|
||||
format("%s is not a member of valid currencies list",
|
||||
tradeCurrency.getCode()));
|
||||
}
|
||||
}
|
||||
};
|
||||
tradeCurrencies.ifPresent(validateCandidateCurrencies);
|
||||
return tradeCurrencies;
|
||||
}
|
||||
|
||||
public static FiatCurrency getCurrencyByCountryCode(String countryCode) {
|
||||
if (countryCode.equals("XK"))
|
||||
return new FiatCurrency("EUR");
|
||||
|
|
|
@ -134,7 +134,7 @@ public class OfferFilter {
|
|||
|
||||
public boolean isAnyPaymentAccountValidForOffer(Offer offer) {
|
||||
return user.getPaymentAccounts() != null &&
|
||||
PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(offer, user.getPaymentAccounts());
|
||||
PaymentAccountUtil.isAnyPaymentAccountValidForOffer(offer, user.getPaymentAccounts());
|
||||
}
|
||||
|
||||
public boolean hasSameProtocolVersion(Offer offer) {
|
||||
|
|
|
@ -198,6 +198,10 @@ public abstract class PaymentAccount implements PersistablePayload {
|
|||
return this instanceof MoneyGramAccount;
|
||||
}
|
||||
|
||||
public boolean isTransferwiseAccount() {
|
||||
return this instanceof TransferwiseAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -41,10 +41,10 @@ import javax.annotation.Nullable;
|
|||
@Slf4j
|
||||
public class PaymentAccountUtil {
|
||||
|
||||
public static boolean isAnyTakerPaymentAccountValidForOffer(Offer offer,
|
||||
Collection<PaymentAccount> takerPaymentAccounts) {
|
||||
for (PaymentAccount takerPaymentAccount : takerPaymentAccounts) {
|
||||
if (isTakerPaymentAccountValidForOffer(offer, takerPaymentAccount))
|
||||
public static boolean isAnyPaymentAccountValidForOffer(Offer offer,
|
||||
Collection<PaymentAccount> paymentAccounts) {
|
||||
for (PaymentAccount paymentAccount : paymentAccounts) {
|
||||
if (isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -55,7 +55,7 @@ public class PaymentAccountUtil {
|
|||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
ObservableList<PaymentAccount> result = FXCollections.observableArrayList();
|
||||
result.addAll(paymentAccounts.stream()
|
||||
.filter(paymentAccount -> isTakerPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.filter(paymentAccount -> isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.filter(paymentAccount -> isAmountValidForOffer(offer, paymentAccount, accountAgeWitnessService))
|
||||
.collect(Collectors.toList()));
|
||||
return result;
|
||||
|
@ -79,7 +79,7 @@ public class PaymentAccountUtil {
|
|||
"Payment method from offer: " + offer.getPaymentMethod().toString();
|
||||
}
|
||||
|
||||
public static boolean isTakerPaymentAccountValidForOffer(Offer offer, PaymentAccount paymentAccount) {
|
||||
public static boolean isPaymentAccountValidForOffer(Offer offer, PaymentAccount paymentAccount) {
|
||||
return new ReceiptValidator(offer, paymentAccount).isValid();
|
||||
}
|
||||
|
||||
|
@ -144,23 +144,4 @@ public class PaymentAccountUtil {
|
|||
filter(e -> e.getPaymentAccountPayload().equals(paymentAccountPayload))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
// TODO no code duplication found in UI code (added for API)
|
||||
// That is optional and set to null if not supported (AltCoins,...)
|
||||
/* public static String getCountryCode(PaymentAccount paymentAccount) {
|
||||
if (paymentAccount instanceof CountryBasedPaymentAccount) {
|
||||
Country country = ((CountryBasedPaymentAccount) paymentAccount).getCountry();
|
||||
return country != null ? country.code : null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}*/
|
||||
|
||||
// TODO no code duplication found in UI code (added for API)
|
||||
/*public static long getMaxTradeLimit(AccountAgeWitnessService accountAgeWitnessService, PaymentAccount paymentAccount, String currencyCode) {
|
||||
if (paymentAccount != null)
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, currencyCode);
|
||||
else
|
||||
return 0;
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class PaymentAccounts {
|
|||
private final BiFunction<Offer, PaymentAccount, Boolean> validator;
|
||||
|
||||
PaymentAccounts(Set<PaymentAccount> accounts, AccountAgeWitnessService accountAgeWitnessService) {
|
||||
this(accounts, accountAgeWitnessService, PaymentAccountUtil::isTakerPaymentAccountValidForOffer);
|
||||
this(accounts, accountAgeWitnessService, PaymentAccountUtil::isPaymentAccountValidForOffer);
|
||||
}
|
||||
|
||||
PaymentAccounts(Set<PaymentAccount> accounts, AccountAgeWitnessService accountAgeWitnessService,
|
||||
|
|
|
@ -105,46 +105,46 @@ public class OfferBookViewModelTest {
|
|||
Collection<PaymentAccount> paymentAccounts;
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSepaAccount("EUR", "DE", "1212324",
|
||||
new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
// empty paymentAccounts
|
||||
paymentAccounts = new ArrayList<>();
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(getSEPAPaymentMethod("EUR", "AT",
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(getSEPAPaymentMethod("EUR", "AT",
|
||||
new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// simple cases: same payment methods
|
||||
|
||||
// offer: alipay paymentAccount: alipay - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getAliPayAccount("CNY")));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getAliPayPaymentMethod("EUR"), paymentAccounts));
|
||||
|
||||
// offer: ether paymentAccount: ether - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getCryptoAccount("ETH")));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getBlockChainsPaymentMethod("ETH"), paymentAccounts));
|
||||
|
||||
// offer: sepa paymentAccount: sepa - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSepaAccount("EUR", "AT", "1212324",
|
||||
new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// offer: nationalBank paymentAccount: nationalBank - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getNationalBankAccount("EUR", "AT", "PSK")));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// offer: SameBank paymentAccount: SameBank - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSameBankAccount("EUR", "AT", "PSK")));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSameBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// offer: sepa paymentAccount: sepa - diff. country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSepaAccount("EUR", "DE", "1212324", new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
|
@ -152,79 +152,79 @@ public class OfferBookViewModelTest {
|
|||
|
||||
// offer: sepa paymentAccount: sepa - same country, same currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSepaAccount("EUR", "AT", "1212324", new ArrayList<>(Arrays.asList("AT", "DE")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
// offer: sepa paymentAccount: nationalBank - same country, same currency
|
||||
// wrong method
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getNationalBankAccount("EUR", "AT", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// wrong currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getNationalBankAccount("USD", "US", "XXX")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// wrong country
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getNationalBankAccount("EUR", "FR", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// sepa wrong country
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getNationalBankAccount("EUR", "CH", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
// sepa wrong currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getNationalBankAccount("CHF", "DE", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getSEPAPaymentMethod("EUR", "AT", new ArrayList<>(Arrays.asList("AT", "DE")), "PSK"), paymentAccounts));
|
||||
|
||||
|
||||
// same bank
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSameBankAccount("EUR", "AT", "PSK")));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// not same bank
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSameBankAccount("EUR", "AT", "Raika")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// same bank, wrong country
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSameBankAccount("EUR", "DE", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// same bank, wrong currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSameBankAccount("USD", "AT", "PSK")));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSpecificBanksAccount("EUR", "AT", "PSK",
|
||||
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
|
||||
assertTrue(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertTrue(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank, missing bank
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSpecificBanksAccount("EUR", "AT", "PSK",
|
||||
new ArrayList<>(FXCollections.singletonObservableList("Raika")))));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank, wrong country
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSpecificBanksAccount("EUR", "FR", "PSK",
|
||||
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
// spec. bank, wrong currency
|
||||
paymentAccounts = new ArrayList<>(FXCollections.singletonObservableList(getSpecificBanksAccount("USD", "AT", "PSK",
|
||||
new ArrayList<>(Arrays.asList("PSK", "Raika")))));
|
||||
assertFalse(PaymentAccountUtil.isAnyTakerPaymentAccountValidForOffer(
|
||||
assertFalse(PaymentAccountUtil.isAnyPaymentAccountValidForOffer(
|
||||
getNationalBankPaymentMethod("EUR", "AT", "PSK"), paymentAccounts));
|
||||
|
||||
//TODO add more tests
|
||||
|
|
Loading…
Add table
Reference in a new issue