diff --git a/core/src/main/java/bisq/core/dao/governance/votereveal/VoteRevealService.java b/core/src/main/java/bisq/core/dao/governance/votereveal/VoteRevealService.java index 5a2aea27c51..ca60e72b9d6 100644 --- a/core/src/main/java/bisq/core/dao/governance/votereveal/VoteRevealService.java +++ b/core/src/main/java/bisq/core/dao/governance/votereveal/VoteRevealService.java @@ -54,6 +54,7 @@ import java.io.IOException; +import java.util.ArrayList; import java.util.List; import lombok.Getter; @@ -73,6 +74,11 @@ */ @Slf4j public class VoteRevealService implements DaoStateListener, DaoSetupService { + + public interface VoteRevealTxPublishedListener { + void onVoteRevealTxPublished(String txId); + } + private final DaoStateService daoStateService; private final BlindVoteListService blindVoteListService; private final PeriodService periodService; @@ -86,7 +92,7 @@ public class VoteRevealService implements DaoStateListener, DaoSetupService { @Getter private final ObservableList voteRevealExceptions = FXCollections.observableArrayList(); private final BsqNode bsqNode; - + private final List voteRevealTxPublishedListeners = new ArrayList<>(); /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -144,6 +150,10 @@ public byte[] getHashOfBlindVoteList() { return VoteRevealConsensus.getHashOfBlindVoteList(blindVotes); } + public void addVoteRevealTxPublishedListener(VoteRevealTxPublishedListener voteRevealTxPublishedListener) { + voteRevealTxPublishedListeners.add(voteRevealTxPublishedListener); + } + /////////////////////////////////////////////////////////////////////////////////////////// // DaoStateListener @@ -267,6 +277,7 @@ private void publishTx(Transaction voteRevealTx) { @Override public void onSuccess(Transaction transaction) { log.info("voteRevealTx successfully broadcasted."); + voteRevealTxPublishedListeners.forEach(l -> l.onVoteRevealTxPublished(transaction.getHashAsString())); } @Override diff --git a/core/src/main/java/bisq/core/util/BsqFormatter.java b/core/src/main/java/bisq/core/util/BsqFormatter.java index 7c9923150d9..cab9752d321 100644 --- a/core/src/main/java/bisq/core/util/BsqFormatter.java +++ b/core/src/main/java/bisq/core/util/BsqFormatter.java @@ -20,6 +20,7 @@ import bisq.core.app.BisqEnvironment; import bisq.core.dao.exceptions.ValidationException; import bisq.core.dao.governance.param.Param; +import bisq.core.locale.GlobalSettings; import bisq.core.locale.Res; import bisq.core.provider.price.MarketPrice; import bisq.core.util.validation.BtcAddressValidator; @@ -36,6 +37,9 @@ import javax.inject.Inject; import java.text.DecimalFormat; +import java.text.NumberFormat; + +import java.util.Locale; import lombok.extern.slf4j.Slf4j; @@ -44,14 +48,17 @@ public class BsqFormatter extends BSFormatter { @SuppressWarnings("PointlessBooleanExpression") private static final boolean useBsqAddressFormat = true || !DevEnv.isDevMode(); private final String prefix = "B"; - private final DecimalFormat amountFormat = new DecimalFormat("###,###,###.##"); - private final DecimalFormat marketCapFormat = new DecimalFormat("###,###,###"); + private DecimalFormat amountFormat; + private DecimalFormat marketCapFormat; private final MonetaryFormat btcCoinFormat; @Inject public BsqFormatter() { super(); + GlobalSettings.localeProperty().addListener((observable, oldValue, newValue) -> setFormatter(newValue)); + setFormatter(GlobalSettings.getLocale()); + btcCoinFormat = super.coinFormat; final String baseCurrencyCode = BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode(); @@ -73,6 +80,16 @@ public BsqFormatter() { amountFormat.setMinimumFractionDigits(2); } + private void setFormatter(Locale locale) { + amountFormat = (DecimalFormat) NumberFormat.getNumberInstance(locale); + amountFormat.setMinimumFractionDigits(2); + amountFormat.setMaximumFractionDigits(2); + + marketCapFormat = (DecimalFormat) NumberFormat.getNumberInstance(locale); + marketCapFormat = new DecimalFormat(); + marketCapFormat.setMaximumFractionDigits(0); + } + /** * Returns the base-58 encoded String representation of this * object, including version and checksum bytes. diff --git a/core/src/main/java/bisq/core/util/validation/UrlInputValidator.java b/core/src/main/java/bisq/core/util/validation/UrlInputValidator.java new file mode 100644 index 00000000000..6b088eebf97 --- /dev/null +++ b/core/src/main/java/bisq/core/util/validation/UrlInputValidator.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 bisq.core.util.validation; + +import bisq.core.locale.Res; + +import java.net.URL; + +import static com.google.common.base.Preconditions.checkArgument; + +public class UrlInputValidator extends InputValidator { + + public UrlInputValidator() { + } + + public ValidationResult validate(String input) { + ValidationResult validationResult = super.validate(input); + if (!validationResult.isValid) + return validationResult; + + try { + new URL(input); // does not cover all invalid urls, so we use a regex as well + String regex = "^(https?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"; + checkArgument(input.matches(regex), "URL does not match regex"); + return validationResult; + } catch (Throwable t) { + return new ValidationResult(false, Res.get("validation.invalidUrl")); + } + } +} diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 4c3c27d9dcc..f49bee79c8f 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1204,6 +1204,10 @@ dao.cycle.voteReveal=Vote reveal phase dao.cycle.voteResult=Vote result dao.cycle.phaseDuration={0} blocks (≈{1}); Block {2} - {3} (≈{4} - ≈{5}) +dao.voteReveal.txPublished.headLine=Vote reveal transaction published +dao.voteReveal.txPublished=Your vote reveal transaction with transaction ID {0} was successfully published.\n\n\ + This happens automatically by the software if you have participated in the DAO voting. + dao.results.cycles.header=Cycles dao.results.cycles.table.header.cycle=Cycle dao.results.cycles.table.header.numProposals=Proposals @@ -1433,7 +1437,7 @@ dao.bond.bondedRoleType.MEDIATOR=Mediator # suppress inspection "UnusedProperty" dao.bond.bondedRoleType.ARBITRATOR=Arbitrator -dao.burnBsq.assetFee=Asset listing fee +dao.burnBsq.assetFee=Asset listing dao.burnBsq.menuItem.assetFee=Asset listing fee dao.burnBsq.menuItem.proofOfBurn=Proof of burn dao.burnBsq.header=Fee for asset listing @@ -1603,7 +1607,9 @@ dao.proposal.display.assetComboBox.label=Asset to remove dao.blindVote=blind vote dao.blindVote.startPublishing=Publishing blind vote transaction... -dao.blindVote.success=Your blind vote has been successfully published. +dao.blindVote.success=Your blind vote transaction has been successfully published.\n\nPlease note, that you have to be \ + online in the vote reveal phase so that your Bisq application can publish the vote reveal transaction. \ + Without the vote reveal transaction your vote would be invalid! dao.wallet.menuItem.send=Send dao.wallet.menuItem.receive=Receive @@ -1695,7 +1701,12 @@ dao.tx.issuanceFromCompReq.tooltip=Compensation request which led to an issuance dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\n\ Issuance date: {0} -dao.proposal.create.missingFunds=You don''t have sufficient funds for creating the proposal.\n\ +dao.proposal.create.missingBsqFunds=You don''t have sufficient BSQ funds for creating the proposal. If you have an \ + unconfirmed BSQ transaction you need to wait for a blockchain confirmation because BSQ is validated only if it is \ + included in a block.\n\ + Missing: {0} +dao.proposal.create.missingMinerFeeFunds=You don''t have sufficient BTC funds for creating the proposal transaction. \ + Any BSQ transaction require also a miner fee in BTC.\n\ Missing: {0} dao.feeTx.confirm=Confirm {0} transaction dao.feeTx.confirm.details={0} fee: {1}\n\ @@ -2561,3 +2572,4 @@ validation.length=Length must be between {0} and {1} validation.pattern=Input must be of format: {0} validation.noHexString=The input is not in HEX format. validation.advancedCash.invalidFormat=Must be a valid email or wallet id of format: X000000000000 +validation.invalidUrl=This is not a valid URL diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index c757dd4f91b..018b6071145 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Entlohnungsanfrage/ausgabe dao.tx.issuanceFromCompReq.tooltip=Entlohnungsanfrage, die zur Ausgabe neuere BSQ führte.\nAusgabedatum: {0} dao.tx.issuanceFromReimbursement=Rückerstattungsantrag/Ausgabe dao.tx.issuanceFromReimbursement.tooltip=Rückerstattungsanfrage, die zur Ausgabe neuer BSQ führte.\nAusgabedatum: {0} -dao.proposal.create.missingFunds=Sie haben nicht genügend Gelder um den Vorschlag zu erstellen.\nFehlend: {0} +dao.proposal.create.missingBsqFunds=Sie haben nicht genügend Gelder um den Vorschlag zu erstellen.\nFehlend: {0} dao.feeTx.confirm=Bestätige {0} Transaktion dao.feeTx.confirm.details={0} Gebühr: {1}\nMining-Gebühr: {2} ({3} Satoshis/Byte)\nTransaktionsgröße: {4} Kb\n\nSind Sie sicher, dass Sie die {5} Transaktion senden wollen? diff --git a/core/src/main/resources/i18n/displayStrings_el.properties b/core/src/main/resources/i18n/displayStrings_el.properties index 0201fe7aadb..791fb41f639 100644 --- a/core/src/main/resources/i18n/displayStrings_el.properties +++ b/core/src/main/resources/i18n/displayStrings_el.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Αίτημα/έκδοση αποζημίωσης dao.tx.issuanceFromCompReq.tooltip=Αίτημα αποζημίωσης το οποίο οδήγησε σε έκδοση νέων BSQ.\nΗμερομηνία έκδοσης: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=Δεν έχεις επαρκή κεφάλαια για τη δημιουργία της πρότασης.\nΥπολείπονται: {0} +dao.proposal.create.missingBsqFunds=Δεν έχεις επαρκή κεφάλαια για τη δημιουργία της πρότασης.\nΥπολείπονται: {0} dao.feeTx.confirm=Επιβεβαίωση συναλλαγής {0} dao.feeTx.confirm.details={0} fee: {1}\nMining fee: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nAre you sure you want to publish the {5} transaction? diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index b7832a63250..9585f8567d2 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Solicitud/emisión de compensación dao.tx.issuanceFromCompReq.tooltip=Solicitud de compensación que lleva a emitir nuevos BSQ.\nFecha de emisión: {0} dao.tx.issuanceFromReimbursement=Solicitud de reembolso/emisión dao.tx.issuanceFromReimbursement.tooltip=Solicitud de reembolso que lleva a una emisión de nuevos BSQ.\nFecha de emisión: {0} -dao.proposal.create.missingFunds=No tiene suficientes fondos para crear la propuesta.\nFaltan: {0} +dao.proposal.create.missingBsqFunds=No tiene suficientes fondos para crear la propuesta.\nFaltan: {0} dao.feeTx.confirm=Confirmar transacción {0} dao.feeTx.confirm.details={0} tasa: {1}\nTasa de minado: {2} ({3} Satoshis/byte)\nTamaño de la transacción: {4} Kb\n\nEstá seguro de que quire publicar la transacción {5}? diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index 2eb7b028bd2..672af9be47c 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=درخواست/صدور خسارت dao.tx.issuanceFromCompReq.tooltip=درخواست خسارت که منجر به صدور BSQ جدید می‌شود.\nتاریخ صدور: {0} dao.tx.issuanceFromReimbursement=درخواست/صدور بازپرداخت dao.tx.issuanceFromReimbursement.tooltip=درخواست بازپرداختی که منجر به صدور BSQ جدید می‌شود.\nتاریخ صدور: {0} -dao.proposal.create.missingFunds=شما وجوه کافی برای ایجاد پیشنهاد را ندارید.\nمقدار مورد نیاز: {0} +dao.proposal.create.missingBsqFunds=شما وجوه کافی برای ایجاد پیشنهاد را ندارید.\nمقدار مورد نیاز: {0} dao.feeTx.confirm=تایید {0} تراکنش dao.feeTx.confirm.details=کارمزد {0}: {1}\nکارمزد استخراج: {2} ({3} ساتوشی بر بایت)\nاندازه تراکنش: {4} Kb\n\nآیا از انتشار تراکنش {5} اطمینان دارید؟ diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index 5baa7938f9d..6ec7a5220e1 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Compensation request/issuance dao.tx.issuanceFromCompReq.tooltip=Compensation request which led to an issuance of new BSQ.\nIssuance date: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=You don''t have sufficient funds for creating the proposal.\nMissing: {0} +dao.proposal.create.missingBsqFunds=You don''t have sufficient funds for creating the proposal.\nMissing: {0} dao.feeTx.confirm=Confirm {0} transaction dao.feeTx.confirm.details={0} fee: {1}\nMining fee: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nAre you sure you want to publish the {5} transaction? diff --git a/core/src/main/resources/i18n/displayStrings_hu.properties b/core/src/main/resources/i18n/displayStrings_hu.properties index 3b232ffb5a2..037e9db8afd 100644 --- a/core/src/main/resources/i18n/displayStrings_hu.properties +++ b/core/src/main/resources/i18n/displayStrings_hu.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Compensation request/issuance dao.tx.issuanceFromCompReq.tooltip=Compensation request which led to an issuance of new BSQ.\nIssuance date: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=Nem rendelkezik elegendő összegekkel a kártérítési kérelem létrehozásához.\nHiányzó: {0} +dao.proposal.create.missingBsqFunds=Nem rendelkezik elegendő összegekkel a kártérítési kérelem létrehozásához.\nHiányzó: {0} dao.feeTx.confirm=Confirm {0} transaction dao.feeTx.confirm.details={0} fee: {1}\nMining fee: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nAre you sure you want to publish the {5} transaction? diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index 63b928d4f86..2f2fc18169d 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Compensation request/issuance dao.tx.issuanceFromCompReq.tooltip=Compensation request which led to an issuance of new BSQ.\nIssuance date: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=Você não tem saldo suficiente para criar a proposta.\nFaltam: {0} +dao.proposal.create.missingBsqFunds=Você não tem saldo suficiente para criar a proposta.\nFaltam: {0} dao.feeTx.confirm=Confirmar transação {0} dao.feeTx.confirm.details=Taxa de {0}: {1}\nTaxa de mineração: {2} ({3} satoshis/byte)\nTamanho da transação: {4} Kb\n\nTem certeza de que deseja publicar a transação {5}? diff --git a/core/src/main/resources/i18n/displayStrings_ro.properties b/core/src/main/resources/i18n/displayStrings_ro.properties index 6efcf95dfa1..d3183e4b3f7 100644 --- a/core/src/main/resources/i18n/displayStrings_ro.properties +++ b/core/src/main/resources/i18n/displayStrings_ro.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Compensation request/issuance dao.tx.issuanceFromCompReq.tooltip=Compensation request which led to an issuance of new BSQ.\nIssuance date: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=Nu ai suficiente fonduri pentru crearea solicitării de despăgubire.\nLipsesc: {0} +dao.proposal.create.missingBsqFunds=Nu ai suficiente fonduri pentru crearea solicitării de despăgubire.\nLipsesc: {0} dao.feeTx.confirm=Confirm {0} transaction dao.feeTx.confirm.details={0} fee: {1}\nMining fee: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nAre you sure you want to publish the {5} transaction? diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index 525fe1f430d..2335b6b9c41 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Запрос/выдача компенсации dao.tx.issuanceFromCompReq.tooltip=Запрос компенсации, который привел к выпуску новых BSQ.\nДата выпуска: {0} dao.tx.issuanceFromReimbursement=Запрос/выдача возмещения dao.tx.issuanceFromReimbursement.tooltip=Запрос возмещения, который привел к выпуску новых BSQ.\nДата выпуска: {0} -dao.proposal.create.missingFunds=У Вас недостаточно средств для создания предложения.\nНехватает: {0} +dao.proposal.create.missingBsqFunds=У Вас недостаточно средств для создания предложения.\nНехватает: {0} dao.feeTx.confirm=Подтвердить транзакцию {0} dao.feeTx.confirm.details={0} сбор: {1}\nкомиссия майнера: {2} ({3} сатоши/байт)\nРазмер транзакиции: {4} Кб\n\nДействительно хотите опубликовать транзакцию {5}? diff --git a/core/src/main/resources/i18n/displayStrings_sr.properties b/core/src/main/resources/i18n/displayStrings_sr.properties index 6c56e7263b2..5fc783659dd 100644 --- a/core/src/main/resources/i18n/displayStrings_sr.properties +++ b/core/src/main/resources/i18n/displayStrings_sr.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Compensation request/issuance dao.tx.issuanceFromCompReq.tooltip=Compensation request which led to an issuance of new BSQ.\nIssuance date: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=You don''t have sufficient funds for creating the proposal.\nMissing: {0} +dao.proposal.create.missingBsqFunds=You don''t have sufficient funds for creating the proposal.\nMissing: {0} dao.feeTx.confirm=Confirm {0} transaction dao.feeTx.confirm.details={0} fee: {1}\nMining fee: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nAre you sure you want to publish the {5} transaction? diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index 209f0b9e46f..f9624671b24 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=คำขอหรือการออกค่า dao.tx.issuanceFromCompReq.tooltip=คำขอค่าสินไหมทดแทน ซึ่งนำไปสู่การออก BSQ ใหม่\nวันที่ออก: {0} dao.tx.issuanceFromReimbursement=การออกคำสั่ง/การยื่นคำร้องขอการชำระเงินคืน dao.tx.issuanceFromReimbursement.tooltip=การเรียกร้องขอการชำระเงินคืนซึ่งเป็นคำสั่งภายใต้ BSQ ฉบับใหม่\nวันที่เริ่มทำการ: {0} -dao.proposal.create.missingFunds=คุณไม่มีเงินเพียงพอสำหรับการสร้างข้อเสนอ\nขาดไป: {0} +dao.proposal.create.missingBsqFunds=คุณไม่มีเงินเพียงพอสำหรับการสร้างข้อเสนอ\nขาดไป: {0} dao.feeTx.confirm=ยืนยันการทำรายการ {0} dao.feeTx.confirm.details={0} ค่าธรรมเนียม: {1}\nค่าธรรมเนียมการขุด: {2} ({3} Satoshis / byte)\nขนาดของธุรกรรม: {4} Kb\n\nคุณแน่ใจหรือไม่ว่าต้องการเผยแพร่ {5} ธุรกรรม? diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index 8ae18b0b2bf..f1d054acefb 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=Yêu cầu bồi thường/ban hành dao.tx.issuanceFromCompReq.tooltip=Yêu cầu bồi thường dẫn đến ban hành BSQ mới.\nNgày ban hành: {0} dao.tx.issuanceFromReimbursement=Yêu cầu/ Phát hành bồi hoàn dao.tx.issuanceFromReimbursement.tooltip=Yêu cầu bồi hoàn dẫn đến ban hành BSQ mới.\nNgày ban hành: {0} -dao.proposal.create.missingFunds=Bạn không có đủ tiền để tạo đề xuất.\nThiếu: {0} +dao.proposal.create.missingBsqFunds=Bạn không có đủ tiền để tạo đề xuất.\nThiếu: {0} dao.feeTx.confirm=Xác nhận {0} giao dịch dao.feeTx.confirm.details={0} phí: {1}\nPhí đào: {2} ({3} Satoshis/byte)\nKích thước giao dịch: {4} Kb\n\nBạn có chắc là muốn công bố giao dịch {5}? diff --git a/core/src/main/resources/i18n/displayStrings_zh.properties b/core/src/main/resources/i18n/displayStrings_zh.properties index ccea4cc7c66..865ee58beb7 100644 --- a/core/src/main/resources/i18n/displayStrings_zh.properties +++ b/core/src/main/resources/i18n/displayStrings_zh.properties @@ -1551,7 +1551,7 @@ dao.tx.issuanceFromCompReq=补偿请求/发行 dao.tx.issuanceFromCompReq.tooltip=导致新BSQ发行的补偿请求\n发行日期: {0} dao.tx.issuanceFromReimbursement=Reimbursement request/issuance dao.tx.issuanceFromReimbursement.tooltip=Reimbursement request which led to an issuance of new BSQ.\nIssuance date: {0} -dao.proposal.create.missingFunds=You don''t have sufficient funds for creating the proposal.\nMissing: {0} +dao.proposal.create.missingBsqFunds=You don''t have sufficient funds for creating the proposal.\nMissing: {0} dao.feeTx.confirm=Confirm {0} transaction dao.feeTx.confirm.details={0} fee: {1}\nMining fee: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nAre you sure you want to publish the {5} transaction? diff --git a/desktop/src/main/java/bisq/desktop/main/dao/DaoView.java b/desktop/src/main/java/bisq/desktop/main/dao/DaoView.java index 40b44d471a4..964fd2ef661 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/DaoView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/DaoView.java @@ -30,8 +30,10 @@ import bisq.desktop.main.dao.governance.GovernanceView; import bisq.desktop.main.dao.wallet.BsqWalletView; import bisq.desktop.main.dao.wallet.dashboard.BsqDashboardView; +import bisq.desktop.main.overlays.popups.Popup; import bisq.core.app.BisqEnvironment; +import bisq.core.dao.governance.votereveal.VoteRevealService; import bisq.core.locale.Res; import bisq.common.app.DevEnv; @@ -61,9 +63,15 @@ public class DaoView extends ActivatableViewAndModel { private BsqWalletView bsqWalletView; @Inject - private DaoView(CachingViewLoader viewLoader, Navigation navigation) { + private DaoView(CachingViewLoader viewLoader, VoteRevealService voteRevealService, Navigation navigation) { this.viewLoader = viewLoader; this.navigation = navigation; + + voteRevealService.addVoteRevealTxPublishedListener(txId -> { + new Popup<>().headLine(Res.get("dao.voteReveal.txPublished.headLine")) + .feedback(Res.get("dao.voteReveal.txPublished", txId)) + .show(); + }); } @Override diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java index 235f19322a0..72844399373 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java @@ -44,7 +44,6 @@ class BondListItem { private final String bondDetails; private final BondState bondState; private final String bondStateString; - private final Date lockupDate; BondListItem(Bond bond, BsqFormatter bsqFormatter) { this.bond = bond; @@ -59,8 +58,7 @@ class BondListItem { bondDetails = Utilities.bytesAsHexString(bond.getBondedAsset().getHash()); } lockupTxId = bond.getLockupTxId(); - lockupDate = new Date(bond.getLockupDate()); - lockupDateString = bsqFormatter.formatDateTime(lockupDate); + lockupDateString = bond.getLockupDate() > 0 ? bsqFormatter.formatDateTime(new Date(bond.getLockupDate())) : "-"; bondState = bond.getBondState(); bondStateString = Res.get("dao.bond.bondState." + bond.getBondState().name()); } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java index 4f140387d24..11331355d63 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java @@ -173,7 +173,7 @@ protected void activate() { if (!DevEnv.isDevMode()) { GUIUtil.showBsqFeeInfoPopup(amount, miningFee, txSize, bsqFormatter, btcFormatter, - Res.get("dao.proofOfBurn.amount"), () -> doPublishFeeTx(transaction, preImageAsString)); + Res.get("dao.proofOfBurn.header"), () -> doPublishFeeTx(transaction, preImageAsString)); } else { doPublishFeeTx(transaction, preImageAsString); } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java index b0a2cbc2687..1709a324911 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java @@ -52,6 +52,7 @@ import bisq.core.locale.Res; import bisq.core.util.BsqFormatter; import bisq.core.util.validation.InputValidator; +import bisq.core.util.validation.UrlInputValidator; import bisq.asset.Asset; @@ -202,7 +203,7 @@ public void createAllFields(String title, int gridRowStartIndex, double top, Pro Res.get("dao.proposal.display.link")); linkInputTextField.setPromptText(Res.get("dao.proposal.display.link.prompt")); if (isMakeProposalScreen) - linkInputTextField.setValidator(new InputValidator()); + linkInputTextField.setValidator(new UrlInputValidator()); inputControls.add(linkInputTextField); Tuple3 tuple = FormBuilder.addTopLabelHyperlinkWithIcon(gridPane, gridRow, diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java index 9b946631fd8..d3e6f82f2cf 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java @@ -215,9 +215,14 @@ private void publishMyProposal(ProposalType type) { doPublishMyProposal(proposal, transaction); } } catch (InsufficientMoneyException e) { - BSFormatter formatter = e instanceof InsufficientBsqException ? bsqFormatter : btcFormatter; - new Popup<>().warning(Res.get("dao.proposal.create.missingFunds", - formatter.formatCoinWithCode(e.missing))).show(); + if (e instanceof InsufficientBsqException) { + new Popup<>().warning(Res.get("dao.proposal.create.missingBsqFunds", + bsqFormatter.formatCoinWithCode(e.missing))).show(); + } else { + new Popup<>().warning(Res.get("dao.proposal.create.missingMinerFeeFunds", + btcFormatter.formatCoinWithCode(e.missing))).show(); + } + } catch (ValidationException e) { String message; if (e.getMinRequestAmount() != null) { @@ -242,7 +247,7 @@ private void doPublishMyProposal(Proposal proposal, Transaction transaction) { proposalDisplay.clearForm(); proposalTypeComboBox.getSelectionModel().clearSelection(); if (!DevEnv.isDevMode()) - new Popup<>().confirmation(Res.get("dao.tx.published.success")).show(); + new Popup<>().feedback(Res.get("dao.tx.published.success")).show(); }, errorMessage -> new Popup<>().warning(errorMessage).show()); } @@ -253,18 +258,20 @@ private ProposalWithTransaction getProposalWithTransaction(ProposalType type) checkNotNull(proposalDisplay, "proposalDisplay must not be null"); + String link = proposalDisplay.linkInputTextField.getText(); + String name = proposalDisplay.nameTextField.getText(); switch (type) { case COMPENSATION_REQUEST: checkNotNull(proposalDisplay.requestedBsqTextField, "proposalDisplay.requestedBsqTextField must not be null"); - return daoFacade.getCompensationProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText(), + return daoFacade.getCompensationProposalWithTransaction(name, + link, bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText())); case REIMBURSEMENT_REQUEST: checkNotNull(proposalDisplay.requestedBsqTextField, "proposalDisplay.requestedBsqTextField must not be null"); - return daoFacade.getReimbursementProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText(), + return daoFacade.getReimbursementProposalWithTransaction(name, + link, bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText())); case CHANGE_PARAM: checkNotNull(proposalDisplay.paramComboBox, @@ -284,8 +291,8 @@ private ProposalWithTransaction getProposalWithTransaction(ProposalType type) log.info("Change param: paramValue={}, paramValueAsString={}", paramValue, paramValueAsString); changeParamValidator.validateParamValue(selectedParam, paramValue); - return daoFacade.getParamProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText(), + return daoFacade.getParamProposalWithTransaction(name, + link, selectedParam, paramValue); } catch (Throwable e) { @@ -295,27 +302,22 @@ private ProposalWithTransaction getProposalWithTransaction(ProposalType type) case BONDED_ROLE: checkNotNull(proposalDisplay.bondedRoleTypeComboBox, "proposalDisplay.bondedRoleTypeComboBox must not be null"); - Role role = new Role(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText(), + Role role = new Role(name, + link, proposalDisplay.bondedRoleTypeComboBox.getSelectionModel().getSelectedItem()); return daoFacade.getBondedRoleProposalWithTransaction(role); case CONFISCATE_BOND: checkNotNull(proposalDisplay.confiscateBondComboBox, "proposalDisplay.confiscateBondComboBox must not be null"); Bond bond = proposalDisplay.confiscateBondComboBox.getSelectionModel().getSelectedItem(); - return daoFacade.getConfiscateBondProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText(), - bond.getLockupTxId()); + return daoFacade.getConfiscateBondProposalWithTransaction(name, link, bond.getLockupTxId()); case GENERIC: - return daoFacade.getGenericProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText()); + return daoFacade.getGenericProposalWithTransaction(name, link); case REMOVE_ASSET: checkNotNull(proposalDisplay.assetComboBox, "proposalDisplay.assetComboBox must not be null"); Asset asset = proposalDisplay.assetComboBox.getSelectionModel().getSelectedItem(); - return daoFacade.getRemoveAssetProposalWithTransaction(proposalDisplay.nameTextField.getText(), - proposalDisplay.linkInputTextField.getText(), - asset); + return daoFacade.getRemoveAssetProposalWithTransaction(name, link, asset); default: final String msg = "Undefined ProposalType " + selectedProposalType; log.error(msg); @@ -372,6 +374,10 @@ private void updateButtonState() { .filter(Objects::nonNull).forEach(comboBox -> { inputsValid.set(inputsValid.get() && comboBox.getSelectionModel().getSelectedItem() != null); }); + + InputTextField linkInputTextField = proposalDisplay.linkInputTextField; + inputsValid.set(inputsValid.get() && + linkInputTextField.getValidator().validate(linkInputTextField.getText()).isValid); } makeProposalButton.setDisable(!inputsValid.get()); diff --git a/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java b/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java index a10ec5fc6c7..ac137b1742e 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java @@ -244,6 +244,7 @@ private void addSendBsqGroup() { txSize, receiversAddressInputTextField.getText(), bsqFormatter, + btcFormatter, () -> { receiversAddressInputTextField.setText(""); amountInputTextField.setText(""); @@ -298,6 +299,7 @@ private void addSendBtcGroup() { miningFee, txSize, receiversBtcAddressInputTextField.getText(), btcFormatter, + btcFormatter, () -> { receiversBtcAddressInputTextField.setText(""); btcAmountInputTextField.setText(""); @@ -330,16 +332,17 @@ private void showTxPopup(Coin receiverAmount, Transaction txWithBtcFee, Coin miningFee, int txSize, String address, - BSFormatter formatter, + BSFormatter amountFormatter, // can be BSQ or BTC formatter + BSFormatter feeFormatter, ResultHandler resultHandler) { new Popup<>().headLine(Res.get("dao.wallet.send.sendFunds.headline")) .confirmation(Res.get("dao.wallet.send.sendFunds.details", - formatter.formatCoinWithCode(receiverAmount), + amountFormatter.formatCoinWithCode(receiverAmount), address, - formatter.formatCoinWithCode(miningFee), + feeFormatter.formatCoinWithCode(miningFee), CoinUtil.getFeePerByte(miningFee, txSize), txSize / 1000d, - formatter.formatCoinWithCode(receiverAmount))) + amountFormatter.formatCoinWithCode(receiverAmount))) .actionButtonText(Res.get("shared.yes")) .onAction(() -> { walletsManager.publishAndCommitBsqTx(txWithBtcFee, new TxBroadcaster.Callback() { diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java b/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java index 68e14647863..e8b175c9bfd 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java @@ -343,6 +343,7 @@ public T warning(String message) { public T error(String message) { type = Type.Error; showReportErrorButtons(); + width = 1100; if (headLine == null) this.headLine = Res.get("popup.headline.error"); this.message = message;