diff --git a/common/pom.xml b/common/pom.xml index 2e6fd34845..5c7fcb0428 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0 diff --git a/common/src/main/java/io/bisq/common/app/Version.java b/common/src/main/java/io/bisq/common/app/Version.java index a0f0c16b5d..551efcdf06 100644 --- a/common/src/main/java/io/bisq/common/app/Version.java +++ b/common/src/main/java/io/bisq/common/app/Version.java @@ -27,7 +27,7 @@ public class Version { // VERSION = 0.5.0 introduces proto buffer for the P2P network and local DB and is a not backward compatible update // Therefore all sub versions start again with 1 // We use semantic versioning with major, minor and patch - public static final String VERSION = "0.6.5"; + public static final String VERSION = "0.6.6"; public static int getMajorVersion(String version) { return getSubVersion(version, 0); diff --git a/common/src/main/java/io/bisq/common/locale/CurrencyUtil.java b/common/src/main/java/io/bisq/common/locale/CurrencyUtil.java index 9e3887f564..737abc2966 100644 --- a/common/src/main/java/io/bisq/common/locale/CurrencyUtil.java +++ b/common/src/main/java/io/bisq/common/locale/CurrencyUtil.java @@ -96,22 +96,19 @@ public class CurrencyUtil { result.add(new CryptoCurrency("BCH", "Bitcoin Cash")); result.add(new CryptoCurrency("BCHC", "Bitcoin Clashic")); result.add(new CryptoCurrency("BTG", "Bitcoin Gold")); - result.add(new CryptoCurrency("DARX", "BitDaric")); result.add(new CryptoCurrency("BURST", "Burstcoin")); result.add(new CryptoCurrency("GBYTE", "Byte")); result.add(new CryptoCurrency("CAGE", "Cagecoin")); result.add(new CryptoCurrency("XCP", "Counterparty")); result.add(new CryptoCurrency("CREA", "Creativecoin")); result.add(new CryptoCurrency("XCN", "Cryptonite")); - result.add(new CryptoCurrency("DAI", "Dai Stablecoin", true)); result.add(new CryptoCurrency("DNET", "DarkNet")); if (!baseCurrencyCode.equals("DASH")) result.add(new CryptoCurrency("DASH", "Dash")); result.add(new CryptoCurrency("DCT", "DECENT")); result.add(new CryptoCurrency("DCR", "Decred")); result.add(new CryptoCurrency("ONION", "DeepOnion")); - if (!baseCurrencyCode.equals("DOGE")) - result.add(new CryptoCurrency("DOGE", "Dogecoin")); + result.add(new CryptoCurrency("DOGE", "Dogecoin")); result.add(new CryptoCurrency("DMC", "DynamicCoin")); result.add(new CryptoCurrency("ELLA", "Ellaism")); result.add(new CryptoCurrency("ESP", "Espers")); @@ -133,7 +130,6 @@ public class CurrencyUtil { result.add(new CryptoCurrency("NMC", "Namecoin")); result.add(new CryptoCurrency("NBT", "NuBits")); result.add(new CryptoCurrency("NXT", "Nxt")); - result.add(new CryptoCurrency("ODN", "Obsidian")); result.add(new CryptoCurrency("888", "OctoCoin")); result.add(new CryptoCurrency("PART", "Particl")); result.add(new CryptoCurrency("PASC", "Pascal Coin", true)); @@ -149,7 +145,7 @@ public class CurrencyUtil { result.add(new CryptoCurrency("SIB", "Sibcoin")); result.add(new CryptoCurrency("XSPEC", "Spectrecoin")); result.add(new CryptoCurrency("STEEM", "STEEM")); - result.add(new CryptoCurrency("STL", "Stellite")); + result.add(new CryptoCurrency("TRC", "Terracoin")); result.add(new CryptoCurrency("MVT", "The Movement", true)); @@ -157,10 +153,23 @@ public class CurrencyUtil { result.add(new CryptoCurrency("CRED", "Verify", true)); result.add(new CryptoCurrency("WAC", "WACoins")); result.add(new CryptoCurrency("WILD", "WILD Token", true)); - result.add(new CryptoCurrency("YTN", "Yenten")); result.add(new CryptoCurrency("XZC", "Zcoin")); result.add(new CryptoCurrency("ZEC", "Zcash")); result.add(new CryptoCurrency("ZEN", "ZenCash")); + + // Added 0.6.6 + result.add(new CryptoCurrency("STL", "Stellite")); + result.add(new CryptoCurrency("DAI", "Dai Stablecoin", true)); + result.add(new CryptoCurrency("YTN", "Yenten")); + result.add(new CryptoCurrency("DARX", "BitDaric")); + result.add(new CryptoCurrency("ODN", "Obsidian")); + result.add(new CryptoCurrency("CDT", "Cassubian Detk")); + result.add(new CryptoCurrency("DGM", "DigiMoney")); + result.add(new CryptoCurrency("SCS", "SpeedCash")); + result.add(new CryptoCurrency("SOS", "SOS Coin", true)); + result.add(new CryptoCurrency("ACH", "AchieveCoin")); + result.add(new CryptoCurrency("VDN", "vDinar")); + result.sort(TradeCurrency::compareTo); // Util for printing all altcoins for adding to FAQ page @@ -185,8 +194,7 @@ public class CurrencyUtil { if (!baseCurrencyCode.equals("DASH")) result.add(new CryptoCurrency("DASH", "Dash")); result.add(new CryptoCurrency("DCR", "Decred")); - if (!baseCurrencyCode.equals("DOGE")) - result.add(new CryptoCurrency("DOGE", "Dogecoin")); + result.add(new CryptoCurrency("ONION", "DeepOnion")); result.add(new CryptoCurrency("ETH", "Ether")); result.add(new CryptoCurrency("ETC", "Ether Classic")); result.add(new CryptoCurrency("GRC", "Gridcoin")); @@ -239,7 +247,72 @@ public class CurrencyUtil { new FiatCurrency("HKD"), new FiatCurrency("CNY") )); - currencies.sort(TradeCurrency::compareTo); + currencies.sort(Comparator.comparing(TradeCurrency::getCode)); + return currencies; + } + + // https://support.uphold.com/hc/en-us/articles/202473803-Supported-currencies + public static List getAllUpholdCurrencies() { + ArrayList currencies = new ArrayList<>(Arrays.asList( + new FiatCurrency("USD"), + new FiatCurrency("EUR"), + new FiatCurrency("GBP"), + new FiatCurrency("CNY"), + new FiatCurrency("JPY"), + new FiatCurrency("CHF"), + new FiatCurrency("INR"), + new FiatCurrency("MXN"), + new FiatCurrency("AUD"), + new FiatCurrency("CAD"), + new FiatCurrency("HKD"), + new FiatCurrency("NZD"), + new FiatCurrency("SGD"), + new FiatCurrency("KES"), + new FiatCurrency("ILS"), + new FiatCurrency("DKK"), + new FiatCurrency("NOK"), + new FiatCurrency("SEK"), + new FiatCurrency("PLN"), + new FiatCurrency("ARS"), + new FiatCurrency("BRL"), + new FiatCurrency("AED"), + new FiatCurrency("PHP") + )); + + currencies.sort(Comparator.comparing(TradeCurrency::getCode)); + return currencies; + } + + //https://www.revolut.com/pa/faq#can-i-hold-multiple-currencies + public static List getAllRevolutCurrencies() { + ArrayList currencies = new ArrayList<>(Arrays.asList( + new FiatCurrency("USD"), + new FiatCurrency("GBP"), + new FiatCurrency("EUR"), + new FiatCurrency("PLN"), + new FiatCurrency("CHF"), + new FiatCurrency("DKK"), + new FiatCurrency("NOK"), + new FiatCurrency("SEK"), + new FiatCurrency("RON"), + new FiatCurrency("SGD"), + new FiatCurrency("HKD"), + new FiatCurrency("AUD"), + new FiatCurrency("NZD"), + new FiatCurrency("TRY"), + new FiatCurrency("ILS"), + new FiatCurrency("AED"), + new FiatCurrency("CAD"), + new FiatCurrency("HUF"), + new FiatCurrency("INR"), + new FiatCurrency("JPY"), + new FiatCurrency("MAD"), + new FiatCurrency("QAR"), + new FiatCurrency("THB"), + new FiatCurrency("ZAR") + )); + + currencies.sort(Comparator.comparing(TradeCurrency::getCode)); return currencies; } diff --git a/common/src/main/proto/pb.proto b/common/src/main/proto/pb.proto index 2a6a53c265..813d3b6727 100644 --- a/common/src/main/proto/pb.proto +++ b/common/src/main/proto/pb.proto @@ -807,6 +807,12 @@ message PaymentAccountPayload { PerfectMoneyAccountPayload perfect_money_account_payload = 12; SwishAccountPayload swish_account_payload = 13; USPostalMoneyOrderAccountPayload u_s_postal_money_order_account_payload = 14; + UpholdAccountPayload uphold_account_payload = 16; + CashAppAccountPayload cash_app_account_payload = 17; + MoneyBeamAccountPayload money_beam_account_payload = 18; + VenmoAccountPayload venmo_account_payload = 19; + PopmoneyAccountPayload popmoney_account_payload = 20; + RevolutAccountPayload revolut_account_payload = 21; } map exclude_from_json_data = 15; } @@ -917,6 +923,32 @@ message OKPayAccountPayload { string account_nr = 1; } +message UpholdAccountPayload { + string account_id = 1; +} + +message CashAppAccountPayload { + string cash_tag = 1; +} + +message MoneyBeamAccountPayload { + string account_id = 1; +} + +message VenmoAccountPayload { + string venmo_user_name = 1; + string holder_name = 2; +} + +message PopmoneyAccountPayload { + string account_id = 1; + string holder_name = 2; +} + +message RevolutAccountPayload { + string account_id = 1; +} + message PerfectMoneyAccountPayload { string account_nr = 1; } @@ -1066,6 +1098,7 @@ message OpenOffer { RESERVED = 2; CLOSED = 3; CANCELED = 4; + DEACTIVATED = 5; } Offer offer = 1; diff --git a/common/src/main/resources/i18n/displayStrings.properties b/common/src/main/resources/i18n/displayStrings.properties index 779468ced4..683de686c1 100644 --- a/common/src/main/resources/i18n/displayStrings.properties +++ b/common/src/main/resources/i18n/displayStrings.properties @@ -84,6 +84,8 @@ shared.bankName=Bank name shared.acceptedBanks=Accepted banks shared.amountMinMax=Amount (min - max) shared.remove=Remove +shared.deactivate=Deactivate +shared.activate=Activate shared.goTo=Go to {0} shared.BTCMinMax=BTC (min - max) shared.removeOffer=Remove offer @@ -316,6 +318,8 @@ offerbook.yesCreateOffer=Yes, create offer offerbook.setupNewAccount=Set up a new trading account offerbook.removeOffer.success=Remove offer was successful. offerbook.removeOffer.failed=Remove offer failed:\n{0} +offerbook.deactivateOffer.failed=Deactivating of offer failed:\n{0} +offerbook.activateOffer.failed=Publishing of offer failed:\n{0} offerbook.withdrawFundsHint=You can withdraw the funds you paid in from the {0} screen. offerbook.warning.noTradingAccountForCurrency.headline=No trading account for selected currency @@ -474,7 +478,7 @@ portfolio.pending.step2_buyer.refTextWarn=DO NOT use any additional notice in th portfolio.pending.step2_buyer.accountDetails=Here are the trade account details of the BTC seller:\n portfolio.pending.step2_buyer.tradeId=Please don't forget to add the trade ID # suppress inspection "TrailingSpacesInProperty" -portfolio.pending.step2_buyer.assign= as \"reason for payment\" so the receiver can assign your payment to this trade.\n\n +portfolio.pending.step2_buyer.assign=as \"reason for payment\" so the receiver can assign your payment to this trade.\n\n portfolio.pending.step2_buyer.fees=If your bank charges fees you have to cover those fees. # suppress inspection "TrailingSpacesInProperty" portfolio.pending.step2_buyer.altcoin=Please transfer from your external {0} wallet\n{1} to the BTC seller.\n\n @@ -765,10 +769,10 @@ setting.preferences.general=General preferences setting.preferences.explorer=Bitcoin block explorer: setting.preferences.deviation=Max. deviation from market price: setting.preferences.autoSelectArbitrators=Auto select arbitrators: -setting.preferences.deviationToLarge=Values higher than 30 % are not allowed. +setting.preferences.deviationToLarge=Values higher than {0}% are not allowed. setting.preferences.txFee=Withdrawal transaction fee (satoshi/byte): setting.preferences.useCustomValue=Use custom value -setting.preferences.txFeeMin=Transaction fee must be at least 5 satoshi/byte +setting.preferences.txFeeMin=Transaction fee must be at least {0} satoshi/byte setting.preferences.txFeeTooLarge=Your input is above any reasonable value (>5000 satoshi/byte). Transaction fee is usually in the range of 50-400 satoshi/byte. setting.preferences.ignorePeers=Ignore peers with onion address (comma sep.): setting.preferences.currenciesInList=Currencies in market price feed list @@ -1560,14 +1564,6 @@ LTC_MAINNET=Litecoin Mainnet LTC_TESTNET=Litecoin Testnet # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin Regtest - -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin Mainnet -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin Testnet -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH Mainnet # suppress inspection "UnusedProperty" @@ -1629,6 +1625,7 @@ seed.restore.error=An error occurred when restoring the wallets with seed words. # Payment methods #################################################################### +payment.account=Account payment.account.no=Account no.: payment.account.name=Account name: payment.account.owner=Account owner full name @@ -1648,9 +1645,6 @@ payment.restore.default=No, restore default currency payment.email=Email: payment.country=Country: payment.extras=Extra requirements: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\n\ - Please use one of the available payment methods for the US like: \ - \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" or \"Cash Deposit\". payment.email.mobile=Email or mobile no.: payment.altcoin.address=Altcoin address: payment.altcoin=Altcoin: @@ -1658,7 +1652,13 @@ payment.select.altcoin=Select or search altcoin payment.secret=Secret question: payment.answer=Answer: payment.wallet=Wallet ID: -payment.supported.okpay=Supported currencies: +payment.uphold.accountId=Username or email or phone no.: +payment.cashApp.cashTag=$Cashtag: +payment.moneyBeam.accountId=Email or phone no.: +payment.venmo.venmoUserName=Venmo username: +payment.popmoney.accountId=Email or phone no.: +payment.revolut.accountId=Email or phone no.: +payment.supportedCurrencies=Supported currencies: payment.limitations=Limitations: payment.salt=Salt for account age verification: payment.error.noHexSalt=The salt need to be in HEX format.\n\ @@ -1703,6 +1703,7 @@ before starting a trade or creating an offer.\n\n\ \t● FirstBank Person to Person Transfers\n\ \t● Frost Send Money\n\ \t● U.S. Bank Send Money\n\ +\t● TD Bank\n\ \t● Wells Fargo SurePay\n\n\ 3. You need to be sure to not exceed the daily or monthly Zelle (ClearXchange) transfer limits.\n\n\ Please use Zelle (ClearXchange) only if you fulfill all those requirements, \ @@ -1715,6 +1716,20 @@ to get in contact with the {1} buyer by using the provided email address or mobi payment.westernUnion.info=When using Western Union the BTC buyer has to send the MTCN (tracking number) and a photo of the receipt by email to the BTC seller. \ The receipt must clearly show the seller''s full name, city, country and the amount. The buyer will get displayed the seller''s email in the trade process. +payment.limits.info=Please be aware that all bank transfers carry a certain amount of chargeback risk.\n\ + \n\ + To mitigate this risk, Bisq sets per-trade limits based on two factors:\n\ + \n\ + 1. The estimated level of chargeback risk for the payment method used\n\ + 2. The age of your account for that payment method\n\ + \n\ + The account you are creating now is new and its age is zero. As your account grows in age over a two-month period, your per-trade limits will grow along with it:\n\ + \n\ + ● During the 1st month, your per-trade limit will be {0}\n\ + ● During the 2nd month, your per-trade limit will be {1}\n\ + ● After the 2nd month, your per-trade limit will be {2}\n\ + \n\ + Please note that there are no limits on the total number of times you can trade. # We use constants from the code so we do not use our normal naming convention # dynamic values are not recognized by IntelliJ @@ -1741,6 +1756,12 @@ WESTERN_UNION_SHORT=Western Union # Do not translate brand names OK_PAY=OKPay +UPHOLD=Uphold +CASH_APP=Cash App +MONEY_BEAM=MoneyBeam (N26) +VENMO=Venmo +POPMONEY=Popmoney +REVOLUT=Revolut PERFECT_MONEY=Perfect Money ALI_PAY=AliPay SEPA=SEPA @@ -1755,6 +1776,18 @@ BLOCK_CHAINS=Altcoins # suppress inspection "UnusedProperty" OK_PAY_SHORT=OKPay # suppress inspection "UnusedProperty" +UPHOLD_SHORT=Uphold +# suppress inspection "UnusedProperty" +CASH_APP_SHORT=Cash App +# suppress inspection "UnusedProperty" +MONEY_BEAM_SHORT=MoneyBeam (N26) +# suppress inspection "UnusedProperty" +VENMO_SHORT=Venmo +# suppress inspection "UnusedProperty" +POPMONEY_SHORT=Popmoney +# suppress inspection "UnusedProperty" +REVOLUT_SHORT=Revolut +# suppress inspection "UnusedProperty" PERFECT_MONEY_SHORT=Perfect Money # suppress inspection "UnusedProperty" ALI_PAY_SHORT=AliPay diff --git a/common/src/main/resources/i18n/displayStrings_de.properties b/common/src/main/resources/i18n/displayStrings_de.properties index afc9869c4d..36d7a2eb11 100644 --- a/common/src/main/resources/i18n/displayStrings_de.properties +++ b/common/src/main/resources/i18n/displayStrings_de.properties @@ -1326,13 +1326,6 @@ LTC_TESTNET=Litecoin-Testnetzwerk # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin-Regtest -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin-Hauptnetzwerk -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin-Testnetzwerk -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin-Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH-Hauptnetz # suppress inspection "UnusedProperty" @@ -1401,7 +1394,6 @@ payment.restore.default=Nein, Standardwährung wiederherstellen payment.email=E-Mail: payment.country=Land: payment.extras=Besondere Anforderungen: -payment.us.info=Überweisungen mit WIRE oder ACH werden in den USA nicht unterstützt, da WIRE zu teuer ist und ACH ein hohes Rückbuchungsrisikio beinhaltet.\n\nBitte nutzen Sie stattdessen die Zahlungsmethoden \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" oder \"Cash Deposit\". payment.email.mobile=E-Mail oder Telefonnummer: payment.altcoin.address=Altcoin-Adresse: payment.altcoin=Altcoin: @@ -1409,7 +1401,7 @@ payment.select.altcoin=Altcoin wählen oder suchen payment.secret=Geheimfrage: payment.answer=Antwort: payment.wallet=Wallet-ID: -payment.supported.okpay=Unterstützte Währungen: +payment.supportedCurrencies=Unterstützte Währungen: payment.limitations=Einschränkungen: payment.accept.euro=Händel aus diesen Euroländern akzeptieren: payment.accept.nonEuro=Händel aus diesen Nicht-Euroländern akzeptieren: diff --git a/common/src/main/resources/i18n/displayStrings_el.properties b/common/src/main/resources/i18n/displayStrings_el.properties index 994a26e00f..6162fc07b1 100644 --- a/common/src/main/resources/i18n/displayStrings_el.properties +++ b/common/src/main/resources/i18n/displayStrings_el.properties @@ -1281,13 +1281,6 @@ LTC_TESTNET=Litecoin Testnet # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin Regtest -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin Mainnet -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin Testnet -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH Mainnet # suppress inspection "UnusedProperty" @@ -1356,7 +1349,6 @@ payment.restore.default=Όχι, επανάφερε το προεπιλεγμέ payment.email=Email: payment.country=Χώρα: payment.extras=Επιπλέον προαπαιτήσεις: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\nPlease use one of the available payment methods for the US like: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" or \"Cash Deposit\". payment.email.mobile=Email ή αριθμός κινητού: payment.altcoin.address=Διεύθυνση altcoin: payment.altcoin=Altcoin: @@ -1364,7 +1356,7 @@ payment.select.altcoin=Διάλεξε ή αναζήτησε altcoin: payment.secret=Ερώτηση ασφάλειας: payment.answer=Απάντηση: payment.wallet=Ταυτότητα πορτοφολιού: -payment.supported.okpay= Υποστηριζόμενα νομίσματα: +payment.supportedCurrencies=Υποστηριζόμενα νομίσματα: payment.limitations=Περιορισμοί: payment.accept.euro=Αποδοχή συναλλαγών από τις ακόλουθες χώρες Ευρώ: payment.accept.nonEuro=Αποδοχή συναλλαγών από τις ακόλουθες χώρες εκτός Ευρώ: diff --git a/common/src/main/resources/i18n/displayStrings_es.properties b/common/src/main/resources/i18n/displayStrings_es.properties index 9bb9b8bacd..44ba87502a 100644 --- a/common/src/main/resources/i18n/displayStrings_es.properties +++ b/common/src/main/resources/i18n/displayStrings_es.properties @@ -1281,13 +1281,6 @@ LTC_TESTNET=Testnet Litecoin # suppress inspection "UnusedProperty" LTC_REGTEST=Regtest Litecoin -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Red principal Dogecoin -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Testnet Dogecoin -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Regtest Dogecoin - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH Mainnet # suppress inspection "UnusedProperty" @@ -1356,7 +1349,6 @@ payment.restore.default=No, restaurar moneda por defecto. payment.email=Email: payment.country=País: payment.extras=Requisitos extra: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\nPlease use one of the available payment methods for the US like: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" or \"Cash Deposit\". payment.email.mobile=Email o número de móvil: payment.altcoin.address=Dirección de altcoin: payment.altcoin=Altcoin: @@ -1364,7 +1356,7 @@ payment.select.altcoin=Seleccione o busque altcoin payment.secret=Pregunta secreta: payment.answer=Respuesta: payment.wallet=ID de cartera: -payment.supported.okpay=Monedas soportadas: +payment.supportedCurrencies=Monedas soportadas: payment.limitations=Límitaciones: payment.accept.euro=Aceptar intercambios desde estos países Euro. payment.accept.nonEuro=Aceptar intercambios desde estos países no-Euro: diff --git a/common/src/main/resources/i18n/displayStrings_hu.properties b/common/src/main/resources/i18n/displayStrings_hu.properties index c202524795..4d716770d6 100644 --- a/common/src/main/resources/i18n/displayStrings_hu.properties +++ b/common/src/main/resources/i18n/displayStrings_hu.properties @@ -1405,13 +1405,6 @@ LTC_TESTNET=Litecoin Testnet # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin Regtest -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin Mainnet -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin Testnet -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH főhálozat # suppress inspection "UnusedProperty" @@ -1484,7 +1477,6 @@ payment.restore.default=Nem, alapértelmezett valuta visszaállítása payment.email=E-mail: payment.country=Ország: payment.extras=Extra követelmények: -payment.us.info=A WIRE vagy ACH átutalása nem támogatott az Egyesült Államokban, mivel hogy a WIRE túl drága és az ACH magas visszaterhelési kockázattal jár.\n\nHasználja helyette a következő fizetési módokat: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Posta Pénz Rendelés\" vagy \"Készpénz befizetése\". payment.email.mobile=E-mail vagy mobil: payment.altcoin.address=Altérmék cím: payment.altcoin=Altérme: @@ -1492,7 +1484,7 @@ payment.select.altcoin=Válassz vagy keress altérmét payment.secret=Titkos kérdés: payment.answer=Válasz: payment.wallet=Pénztárca azonosító: -payment.supported.okpay=Támogatott valuták: +payment.supportedCurrencies=Támogatott valuták: payment.limitations=Korlátozások: payment.salt=Só a fiók korhatár ellenőrzéséhez: payment.error.noHexSalt=A sónak HEX formátumban kell lennie.\nCsak akkor ajánlatos szerkeszteni a só mezőt, ha át szeretné vinni a sót egy régebbi fiókból, a fiók korának megőrzése érdekében. A fiók korát a fiók sójának és az azonosító számlaadatok (pl. IBAN) használatával lesz ellenőrizve. diff --git a/common/src/main/resources/i18n/displayStrings_pt.properties b/common/src/main/resources/i18n/displayStrings_pt.properties index 15a8efe4d9..0c09adeb0a 100644 --- a/common/src/main/resources/i18n/displayStrings_pt.properties +++ b/common/src/main/resources/i18n/displayStrings_pt.properties @@ -1281,13 +1281,6 @@ LTC_TESTNET=Litecoin Testnet # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin Regtest -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin Mainnet -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin Testnet -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH Mainnet # suppress inspection "UnusedProperty" @@ -1356,7 +1349,6 @@ payment.restore.default=Não, resturar para a moeda padrão payment.email=Email: payment.country=País: payment.extras=Requerimentos adicionais: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\nPlease use one of the available payment methods for the US like: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" or \"Cash Deposit\". payment.email.mobile=Email ou celular: payment.altcoin.address=Endereço altcoin: payment.altcoin=Altcoin: @@ -1364,7 +1356,7 @@ payment.select.altcoin=Selecionar ou buscar altcoin payment.secret=Pergunta secreta: payment.answer=Resposta: payment.wallet=ID da carteira: -payment.supported.okpay=Moedas suportadas: +payment.supportedCurrencies=Moedas suportadas: payment.limitations=Limitações: payment.accept.euro=Aceitar negociações destes países do Euro: payment.accept.nonEuro=Aceitar negociações desses países fora do Euro: diff --git a/common/src/main/resources/i18n/displayStrings_ro.properties b/common/src/main/resources/i18n/displayStrings_ro.properties index 6e951b5818..23f1c36843 100644 --- a/common/src/main/resources/i18n/displayStrings_ro.properties +++ b/common/src/main/resources/i18n/displayStrings_ro.properties @@ -1405,13 +1405,6 @@ LTC_TESTNET=Litecoin Testnet # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin Regtest -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin Mainnet -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin Testnet -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=Rețeaua principală DASH # suppress inspection "UnusedProperty" @@ -1484,7 +1477,6 @@ payment.restore.default=Nu, restaurează valuta prestabilită payment.email=E-mail: payment.country=Țara: payment.extras=Cerințe extra: -payment.us.info=Transferul bancar cu WIRE sau ACH nu sunt acceptate pentru SUA, deoarece WIRE este prea scump și ACH are un risc prea mare de rambursare.\n\nTe rugăm să folosești mai degrabă metode de plată disponibile în SUA precum: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"Ordin de plată poștală SUA\" sau \"Depozit Numerar\". payment.email.mobile=E-mail sau nr. mobil: payment.altcoin.address=Adresă altcoin: payment.altcoin=Altcoin: @@ -1492,7 +1484,7 @@ payment.select.altcoin=Selectează sau caută altcoin payment.secret=Întrebarea secretă: payment.answer=Răspuns: payment.wallet=Cod portofel: -payment.supported.okpay=Valute acceptate: +payment.supportedCurrencies=Valute acceptate: payment.limitations=Limite: payment.salt=Sare pentru verificarea vechimii contului: payment.error.noHexSalt=Sarea trebuie să fie în format HEX.\nSe recomandă editarea câmpul de sare dacă dorești să transferi sarea dintr-un cont vechi pentru a păstra vechimea contului. Vechimea contului este verificată folosind sarea contului și datele de identificare ale acestuia (de exemplu codul IBAN). diff --git a/common/src/main/resources/i18n/displayStrings_ru.properties b/common/src/main/resources/i18n/displayStrings_ru.properties index e4023be8de..d89cc6b885 100644 --- a/common/src/main/resources/i18n/displayStrings_ru.properties +++ b/common/src/main/resources/i18n/displayStrings_ru.properties @@ -1281,13 +1281,6 @@ LTC_TESTNET=Litecoin Тест-сеть # suppress inspection "UnusedProperty" LTC_REGTEST=Litecoin Регистр.-тест -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogecoin основная сеть -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogecoin тест-сеть -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogecoin Регистр. -тест - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH Mainnet # suppress inspection "UnusedProperty" @@ -1356,7 +1349,6 @@ payment.restore.default=Нет, восстановить валюту по ум payment.email=Электронная почта: payment.country=Страна: payment.extras=Дополнительные требования: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\nPlease use one of the available payment methods for the US like: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" or \"Cash Deposit\". payment.email.mobile=Электронная почта или номер моб. тел.: payment.altcoin.address=Альткоин-адрес: payment.altcoin=Альткоин: @@ -1364,7 +1356,7 @@ payment.select.altcoin=Выбор или поиск альткоин payment.secret=Секретный вопрос: payment.answer=Ответ: payment.wallet=Идентификатор кошелька: -payment.supported.okpay=Поддерживаемые валюты: +payment.supportedCurrencies=Поддерживаемые валюты: payment.limitations=Ограничения: payment.accept.euro=Принять сделки от этих стран Евро: payment.accept.nonEuro=Примите сделки от этих не- Евро стран: diff --git a/common/src/main/resources/i18n/displayStrings_sr.properties b/common/src/main/resources/i18n/displayStrings_sr.properties index 16920a37de..a9d592ede7 100644 --- a/common/src/main/resources/i18n/displayStrings_sr.properties +++ b/common/src/main/resources/i18n/displayStrings_sr.properties @@ -1281,13 +1281,6 @@ LTC_TESTNET=Lajtkoin Testnet # suppress inspection "UnusedProperty" LTC_REGTEST=Lajtkoin Regtest -# suppress inspection "UnusedProperty" -DOGE_MAINNET=Dogekoin Mejnnet -# suppress inspection "UnusedProperty" -DOGE_TESTNET=Dogekoin Testnet -# suppress inspection "UnusedProperty" -DOGE_REGTEST=Dogekoin Regtest - # suppress inspection "UnusedProperty" DASH_MAINNET=DASH Mainnet # suppress inspection "UnusedProperty" @@ -1356,7 +1349,6 @@ payment.restore.default=Ne, vrati podrazumevanu valutu payment.email=Email: payment.country=Država: payment.extras=Dodatni zahtevi: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\nPlease use one of the available payment methods for the US like: \"Zelle (ClearXchange)\", \"Chase QuickPay\", \"US Postal Money Order\" or \"Cash Deposit\". payment.email.mobile=Email ili br. mobilnog: payment.altcoin.address=Altkoin adresa: payment.altcoin=Altkoin: @@ -1364,7 +1356,7 @@ payment.select.altcoin=Izaberi ili traži altkoin payment.secret=Tajno pitanje: payment.answer=Odgovor: payment.wallet=ID novčanika: -payment.supported.okpay=Podržane valute: +payment.supportedCurrencies=Podržane valute: payment.limitations=Ograničenja: payment.accept.euro=Prihvati trgovine od ovih Euro država: payment.accept.nonEuro=Prihvati trgovine od ovih ne-Euro država: diff --git a/common/src/main/resources/i18n/displayStrings_zh.properties b/common/src/main/resources/i18n/displayStrings_zh.properties index f0e3b6b246..54db2683af 100644 --- a/common/src/main/resources/i18n/displayStrings_zh.properties +++ b/common/src/main/resources/i18n/displayStrings_zh.properties @@ -1281,13 +1281,6 @@ LTC_TESTNET=莱特币测试网络 # suppress inspection "UnusedProperty" LTC_REGTEST=莱特币回归测试 -# suppress inspection "UnusedProperty" -DOGE_MAINNET=狗狗币主干网络 -# suppress inspection "UnusedProperty" -DOGE_TESTNET=狗狗币测试网络 -# suppress inspection "UnusedProperty" -DOGE_REGTEST=狗狗币回归测试 - # suppress inspection "UnusedProperty" DASH_MAINNET=达世币主干网络 # suppress inspection "UnusedProperty" @@ -1356,7 +1349,6 @@ payment.restore.default=不,恢复默认值 payment.email=电子邮箱: payment.country=国家: payment.extras=额外要求: -payment.us.info=不支持美国银行使用WIRE或ACH方式的转账. 因为WIRE方式太昂贵而ACH方式有很高的撤销风险.\n请使用\"ClearXchange\", \"US Postal Money Order\" 或 \"Cash/ATM Deposit\" 支付方式. payment.email.mobile=电子邮箱或手机号码: payment.altcoin.address=数字货币地址: payment.altcoin=数字货币: @@ -1364,7 +1356,7 @@ payment.select.altcoin=选择或搜索数字货币 payment.secret=密保问题: payment.answer=答案: payment.wallet=钱包ID: -payment.supported.okpay=支持的货币: +payment.supportedCurrencies=支持的货币: payment.limitations=限制条件: payment.accept.euro=接受来自这些欧元国家的交易: payment.accept.nonEuro=接受来自这些非欧元国家的交易: diff --git a/common/src/main/resources/i18n/in_dev/displayStrings_fr.properties b/common/src/main/resources/i18n/in_dev/displayStrings_fr.properties index 83a9e3eb54..1526fb5832 100644 --- a/common/src/main/resources/i18n/in_dev/displayStrings_fr.properties +++ b/common/src/main/resources/i18n/in_dev/displayStrings_fr.properties @@ -45,7 +45,6 @@ payment.email=Email: payment.country=Country: payment.owner.email=Account holder email: payment.extras=Extra requirements: -payment.us.info=Bank transfer with WIRE or ACH is not supported for the US because WIRE is too expensive and ACH has a high chargeback risk.\n\nPlease use payment methods \"Zelle (ClearXchange)\", \"US Postal Money Order\" or \"Cash Deposit\" instead. payment.email.mobile=Email or mobile no.: payment.altcoin.address=Altcoin address: payment.address=address: diff --git a/consensus/pom.xml b/consensus/pom.xml index 75343cdf2b..34af05fe64 100644 --- a/consensus/pom.xml +++ b/consensus/pom.xml @@ -5,7 +5,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0 diff --git a/core/pom.xml b/core/pom.xml index a6c9c90190..12792bc63d 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -6,7 +6,7 @@ parent io.bisq - 0.6.5 + 0.6.6 core diff --git a/core/src/main/java/io/bisq/core/btc/BaseCurrencyNetwork.java b/core/src/main/java/io/bisq/core/btc/BaseCurrencyNetwork.java index d56a432bf8..a66d4af168 100644 --- a/core/src/main/java/io/bisq/core/btc/BaseCurrencyNetwork.java +++ b/core/src/main/java/io/bisq/core/btc/BaseCurrencyNetwork.java @@ -20,7 +20,6 @@ package io.bisq.core.btc; import io.bisq.core.app.BisqEnvironment; import io.bisq.core.provider.fee.FeeService; import lombok.Getter; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; @@ -36,10 +35,6 @@ public enum BaseCurrencyNetwork { LTC_TESTNET(LitecoinTestNet3Params.get(), "LTC", "TESTNET", "Litecoin"), LTC_REGTEST(LitecoinRegTestParams.get(), "LTC", "REGTEST", "Litecoin"), - DOGE_MAINNET(DogecoinMainNetParams.get(), "DOGE", "MAINNET", "Dogecoin"), - DOGE_TESTNET(DogecoinTestNet3Params.get(), "DOGE", "TESTNET", "Dogecoin"), - DOGE_REGTEST(DogecoinRegTestParams.get(), "DOGE", "REGTEST", "Dogecoin"), - DASH_MAINNET(DashMainNetParams.get(), "DASH", "MAINNET", "Dash"), DASH_TESTNET(DashTestNet3Params.get(), "DASH", "TESTNET", "Dash"), DASH_REGTEST(DashRegTestParams.get(), "DASH", "REGTEST", "Dash"); @@ -80,21 +75,14 @@ public enum BaseCurrencyNetwork { return "DASH".equals(currencyCode); } - public boolean isDoge() { - return "DOGE".equals(currencyCode); - } - - - public Coin getDefaultMinFee() { + public long getDefaultMinFeePerByte() { switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) { case "BTC": - return FeeService.BTC_REFERENCE_DEFAULT_MIN_TX_FEE; + return FeeService.BTC_REFERENCE_DEFAULT_MIN_TX_FEE_PER_KB.divide(1000).value; case "LTC": - return FeeService.LTC_REFERENCE_DEFAULT_MIN_TX_FEE; - case "DOGE": - return FeeService.DOGE_REFERENCE_DEFAULT_MIN_TX_FEE; + return FeeService.LTC_REFERENCE_DEFAULT_MIN_TX_FEE.value; case "DASH": - return FeeService.DASH_REFERENCE_DEFAULT_MIN_TX_FEE; + return FeeService.DASH_REFERENCE_DEFAULT_MIN_TX_FEE.value; default: throw new RuntimeException("Unsupported code at getDefaultMinFee: " + BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()); } diff --git a/core/src/main/java/io/bisq/core/btc/Restrictions.java b/core/src/main/java/io/bisq/core/btc/Restrictions.java index cea1ded3af..63cc559d16 100644 --- a/core/src/main/java/io/bisq/core/btc/Restrictions.java +++ b/core/src/main/java/io/bisq/core/btc/Restrictions.java @@ -54,9 +54,6 @@ public class Restrictions { case "LTC": MIN_TRADE_AMOUNT = Coin.valueOf(100_000); // 0.04 EUR @ 40 EUR/LTC break; - case "DOGE": - MIN_TRADE_AMOUNT = Coin.valueOf(1_000_000_000L); // 0.03 EUR at DOGE price 0.003 EUR; - break; case "DASH": MIN_TRADE_AMOUNT = Coin.valueOf(20_000L); // 0.03 EUR at @ 150 EUR/DASH; break; @@ -74,9 +71,6 @@ public class Restrictions { case "LTC": MAX_BUYER_SECURITY_DEPOSIT = Coin.valueOf(1_200_000_000); // 500 EUR @ 40 EUR/LTC break; - case "DOGE": - MAX_BUYER_SECURITY_DEPOSIT = Coin.valueOf(20_000_000_000_000L); // 500 EUR @ 0.0025 EUR/DOGE; - break; case "DASH": MAX_BUYER_SECURITY_DEPOSIT = Coin.valueOf(300_000_000L); // 450 EUR @ 150 EUR/DASH; break; @@ -94,9 +88,6 @@ public class Restrictions { case "LTC": MIN_BUYER_SECURITY_DEPOSIT = Coin.valueOf(6_000_000); // 2.4 EUR @ 40 EUR/LTC break; - case "DOGE": - MIN_BUYER_SECURITY_DEPOSIT = Coin.valueOf(100_000_000_000L); // 2.5 EUR @ 0.0025 EUR/DOGE; - break; case "DASH": MIN_BUYER_SECURITY_DEPOSIT = Coin.valueOf(1_500_000L); // 2.5 EUR @ 150 EUR/DASH; break; @@ -113,9 +104,6 @@ public class Restrictions { case "LTC": DEFAULT_BUYER_SECURITY_DEPOSIT = Coin.valueOf(200_000_000); // 75 EUR @ 40 EUR/LTC break; - case "DOGE": - DEFAULT_BUYER_SECURITY_DEPOSIT = Coin.valueOf(3_000_000_000_000L); // 75 EUR @ 0.0025 EUR/DOGE; - break; case "DASH": DEFAULT_BUYER_SECURITY_DEPOSIT = Coin.valueOf(50_000_000L); // 75 EUR @ 150 EUR/DASH; break; @@ -132,9 +120,6 @@ public class Restrictions { case "LTC": SELLER_SECURITY_DEPOSIT = Coin.valueOf(60_000_000); // 25 EUR @ 40 EUR/LTC break; - case "DOGE": - SELLER_SECURITY_DEPOSIT = Coin.valueOf(1_000_000_000_000L); // 25 EUR @ 0.0025 EUR/DOGE; - break; case "DASH": SELLER_SECURITY_DEPOSIT = Coin.valueOf(15_000_000L); // 25 EUR @ 150 EUR/DASH; break; diff --git a/core/src/main/java/io/bisq/core/btc/wallet/BtcWalletService.java b/core/src/main/java/io/bisq/core/btc/wallet/BtcWalletService.java index 67f9b1f9cc..0ce78b3bf5 100644 --- a/core/src/main/java/io/bisq/core/btc/wallet/BtcWalletService.java +++ b/core/src/main/java/io/bisq/core/btc/wallet/BtcWalletService.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import io.bisq.common.handlers.ErrorMessageHandler; -import io.bisq.core.app.BisqEnvironment; import io.bisq.core.btc.*; import io.bisq.core.btc.exceptions.TransactionVerificationException; import io.bisq.core.btc.exceptions.WalletException; @@ -293,6 +292,7 @@ public class BtcWalletService extends WalletService { int numInputs = preparedBsqTxInputs.size() + 1; // We add 1 for the BTC fee input Transaction resultTx = null; boolean isFeeOutsideTolerance; + boolean opReturnIsOnlyOutput; do { counter++; if (counter >= 10) { @@ -331,7 +331,8 @@ public class BtcWalletService extends WalletService { // We might have the rare case that both inputs matched the required fees, so both did not require // a change output. // In such cases we need to add artificially a change output (OP_RETURN is not allowed as only output) - forcedChangeValue = resultTx.getOutputs().size() == 0 ? Restrictions.getMinNonDustOutput() : Coin.ZERO; + opReturnIsOnlyOutput = resultTx.getOutputs().size() == 0; + forcedChangeValue = opReturnIsOnlyOutput ? Restrictions.getMinNonDustOutput() : Coin.ZERO; // add OP_RETURN output if (opReturnData != null) @@ -343,7 +344,9 @@ public class BtcWalletService extends WalletService { // calculated fee must be inside of a tolerance range with tx fee isFeeOutsideTolerance = Math.abs(resultTx.getFee().value - estimatedFeeAsLong) > 1000; } - while (forcedChangeValue.isPositive() || isFeeOutsideTolerance); + while (opReturnIsOnlyOutput || + isFeeOutsideTolerance || + resultTx.getFee().value < txFeePerByte.multiply(resultTx.bitcoinSerialize().length).value); // Sign all BTC inputs for (int i = preparedBsqTxInputs.size(); i < resultTx.getInputs().size(); i++) { @@ -603,10 +606,6 @@ public class BtcWalletService extends WalletService { do { counter++; fee = txFeeForWithdrawalPerByte.multiply(txSize); - final Coin defaultMinFee = BisqEnvironment.getBaseCurrencyNetwork().getDefaultMinFee(); - if (fee.compareTo(defaultMinFee) < 0) - fee = defaultMinFee; - newTransaction.clearOutputs(); newTransaction.addOutput(amount.subtract(fee), toAddress); @@ -621,9 +620,10 @@ public class BtcWalletService extends WalletService { tx = sendRequest.tx; txSize = tx.bitcoinSerialize().length; printTx("FeeEstimationTransaction", tx); - sendRequest.tx.getOutputs().stream().forEach(o -> log.debug("Output value " + o.getValue().toFriendlyString())); + sendRequest.tx.getOutputs().forEach(o -> log.debug("Output value " + o.getValue().toFriendlyString())); } - while (counter < 10 && Math.abs(tx.getFee().value - txFeeForWithdrawalPerByte.multiply(txSize).value) > 1000); + while (feeEstimationNotSatisfied(counter, tx)); + if (counter == 10) log.error("Could not calculate the fee. Tx=" + tx); @@ -722,17 +722,13 @@ public class BtcWalletService extends WalletService { do { counter++; fee = txFeeForWithdrawalPerByte.multiply(txSize); - final Coin defaultMinFee = BisqEnvironment.getBaseCurrencyNetwork().getDefaultMinFee(); - if (fee.compareTo(defaultMinFee) < 0) - fee = defaultMinFee; - SendRequest sendRequest = getSendRequest(fromAddress, toAddress, amount, fee, aesKey, context); wallet.completeTx(sendRequest); tx = sendRequest.tx; txSize = tx.bitcoinSerialize().length; printTx("FeeEstimationTransaction", tx); } - while (counter < 10 && Math.abs(tx.getFee().value - txFeeForWithdrawalPerByte.multiply(txSize).value) > 1000); + while (feeEstimationNotSatisfied(counter, tx)); if (counter == 10) log.error("Could not calculate the fee. Tx=" + tx); @@ -773,9 +769,6 @@ public class BtcWalletService extends WalletService { do { counter++; fee = txFeeForWithdrawalPerByte.multiply(txSize); - final Coin defaultMinFee = BisqEnvironment.getBaseCurrencyNetwork().getDefaultMinFee(); - if (fee.compareTo(defaultMinFee) < 0) - fee = defaultMinFee; // We use a dummy address for the output SendRequest sendRequest = getSendRequestForMultipleAddresses(fromAddresses, getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddressString(), amount, fee, null, aesKey); wallet.completeTx(sendRequest); @@ -783,7 +776,7 @@ public class BtcWalletService extends WalletService { txSize = tx.bitcoinSerialize().length; printTx("FeeEstimationTransactionForMultipleAddresses", tx); } - while (counter < 10 && Math.abs(tx.getFee().value - txFeeForWithdrawalPerByte.multiply(txSize).value) > 1000); + while (feeEstimationNotSatisfied(counter, tx)); if (counter == 10) log.error("Could not calculate the fee. Tx=" + tx); @@ -795,6 +788,14 @@ public class BtcWalletService extends WalletService { } } + private boolean feeEstimationNotSatisfied(int counter, Transaction tx) { + long targetFee = getTxFeeForWithdrawalPerByte().multiply(tx.bitcoinSerialize().length).value; + return counter < 10 && + (tx.getFee().value < targetFee || + tx.getFee().value - targetFee > 1000); + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Withdrawal Send /////////////////////////////////////////////////////////////////////////////////////////// @@ -873,7 +874,7 @@ public class BtcWalletService extends WalletService { "The amount is too low (dust limit)."); final Coin netValue = amount.subtract(fee); - if(netValue.isNegative()) + if (netValue.isNegative()) throw new InsufficientMoneyException(netValue.multiply(-1), "The mining fee for that transaction exceed the available amount."); tx.addOutput(netValue, Address.fromBase58(params, toAddress)); diff --git a/core/src/main/java/io/bisq/core/btc/wallet/WalletService.java b/core/src/main/java/io/bisq/core/btc/wallet/WalletService.java index e32c956be3..23c8da8ca4 100644 --- a/core/src/main/java/io/bisq/core/btc/wallet/WalletService.java +++ b/core/src/main/java/io/bisq/core/btc/wallet/WalletService.java @@ -427,7 +427,7 @@ public abstract class WalletService { return outputs; } - Coin getTxFeeForWithdrawalPerByte() { + public Coin getTxFeeForWithdrawalPerByte() { Coin fee = (preferences.isUseCustomWithdrawalTxFee()) ? Coin.valueOf(preferences.getWithdrawalTxFeeInBytes()) : feeService.getTxFeePerByte(); diff --git a/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java b/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java index 49eb54e8a3..53219e7b55 100644 --- a/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java +++ b/core/src/main/java/io/bisq/core/network/CoreSeedNodesRepository.java @@ -115,9 +115,6 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { new NodeAddress("acyvotgewx46pebw.onion:8003"), new NodeAddress("pklgy3vdfn3obkur.onion:8003"), - // DOGE mainnet - // new NodeAddress("t6bwuj75mvxswavs.onion:8006"), removed in version 0.6 (DOGE not supported anymore) - // DASH mainnet new NodeAddress("toeu5ikb27ydscxt.onion:8009"), new NodeAddress("ae4yvaivhnekkhqf.onion:8009") @@ -151,9 +148,6 @@ public class CoreSeedNodesRepository implements SeedNodesRepository { // regtest new NodeAddress("localhost:2005"), - // DOGE regtest - new NodeAddress("localhost:2008"), - // DASH regtest new NodeAddress("localhost:2011") ); diff --git a/core/src/main/java/io/bisq/core/offer/OfferBookService.java b/core/src/main/java/io/bisq/core/offer/OfferBookService.java index 6ef7deb6d6..bd2dd2038b 100644 --- a/core/src/main/java/io/bisq/core/offer/OfferBookService.java +++ b/core/src/main/java/io/bisq/core/offer/OfferBookService.java @@ -144,6 +144,14 @@ public class OfferBookService { } } + public void activateOffer(Offer offer, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) { + addOffer(offer, resultHandler, errorMessageHandler); + } + + public void deactivateOffer(OfferPayload offerPayload, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) { + removeOffer(offerPayload, resultHandler, errorMessageHandler); + } + public void removeOffer(OfferPayload offerPayload, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) { if (p2PService.removeData(offerPayload, true)) { log.trace("Remove offer from network was successful. OfferPayload ID = " + offerPayload.getId()); diff --git a/core/src/main/java/io/bisq/core/offer/OpenOffer.java b/core/src/main/java/io/bisq/core/offer/OpenOffer.java index c28ea0e4d1..e10a7ed48b 100644 --- a/core/src/main/java/io/bisq/core/offer/OpenOffer.java +++ b/core/src/main/java/io/bisq/core/offer/OpenOffer.java @@ -19,6 +19,7 @@ package io.bisq.core.offer; import io.bisq.common.Timer; import io.bisq.common.UserThread; +import io.bisq.common.proto.ProtoUtil; import io.bisq.common.storage.Storage; import io.bisq.core.trade.Tradable; import io.bisq.core.trade.TradableList; @@ -40,29 +41,34 @@ public final class OpenOffer implements Tradable { AVAILABLE, RESERVED, CLOSED, - CANCELED + CANCELED, + DEACTIVATED } @Getter private final Offer offer; @Getter - private State state = State.AVAILABLE; + private State state; transient private Storage> storage; public OpenOffer(Offer offer, Storage> storage) { this.offer = offer; this.storage = storage; + state = State.AVAILABLE; } /////////////////////////////////////////////////////////////////////////////////////////// // PROTO BUFFER /////////////////////////////////////////////////////////////////////////////////////////// - private OpenOffer(Offer offer) { + private OpenOffer(Offer offer, State state) { this.offer = offer; - } + this.state = state; + if (this.state == State.RESERVED) + setState(State.AVAILABLE); + } @Override public PB.Tradable toProtoMessage() { @@ -73,11 +79,8 @@ public final class OpenOffer implements Tradable { } public static Tradable fromProto(PB.OpenOffer proto) { - OpenOffer openOffer = new OpenOffer(Offer.fromProto(proto.getOffer())); - // If we have a reserved state from the local db we reset it - if (openOffer.getState() == State.RESERVED) - openOffer.setState(State.AVAILABLE); - return openOffer; + return new OpenOffer(Offer.fromProto(proto.getOffer()), + ProtoUtil.enumFromProto(OpenOffer.State.class, proto.getState().name())); } @@ -118,6 +121,10 @@ public final class OpenOffer implements Tradable { stopTimeout(); } + public boolean isDeactivated() { + return state == State.DEACTIVATED; + } + private void startTimeout() { stopTimeout(); diff --git a/core/src/main/java/io/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/io/bisq/core/offer/OpenOfferManager.java index 24fda8c9d7..4de1a1e759 100644 --- a/core/src/main/java/io/bisq/core/offer/OpenOfferManager.java +++ b/core/src/main/java/io/bisq/core/offer/OpenOfferManager.java @@ -327,7 +327,30 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } } - // Remove from my offers + public void activateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + Offer offer = openOffer.getOffer(); + openOffer.setStorage(openOfferTradableListStorage); + offerBookService.activateOffer(offer, + () -> { + openOffer.setState(OpenOffer.State.AVAILABLE); + log.debug("activateOpenOffer, offerId={}", offer.getId()); + resultHandler.handleResult(); + }, + errorMessageHandler); + } + + public void deactivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + Offer offer = openOffer.getOffer(); + openOffer.setStorage(openOfferTradableListStorage); + offerBookService.deactivateOffer(offer.getOfferPayload(), + () -> { + openOffer.setState(OpenOffer.State.DEACTIVATED); + log.debug("deactivateOpenOffer, offerId={}", offer.getId()); + resultHandler.handleResult(); + }, + errorMessageHandler); + } + public void removeOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { Offer offer = openOffer.getOffer(); offerBookService.removeOffer(offer.getOfferPayload(), @@ -483,13 +506,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe final OpenOffer openOffer = openOffersList.get(i); UserThread.runAfterRandomDelay(() -> { if (openOffers.contains(openOffer)) { - // The openOffer.getId().contains("_") check is because there was once a version - // where we encoded the version nr in the offer id with a "_" as separator. - // That caused several issues and was reverted. So if there are still old offers out with that - // special offer ID format those must not be published as they cause failed taker attempts - // with lost taker fee. String id = openOffer.getId(); - if (id != null && !id.contains("_")) + if (id != null && !openOffer.isDeactivated()) republishOffer(openOffer); else log.warn("You have an offer with an invalid offer ID: offerID=" + id); @@ -567,7 +585,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe final OpenOffer openOffer = openOffersList.get(i); UserThread.runAfterRandomDelay(() -> { // we need to check if in the meantime the offer has been removed - if (openOffers.contains(openOffer)) + if (openOffers.contains(openOffer) && !openOffer.isDeactivated()) refreshOffer(openOffer); }, minDelay, maxDelay, TimeUnit.MILLISECONDS); } diff --git a/core/src/main/java/io/bisq/core/payment/CashAppAccount.java b/core/src/main/java/io/bisq/core/payment/CashAppAccount.java new file mode 100644 index 0000000000..8e2380e12a --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/CashAppAccount.java @@ -0,0 +1,46 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment; + +import io.bisq.common.locale.FiatCurrency; +import io.bisq.core.payment.payload.CashAppAccountPayload; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PaymentMethod; +import lombok.EqualsAndHashCode; + +//TODO missing support for selected trade currency +@EqualsAndHashCode(callSuper = true) +public final class CashAppAccount extends PaymentAccount { + public CashAppAccount() { + super(PaymentMethod.CASH_APP); + setSingleTradeCurrency(new FiatCurrency("USD")); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new CashAppAccountPayload(paymentMethod.getId(), id); + } + + public void setCashTag(String cashTag) { + ((CashAppAccountPayload) paymentAccountPayload).setCashTag(cashTag); + } + + public String getCashTag() { + return ((CashAppAccountPayload) paymentAccountPayload).getCashTag(); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/MoneyBeamAccount.java b/core/src/main/java/io/bisq/core/payment/MoneyBeamAccount.java new file mode 100644 index 0000000000..f1e208b1c1 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/MoneyBeamAccount.java @@ -0,0 +1,46 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment; + +import io.bisq.common.locale.FiatCurrency; +import io.bisq.core.payment.payload.MoneyBeamAccountPayload; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PaymentMethod; +import lombok.EqualsAndHashCode; + +//TODO missing support for selected trade currency +@EqualsAndHashCode(callSuper = true) +public final class MoneyBeamAccount extends PaymentAccount { + public MoneyBeamAccount() { + super(PaymentMethod.MONEY_BEAM); + setSingleTradeCurrency(new FiatCurrency("EUR")); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new MoneyBeamAccountPayload(paymentMethod.getId(), id); + } + + public void setAccountId(String accountId) { + ((MoneyBeamAccountPayload) paymentAccountPayload).setAccountId(accountId); + } + + public String getAccountId() { + return ((MoneyBeamAccountPayload) paymentAccountPayload).getAccountId(); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/PaymentAccount.java b/core/src/main/java/io/bisq/core/payment/PaymentAccount.java index 239a543af5..d00ce84d19 100644 --- a/core/src/main/java/io/bisq/core/payment/PaymentAccount.java +++ b/core/src/main/java/io/bisq/core/payment/PaymentAccount.java @@ -47,10 +47,8 @@ public abstract class PaymentAccount implements PersistablePayload { protected String id; @Setter protected long creationDate; - @Setter public PaymentAccountPayload paymentAccountPayload; - @Setter protected String accountName; protected final List tradeCurrencies = new ArrayList<>(); @@ -138,7 +136,7 @@ public abstract class PaymentAccount implements PersistablePayload { @Nullable public TradeCurrency getSingleTradeCurrency() { - if (!tradeCurrencies.isEmpty()) + if (tradeCurrencies.size() == 1) return tradeCurrencies.get(0); else return null; diff --git a/core/src/main/java/io/bisq/core/payment/PaymentAccountFactory.java b/core/src/main/java/io/bisq/core/payment/PaymentAccountFactory.java index abfc0e32da..5ef280ab2d 100644 --- a/core/src/main/java/io/bisq/core/payment/PaymentAccountFactory.java +++ b/core/src/main/java/io/bisq/core/payment/PaymentAccountFactory.java @@ -24,6 +24,18 @@ public class PaymentAccountFactory { switch (paymentMethod.getId()) { case PaymentMethod.OK_PAY_ID: return new OKPayAccount(); + case PaymentMethod.UPHOLD_ID: + return new UpholdAccount(); + case PaymentMethod.CASH_APP_ID: + return new CashAppAccount(); + case PaymentMethod.MONEY_BEAM_ID: + return new MoneyBeamAccount(); + case PaymentMethod.VENMO_ID: + return new VenmoAccount(); + case PaymentMethod.POPMONEY_ID: + return new PopmoneyAccount(); + case PaymentMethod.REVOLUT_ID: + return new RevolutAccount(); case PaymentMethod.PERFECT_MONEY_ID: return new PerfectMoneyAccount(); case PaymentMethod.SEPA_ID: diff --git a/core/src/main/java/io/bisq/core/payment/PopmoneyAccount.java b/core/src/main/java/io/bisq/core/payment/PopmoneyAccount.java new file mode 100644 index 0000000000..00c03b7e5f --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/PopmoneyAccount.java @@ -0,0 +1,54 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment; + +import io.bisq.common.locale.FiatCurrency; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PaymentMethod; +import io.bisq.core.payment.payload.PopmoneyAccountPayload; +import lombok.EqualsAndHashCode; + +//TODO missing support for selected trade currency +@EqualsAndHashCode(callSuper = true) +public final class PopmoneyAccount extends PaymentAccount { + public PopmoneyAccount() { + super(PaymentMethod.POPMONEY); + setSingleTradeCurrency(new FiatCurrency("USD")); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new PopmoneyAccountPayload(paymentMethod.getId(), id); + } + + public void setAccountId(String accountId) { + ((PopmoneyAccountPayload) paymentAccountPayload).setAccountId(accountId); + } + + public String getAccountId() { + return ((PopmoneyAccountPayload) paymentAccountPayload).getAccountId(); + } + + public void setHolderName(String holderName) { + ((PopmoneyAccountPayload) paymentAccountPayload).setHolderName(holderName); + } + + public String getHolderName() { + return ((PopmoneyAccountPayload) paymentAccountPayload).getHolderName(); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/RevolutAccount.java b/core/src/main/java/io/bisq/core/payment/RevolutAccount.java new file mode 100644 index 0000000000..d6ae8d800a --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/RevolutAccount.java @@ -0,0 +1,45 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment; + +import io.bisq.common.locale.CurrencyUtil; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PaymentMethod; +import io.bisq.core.payment.payload.RevolutAccountPayload; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +public final class RevolutAccount extends PaymentAccount { + public RevolutAccount() { + super(PaymentMethod.REVOLUT); + tradeCurrencies.addAll(CurrencyUtil.getAllRevolutCurrencies()); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new RevolutAccountPayload(paymentMethod.getId(), id); + } + + public void setAccountId(String accountId) { + ((RevolutAccountPayload) paymentAccountPayload).setAccountId(accountId); + } + + public String getAccountId() { + return ((RevolutAccountPayload) paymentAccountPayload).getAccountId(); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/UpholdAccount.java b/core/src/main/java/io/bisq/core/payment/UpholdAccount.java new file mode 100644 index 0000000000..570adef1d5 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/UpholdAccount.java @@ -0,0 +1,46 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment; + +import io.bisq.common.locale.CurrencyUtil; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PaymentMethod; +import io.bisq.core.payment.payload.UpholdAccountPayload; +import lombok.EqualsAndHashCode; + +//TODO missing support for selected trade currency +@EqualsAndHashCode(callSuper = true) +public final class UpholdAccount extends PaymentAccount { + public UpholdAccount() { + super(PaymentMethod.UPHOLD); + tradeCurrencies.addAll(CurrencyUtil.getAllUpholdCurrencies()); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new UpholdAccountPayload(paymentMethod.getId(), id); + } + + public void setAccountId(String accountId) { + ((UpholdAccountPayload) paymentAccountPayload).setAccountId(accountId); + } + + public String getAccountId() { + return ((UpholdAccountPayload) paymentAccountPayload).getAccountId(); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/VenmoAccount.java b/core/src/main/java/io/bisq/core/payment/VenmoAccount.java new file mode 100644 index 0000000000..fd64e50d49 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/VenmoAccount.java @@ -0,0 +1,54 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment; + +import io.bisq.common.locale.FiatCurrency; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PaymentMethod; +import io.bisq.core.payment.payload.VenmoAccountPayload; +import lombok.EqualsAndHashCode; + +//TODO missing support for selected trade currency +@EqualsAndHashCode(callSuper = true) +public final class VenmoAccount extends PaymentAccount { + public VenmoAccount() { + super(PaymentMethod.VENMO); + setSingleTradeCurrency(new FiatCurrency("USD")); + } + + @Override + protected PaymentAccountPayload createPayload() { + return new VenmoAccountPayload(paymentMethod.getId(), id); + } + + public void setVenmoUserName(String venmoUserName) { + ((VenmoAccountPayload) paymentAccountPayload).setVenmoUserName(venmoUserName); + } + + public String getVenmoUserName() { + return ((VenmoAccountPayload) paymentAccountPayload).getVenmoUserName(); + } + + public void setHolderName(String holderName) { + ((VenmoAccountPayload) paymentAccountPayload).setHolderName(holderName); + } + + public String getHolderName() { + return ((VenmoAccountPayload) paymentAccountPayload).getHolderName(); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/payload/CashAppAccountPayload.java b/core/src/main/java/io/bisq/core/payment/payload/CashAppAccountPayload.java new file mode 100644 index 0000000000..d5e3481993 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/payload/CashAppAccountPayload.java @@ -0,0 +1,98 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment.payload; + +import com.google.protobuf.Message; +import io.bisq.generated.protobuffer.PB; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +@Setter +@Getter +@Slf4j +public final class CashAppAccountPayload extends PaymentAccountPayload { + private String cashTag = ""; + + public CashAppAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + private CashAppAccountPayload(String paymentMethod, + String id, + String cashTag, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + maxTradePeriod, + excludeFromJsonDataMap); + + this.cashTag = cashTag; + } + + @Override + public Message toProtoMessage() { + return getPaymentAccountPayloadBuilder() + .setCashAppAccountPayload(PB.CashAppAccountPayload.newBuilder() + .setCashTag(cashTag)) + .build(); + } + + public static CashAppAccountPayload fromProto(PB.PaymentAccountPayload proto) { + return new CashAppAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + proto.getCashAppAccountPayload().getCashTag(), + proto.getMaxTradePeriod(), + CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public String getPaymentDetails() { + return "CashApp - Account: " + cashTag; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(cashTag.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/payload/MoneyBeamAccountPayload.java b/core/src/main/java/io/bisq/core/payment/payload/MoneyBeamAccountPayload.java new file mode 100644 index 0000000000..d405e4bda7 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/payload/MoneyBeamAccountPayload.java @@ -0,0 +1,98 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment.payload; + +import com.google.protobuf.Message; +import io.bisq.generated.protobuffer.PB; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +@Setter +@Getter +@Slf4j +public final class MoneyBeamAccountPayload extends PaymentAccountPayload { + private String accountId = ""; + + public MoneyBeamAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + private MoneyBeamAccountPayload(String paymentMethod, + String id, + String accountId, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + maxTradePeriod, + excludeFromJsonDataMap); + + this.accountId = accountId; + } + + @Override + public Message toProtoMessage() { + return getPaymentAccountPayloadBuilder() + .setMoneyBeamAccountPayload(PB.MoneyBeamAccountPayload.newBuilder() + .setAccountId(accountId)) + .build(); + } + + public static MoneyBeamAccountPayload fromProto(PB.PaymentAccountPayload proto) { + return new MoneyBeamAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + proto.getMoneyBeamAccountPayload().getAccountId(), + proto.getMaxTradePeriod(), + CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public String getPaymentDetails() { + return "MoneyBeam - Account: " + accountId; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(accountId.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/payload/PaymentMethod.java b/core/src/main/java/io/bisq/core/payment/payload/PaymentMethod.java index 577866fb33..47841d6b18 100644 --- a/core/src/main/java/io/bisq/core/payment/payload/PaymentMethod.java +++ b/core/src/main/java/io/bisq/core/payment/payload/PaymentMethod.java @@ -28,7 +28,10 @@ import lombok.extern.slf4j.Slf4j; import org.bitcoinj.core.Coin; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; @EqualsAndHashCode(exclude = {"maxTradePeriod", "maxTradeLimit"}) @@ -44,6 +47,12 @@ public final class PaymentMethod implements PersistablePayload, Comparable { private static final long DAY = TimeUnit.HOURS.toMillis(24); public static final String OK_PAY_ID = "OK_PAY"; + public static final String UPHOLD_ID = "UPHOLD"; + public static final String CASH_APP_ID = "CASH_APP"; + public static final String MONEY_BEAM_ID = "MONEY_BEAM"; + public static final String VENMO_ID = "VENMO"; + public static final String POPMONEY_ID = "POPMONEY"; + public static final String REVOLUT_ID = "REVOLUT"; public static final String PERFECT_MONEY_ID = "PERFECT_MONEY"; public static final String SEPA_ID = "SEPA"; public static final String SEPA_INSTANT_ID = "SEPA_INSTANT"; @@ -62,6 +71,12 @@ public final class PaymentMethod implements PersistablePayload, Comparable { public static final String BLOCK_CHAINS_ID = "BLOCK_CHAINS"; public static PaymentMethod OK_PAY; + public static PaymentMethod UPHOLD; + public static PaymentMethod CASH_APP; + public static PaymentMethod MONEY_BEAM; + public static PaymentMethod VENMO; + public static PaymentMethod POPMONEY; + public static PaymentMethod REVOLUT; public static PaymentMethod PERFECT_MONEY; public static PaymentMethod SEPA; public static PaymentMethod SEPA_INSTANT; @@ -117,31 +132,27 @@ public final class PaymentMethod implements PersistablePayload, Comparable { public static List getAllValues() { if (ALL_VALUES == null) { + Coin maxTradeLimitHighRisk; Coin maxTradeLimitMidRisk; Coin maxTradeLimitLowRisk; Coin maxTradeLimitVeryLowRisk; switch (BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode()) { case "BTC": - // av. price June 2017: 2500 EUR/BTC - // av. price Oct 2017: 4700 EUR/BTC + // we want to avoid more then 4 decimal places (0.125 / 4 = 0.03125), so we use a bit higher value to get 0.04 for first month + maxTradeLimitHighRisk = Coin.parseCoin("0.16"); + maxTradeLimitMidRisk = Coin.parseCoin("0.25"); maxTradeLimitLowRisk = Coin.parseCoin("0.5"); maxTradeLimitVeryLowRisk = Coin.parseCoin("1"); break; case "LTC": - // av. price June 2017: 40 EUR/LTC + maxTradeLimitHighRisk = Coin.parseCoin("12.5"); maxTradeLimitMidRisk = Coin.parseCoin("25"); maxTradeLimitLowRisk = Coin.parseCoin("50"); maxTradeLimitVeryLowRisk = Coin.parseCoin("100"); break; - case "DOGE": - // av. price June 2017: 0.002850 EUR/DOGE - maxTradeLimitMidRisk = Coin.parseCoin("250000"); - maxTradeLimitLowRisk = Coin.parseCoin("500000"); - maxTradeLimitVeryLowRisk = Coin.parseCoin("1000000"); - break; case "DASH": - // av. price June 2017: 150 EUR/DASH + maxTradeLimitHighRisk = Coin.parseCoin("5"); maxTradeLimitMidRisk = Coin.parseCoin("10"); maxTradeLimitLowRisk = Coin.parseCoin("20"); maxTradeLimitVeryLowRisk = Coin.parseCoin("40"); @@ -156,6 +167,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable { // EUR SEPA = new PaymentMethod(SEPA_ID, 6 * DAY, maxTradeLimitMidRisk), SEPA_INSTANT = new PaymentMethod(SEPA_INSTANT_ID, DAY, maxTradeLimitMidRisk), + MONEY_BEAM = new PaymentMethod(MONEY_BEAM_ID, DAY, maxTradeLimitHighRisk), // UK FASTER_PAYMENTS = new PaymentMethod(FASTER_PAYMENTS_ID, DAY, maxTradeLimitMidRisk), @@ -165,6 +177,11 @@ public final class PaymentMethod implements PersistablePayload, Comparable { // US CLEAR_X_CHANGE = new PaymentMethod(CLEAR_X_CHANGE_ID, 4 * DAY, maxTradeLimitMidRisk), + CASH_APP = new PaymentMethod(CASH_APP_ID, DAY, maxTradeLimitHighRisk), + + VENMO = new PaymentMethod(VENMO_ID, DAY, maxTradeLimitHighRisk), + + POPMONEY = new PaymentMethod(POPMONEY_ID, DAY, maxTradeLimitHighRisk), CHASE_QUICK_PAY = new PaymentMethod(CHASE_QUICK_PAY_ID, DAY, maxTradeLimitMidRisk), US_POSTAL_MONEY_ORDER = new PaymentMethod(US_POSTAL_MONEY_ORDER_ID, 8 * DAY, maxTradeLimitMidRisk), @@ -180,6 +197,8 @@ public final class PaymentMethod implements PersistablePayload, Comparable { // Trans national OK_PAY = new PaymentMethod(OK_PAY_ID, DAY, maxTradeLimitVeryLowRisk), + UPHOLD = new PaymentMethod(UPHOLD_ID, DAY, maxTradeLimitHighRisk), + REVOLUT = new PaymentMethod(REVOLUT_ID, DAY, maxTradeLimitHighRisk), PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, DAY, maxTradeLimitLowRisk), // China @@ -233,10 +252,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable { public static PaymentMethod getPaymentMethodById(String id) { Optional paymentMethodOptional = getAllValues().stream().filter(e -> e.getId().equals(id)).findFirst(); - if (paymentMethodOptional.isPresent()) - return paymentMethodOptional.get(); - else - return new PaymentMethod(Res.get("shared.na")); + return paymentMethodOptional.orElseGet(() -> new PaymentMethod(Res.get("shared.na"))); } // Hack for SF as the smallest unit is 1 SF ;-( and price is about 3 BTC! diff --git a/core/src/main/java/io/bisq/core/payment/payload/PopmoneyAccountPayload.java b/core/src/main/java/io/bisq/core/payment/payload/PopmoneyAccountPayload.java new file mode 100644 index 0000000000..3e62f85074 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/payload/PopmoneyAccountPayload.java @@ -0,0 +1,103 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment.payload; + +import com.google.protobuf.Message; +import io.bisq.generated.protobuffer.PB; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +@Setter +@Getter +@Slf4j +public final class PopmoneyAccountPayload extends PaymentAccountPayload { + private String accountId = ""; + private String holderName = ""; + + public PopmoneyAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + private PopmoneyAccountPayload(String paymentMethod, + String id, + String accountId, + String holderName, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + maxTradePeriod, + excludeFromJsonDataMap); + + this.accountId = accountId; + this.holderName = holderName; + } + + @Override + public Message toProtoMessage() { + return getPaymentAccountPayloadBuilder() + .setPopmoneyAccountPayload(PB.PopmoneyAccountPayload.newBuilder() + .setAccountId(accountId) + .setHolderName(holderName)) + .build(); + } + + public static PopmoneyAccountPayload fromProto(PB.PaymentAccountPayload proto) { + return new PopmoneyAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + proto.getPopmoneyAccountPayload().getAccountId(), + proto.getPopmoneyAccountPayload().getHolderName(), + proto.getMaxTradePeriod(), + CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public String getPaymentDetails() { + return "Popmoney - Holder name: " + holderName + ", email or phone no.: " + accountId; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(accountId.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/payload/RevolutAccountPayload.java b/core/src/main/java/io/bisq/core/payment/payload/RevolutAccountPayload.java new file mode 100644 index 0000000000..3f33e44f28 --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/payload/RevolutAccountPayload.java @@ -0,0 +1,99 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment.payload; + +import com.google.protobuf.Message; +import io.bisq.common.locale.Res; +import io.bisq.generated.protobuffer.PB; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +@Setter +@Getter +@Slf4j +public final class RevolutAccountPayload extends PaymentAccountPayload { + private String accountId = ""; + + public RevolutAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + private RevolutAccountPayload(String paymentMethod, + String id, + String accountId, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + maxTradePeriod, + excludeFromJsonDataMap); + + this.accountId = accountId; + } + + @Override + public Message toProtoMessage() { + return getPaymentAccountPayloadBuilder() + .setRevolutAccountPayload(PB.RevolutAccountPayload.newBuilder() + .setAccountId(accountId)) + .build(); + } + + public static RevolutAccountPayload fromProto(PB.PaymentAccountPayload proto) { + return new RevolutAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + proto.getRevolutAccountPayload().getAccountId(), + proto.getMaxTradePeriod(), + CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public String getPaymentDetails() { + return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account") + accountId; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(accountId.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/payload/UpholdAccountPayload.java b/core/src/main/java/io/bisq/core/payment/payload/UpholdAccountPayload.java new file mode 100644 index 0000000000..adaea17e9f --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/payload/UpholdAccountPayload.java @@ -0,0 +1,98 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment.payload; + +import com.google.protobuf.Message; +import io.bisq.generated.protobuffer.PB; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +@Setter +@Getter +@Slf4j +public final class UpholdAccountPayload extends PaymentAccountPayload { + private String accountId = ""; + + public UpholdAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + private UpholdAccountPayload(String paymentMethod, + String id, + String accountId, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + maxTradePeriod, + excludeFromJsonDataMap); + + this.accountId = accountId; + } + + @Override + public Message toProtoMessage() { + return getPaymentAccountPayloadBuilder() + .setUpholdAccountPayload(PB.UpholdAccountPayload.newBuilder() + .setAccountId(accountId)) + .build(); + } + + public static UpholdAccountPayload fromProto(PB.PaymentAccountPayload proto) { + return new UpholdAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + proto.getUpholdAccountPayload().getAccountId(), + proto.getMaxTradePeriod(), + CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public String getPaymentDetails() { + return "Uphold - Account: " + accountId; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(accountId.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/core/src/main/java/io/bisq/core/payment/payload/VenmoAccountPayload.java b/core/src/main/java/io/bisq/core/payment/payload/VenmoAccountPayload.java new file mode 100644 index 0000000000..a49488769e --- /dev/null +++ b/core/src/main/java/io/bisq/core/payment/payload/VenmoAccountPayload.java @@ -0,0 +1,103 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.core.payment.payload; + +import com.google.protobuf.Message; +import io.bisq.generated.protobuffer.PB; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@ToString +@Setter +@Getter +@Slf4j +public final class VenmoAccountPayload extends PaymentAccountPayload { + private String venmoUserName = ""; + private String holderName = ""; + + public VenmoAccountPayload(String paymentMethod, String id) { + super(paymentMethod, id); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // PROTO BUFFER + /////////////////////////////////////////////////////////////////////////////////////////// + + private VenmoAccountPayload(String paymentMethod, + String id, + String venmoUserName, + String holderName, + long maxTradePeriod, + Map excludeFromJsonDataMap) { + super(paymentMethod, + id, + maxTradePeriod, + excludeFromJsonDataMap); + + this.venmoUserName = venmoUserName; + this.holderName = holderName; + } + + @Override + public Message toProtoMessage() { + return getPaymentAccountPayloadBuilder() + .setVenmoAccountPayload(PB.VenmoAccountPayload.newBuilder() + .setVenmoUserName(venmoUserName) + .setHolderName(holderName)) + .build(); + } + + public static VenmoAccountPayload fromProto(PB.PaymentAccountPayload proto) { + return new VenmoAccountPayload(proto.getPaymentMethodId(), + proto.getId(), + proto.getVenmoAccountPayload().getVenmoUserName(), + proto.getVenmoAccountPayload().getHolderName(), + proto.getMaxTradePeriod(), + CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap())); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public String getPaymentDetails() { + return "Venmo - Holder name: " + holderName + ", Venmo username: " + venmoUserName; + } + + @Override + public String getPaymentDetailsForTradePopup() { + return getPaymentDetails(); + } + + @Override + public byte[] getAgeWitnessInputData() { + return super.getAgeWitnessInputData(venmoUserName.getBytes(Charset.forName("UTF-8"))); + } +} diff --git a/core/src/main/java/io/bisq/core/proto/CoreProtoResolver.java b/core/src/main/java/io/bisq/core/proto/CoreProtoResolver.java index 89e0e43e70..3de657f5f9 100644 --- a/core/src/main/java/io/bisq/core/proto/CoreProtoResolver.java +++ b/core/src/main/java/io/bisq/core/proto/CoreProtoResolver.java @@ -60,6 +60,18 @@ public class CoreProtoResolver implements ProtoResolver { return InteracETransferAccountPayload.fromProto(proto); case O_K_PAY_ACCOUNT_PAYLOAD: return OKPayAccountPayload.fromProto(proto); + case UPHOLD_ACCOUNT_PAYLOAD: + return UpholdAccountPayload.fromProto(proto); + case CASH_APP_ACCOUNT_PAYLOAD: + return CashAppAccountPayload.fromProto(proto); + case MONEY_BEAM_ACCOUNT_PAYLOAD: + return MoneyBeamAccountPayload.fromProto(proto); + case VENMO_ACCOUNT_PAYLOAD: + return VenmoAccountPayload.fromProto(proto); + case POPMONEY_ACCOUNT_PAYLOAD: + return PopmoneyAccountPayload.fromProto(proto); + case REVOLUT_ACCOUNT_PAYLOAD: + return RevolutAccountPayload.fromProto(proto); case PERFECT_MONEY_ACCOUNT_PAYLOAD: return PerfectMoneyAccountPayload.fromProto(proto); case SWISH_ACCOUNT_PAYLOAD: diff --git a/core/src/main/java/io/bisq/core/provider/fee/FeeProvider.java b/core/src/main/java/io/bisq/core/provider/fee/FeeProvider.java index 44250cbb73..02d50b895a 100644 --- a/core/src/main/java/io/bisq/core/provider/fee/FeeProvider.java +++ b/core/src/main/java/io/bisq/core/provider/fee/FeeProvider.java @@ -52,12 +52,10 @@ public class FeeProvider extends HttpClientProvider { LinkedTreeMap dataMap = (LinkedTreeMap) linkedTreeMap.get("dataMap"); Long btcTxFee = dataMap.get("btcTxFee").longValue(); Long ltcTxFee = dataMap.get("ltcTxFee").longValue(); - Long dogeTxFee = dataMap.get("dogeTxFee").longValue(); Long dashTxFee = dataMap.get("dashTxFee").longValue(); map.put("BTC", btcTxFee); map.put("LTC", ltcTxFee); - map.put("DOGE", dogeTxFee); map.put("DASH", dashTxFee); } catch (Throwable t) { log.error(t.toString()); diff --git a/core/src/main/java/io/bisq/core/provider/fee/FeeService.java b/core/src/main/java/io/bisq/core/provider/fee/FeeService.java index 2de865bc8c..403f2d33c2 100644 --- a/core/src/main/java/io/bisq/core/provider/fee/FeeService.java +++ b/core/src/main/java/io/bisq/core/provider/fee/FeeService.java @@ -45,11 +45,9 @@ public class FeeService { private static final Logger log = LoggerFactory.getLogger(FeeService.class); // fixed min fee - public static final Coin BTC_REFERENCE_DEFAULT_MIN_TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; // 5000 + public static final Coin BTC_REFERENCE_DEFAULT_MIN_TX_FEE_PER_KB = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; // 5000 // https://litecoin.info/Transaction_fees min fee is 100_000 public static final Coin LTC_REFERENCE_DEFAULT_MIN_TX_FEE = Coin.valueOf(100_000); - // min fee is 1 DOGE - public static final Coin DOGE_REFERENCE_DEFAULT_MIN_TX_FEE = Coin.valueOf(1_000_000_000); //TODO check // min tx fee per tx is 10000 now, 1000 in sept 2017 public static final Coin DASH_REFERENCE_DEFAULT_MIN_TX_FEE = Coin.valueOf(10_000); @@ -58,7 +56,6 @@ public class FeeService { // fees are per byte public static final long BTC_DEFAULT_TX_FEE = 200; // fees are between 20-600 sat/byte. We try to stay on the safe side. public static final long LTC_DEFAULT_TX_FEE = LTC_REFERENCE_DEFAULT_MIN_TX_FEE.value / 200; - public static final long DOGE_DEFAULT_TX_FEE = DOGE_REFERENCE_DEFAULT_MIN_TX_FEE.value / 200; // 200 bytes tx -> 200*5_000_000L=1_000_000_000 (1 DOGE) public static final long DASH_DEFAULT_TX_FEE = DASH_REFERENCE_DEFAULT_MIN_TX_FEE.value / 200; // 200 bytes tx -> 200*50=10000 private static long MIN_MAKER_FEE_IN_BASE_CUR; @@ -80,6 +77,7 @@ public class FeeService { private long epochInSecondAtLastRequest; private long lastRequest; private IntegerProperty feeUpdateCounter = new SimpleIntegerProperty(0); + private long minFeePerByte; /////////////////////////////////////////////////////////////////////////////////////////// @@ -99,8 +97,8 @@ public class FeeService { */ switch (baseCurrencyCode) { case "BTC": - MIN_MAKER_FEE_IN_BASE_CUR = 20_000; // 4 USD at BTC price 20000 USD - MIN_TAKER_FEE_IN_BASE_CUR = 20_000; + MIN_MAKER_FEE_IN_BASE_CUR = 5_000; // 1 USD at BTC price 20000 USD + MIN_TAKER_FEE_IN_BASE_CUR = 5_000; DEFAULT_MAKER_FEE_IN_BASE_CUR = 200_000; // 10 USD at BTC price 20000 USD for 0.25 BTC (maxTradeAmount for most fiat trades) DEFAULT_TAKER_FEE_IN_BASE_CUR = 200_000; txFeePerByte = BTC_DEFAULT_TX_FEE; @@ -112,13 +110,6 @@ public class FeeService { DEFAULT_TAKER_FEE_IN_BASE_CUR = 360_000; // 7.5 USD at LTC price 40 USD txFeePerByte = LTC_DEFAULT_TX_FEE; break; - case "DOGE": - MIN_MAKER_FEE_IN_BASE_CUR = 20_000_000_000L; // 0.5 USD at DOGE price 0.003 USD - MIN_TAKER_FEE_IN_BASE_CUR = 20_000_000_000L; - DEFAULT_MAKER_FEE_IN_BASE_CUR = 200_000; // 5 USD at DOGE price 0.003 USD for 800 000 DOGE (maxTradeAmount) - DEFAULT_TAKER_FEE_IN_BASE_CUR = 300_000; // 7.5 USD at DOGE price 0.003 USD - txFeePerByte = DOGE_DEFAULT_TX_FEE; - break; case "DASH": MIN_MAKER_FEE_IN_BASE_CUR = 300_000; // 0.5 USD at DASH price 150 USD MIN_TAKER_FEE_IN_BASE_CUR = 300_000; @@ -132,6 +123,8 @@ public class FeeService { } public void onAllServicesInitialized() { + minFeePerByte = BisqEnvironment.getBaseCurrencyNetwork().getDefaultMinFeePerByte(); + requestFees(null, null); // We update all 5 min. @@ -154,6 +147,12 @@ public class FeeService { epochInSecondAtLastRequest = timeStampMap.get("bitcoinFeesTs"); final Map map = result.second; txFeePerByte = map.get(baseCurrencyCode); + + if (txFeePerByte < minFeePerByte) { + log.warn("The delivered fee per byte is smaller than the min. default fee of 5 sat/byte"); + txFeePerByte = minFeePerByte; + } + feeUpdateCounter.set(feeUpdateCounter.get() + 1); log.info("{} tx fee: txFeePerByte={}", baseCurrencyCode, txFeePerByte); if (resultHandler != null) diff --git a/core/src/main/java/io/bisq/core/provider/price/PriceFeedService.java b/core/src/main/java/io/bisq/core/provider/price/PriceFeedService.java index 8dcfa30291..e802c25a06 100644 --- a/core/src/main/java/io/bisq/core/provider/price/PriceFeedService.java +++ b/core/src/main/java/io/bisq/core/provider/price/PriceFeedService.java @@ -382,7 +382,6 @@ public class PriceFeedService { cache.putAll(priceMap); break; case "LTC": - case "DOGE": case "DASH": // apply conversion of btc based price to baseCurrencyCode based with btc/baseCurrencyCode price MarketPrice baseCurrencyPrice = priceMap.get(baseCurrencyCode); diff --git a/core/src/main/java/io/bisq/core/trade/statistics/TradeStatisticsManager.java b/core/src/main/java/io/bisq/core/trade/statistics/TradeStatisticsManager.java index aed627af8f..3cf287b23f 100644 --- a/core/src/main/java/io/bisq/core/trade/statistics/TradeStatisticsManager.java +++ b/core/src/main/java/io/bisq/core/trade/statistics/TradeStatisticsManager.java @@ -257,6 +257,12 @@ public class TradeStatisticsManager { newlyAdded.add("YTN"); newlyAdded.add("DARX"); newlyAdded.add("ODN"); + newlyAdded.add("CDT"); + newlyAdded.add("DGM"); + newlyAdded.add("SCS"); + newlyAdded.add("SOS"); + newlyAdded.add("ACH"); + newlyAdded.add("VDN"); coinsWithValidator.addAll(newlyAdded); diff --git a/core/src/main/java/io/bisq/core/user/Preferences.java b/core/src/main/java/io/bisq/core/user/Preferences.java index f248857172..6cb0b17e26 100644 --- a/core/src/main/java/io/bisq/core/user/Preferences.java +++ b/core/src/main/java/io/bisq/core/user/Preferences.java @@ -75,13 +75,6 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid new BlockChainExplorer("SoChain", "https://chain.so/tx/LTCTEST/", "https://chain.so/address/LTCTEST/") )); - private static final ArrayList DOGE_MAIN_NET_EXPLORERS = new ArrayList<>(Arrays.asList( - new BlockChainExplorer("SoChain", "https://chain.so/tx/doge/", "https://chain.so/address/doge/") - )); - private static final ArrayList DOGE_TEST_NET_EXPLORERS = new ArrayList<>(Arrays.asList( - new BlockChainExplorer("SoChain", "https://chain.so/tx/DOGETEST/", "https://chain.so/address/DOGETEST/") - )); - private static final ArrayList DASH_MAIN_NET_EXPLORERS = new ArrayList<>(Arrays.asList( new BlockChainExplorer("SoChain", "https://chain.so/tx/dash/", "https://chain.so/address/dash/") )); @@ -195,10 +188,6 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid setBlockChainExplorerMainNet(LTC_MAIN_NET_EXPLORERS.get(0)); setBlockChainExplorerTestNet(LTC_TEST_NET_EXPLORERS.get(0)); break; - case "DOGE": - setBlockChainExplorerMainNet(DOGE_MAIN_NET_EXPLORERS.get(0)); - setBlockChainExplorerTestNet(DOGE_TEST_NET_EXPLORERS.get(0)); - break; case "DASH": setBlockChainExplorerMainNet(DASH_MAIN_NET_EXPLORERS.get(0)); setBlockChainExplorerTestNet(DASH_TEST_NET_EXPLORERS.get(0)); @@ -552,11 +541,6 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid case LTC_TESTNET: case LTC_REGTEST: return LTC_TEST_NET_EXPLORERS; - case DOGE_MAINNET: - return DOGE_MAIN_NET_EXPLORERS; - case DOGE_TESTNET: - case DOGE_REGTEST: - return DOGE_TEST_NET_EXPLORERS; case DASH_MAINNET: return DASH_MAIN_NET_EXPLORERS; case DASH_REGTEST: @@ -604,6 +588,10 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid return prefPayload.getBridgeAddresses(); } + public long getWithdrawalTxFeeInBytes() { + return Math.max(prefPayload.getWithdrawalTxFeeInBytes(), BisqEnvironment.getBaseCurrencyNetwork().getDefaultMinFeePerByte()); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Private @@ -688,8 +676,6 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid void setBridgeAddresses(List bridgeAddresses); - List getBridgeAddresses(); - void setBridgeOptionOrdinal(int bridgeOptionOrdinal); void setTorTransportOrdinal(int torTransportOrdinal); @@ -697,5 +683,9 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid void setCustomBridges(String customBridges); void setBitcoinNodesOptionOrdinal(int bitcoinNodesOption); + + List getBridgeAddresses(); + + long getWithdrawalTxFeeInBytes(); } } diff --git a/core/src/main/java/io/bisq/core/user/PreferencesPayload.java b/core/src/main/java/io/bisq/core/user/PreferencesPayload.java index 6dc54640d2..a51a6930f3 100644 --- a/core/src/main/java/io/bisq/core/user/PreferencesPayload.java +++ b/core/src/main/java/io/bisq/core/user/PreferencesPayload.java @@ -44,7 +44,7 @@ public final class PreferencesPayload implements PersistableEnvelope { private TradeCurrency preferredTradeCurrency; private long withdrawalTxFeeInBytes = 100; private boolean useCustomWithdrawalTxFee = false; - private double maxPriceDistanceInPercent = 0.1; + private double maxPriceDistanceInPercent = 0.3; @Nullable private String offerBookChartScreenCurrencyCode; @Nullable diff --git a/gui/pom.xml b/gui/pom.xml index 025d896a07..601d8a0909 100644 --- a/gui/pom.xml +++ b/gui/pom.xml @@ -22,7 +22,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0 diff --git a/gui/src/main/java/io/bisq/gui/bisq.css b/gui/src/main/java/io/bisq/gui/bisq.css index d1bb3db744..9a0849d54b 100644 --- a/gui/src/main/java/io/bisq/gui/bisq.css +++ b/gui/src/main/java/io/bisq/gui/bisq.css @@ -686,6 +686,11 @@ textfield */ -fx-background-color: -bs-very-light-grey; } +/* Open Offer */ +.offer-disabled { + -fx-text-fill: -bs-light-grey; +} + /* OfferBook */ .table-title { diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/BankForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/BankForm.java index 394ddbae93..175ed50cad 100644 --- a/gui/src/main/java/io/bisq/gui/components/paymentmethods/BankForm.java +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/BankForm.java @@ -292,109 +292,104 @@ abstract class BankForm extends PaymentMethodForm { countryComboBox.setOnAction(e -> { Country selectedItem = countryComboBox.getSelectionModel().getSelectedItem(); if (selectedItem != null) { - if (selectedItem.code.equals("US")) { - new Popup<>().information(Res.get("payment.us.info")) - .onClose(closeHandler::run) - .show(); + getCountryBasedPaymentAccount().setCountry(selectedItem); + String countryCode = selectedItem.code; + TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(countryCode); + paymentAccount.setSingleTradeCurrency(currency); + currencyComboBox.setDisable(false); + currencyComboBox.getSelectionModel().select(currency); + + bankIdLabel.setText(BankUtil.getBankIdLabel(countryCode)); + branchIdLabel.setText(BankUtil.getBranchIdLabel(countryCode)); + accountNrLabel.setText(BankUtil.getAccountNrLabel(countryCode)); + accountTypeLabel.setText(BankUtil.getAccountTypeLabel(countryCode)); + + bankNameInputTextField.setText(""); + bankIdInputTextField.setText(""); + branchIdInputTextField.setText(""); + accountNrInputTextField.setText(""); + accountTypeComboBox.getSelectionModel().clearSelection(); + accountTypeComboBox.setItems(FXCollections.observableArrayList(BankUtil.getAccountTypeValues(countryCode))); + + if (BankUtil.useValidation(countryCode) && !validatorsApplied) { + validatorsApplied = true; + if (useHolderID) + holderIdInputTextField.setValidator(inputValidator); + bankNameInputTextField.setValidator(inputValidator); + bankIdInputTextField.setValidator(new BankIdValidator(countryCode)); + branchIdInputTextField.setValidator(new BranchIdValidator(countryCode)); + accountNrInputTextField.setValidator(new AccountNrValidator(countryCode)); } else { - getCountryBasedPaymentAccount().setCountry(selectedItem); - String countryCode = selectedItem.code; - TradeCurrency currency = CurrencyUtil.getCurrencyByCountryCode(countryCode); - paymentAccount.setSingleTradeCurrency(currency); - currencyComboBox.setDisable(false); - currencyComboBox.getSelectionModel().select(currency); - - bankIdLabel.setText(BankUtil.getBankIdLabel(countryCode)); - branchIdLabel.setText(BankUtil.getBranchIdLabel(countryCode)); - accountNrLabel.setText(BankUtil.getAccountNrLabel(countryCode)); - accountTypeLabel.setText(BankUtil.getAccountTypeLabel(countryCode)); - - bankNameInputTextField.setText(""); - bankIdInputTextField.setText(""); - branchIdInputTextField.setText(""); - accountNrInputTextField.setText(""); - accountTypeComboBox.getSelectionModel().clearSelection(); - accountTypeComboBox.setItems(FXCollections.observableArrayList(BankUtil.getAccountTypeValues(countryCode))); - - if (BankUtil.useValidation(countryCode) && !validatorsApplied) { - validatorsApplied = true; - if (useHolderID) - holderIdInputTextField.setValidator(inputValidator); - bankNameInputTextField.setValidator(inputValidator); - bankIdInputTextField.setValidator(new BankIdValidator(countryCode)); - branchIdInputTextField.setValidator(new BranchIdValidator(countryCode)); - accountNrInputTextField.setValidator(new AccountNrValidator(countryCode)); - } else { - validatorsApplied = false; - if (useHolderID) - holderIdInputTextField.setValidator(null); - bankNameInputTextField.setValidator(null); - bankIdInputTextField.setValidator(null); - branchIdInputTextField.setValidator(null); - accountNrInputTextField.setValidator(null); - } - holderNameInputTextField.resetValidation(); - bankNameInputTextField.resetValidation(); - bankIdInputTextField.resetValidation(); - branchIdInputTextField.resetValidation(); - accountNrInputTextField.resetValidation(); - - boolean requiresHolderId = BankUtil.isHolderIdRequired(countryCode); - if (requiresHolderId) { - holderNameInputTextField.minWidthProperty().unbind(); - holderNameInputTextField.setMinWidth(250); - } else { - holderNameInputTextField.minWidthProperty().bind(currencyComboBox.widthProperty()); - } - - if (useHolderID) { - if (!requiresHolderId) - holderIdInputTextField.setText(""); - - holderIdInputTextField.resetValidation(); - holderIdInputTextField.setVisible(requiresHolderId); - holderIdInputTextField.setManaged(requiresHolderId); - - holderIdLabel.setText(BankUtil.getHolderIdLabel(countryCode)); - holderIdLabel.setVisible(requiresHolderId); - holderIdLabel.setManaged(requiresHolderId); - } - - - boolean bankNameRequired = BankUtil.isBankNameRequired(countryCode); - bankNameTuple.first.setVisible(bankNameRequired); - bankNameTuple.first.setManaged(bankNameRequired); - bankNameInputTextField.setVisible(bankNameRequired); - bankNameInputTextField.setManaged(bankNameRequired); - - boolean bankIdRequired = BankUtil.isBankIdRequired(countryCode); - bankIdTuple.first.setVisible(bankIdRequired); - bankIdTuple.first.setManaged(bankIdRequired); - bankIdInputTextField.setVisible(bankIdRequired); - bankIdInputTextField.setManaged(bankIdRequired); - - boolean branchIdRequired = BankUtil.isBranchIdRequired(countryCode); - branchIdTuple.first.setVisible(branchIdRequired); - branchIdTuple.first.setManaged(branchIdRequired); - branchIdInputTextField.setVisible(branchIdRequired); - branchIdInputTextField.setManaged(branchIdRequired); - - boolean accountNrRequired = BankUtil.isAccountNrRequired(countryCode); - accountNrTuple.first.setVisible(accountNrRequired); - accountNrTuple.first.setManaged(accountNrRequired); - accountNrInputTextField.setVisible(accountNrRequired); - accountNrInputTextField.setManaged(accountNrRequired); - - boolean accountTypeRequired = BankUtil.isAccountTypeRequired(countryCode); - accountTypeTuple.first.setVisible(accountTypeRequired); - accountTypeTuple.first.setManaged(accountTypeRequired); - accountTypeTuple.second.setVisible(accountTypeRequired); - accountTypeTuple.second.setManaged(accountTypeRequired); - - updateFromInputs(); - - onCountryChanged(); + validatorsApplied = false; + if (useHolderID) + holderIdInputTextField.setValidator(null); + bankNameInputTextField.setValidator(null); + bankIdInputTextField.setValidator(null); + branchIdInputTextField.setValidator(null); + accountNrInputTextField.setValidator(null); } + holderNameInputTextField.resetValidation(); + bankNameInputTextField.resetValidation(); + bankIdInputTextField.resetValidation(); + branchIdInputTextField.resetValidation(); + accountNrInputTextField.resetValidation(); + + boolean requiresHolderId = BankUtil.isHolderIdRequired(countryCode); + if (requiresHolderId) { + holderNameInputTextField.minWidthProperty().unbind(); + holderNameInputTextField.setMinWidth(250); + } else { + holderNameInputTextField.minWidthProperty().bind(currencyComboBox.widthProperty()); + } + + if (useHolderID) { + if (!requiresHolderId) + holderIdInputTextField.setText(""); + + holderIdInputTextField.resetValidation(); + holderIdInputTextField.setVisible(requiresHolderId); + holderIdInputTextField.setManaged(requiresHolderId); + + holderIdLabel.setText(BankUtil.getHolderIdLabel(countryCode)); + holderIdLabel.setVisible(requiresHolderId); + holderIdLabel.setManaged(requiresHolderId); + } + + + boolean bankNameRequired = BankUtil.isBankNameRequired(countryCode); + bankNameTuple.first.setVisible(bankNameRequired); + bankNameTuple.first.setManaged(bankNameRequired); + bankNameInputTextField.setVisible(bankNameRequired); + bankNameInputTextField.setManaged(bankNameRequired); + + boolean bankIdRequired = BankUtil.isBankIdRequired(countryCode); + bankIdTuple.first.setVisible(bankIdRequired); + bankIdTuple.first.setManaged(bankIdRequired); + bankIdInputTextField.setVisible(bankIdRequired); + bankIdInputTextField.setManaged(bankIdRequired); + + boolean branchIdRequired = BankUtil.isBranchIdRequired(countryCode); + branchIdTuple.first.setVisible(branchIdRequired); + branchIdTuple.first.setManaged(branchIdRequired); + branchIdInputTextField.setVisible(branchIdRequired); + branchIdInputTextField.setManaged(branchIdRequired); + + boolean accountNrRequired = BankUtil.isAccountNrRequired(countryCode); + accountNrTuple.first.setVisible(accountNrRequired); + accountNrTuple.first.setManaged(accountNrRequired); + accountNrInputTextField.setVisible(accountNrRequired); + accountNrInputTextField.setManaged(accountNrRequired); + + boolean accountTypeRequired = BankUtil.isAccountTypeRequired(countryCode); + accountTypeTuple.first.setVisible(accountTypeRequired); + accountTypeTuple.first.setManaged(accountTypeRequired); + accountTypeTuple.second.setVisible(accountTypeRequired); + accountTypeTuple.second.setManaged(accountTypeRequired); + + updateFromInputs(); + + onCountryChanged(); + } }); diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/CashAppForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/CashAppForm.java new file mode 100644 index 0000000000..3e3231b95a --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/CashAppForm.java @@ -0,0 +1,101 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.components.paymentmethods; + +import io.bisq.common.locale.Res; +import io.bisq.common.locale.TradeCurrency; +import io.bisq.core.payment.AccountAgeWitnessService; +import io.bisq.core.payment.CashAppAccount; +import io.bisq.core.payment.PaymentAccount; +import io.bisq.core.payment.payload.CashAppAccountPayload; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.gui.components.InputTextField; +import io.bisq.gui.util.BSFormatter; +import io.bisq.gui.util.Layout; +import io.bisq.gui.util.validation.CashAppValidator; +import io.bisq.gui.util.validation.InputValidator; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import org.apache.commons.lang3.StringUtils; + +import static io.bisq.gui.util.FormBuilder.*; + +public class CashAppForm extends PaymentMethodForm { + private final CashAppAccount account; + private final CashAppValidator validator; + private InputTextField accountIdInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.cashApp.cashTag"), ((CashAppAccountPayload) paymentAccountPayload).getCashTag()); + return gridRow; + } + + public CashAppForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, CashAppValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (CashAppAccount) paymentAccount; + this.validator = aliPayValidator; + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + accountIdInputTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.cashApp.cashTag")).second; + accountIdInputTextField.setValidator(validator); + accountIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setCashTag(newValue); + updateFromInputs(); + }); + + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + String accountNr = accountIdInputTextField.getText(); + accountNr = StringUtils.abbreviate(accountNr, 9); + String method = Res.get(paymentAccount.getPaymentMethod().getId()); + accountNameTextField.setText(method.concat(": ").concat(accountNr)); + } + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), Res.get(account.getPaymentMethod().getId())); + TextField field = addLabelTextField(gridPane, ++gridRow, Res.get("payment.cashApp.cashTag"), account.getCashTag()).second; + field.setMouseTransparent(false); + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && validator.validate(account.getCashTag()).isValid + && account.getTradeCurrencies().size() > 0); + } +} diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/MoneyBeamForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/MoneyBeamForm.java new file mode 100644 index 0000000000..86940fdc57 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/MoneyBeamForm.java @@ -0,0 +1,101 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.components.paymentmethods; + +import io.bisq.common.locale.Res; +import io.bisq.common.locale.TradeCurrency; +import io.bisq.core.payment.AccountAgeWitnessService; +import io.bisq.core.payment.MoneyBeamAccount; +import io.bisq.core.payment.PaymentAccount; +import io.bisq.core.payment.payload.MoneyBeamAccountPayload; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.gui.components.InputTextField; +import io.bisq.gui.util.BSFormatter; +import io.bisq.gui.util.Layout; +import io.bisq.gui.util.validation.InputValidator; +import io.bisq.gui.util.validation.MoneyBeamValidator; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import org.apache.commons.lang3.StringUtils; + +import static io.bisq.gui.util.FormBuilder.*; + +public class MoneyBeamForm extends PaymentMethodForm { + private final MoneyBeamAccount account; + private final MoneyBeamValidator validator; + private InputTextField accountIdInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.moneyBeam.accountId"), ((MoneyBeamAccountPayload) paymentAccountPayload).getAccountId()); + return gridRow; + } + + public MoneyBeamForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, MoneyBeamValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (MoneyBeamAccount) paymentAccount; + this.validator = aliPayValidator; + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + accountIdInputTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.moneyBeam.accountId")).second; + accountIdInputTextField.setValidator(validator); + accountIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setAccountId(newValue); + updateFromInputs(); + }); + + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + String accountNr = accountIdInputTextField.getText(); + accountNr = StringUtils.abbreviate(accountNr, 9); + String method = Res.get(paymentAccount.getPaymentMethod().getId()); + accountNameTextField.setText(method.concat(": ").concat(accountNr)); + } + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), Res.get(account.getPaymentMethod().getId())); + TextField field = addLabelTextField(gridPane, ++gridRow, Res.get("payment.moneyBeam.accountId"), account.getAccountId()).second; + field.setMouseTransparent(false); + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && validator.validate(account.getAccountId()).isValid + && account.getTradeCurrencies().size() > 0); + } +} diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/OKPayForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/OKPayForm.java index 70e1d2393e..04f3167c90 100644 --- a/gui/src/main/java/io/bisq/gui/components/paymentmethods/OKPayForm.java +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/OKPayForm.java @@ -82,7 +82,7 @@ public class OKPayForm extends PaymentMethodForm { } private void addCurrenciesGrid(boolean isEditable) { - Label label = addLabel(gridPane, ++gridRow, Res.get("payment.supported.okpay"), 0); + Label label = addLabel(gridPane, ++gridRow, Res.get("payment.supportedCurrencies"), 0); GridPane.setValignment(label, VPos.TOP); FlowPane flowPane = new FlowPane(); flowPane.setPadding(new Insets(10, 10, 10, 10)); diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/PopmoneyForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/PopmoneyForm.java new file mode 100644 index 0000000000..47867e6c13 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/PopmoneyForm.java @@ -0,0 +1,114 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.components.paymentmethods; + +import io.bisq.common.locale.Res; +import io.bisq.common.locale.TradeCurrency; +import io.bisq.core.payment.AccountAgeWitnessService; +import io.bisq.core.payment.PaymentAccount; +import io.bisq.core.payment.PopmoneyAccount; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.PopmoneyAccountPayload; +import io.bisq.gui.components.InputTextField; +import io.bisq.gui.util.BSFormatter; +import io.bisq.gui.util.Layout; +import io.bisq.gui.util.validation.InputValidator; +import io.bisq.gui.util.validation.PopmoneyValidator; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import org.apache.commons.lang3.StringUtils; + +import static io.bisq.gui.util.FormBuilder.*; + +public class PopmoneyForm extends PaymentMethodForm { + private final PopmoneyAccount account; + private final PopmoneyValidator validator; + private InputTextField accountIdInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("payment.account.owner"), + ((PopmoneyAccountPayload) paymentAccountPayload).getHolderName()); + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.popmoney.accountId"), ((PopmoneyAccountPayload) paymentAccountPayload).getAccountId()); + return gridRow; + } + + public PopmoneyForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, PopmoneyValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (PopmoneyAccount) paymentAccount; + this.validator = aliPayValidator; + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + InputTextField holderNameInputTextField = addLabelInputTextField(gridPane, ++gridRow, + Res.getWithCol("payment.account.owner")).second; + holderNameInputTextField.setValidator(inputValidator); + holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setHolderName(newValue); + updateFromInputs(); + }); + + accountIdInputTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.popmoney.accountId")).second; + accountIdInputTextField.setValidator(validator); + accountIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setAccountId(newValue); + updateFromInputs(); + }); + + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + String accountNr = accountIdInputTextField.getText(); + accountNr = StringUtils.abbreviate(accountNr, 9); + String method = Res.get(paymentAccount.getPaymentMethod().getId()); + accountNameTextField.setText(method.concat(": ").concat(accountNr)); + } + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), Res.get(account.getPaymentMethod().getId())); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("payment.account.owner"), + account.getHolderName()); + TextField field = addLabelTextField(gridPane, ++gridRow, Res.get("payment.popmoney.accountId"), account.getAccountId()).second; + field.setMouseTransparent(false); + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && inputValidator.validate(account.getHolderName()).isValid + && validator.validate(account.getAccountId()).isValid + && account.getTradeCurrencies().size() > 0); + } +} diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/RevolutForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/RevolutForm.java new file mode 100644 index 0000000000..408be054aa --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/RevolutForm.java @@ -0,0 +1,146 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.components.paymentmethods; + +import io.bisq.common.locale.CurrencyUtil; +import io.bisq.common.locale.Res; +import io.bisq.core.payment.AccountAgeWitnessService; +import io.bisq.core.payment.PaymentAccount; +import io.bisq.core.payment.RevolutAccount; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.RevolutAccountPayload; +import io.bisq.gui.components.InputTextField; +import io.bisq.gui.util.BSFormatter; +import io.bisq.gui.util.Layout; +import io.bisq.gui.util.validation.InputValidator; +import io.bisq.gui.util.validation.RevolutValidator; +import javafx.geometry.Insets; +import javafx.geometry.VPos; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.GridPane; +import org.apache.commons.lang3.StringUtils; + +import static io.bisq.gui.util.FormBuilder.*; + +public class RevolutForm extends PaymentMethodForm { + private final RevolutAccount account; + private RevolutValidator validator; + private InputTextField accountIdInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.revolut.accountId"), + ((RevolutAccountPayload) paymentAccountPayload).getAccountId()); + return gridRow; + } + + public RevolutForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, + RevolutValidator revolutValidator, InputValidator inputValidator, GridPane gridPane, + int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (RevolutAccount) paymentAccount; + this.validator = revolutValidator; + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + accountIdInputTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.revolut.accountId")).second; + accountIdInputTextField.setValidator(validator); + accountIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setAccountId(newValue); + updateFromInputs(); + }); + + addCurrenciesGrid(true); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + } + + private void addCurrenciesGrid(boolean isEditable) { + Label label = addLabel(gridPane, ++gridRow, Res.get("payment.supportedCurrencies"), 0); + GridPane.setValignment(label, VPos.TOP); + FlowPane flowPane = new FlowPane(); + flowPane.setPadding(new Insets(10, 10, 10, 10)); + flowPane.setVgap(10); + flowPane.setHgap(10); + + if (isEditable) + flowPane.setId("flow-pane-checkboxes-bg"); + else + flowPane.setId("flow-pane-checkboxes-non-editable-bg"); + + CurrencyUtil.getAllRevolutCurrencies().forEach(e -> { + CheckBox checkBox = new CheckBox(e.getCode()); + checkBox.setMouseTransparent(!isEditable); + checkBox.setSelected(account.getTradeCurrencies().contains(e)); + checkBox.setMinWidth(60); + checkBox.setMaxWidth(checkBox.getMinWidth()); + checkBox.setTooltip(new Tooltip(e.getName())); + checkBox.setOnAction(event -> { + if (checkBox.isSelected()) + account.addCurrency(e); + else + account.removeCurrency(e); + + updateAllInputsValid(); + }); + flowPane.getChildren().add(checkBox); + }); + + GridPane.setRowIndex(flowPane, gridRow); + GridPane.setColumnIndex(flowPane, 1); + gridPane.getChildren().add(flowPane); + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + String AccountId = accountIdInputTextField.getText(); + AccountId = StringUtils.abbreviate(AccountId, 9); + String method = Res.get(paymentAccount.getPaymentMethod().getId()); + accountNameTextField.setText(method.concat(": ").concat(AccountId)); + } + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), + account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), + Res.get(account.getPaymentMethod().getId())); + TextField field = addLabelTextField(gridPane, ++gridRow, Res.get("payment.revolut.accountId"), + account.getAccountId()).second; + field.setMouseTransparent(false); + addLimitations(); + addCurrenciesGrid(false); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && validator.validate(account.getAccountId()).isValid + && account.getTradeCurrencies().size() > 0); + } +} diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/UpholdForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/UpholdForm.java new file mode 100644 index 0000000000..eef97092ec --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/UpholdForm.java @@ -0,0 +1,147 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.components.paymentmethods; + +import io.bisq.common.locale.CurrencyUtil; +import io.bisq.common.locale.Res; +import io.bisq.core.payment.AccountAgeWitnessService; +import io.bisq.core.payment.PaymentAccount; +import io.bisq.core.payment.UpholdAccount; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.UpholdAccountPayload; +import io.bisq.gui.components.InputTextField; +import io.bisq.gui.util.BSFormatter; +import io.bisq.gui.util.Layout; +import io.bisq.gui.util.validation.InputValidator; +import io.bisq.gui.util.validation.UpholdValidator; +import javafx.geometry.Insets; +import javafx.geometry.VPos; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.GridPane; +import org.apache.commons.lang3.StringUtils; + +import static io.bisq.gui.util.FormBuilder.*; + +public class UpholdForm extends PaymentMethodForm { + private final UpholdAccount upholdAccount; + private UpholdValidator upholdValidator; + private InputTextField accountIdInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, + PaymentAccountPayload paymentAccountPayload) { + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.uphold.accountId"), + ((UpholdAccountPayload) paymentAccountPayload).getAccountId()); + return gridRow; + } + + public UpholdForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, + UpholdValidator upholdValidator, InputValidator inputValidator, GridPane gridPane, + int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.upholdAccount = (UpholdAccount) paymentAccount; + this.upholdValidator = upholdValidator; + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + accountIdInputTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.uphold.accountId")).second; + accountIdInputTextField.setValidator(upholdValidator); + accountIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + upholdAccount.setAccountId(newValue); + updateFromInputs(); + }); + + addCurrenciesGrid(true); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + } + + private void addCurrenciesGrid(boolean isEditable) { + Label label = addLabel(gridPane, ++gridRow, Res.get("payment.supportedCurrencies"), 0); + GridPane.setValignment(label, VPos.TOP); + FlowPane flowPane = new FlowPane(); + flowPane.setPadding(new Insets(10, 10, 10, 10)); + flowPane.setVgap(10); + flowPane.setHgap(10); + + if (isEditable) + flowPane.setId("flow-pane-checkboxes-bg"); + else + flowPane.setId("flow-pane-checkboxes-non-editable-bg"); + + CurrencyUtil.getAllUpholdCurrencies().stream().forEach(e -> + { + CheckBox checkBox = new CheckBox(e.getCode()); + checkBox.setMouseTransparent(!isEditable); + checkBox.setSelected(upholdAccount.getTradeCurrencies().contains(e)); + checkBox.setMinWidth(60); + checkBox.setMaxWidth(checkBox.getMinWidth()); + checkBox.setTooltip(new Tooltip(e.getName())); + checkBox.setOnAction(event -> { + if (checkBox.isSelected()) + upholdAccount.addCurrency(e); + else + upholdAccount.removeCurrency(e); + + updateAllInputsValid(); + }); + flowPane.getChildren().add(checkBox); + }); + + GridPane.setRowIndex(flowPane, gridRow); + GridPane.setColumnIndex(flowPane, 1); + gridPane.getChildren().add(flowPane); + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + String AccountId = accountIdInputTextField.getText(); + AccountId = StringUtils.abbreviate(AccountId, 9); + String method = Res.get(paymentAccount.getPaymentMethod().getId()); + accountNameTextField.setText(method.concat(": ").concat(AccountId)); + } + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), + upholdAccount.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), + Res.get(upholdAccount.getPaymentMethod().getId())); + TextField field = addLabelTextField(gridPane, ++gridRow, Res.get("payment.uphold.accountId"), + upholdAccount.getAccountId()).second; + field.setMouseTransparent(false); + addLimitations(); + addCurrenciesGrid(false); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && upholdValidator.validate(upholdAccount.getAccountId()).isValid + && upholdAccount.getTradeCurrencies().size() > 0); + } +} diff --git a/gui/src/main/java/io/bisq/gui/components/paymentmethods/VenmoForm.java b/gui/src/main/java/io/bisq/gui/components/paymentmethods/VenmoForm.java new file mode 100644 index 0000000000..645ff8544c --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/components/paymentmethods/VenmoForm.java @@ -0,0 +1,114 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.components.paymentmethods; + +import io.bisq.common.locale.Res; +import io.bisq.common.locale.TradeCurrency; +import io.bisq.core.payment.AccountAgeWitnessService; +import io.bisq.core.payment.PaymentAccount; +import io.bisq.core.payment.VenmoAccount; +import io.bisq.core.payment.payload.PaymentAccountPayload; +import io.bisq.core.payment.payload.VenmoAccountPayload; +import io.bisq.gui.components.InputTextField; +import io.bisq.gui.util.BSFormatter; +import io.bisq.gui.util.Layout; +import io.bisq.gui.util.validation.InputValidator; +import io.bisq.gui.util.validation.VenmoValidator; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import org.apache.commons.lang3.StringUtils; + +import static io.bisq.gui.util.FormBuilder.*; + +public class VenmoForm extends PaymentMethodForm { + private final VenmoAccount account; + private final VenmoValidator validator; + private InputTextField accountIdInputTextField; + + public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload paymentAccountPayload) { + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("payment.account.owner"), + ((VenmoAccountPayload) paymentAccountPayload).getHolderName()); + addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, Res.get("payment.venmo.venmoUserName"), ((VenmoAccountPayload) paymentAccountPayload).getVenmoUserName()); + return gridRow; + } + + public VenmoForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, VenmoValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); + this.account = (VenmoAccount) paymentAccount; + this.validator = aliPayValidator; + } + + @Override + public void addFormForAddAccount() { + gridRowFrom = gridRow + 1; + + InputTextField holderNameInputTextField = addLabelInputTextField(gridPane, ++gridRow, + Res.getWithCol("payment.account.owner")).second; + holderNameInputTextField.setValidator(inputValidator); + holderNameInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setHolderName(newValue); + updateFromInputs(); + }); + + accountIdInputTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("payment.venmo.venmoUserName")).second; + accountIdInputTextField.setValidator(validator); + accountIdInputTextField.textProperty().addListener((ov, oldValue, newValue) -> { + account.setVenmoUserName(newValue); + updateFromInputs(); + }); + + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + addAccountNameTextFieldWithAutoFillCheckBox(); + } + + @Override + protected void autoFillNameTextField() { + if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) { + String accountNr = accountIdInputTextField.getText(); + accountNr = StringUtils.abbreviate(accountNr, 9); + String method = Res.get(paymentAccount.getPaymentMethod().getId()); + accountNameTextField.setText(method.concat(": ").concat(accountNr)); + } + } + + @Override + public void addFormForDisplayAccount() { + gridRowFrom = gridRow; + addLabelTextField(gridPane, gridRow, Res.get("payment.account.name"), account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.paymentMethod"), Res.get(account.getPaymentMethod().getId())); + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("payment.account.owner"), + account.getHolderName()); + TextField field = addLabelTextField(gridPane, ++gridRow, Res.get("payment.venmo.venmoUserName"), account.getVenmoUserName()).second; + field.setMouseTransparent(false); + final TradeCurrency singleTradeCurrency = account.getSingleTradeCurrency(); + final String nameAndCode = singleTradeCurrency != null ? singleTradeCurrency.getNameAndCode() : ""; + addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.currency"), nameAndCode); + addLimitations(); + } + + @Override + public void updateAllInputsValid() { + allInputsValid.set(isAccountNameValid() + && inputValidator.validate(account.getHolderName()).isValid + && validator.validate(account.getVenmoUserName()).isValid + && account.getTradeCurrencies().size() > 0); + } +} diff --git a/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsDataModel.java b/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsDataModel.java index 40127a1a98..2d0f0d22f9 100644 --- a/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsDataModel.java +++ b/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsDataModel.java @@ -19,6 +19,7 @@ package io.bisq.gui.main.account.content.fiataccounts; import com.google.inject.Inject; import io.bisq.common.locale.CryptoCurrency; +import io.bisq.common.locale.CurrencyUtil; import io.bisq.common.locale.FiatCurrency; import io.bisq.common.locale.TradeCurrency; import io.bisq.common.proto.persistable.PersistenceProtoResolver; @@ -108,7 +109,12 @@ class FiatAccountsDataModel extends ActivatableDataModel { else preferences.addCryptoCurrency((CryptoCurrency) singleTradeCurrency); } else if (tradeCurrencies != null && !tradeCurrencies.isEmpty()) { - tradeCurrencies.stream().forEach(tradeCurrency -> { + if (tradeCurrencies.contains(CurrencyUtil.getDefaultTradeCurrency())) + paymentAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency()); + else + paymentAccount.setSelectedTradeCurrency(tradeCurrencies.get(0)); + + tradeCurrencies.forEach(tradeCurrency -> { if (tradeCurrency instanceof FiatCurrency) preferences.addFiatCurrency((FiatCurrency) tradeCurrency); else diff --git a/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsView.java b/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsView.java index 6751c68b41..f5de364791 100644 --- a/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsView.java +++ b/gui/src/main/java/io/bisq/gui/main/account/content/fiataccounts/FiatAccountsView.java @@ -46,6 +46,7 @@ import javafx.scene.layout.GridPane; import javafx.scene.text.TextAlignment; import javafx.util.Callback; import javafx.util.StringConverter; +import org.bitcoinj.core.Coin; import javax.inject.Inject; import java.util.List; @@ -64,6 +65,12 @@ public class FiatAccountsView extends ActivatableViewAndModel().information(Res.get("payment.clearXchange.info", currencyName, currencyName)) - .width(900) - .closeButtonText(Res.get("shared.cancel")) - .actionButtonText(Res.get("shared.iConfirm")) - .onAction(() -> doSaveNewAccount(paymentAccount)) - .show(); - } else if (paymentAccount instanceof WesternUnionAccount) { - new Popup<>().information(Res.get("payment.westernUnion.info", currencyName, currencyName)) - .width(700) - .closeButtonText(Res.get("shared.cancel")) - .actionButtonText(Res.get("shared.iUnderstand")) - .onAction(() -> doSaveNewAccount(paymentAccount)) - .show(); - } else { - doSaveNewAccount(paymentAccount); - } + Coin maxTradeLimitAsCoin = paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin("USD"); + Coin maxTradeLimitSecondMonth = maxTradeLimitAsCoin.divide(2L); + Coin maxTradeLimitFirstMonth = maxTradeLimitAsCoin.divide(4L); + new Popup<>().information(Res.get("payment.limits.info", + formatter.formatCoinWithCode(maxTradeLimitFirstMonth), + formatter.formatCoinWithCode(maxTradeLimitSecondMonth), + formatter.formatCoinWithCode(maxTradeLimitAsCoin))) + .width(700) + .closeButtonText(Res.get("shared.cancel")) + .actionButtonText(Res.get("shared.iUnderstand")) + .onAction(() -> { + final String currencyName = BisqEnvironment.getBaseCurrencyNetwork().getCurrencyName(); + if (paymentAccount instanceof ClearXchangeAccount) { + new Popup<>().information(Res.get("payment.clearXchange.info", currencyName, currencyName)) + .width(900) + .closeButtonText(Res.get("shared.cancel")) + .actionButtonText(Res.get("shared.iConfirm")) + .onAction(() -> doSaveNewAccount(paymentAccount)) + .show(); + } else if (paymentAccount instanceof WesternUnionAccount) { + new Popup<>().information(Res.get("payment.westernUnion.info")) + .width(700) + .closeButtonText(Res.get("shared.cancel")) + .actionButtonText(Res.get("shared.iUnderstand")) + .onAction(() -> doSaveNewAccount(paymentAccount)) + .show(); + } else { + doSaveNewAccount(paymentAccount); + } + }) + .show(); } private void doSaveNewAccount(PaymentAccount paymentAccount) { - if (!model.getPaymentAccounts().stream().filter(e -> e.getAccountName() != null && - e.getAccountName().equals(paymentAccount.getAccountName())) - .findAny() - .isPresent()) { - - // TODO apply salt if user provided it - // testing - // paymentAccount.setSaltAsHex("a25b65f612e49ba6c4ab80a95fc9b723bcff9e7c6bd06f020d4bdffdac060eed"); - + if (model.getPaymentAccounts().stream().noneMatch(e -> e.getAccountName() != null && + e.getAccountName().equals(paymentAccount.getAccountName()))) { model.onSaveNewAccount(paymentAccount); removeNewAccountForm(); } else { @@ -341,6 +366,18 @@ public class FiatAccountsView extends ActivatableViewAndModel() { - @Override - public String toString(PaymentAccount paymentAccount) { - TradeCurrency singleTradeCurrency = paymentAccount.getSingleTradeCurrency(); - String code = singleTradeCurrency != null ? singleTradeCurrency.getCode() : ""; - return paymentAccount.getAccountName() + " (" + code + ", " + - Res.get(paymentAccount.getPaymentMethod().getId()) + ")"; - } - - @Override - public PaymentAccount fromString(String s) { - return null; - } - }); + paymentAccountsComboBox.setConverter(GUIUtil.getPaymentAccountsComboBoxStringConverter()); GUIUtil.focusWhenAddedToScene(amountTextField); } @@ -433,6 +420,10 @@ public class CreateOfferView extends ActivatableViewAndModel tradeCurrencies = paymentAccount.getTradeCurrencies(); currencyComboBox.setItems(FXCollections.observableArrayList(tradeCurrencies)); - - // we select comboBox following the user currency, if user currency not available in account, we select first - TradeCurrency tradeCurrency = model.getTradeCurrency(); - if (tradeCurrencies.contains(tradeCurrency)) - currencyComboBox.getSelectionModel().select(tradeCurrency); + if (paymentAccount.getSelectedTradeCurrency() != null) + currencyComboBox.getSelectionModel().select(paymentAccount.getSelectedTradeCurrency()); + else if (tradeCurrencies.contains(model.getTradeCurrency())) + currencyComboBox.getSelectionModel().select(model.getTradeCurrency()); else currencyComboBox.getSelectionModel().select(tradeCurrencies.get(0)); @@ -461,6 +451,8 @@ public class CreateOfferView extends ActivatableViewAndModel - model.onTakeOffer(() -> { - offerDetailsWindow.hide(); - offerDetailsWindowDisplayed = false; - }) + model.onTakeOffer(() -> { + offerDetailsWindow.hide(); + offerDetailsWindowDisplayed = false; + }) ).show(model.getOffer(), model.dataModel.getAmount().get(), model.dataModel.tradePrice); offerDetailsWindowDisplayed = true; } else { @@ -684,20 +680,7 @@ public class TakeOfferView extends ActivatableViewAndModel() { - @Override - public String toString(PaymentAccount paymentAccount) { - TradeCurrency singleTradeCurrency = paymentAccount.getSingleTradeCurrency(); - String code = singleTradeCurrency != null ? singleTradeCurrency.getCode() : ""; - return paymentAccount.getAccountName() + " (" + code + ", " + - Res.get(paymentAccount.getPaymentMethod().getId()) + ")"; - } - - @Override - public PaymentAccount fromString(String s) { - return null; - } - }); + paymentAccountsComboBox.setConverter(GUIUtil.getPaymentAccountsComboBoxStringConverter()); paymentAccountsComboBox.setVisible(false); paymentAccountsComboBox.setManaged(false); paymentAccountsComboBox.setOnAction(e -> { @@ -971,7 +954,7 @@ public class TakeOfferView extends ActivatableViewAndModel amountValueCurrencyBoxTuple = getNonEditableValueCurrencyBox(); amountRangeTextField = amountValueCurrencyBoxTuple.second; - Tuple2 amountInputBoxTuple = getTradeInputBox( amountValueCurrencyBoxTuple.first, + Tuple2 amountInputBoxTuple = getTradeInputBox(amountValueCurrencyBoxTuple.first, Res.get("takeOffer.amountPriceBox.amountRangeDescription")); amountRangeBox = amountInputBoxTuple.second; diff --git a/gui/src/main/java/io/bisq/gui/main/overlays/windows/downloadupdate/BisqInstaller.java b/gui/src/main/java/io/bisq/gui/main/overlays/windows/downloadupdate/BisqInstaller.java index e34da23968..bcc4911819 100644 --- a/gui/src/main/java/io/bisq/gui/main/overlays/windows/downloadupdate/BisqInstaller.java +++ b/gui/src/main/java/io/bisq/gui/main/overlays/windows/downloadupdate/BisqInstaller.java @@ -38,10 +38,11 @@ import static com.google.common.base.Preconditions.checkArgument; @Slf4j public class BisqInstaller { - static final String FINGER_PRINT_MANFRED_KARRER = "F379A1C6"; - static final String FINGER_PRINT_CHRIS_BEAMS = "5BC5ED73"; - static final String PUB_KEY_HOSTING_URL = "https://bisq.network/pubkey/"; - static final String DOWNLOAD_HOST_URL = "https://github.com/bisq-network/exchange/releases/download/"; + private static final String FINGER_PRINT_MANFRED_KARRER = "F379A1C6"; + private static final String FINGER_PRINT_CHRIS_BEAMS = "5BC5ED73"; + private static final String FINGER_PRINT_CHRISTOPH_ATTENEDER = "29CDFD3B"; + private static final String PUB_KEY_HOSTING_URL = "https://bisq.network/pubkey/"; + private static final String DOWNLOAD_HOST_URL = "https://github.com/bisq-network/exchange/releases/download/"; public boolean isSupportedOS() { return Utilities.isOSX() || Utilities.isWindows() || Utilities.isLinux(); @@ -79,7 +80,7 @@ public class BisqInstaller { try { return Optional.of(downloadFiles(fileDescriptors, Utilities.getDownloadOfHomeDir())); } catch (IOException exception) { - return Optional.empty(); + return Optional.empty(); } } @@ -91,7 +92,7 @@ public class BisqInstaller { * @return The task handling the download * @throws IOException */ - public static DownloadTask downloadFiles(List fileDescriptors, String saveDir) throws IOException { + private static DownloadTask downloadFiles(List fileDescriptors, String saveDir) throws IOException { if (saveDir == null) saveDir = Utilities.getDownloadOfHomeDir(); DownloadTask task = new DownloadTask(fileDescriptors, saveDir); @@ -178,7 +179,7 @@ public class BisqInstaller { } @NotNull - public FileDescriptor getInstallerDescriptor(String version, String partialUrl) { + private FileDescriptor getInstallerDescriptor(String version, String partialUrl) { String fileName; String prefix = "Bisq-"; // https://github.com/bisq-network/exchange/releases/download/v0.5.1/Bisq-0.5.1.dmg @@ -200,7 +201,7 @@ public class BisqInstaller { } @NotNull - public FileDescriptor getSigningKeyDescriptor(String url) { + private FileDescriptor getSigningKeyDescriptor(String url) { String fileName = "signingkey.asc"; return FileDescriptor.builder() .type(DownloadType.SIGNING_KEY) @@ -217,7 +218,7 @@ public class BisqInstaller { * * @return list of keys to check agains corresponding sigs. */ - public List getKeyFileDescriptors() { + private List getKeyFileDescriptors() { List list = new ArrayList<>(); list.add(getKeyFileDescriptor(FINGER_PRINT_MANFRED_KARRER)); @@ -226,6 +227,9 @@ public class BisqInstaller { list.add(getKeyFileDescriptor(FINGER_PRINT_CHRIS_BEAMS)); list.add(getLocalKeyFileDescriptor(FINGER_PRINT_CHRIS_BEAMS)); + list.add(getKeyFileDescriptor(FINGER_PRINT_CHRISTOPH_ATTENEDER)); + list.add(getLocalKeyFileDescriptor(FINGER_PRINT_CHRISTOPH_ATTENEDER)); + return list; } @@ -260,7 +264,7 @@ public class BisqInstaller { List result = Lists.newArrayList(); for (FileDescriptor key : keys) { - if (!result.stream().filter(e -> e.getId().equals(key.getId())).findAny().isPresent()) { + if (result.stream().noneMatch(e -> e.getId().equals(key.getId()))) { result.add(FileDescriptor.builder() .type(DownloadType.SIG) .fileName(installerFileDescriptor.getFileName().concat(suffix)) diff --git a/gui/src/main/java/io/bisq/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java b/gui/src/main/java/io/bisq/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java index f0aa9727dd..787ba5c742 100644 --- a/gui/src/main/java/io/bisq/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java +++ b/gui/src/main/java/io/bisq/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java @@ -35,8 +35,8 @@ class ClosedTradesViewModel extends ActivatableWithDataModel - - - - - - - - + + + + + + + + + - \ No newline at end of file + diff --git a/gui/src/main/java/io/bisq/gui/main/portfolio/openoffer/OpenOffersView.java b/gui/src/main/java/io/bisq/gui/main/portfolio/openoffer/OpenOffersView.java index aca986f47a..66fcb3b152 100644 --- a/gui/src/main/java/io/bisq/gui/main/portfolio/openoffer/OpenOffersView.java +++ b/gui/src/main/java/io/bisq/gui/main/portfolio/openoffer/OpenOffersView.java @@ -40,6 +40,7 @@ import javafx.scene.control.*; import javafx.scene.image.ImageView; import javafx.scene.layout.VBox; import javafx.util.Callback; +import org.jetbrains.annotations.NotNull; import javax.inject.Inject; @@ -50,7 +51,7 @@ public class OpenOffersView extends ActivatableViewAndModel tableView; @FXML TableColumn priceColumn, amountColumn, volumeColumn, - marketColumn, directionColumn, dateColumn, offerIdColumn, removeItemColumn; + marketColumn, directionColumn, dateColumn, offerIdColumn, deactivateItemColumn, removeItemColumn; private final Navigation navigation; private final OfferDetailsWindow offerDetailsWindow; private SortedList sortedList; @@ -71,6 +72,7 @@ public class OpenOffersView extends ActivatableViewAndModel { + log.debug("Deactivate offer was successful"); + }, + (message) -> { + log.error(message); + new Popup<>().warning(Res.get("offerbook.deactivateOffer.failed", message)).show(); + }); + } else { + new Popup<>().information(Res.get("popup.warning.notFullyConnected")).show(); + } + } + + private void onActivateOpenOffer(OpenOffer openOffer) { + if (model.isBootstrapped()) { + model.onActivateOpenOffer(openOffer, + () -> { + log.debug("Activate offer was successful"); + }, + (message) -> { + log.error(message); + new Popup<>().warning(Res.get("offerbook.activateOffer.failed", message)).show(); + }); + } else { + new Popup<>().information(Res.get("popup.warning.notFullyConnected")).show(); + } + } + private void onRemoveOpenOffer(OpenOffer openOffer) { if (model.isBootstrapped()) { String key = "RemoveOfferWarning"; @@ -135,7 +168,7 @@ public class OpenOffersView extends ActivatableViewAndModel { log.debug("Remove offer was successful"); String key = "WithdrawFundsAfterRemoveOfferInfo"; @@ -196,10 +229,12 @@ public class OpenOffersView extends ActivatableViewAndModel new ReadOnlyObjectWrapper<>(offerListItem.getValue())); + deactivateItemColumn.setCellFactory( + new Callback, TableCell>() { + @Override + public TableCell call(TableColumn column) { + return new TableCell() { + final ImageView iconView = new ImageView(); + Button button; + + private void updateState(@NotNull OpenOffer openOffer) { + if (openOffer.isDeactivated()) { + button.setText(Res.get("shared.activate")); + iconView.setId("image-alert-round"); + button.setGraphic(iconView); + } else { + button.setText(Res.get("shared.deactivate")); + iconView.setId("image-green_circle"); + button.setGraphic(iconView); + } + } + + @Override + public void updateItem(final OpenOfferListItem item, boolean empty) { + super.updateItem(item, empty); + + if (item != null && !empty) { + if (button == null) { + button = new AutoTooltipButton(); + button.setGraphic(iconView); + updateState(item.getOpenOffer()); + button.setMinWidth(70); + setGraphic(button); + } + button.setOnAction(event -> { + if (item.getOpenOffer().isDeactivated()) { + onActivateOpenOffer(item.getOpenOffer()); + } else { + onDeactivateOpenOffer(item.getOpenOffer()); + } + updateState(item.getOpenOffer()); + tableView.refresh(); + }); + } else { + setGraphic(null); + if (button != null) { + button.setOnAction(null); + button = null; + } + } + } + }; + } + }); + } + private void setRemoveColumnCellFactory() { removeItemColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue())); removeItemColumn.setCellFactory( @@ -323,6 +420,7 @@ public class OpenOffersView extends ActivatableViewAndModel this.formatter = formatter; } - void onCancelOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - dataModel.onCancelOpenOffer(openOffer, resultHandler, errorMessageHandler); + void onActivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + dataModel.onActivateOpenOffer(openOffer, resultHandler, errorMessageHandler); + } + + void onDeactivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + dataModel.onDeactivateOpenOffer(openOffer, resultHandler, errorMessageHandler); + } + + void onRemoveOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + dataModel.onRemoveOpenOffer(openOffer, resultHandler, errorMessageHandler); } public ObservableList getList() { @@ -99,6 +107,10 @@ class OpenOffersViewModel extends ActivatableWithDataModel return formatter.formatDateTime(item.getOffer().getDate()); } + boolean isDeactivated(OpenOfferListItem item) { + return item != null && item.getOpenOffer() != null && item.getOpenOffer().isDeactivated(); + } + boolean isBootstrapped() { return p2PService.isBootstrapped(); } diff --git a/gui/src/main/java/io/bisq/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/gui/src/main/java/io/bisq/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index 233ffe7176..760ab13c99 100644 --- a/gui/src/main/java/io/bisq/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/gui/src/main/java/io/bisq/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -157,6 +157,24 @@ public class BuyerStep2View extends TradeStepView { case PaymentMethod.OK_PAY_ID: gridRow = OKPayForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); break; + case PaymentMethod.UPHOLD_ID: + gridRow = UpholdForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.CASH_APP_ID: + gridRow = CashAppForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.MONEY_BEAM_ID: + gridRow = MoneyBeamForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.VENMO_ID: + gridRow = VenmoForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.POPMONEY_ID: + gridRow = PopmoneyForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; + case PaymentMethod.REVOLUT_ID: + gridRow = RevolutForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); + break; case PaymentMethod.PERFECT_MONEY_ID: gridRow = PerfectMoneyForm.addFormForBuyer(gridPane, gridRow, paymentAccountPayload); break; diff --git a/gui/src/main/java/io/bisq/gui/main/settings/preferences/PreferencesView.java b/gui/src/main/java/io/bisq/gui/main/settings/preferences/PreferencesView.java index f0101c4003..476e918d13 100644 --- a/gui/src/main/java/io/bisq/gui/main/settings/preferences/PreferencesView.java +++ b/gui/src/main/java/io/bisq/gui/main/settings/preferences/PreferencesView.java @@ -51,6 +51,7 @@ import javafx.scene.layout.GridPane; import javafx.util.Callback; import javafx.util.StringConverter; import org.apache.commons.lang3.StringUtils; +import org.bitcoinj.core.Coin; import javax.inject.Inject; import java.util.Arrays; @@ -217,15 +218,16 @@ public class PreferencesView extends ActivatableViewAndModel().warning(Res.get("setting.preferences.txFeeMin")).show(); + int withdrawalTxFeePerByte = Integer.parseInt(transactionFeeInputTextField.getText()); + final long minFeePerByte = BisqEnvironment.getBaseCurrencyNetwork().getDefaultMinFeePerByte(); + if (withdrawalTxFeePerByte < minFeePerByte) { + new Popup<>().warning(Res.get("setting.preferences.txFeeMin", minFeePerByte)).show(); transactionFeeInputTextField.setText(estimatedFee); - } else if (withdrawalTxFeeInBytes > 5000) { + } else if (withdrawalTxFeePerByte > 5000) { new Popup<>().warning(Res.get("setting.preferences.txFeeTooLarge")).show(); transactionFeeInputTextField.setText(estimatedFee); } else { - preferences.setWithdrawalTxFeeInBytes(withdrawalTxFeeInBytes); + preferences.setWithdrawalTxFeeInBytes(withdrawalTxFeePerByte); } } catch (NumberFormatException t) { log.error(t.toString()); @@ -249,10 +251,11 @@ public class PreferencesView extends ActivatableViewAndModel { try { double value = formatter.parsePercentStringToDouble(newValue); - if (value <= 0.3) { + final double maxDeviation = 0.5; + if (value <= maxDeviation) { preferences.setMaxPriceDistanceInPercent(value); } else { - new Popup<>().warning(Res.get("setting.preferences.deviationToLarge")).show(); + new Popup<>().warning(Res.get("setting.preferences.deviationToLarge", maxDeviation * 100)).show(); UserThread.runAfter(() -> deviationInputTextField.setText(formatter.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); } } catch (NumberFormatException t) { @@ -451,12 +454,6 @@ public class PreferencesView extends ActivatableViewAndModel baseCurrencyNetworks = Arrays.asList(BaseCurrencyNetwork.values()); - // We don't support DOGE anymore due lack of interest but leave it in the code in case it will get - // re-activated some day - baseCurrencyNetworks = baseCurrencyNetworks.stream() - .filter(e -> !e.isDoge()) - .collect(Collectors.toList()); - // show ony mainnet in production version if (!DevEnv.DEV_MODE) baseCurrencyNetworks = baseCurrencyNetworks.stream() @@ -475,7 +472,7 @@ public class PreferencesView extends ActivatableViewAndModel getPaymentAccountsComboBoxStringConverter() { + return new StringConverter() { + @Override + public String toString(PaymentAccount paymentAccount) { + if (paymentAccount.hasMultipleCurrencies()) { + return paymentAccount.getAccountName() + " (" + Res.get(paymentAccount.getPaymentMethod().getId()) + ")"; + } else { + TradeCurrency singleTradeCurrency = paymentAccount.getSingleTradeCurrency(); + String prefix = singleTradeCurrency != null ? singleTradeCurrency.getCode() + ", " : ""; + return paymentAccount.getAccountName() + " (" + prefix + + Res.get(paymentAccount.getPaymentMethod().getId()) + ")"; + } + } + + @Override + public PaymentAccount fromString(String s) { + return null; + } + }; + } } diff --git a/gui/src/main/java/io/bisq/gui/util/validation/AltCoinAddressValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/AltCoinAddressValidator.java index 32c7c4076b..d8c14580d6 100644 --- a/gui/src/main/java/io/bisq/gui/util/validation/AltCoinAddressValidator.java +++ b/gui/src/main/java/io/bisq/gui/util/validation/AltCoinAddressValidator.java @@ -75,9 +75,6 @@ public final class AltCoinAddressValidator extends InputValidator { case LTC_MAINNET: case LTC_TESTNET: case LTC_REGTEST: - case DOGE_MAINNET: - case DOGE_TESTNET: - case DOGE_REGTEST: case DASH_MAINNET: case DASH_TESTNET: case DASH_REGTEST: @@ -118,9 +115,6 @@ public final class AltCoinAddressValidator extends InputValidator { case BTC_MAINNET: case BTC_TESTNET: case BTC_REGTEST: - case DOGE_MAINNET: - case DOGE_TESTNET: - case DOGE_REGTEST: case DASH_MAINNET: case DASH_TESTNET: case DASH_REGTEST: @@ -140,26 +134,7 @@ public final class AltCoinAddressValidator extends InputValidator { } case "DOGE": try { - switch (BisqEnvironment.getBaseCurrencyNetwork()) { - case BTC_MAINNET: - case BTC_TESTNET: - case BTC_REGTEST: - case LTC_MAINNET: - case LTC_TESTNET: - case LTC_REGTEST: - case DASH_MAINNET: - case DASH_TESTNET: - case DASH_REGTEST: - case DOGE_MAINNET: - Address.fromBase58(DogecoinMainNetParams.get(), input); - break; - case DOGE_TESTNET: - Address.fromBase58(DogecoinTestNet3Params.get(), input); - break; - case DOGE_REGTEST: - Address.fromBase58(DogecoinRegTestParams.get(), input); - break; - } + Address.fromBase58(DogecoinMainNetParams.get(), input); return new ValidationResult(true); } catch (AddressFormatException e) { return new ValidationResult(false, getErrorMessage(e)); @@ -173,9 +148,6 @@ public final class AltCoinAddressValidator extends InputValidator { case LTC_MAINNET: case LTC_TESTNET: case LTC_REGTEST: - case DOGE_MAINNET: - case DOGE_TESTNET: - case DOGE_REGTEST: case DASH_MAINNET: Address.fromBase58(DashMainNetParams.get(), input); break; @@ -458,6 +430,40 @@ public final class AltCoinAddressValidator extends InputValidator { } catch (AddressFormatException e) { return new ValidationResult(false, getErrorMessage(e)); } + case "CDT": + if (input.startsWith("D")) + return new ValidationResult(true); + else + return new ValidationResult(false); + case "DGM": + if (input.matches("^[D-E][a-zA-Z0-9]{33}$")) + return new ValidationResult(true); + else + return regexTestFailed; + case "SCS": + try { + Address.fromBase58(SpeedCashParams.get(), input); + return new ValidationResult(true); + } catch (AddressFormatException e) { + return new ValidationResult(false, getErrorMessage(e)); + } + case "SOS": + if (!input.matches("^(0x)?[0-9a-fA-F]{40}$")) + return regexTestFailed; + else + return new ValidationResult(true); + case "ACH": + try { + Address.fromBase58(ACHParams.get(), input); + return new ValidationResult(true); + } catch (AddressFormatException e) { + return new ValidationResult(false, getErrorMessage(e)); + } + case "VDN": + if (!input.matches("^[D][0-9a-zA-Z]{33}$")) + return regexTestFailed; + else + return new ValidationResult(true); // Add new coins at the end... default: diff --git a/gui/src/main/java/io/bisq/gui/util/validation/CashAppValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/CashAppValidator.java new file mode 100644 index 0000000000..283d03e980 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/CashAppValidator.java @@ -0,0 +1,28 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation; + + +public final class CashAppValidator extends InputValidator { + + @Override + public ValidationResult validate(String input) { + // TODO + return super.validate(input); + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/MoneyBeamValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/MoneyBeamValidator.java new file mode 100644 index 0000000000..785e04b783 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/MoneyBeamValidator.java @@ -0,0 +1,28 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation; + + +public final class MoneyBeamValidator extends InputValidator { + + @Override + public ValidationResult validate(String input) { + // TODO + return super.validate(input); + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/PopmoneyValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/PopmoneyValidator.java new file mode 100644 index 0000000000..1a70dc7bd2 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/PopmoneyValidator.java @@ -0,0 +1,28 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation; + + +public final class PopmoneyValidator extends InputValidator { + + @Override + public ValidationResult validate(String input) { + // TODO + return super.validate(input); + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/RevolutValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/RevolutValidator.java new file mode 100644 index 0000000000..3068ecc8f3 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/RevolutValidator.java @@ -0,0 +1,28 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation; + + +public final class RevolutValidator extends InputValidator { + + @Override + public ValidationResult validate(String input) { + // TODO + return super.validate(input); + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/UpholdValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/UpholdValidator.java new file mode 100644 index 0000000000..bee83be9ea --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/UpholdValidator.java @@ -0,0 +1,28 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation; + + +public final class UpholdValidator extends InputValidator { + + @Override + public ValidationResult validate(String input) { + // TODO + return super.validate(input); + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/VenmoValidator.java b/gui/src/main/java/io/bisq/gui/util/validation/VenmoValidator.java new file mode 100644 index 0000000000..9945e234ad --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/VenmoValidator.java @@ -0,0 +1,28 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation; + + +public final class VenmoValidator extends InputValidator { + + @Override + public ValidationResult validate(String input) { + // TODO + return super.validate(input); + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/params/ACHParams.java b/gui/src/main/java/io/bisq/gui/util/validation/params/ACHParams.java new file mode 100644 index 0000000000..e757ec9b73 --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/params/ACHParams.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013 Google Inc. + * Copyright 2015 Andreas Schildbach + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.bisq.gui.util.validation.params; + +import org.bitcoinj.core.Utils; +import org.bitcoinj.params.AbstractBitcoinNetParams; + +public class ACHParams extends AbstractBitcoinNetParams { + + public ACHParams() { + super(); + interval = INTERVAL; + targetTimespan = TARGET_TIMESPAN; + maxTarget = Utils.decodeCompactBits(0x1d00ffffL); + dumpedPrivateKeyHeader = 128; + + // Address format is different to BTC, rest is the same + addressHeader = 23; //BTG 38; + p2shHeader = 34; //BTG 23; + + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + port = 7337; //BTC and BTG 8333 + packetMagic = 0x1461de3cL; //BTG 0xe1476d44L, BTC 0xf9beb4d9L; + bip32HeaderPub = 0x02651F71; //BTG and BTC 0x0488B21E; //The 4 byte header that serializes in base58 to "xpub". + bip32HeaderPriv = 0x02355E56; //BTG and BTC 0x0488ADE4; //The 4 byte header that serializes in base58 to "xprv" + + id = ID_MAINNET; + } + + private static ACHParams instance; + + public static synchronized ACHParams get() { + if (instance == null) { + instance = new ACHParams(); + } + return instance; + } + + @Override + public String getPaymentProtocolId() { + return PAYMENT_PROTOCOL_ID_MAINNET; + } +} diff --git a/gui/src/main/java/io/bisq/gui/util/validation/params/SpeedCashParams.java b/gui/src/main/java/io/bisq/gui/util/validation/params/SpeedCashParams.java new file mode 100644 index 0000000000..202865ed4e --- /dev/null +++ b/gui/src/main/java/io/bisq/gui/util/validation/params/SpeedCashParams.java @@ -0,0 +1,88 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package io.bisq.gui.util.validation.params; + +import org.bitcoinj.core.*; +import org.bitcoinj.store.BlockStore; +import org.bitcoinj.store.BlockStoreException; +import org.bitcoinj.utils.MonetaryFormat; + +public class SpeedCashParams extends NetworkParameters { + + private static SpeedCashParams instance; + + public static synchronized SpeedCashParams get() { + if (instance == null) { + instance = new SpeedCashParams(); + } + return instance; + } + + // We only use the properties needed for address validation + public SpeedCashParams() { + super(); + addressHeader = 63; + p2shHeader = 85; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + + // default dummy implementations, not used... + @Override + public String getPaymentProtocolId() { + return PAYMENT_PROTOCOL_ID_MAINNET; + } + + @Override + public void checkDifficultyTransitions(StoredBlock storedPrev, Block next, BlockStore blockStore) throws VerificationException, BlockStoreException { + } + + @Override + public Coin getMaxMoney() { + return null; + } + + @Override + public Coin getMinNonDustOutput() { + return null; + } + + @Override + public MonetaryFormat getMonetaryFormat() { + return null; + } + + @Override + public String getUriScheme() { + return null; + } + + @Override + public boolean hasMaxMoney() { + return false; + } + + @Override + public BitcoinSerializer getSerializer(boolean parseRetain) { + return null; + } + + @Override + public int getProtocolVersionNum(ProtocolVersion version) { + return 0; + } +} diff --git a/gui/src/main/resources/keys/29CDFD3B.asc b/gui/src/main/resources/keys/29CDFD3B.asc new file mode 100644 index 0000000000..18f37a913f --- /dev/null +++ b/gui/src/main/resources/keys/29CDFD3B.asc @@ -0,0 +1,51 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFl5pBEBEACmse+BgUYi+WLTHR4xDwFE5LyEIT3a5t+lGolO3cVkfw5RI+7g +FEpxXzWontiLxDdDi34nr1zXOIEjSgQ7HzdtnFiTRN4tIENCBul4YiCOiyBi5ofN +ejAHqmeiO0KsDBQZBdyiK1iWi6yNbpG/rARwHu/Rx5ouT1YX1hV92Qh1bnU+4j4O +FcePQRNl+4q/SrtKdm047Ikr/LBvy/WYBYe9BcQGhbHI4DrUOSnIuI/Zq7xLF8QS +U/an/d0ftbSBZNX3anDiZjzSmR16seRQtvRO6mehWFNlgLMOGgFeJzPkByTd1TlV +K/KaHKQ71FNkRiP87pwkHZI5zJPAQfve+KmYPwOyETUaX43XOuixqutUV6Lrd0ng +bKe6q4nZDOWi5a4I3+hkrfzaGOKm9TlZoEmpJHh6pa5ULoDnEpKCg5Dgn3NGwokw +57sDAC2mtf41/uSkR20ALN1q4iOLXiHn+T6Z+Uq7aL3OcKGcBu4xC6Jfofmmdfdd +QxEEaeHvAI9ETlKy3tsMhEs5XD6m90rCKLnb97Y8eT/xJL4/oDsxI0o7qICz1nFS +2IhV8xULZ2533vNQPMEbSLoTzgz1OEPYwI1b+YJDFlp1y0XRiEtDZiAFfgsJY7UE +DizfuUFsK5LOkw2+NVmLphDVrDW1MXbhX1xspZDmBG9giE08sPtHj/EZHwARAQAB +tDNDaHJpc3RvcGggQXR0ZW5lZGVyIDxjaHJpc3RvcGguYXR0ZW5lZGVyQGdtYWls +LmNvbT6JAj0EEwEKACcFAll5pBECGwMFCQeGH4AFCwkIBwMFFQoJCAsFFgIDAQAC +HgECF4AACgkQzV3BxSnN/Ts46g/+KJL3M6Bfr9K9muNjEeA6yBS5HmZ2tBJI3PiF +pJC5MBO5H+3ukI8nyzYil3JhEqCcTUspBGbbkqbwbSQuS19VYBHHxhSAn7B/MHFC +FnlbKEzS3cHyp95lGPLJ/y5FXXnSxdlC1EXFcuSjHWR27cCUGuH+1diuyh2eZoT5 +fN27g5B5ej0ExXoCp8J4MtMhcHXjGy7Kiv0CbcY8vYEYbqd5GsMvk7UZIa+vWTMz +JE1fp6msFfUFzHXYRhO/TKi8iRtVaUUcaOHz7kb226ckVnzIO3CjsGg7y19BYaWf +C6Rw0XqPfCf7PoJjhRxbC/9ZWujy/pkaOtOBoq+IZECkiHsKUcZgNdU7xMyCE0a5 +jOvJrzKna6MELPczTyeWqZvL0dKNhllw5WJIhzf5mcFqOb1OlNjWxC1BnOeNk51f ++FDtjxOyp6P7uL0dPy7j4TA7aHgQNKy2Uvx3+Eu9EHKL2T35xXPvma1ZVybQlMBK +z7rbjTIiKTf5LqTtFyE4Kx6IS29rygyJPxz81r4pbjoGUIxLnhxL+6LwxCPwmbkI +fFRD+gk8ODmhgY947D6VBPPrrH4U9YiUJZ718b3tCJoubLPrGUfbFlKaGBloK+Ld +0ulJGZrQWxiK3y1KO1AF8k1ge9utJowLAq8rZOUdSPb/cjo3OsspqJR9OQQXNO0n +6WL3Y/a5Ag0EWXmkEQEQAMt06beoYe/vmAWR91y5BUIu1zNmQP2NNAZ1Jh1K3q7a +AVEamyVmdF4i2JVF7fTnRGWDiKgjF2f9KJA2mC9v6EK6l7KK/7oQfFgympku8hSL +jtp/TWIZZ1D9z16GdqmWaRGdMkqmjf7Wpy26A5TCsUbGvn1tm9P8PxqNfgCv3Cap +FhPciK4o/e4gXY7tUbYMC65Dmq3OoJWWzAGqeDmbH4U5BcoZBk+SFyknF/5NWGuz +E0yl6TRkgEhzneyBcaV1bmSVcWBpNozoyZC49JggrwFJExd5QQE06iWbx+OkWHYt +ObJSKQd3liC1EcAFzI0BoZQ5ZE8VoTXpVQXQcsYtbWKj5BReiEIovi3/+CmjxUFS +M7fjeelRwVWeh0/FnD7KxF5LshUDlrc/JIRxI9RYZcbhoXB1UMc/5SX5AT0+a86p +Gay7yE0JQGtap1Hi5yf1yDMJr1i89u1LfKXbHb2jMOzyiDYR2kaPO0IDpDJ6kjPc +fFAcNt/FpJw5U3mBKy8tHlIMoFd/5hTFBf9Pnrj3bmXx2dSd1Y3l6sQjhceSIALQ +I95QfXY57a04mHURO/CCxwzLlKeI1Qp7zT9TiV7oBx85uY2VtrxPdPmPHF0y9Fnh +K1Pq2VAN53WHGK9MEuyIV/VxebN7w2tDhVi9SI2UmdGuDdrLlCBhT0UeCYt2jFxF +ABEBAAGJAiUEGAEKAA8FAll5pBECGwwFCQeGH4AACgkQzV3BxSnN/TsbkQ//dsg1 +fvzYZDv989U/dcvZHWdQHhjRz1+Y2oSmRzsab+lbCMd9nbtHa4CNjc5UxFrZst83 +7fBvUPrldNFCA94UOEEORRUJntLdcHhNnPK+pBkLzLcQbtww9nD94B6hqdLND5iW +hnKuI7BXFg8uzH3fRrEhxNByfXv1Uyq9aolsbvRjfFsL7n/+02aKuBzIO5VbFedN +0aZ52mA1aooDKD69kppBWXs+sxPkHkpCexJUkr3ekjsH8jk10Over8DNj8QN4ii2 +I3/xsRCCvrvcKNfm4LR49KJ+5YUUkOo1xWSwOzWHV9lpn2abMEqqIqnubvENclNi +qIbE6vkAaILyubilgxTVbc6SntUarUO/59j2a0c+pDnHgLB799bnh0mAmXXCVO3Z +14GpaH15iaUCgRgxx9uP+lQIj6LtrPOsc5b5J6VLgdxQlDXejKe9PaM6+agtIBmb +I24t36ljmRrha2QH90MhyDPrJ/U6ch/ilgTTNRWbfTsALRxzNmnHvj0Y55IsdYg3 +bm71QT99x9kNuozo7I4MrGElS+9Pwy31lcY17OSy/K1wqpLCW1exc4SwJRsAImNW +QLNcwMx1fIBhPiyuhRVsjoCEda5rO+NYF8U8u/UrXixNXsHGBgaynWO/rI9KFg0f +NYeOG8Xnm4CxuWqUu0FDMv6BhkMCTz2X4xcnbtI= +=9LRS +-----END PGP PUBLIC KEY BLOCK----- diff --git a/gui/src/test/java/io/bisq/gui/util/validation/AltCoinAddressValidatorTest.java b/gui/src/test/java/io/bisq/gui/util/validation/AltCoinAddressValidatorTest.java index 35c5bff1cf..425b3e1a26 100644 --- a/gui/src/test/java/io/bisq/gui/util/validation/AltCoinAddressValidatorTest.java +++ b/gui/src/test/java/io/bisq/gui/util/validation/AltCoinAddressValidatorTest.java @@ -643,4 +643,99 @@ public class AltCoinAddressValidatorTest { assertFalse(validator.validate("SSnwqFBiyqK1n4BV7kPX86iesev2NobhEo").isValid); assertFalse(validator.validate("").isValid); } + + @Test + public void testCDT() { + AltCoinAddressValidator validator = new AltCoinAddressValidator(); + validator.setCurrencyCode("CDT"); + + assertTrue(validator.validate("DM7BjopQ3bGYxSPZ4yhfttxqnDrEkyc3sw").isValid); + assertTrue(validator.validate("DB4CaJ81SiT3VtpGC8K1RMirPJZjsmKiZd").isValid); + assertTrue(validator.validate("DE7uB1mws1RwYNDPpfEnQ7a4i9tdqqV1Lf").isValid); + assertTrue(validator.validate("DJ8FnzVCa8AXEBt5aqPcJubKRzanQKvxkY").isValid); + assertTrue(validator.validate("D5QmzfBjwrUyAKtvectJL7kBawfWtwdJqz").isValid); + assertTrue(validator.validate("DDRJemKbVtTVV8r2jSG9wevv3JeUj2edAr").isValid); + + assertFalse(validator.validate("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhemqq").isValid); + assertFalse(validator.validate("0x2a65Aca4D5fC5B5C859090a6c34d1641353982266").isValid); + assertFalse(validator.validate("SSnwqFBiyqK1n4BV7kPX86iesev2NobhEo").isValid); + assertFalse(validator.validate("").isValid); + } + + @Test + public void testDGM() { + AltCoinAddressValidator validator = new AltCoinAddressValidator(); + validator.setCurrencyCode("DGM"); + + assertTrue(validator.validate("DvaAgcLKrno2AC7kYhHVDCrkhx2xHFpXUf").isValid); + assertTrue(validator.validate("E9p49poRmnuLdnu55bzKe7t48xtYv2bRES").isValid); + + assertFalse(validator.validate("0xmnuL9poRmnuLd55bzKe7t48xtYv2bRES").isValid); + assertFalse(validator.validate("DvaAgcLKrno2AC7kYhHVDC").isValid); + assertFalse(validator.validate("19p49poRmnuLdnu55bzKe7t48xtYv2bRES").isValid); + assertFalse(validator.validate("").isValid); + } + + @Test + public void testSCS() { + AltCoinAddressValidator validator = new AltCoinAddressValidator(); + validator.setCurrencyCode("SCS"); + + assertTrue(validator.validate("SNrVzPaFVCQGH4Rdch2EuhoyeWMfgWqk1J").isValid); + assertTrue(validator.validate("SXPvGe87gdCFQH8zPU3JdKNGwAa4c6979r").isValid); + assertTrue(validator.validate("STGvWjZdkwDeNoYa73cqMrAFFYm5xtJndc").isValid); + assertTrue(validator.validate("SVPZMBgDxBVDRisdDZGD1XQwyAz8RBbo3J").isValid); + + assertFalse(validator.validate("SVPZMBgDxBVDRisdDZGD1XQwyAz8RBbo3R").isValid); + assertFalse(validator.validate("mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn").isValid); + assertFalse(validator.validate("XLfvvLuwjUrz2kf5gghEmUPFE3vFvwfEiL").isValid); + assertFalse(validator.validate("").isValid); + } + + @Test + public void testSOS() { + AltCoinAddressValidator validator = new AltCoinAddressValidator(); + validator.setCurrencyCode("SOS"); + + assertTrue(validator.validate("0x2a65Aca4D5fC5B5C859090a6c34d164135398226").isValid); + assertTrue(validator.validate("2a65Aca4D5fC5B5C859090a6c34d164135398226").isValid); + + assertFalse(validator.validate("0x2a65Aca4D5fC5B5C859090a6c34d1641353982266").isValid); + assertFalse(validator.validate("0x2a65Aca4D5fC5B5C859090a6c34d16413539822g").isValid); + assertFalse(validator.validate("2a65Aca4D5fC5B5C859090a6c34d16413539822g").isValid); + assertFalse(validator.validate("").isValid); + } + + @Test + public void testACH() { + AltCoinAddressValidator validator = new AltCoinAddressValidator(); + validator.setCurrencyCode("ACH"); + + assertTrue(validator.validate("AciV7ZyJDpCg7kGGmbo97VjgjpVZkXRTMD").isValid); + assertTrue(validator.validate("ARhW8anWaZtExdK2cQkBwsvsQZ9TkC9bwH").isValid); + assertTrue(validator.validate("AcxpGTWX4zFiD8p8hfYw99RXV7MY2y8hs9").isValid); + + assertFalse(validator.validate("GWaSW6PHfQKBv8EXV3xiqGG2zxKZh4XYNu").isValid); + assertFalse(validator.validate("AcxpGTWX4zFiD8p8hfY099RXV7MY2y8hs9").isValid); + assertFalse(validator.validate("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem").isValid); + assertFalse(validator.validate("").isValid); + } + + @Test + public void testVDN() { + AltCoinAddressValidator validator = new AltCoinAddressValidator(); + validator.setCurrencyCode("VDN"); + + assertTrue(validator.validate("DG1KpSsSXd3uitgwHaA1i6T1Bj1hWEwAxB").isValid); + assertTrue(validator.validate("DPEfTj1C9tTKEqkLPUwtUtCZHd7ViedBmZ").isValid); + assertTrue(validator.validate("DLzjxv6Rk9hMYEFHBLqvyT8pkfS43u9Md5").isValid); + assertTrue(validator.validate("DHexLqYt4ooDDnpmfEMSa1oJBbaZBxURZH").isValid); + assertTrue(validator.validate("DHPybrRc2iqeE4aU8mmXKf8v38JTDyH2V9").isValid); + + assertFalse(validator.validate("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhemqq").isValid); + assertFalse(validator.validate("3CDJNfdWX8m2NwuGUV3nhXHXEeLygMXoAj").isValid); + assertFalse(validator.validate("DG1KpSsSXd3uitgwHaA1i6T1BjSHORTER").isValid); + assertFalse(validator.validate("DG1KpSsSXd3uitgwHaA1i6T1Bj1hWLONGER").isValid); + assertFalse(validator.validate("HG1KpSsSXd3uitgwHaA1i6T1Bj1hWEwAxB").isValid); + } } diff --git a/monitor/pom.xml b/monitor/pom.xml index 5738c6a275..ac68de577f 100644 --- a/monitor/pom.xml +++ b/monitor/pom.xml @@ -22,7 +22,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0 diff --git a/network/pom.xml b/network/pom.xml index bbba81741c..e4076b8308 100644 --- a/network/pom.xml +++ b/network/pom.xml @@ -5,7 +5,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0 diff --git a/network/src/main/resources/PersistableNetworkPayloadMap_BTC_MAINNET b/network/src/main/resources/PersistableNetworkPayloadMap_BTC_MAINNET index b6cde27594..eefeb93c6c 100644 Binary files a/network/src/main/resources/PersistableNetworkPayloadMap_BTC_MAINNET and b/network/src/main/resources/PersistableNetworkPayloadMap_BTC_MAINNET differ diff --git a/package/linux/32bitBuild.sh b/package/linux/32bitBuild.sh index c353fc9387..59851f5cd6 100644 --- a/package/linux/32bitBuild.sh +++ b/package/linux/32bitBuild.sh @@ -6,7 +6,7 @@ mkdir -p gui/deploy set -e # Edit version -version=0.6.5 +version=0.6.6 dir="/media/sf_vm_shared_ubuntu14_32bit" diff --git a/package/linux/64bitBuild.sh b/package/linux/64bitBuild.sh index 6d7b5bf7c2..d450b75510 100644 --- a/package/linux/64bitBuild.sh +++ b/package/linux/64bitBuild.sh @@ -6,7 +6,7 @@ mkdir -p gui/deploy set -e # Edit version -version=0.6.5 +version=0.6.6 dir="/media/sf_vm_shared_ubuntu" diff --git a/package/linux/Dockerfile b/package/linux/Dockerfile index 1acad84e2b..2a6dffc171 100644 --- a/package/linux/Dockerfile +++ b/package/linux/Dockerfile @@ -8,7 +8,7 @@ # pull base image FROM openjdk:8-jdk -ENV version 0.6.5 +ENV version 0.6.6 RUN apt-get update && apt-get install -y --no-install-recommends openjfx && rm -rf /var/lib/apt/lists/* && apt-get install -y vim fakeroot diff --git a/package/osx/create_app.sh b/package/osx/create_app.sh index 9303bb8952..5192c240f9 100755 --- a/package/osx/create_app.sh +++ b/package/osx/create_app.sh @@ -5,7 +5,7 @@ mkdir -p gui/deploy set -e -version="0.6.5" +version="0.6.6" mvn clean package verify -DskipTests -Dmaven.javadoc.skip=true diff --git a/package/osx/finalize.sh b/package/osx/finalize.sh index f8417bb08c..5e6e4fbf38 100644 --- a/package/osx/finalize.sh +++ b/package/osx/finalize.sh @@ -1,6 +1,6 @@ #!/bin/bash -version="0.6.5" +version="0.6.6" target_dir="/Users/dev/Documents/__bisq/_releases/$version" src_dir="/Users/dev/idea/exchange" @@ -16,6 +16,8 @@ mkdir -p $target_dir cp "$target_dir/../F379A1C6.asc" "$target_dir/" # sig key cbeams cp "$target_dir/../5BC5ED73.asc" "$target_dir/" +# sig key Christoph Atteneder +cp "$target_dir/../29CDFD3B.asc" "$target_dir/" # signing key cp "$target_dir/../signingkey.asc" "$target_dir/" diff --git a/package/windows/32bitBuild.bat b/package/windows/32bitBuild.bat index 6c08f4932d..5c1d165c3b 100644 --- a/package/windows/32bitBuild.bat +++ b/package/windows/32bitBuild.bat @@ -5,7 +5,7 @@ :: 32 bit build :: Needs Inno Setup 5 or later (http://www.jrsoftware.org/isdl.php) -SET version=0.6.5 +SET version=0.6.6 :: Private setup SET outdir=\\VBOXSVR\vm_shared_windows_32bit diff --git a/package/windows/64bitBuild.bat b/package/windows/64bitBuild.bat index 94e6e6e935..50cbe54e2a 100644 --- a/package/windows/64bitBuild.bat +++ b/package/windows/64bitBuild.bat @@ -5,7 +5,7 @@ :: 64 bit build :: Needs Inno Setup 5 or later (http://www.jrsoftware.org/isdl.php) -SET version=0.6.5 +SET version=0.6.6 :: Private setup SET outdir=\\VBOXSVR\vm_shared_windows diff --git a/package/windows/Bisq.iss b/package/windows/Bisq.iss index 6d565dc94a..d0055b4986 100755 --- a/package/windows/Bisq.iss +++ b/package/windows/Bisq.iss @@ -3,7 +3,7 @@ [Setup] AppId={{bisq}} AppName=Bisq -AppVersion=0.6.5 +AppVersion=0.6.6 AppVerName=Bisq AppPublisher=Bisq AppComments=Bisq diff --git a/pom.xml b/pom.xml index 018e160a78..f5f8b1fa35 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.bisq parent pom - 0.6.5 + 0.6.6 Bisq - The decentralized exchange network https://bisq.io diff --git a/seednode/pom.xml b/seednode/pom.xml index ccf0f035a0..a00fca7a08 100644 --- a/seednode/pom.xml +++ b/seednode/pom.xml @@ -22,7 +22,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0 diff --git a/statistics/pom.xml b/statistics/pom.xml index 908332990c..827e513290 100644 --- a/statistics/pom.xml +++ b/statistics/pom.xml @@ -22,7 +22,7 @@ parent io.bisq - 0.6.5 + 0.6.6 4.0.0