diff --git a/core/src/main/java/haveno/core/api/CoreApi.java b/core/src/main/java/haveno/core/api/CoreApi.java index 5b0c9e247a..99fb3bc74f 100644 --- a/core/src/main/java/haveno/core/api/CoreApi.java +++ b/core/src/main/java/haveno/core/api/CoreApi.java @@ -425,6 +425,7 @@ public class CoreApi { String paymentAccountId, boolean isPrivateOffer, boolean buyerAsTakerWithoutDeposit, + String extraInfo, Consumer resultHandler, ErrorMessageHandler errorMessageHandler) { coreOffersService.postOffer(currencyCode, @@ -440,6 +441,7 @@ public class CoreApi { paymentAccountId, isPrivateOffer, buyerAsTakerWithoutDeposit, + extraInfo, resultHandler, errorMessageHandler); } @@ -455,7 +457,8 @@ public class CoreApi { double securityDepositPct, PaymentAccount paymentAccount, boolean isPrivateOffer, - boolean buyerAsTakerWithoutDeposit) { + boolean buyerAsTakerWithoutDeposit, + String extraInfo) { return coreOffersService.editOffer(offerId, currencyCode, direction, @@ -467,7 +470,8 @@ public class CoreApi { securityDepositPct, paymentAccount, isPrivateOffer, - buyerAsTakerWithoutDeposit); + buyerAsTakerWithoutDeposit, + extraInfo); } public void cancelOffer(String id, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { diff --git a/core/src/main/java/haveno/core/api/CoreOffersService.java b/core/src/main/java/haveno/core/api/CoreOffersService.java index 8232827887..a66388c040 100644 --- a/core/src/main/java/haveno/core/api/CoreOffersService.java +++ b/core/src/main/java/haveno/core/api/CoreOffersService.java @@ -178,6 +178,7 @@ public class CoreOffersService { String paymentAccountId, boolean isPrivateOffer, boolean buyerAsTakerWithoutDeposit, + String extraInfo, Consumer resultHandler, ErrorMessageHandler errorMessageHandler) { coreWalletsService.verifyWalletsAreAvailable(); @@ -204,7 +205,8 @@ public class CoreOffersService { securityDepositPct, paymentAccount, isPrivateOffer, - buyerAsTakerWithoutDeposit); + buyerAsTakerWithoutDeposit, + extraInfo); verifyPaymentAccountIsValidForNewOffer(offer, paymentAccount); @@ -230,7 +232,8 @@ public class CoreOffersService { double securityDepositPct, PaymentAccount paymentAccount, boolean isPrivateOffer, - boolean buyerAsTakerWithoutDeposit) { + boolean buyerAsTakerWithoutDeposit, + String extraInfo) { return createOfferService.createAndGetOffer(offerId, direction, currencyCode.toUpperCase(), @@ -242,7 +245,8 @@ public class CoreOffersService { securityDepositPct, paymentAccount, isPrivateOffer, - buyerAsTakerWithoutDeposit); + buyerAsTakerWithoutDeposit, + extraInfo); } void cancelOffer(String id, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { diff --git a/core/src/main/java/haveno/core/api/model/OfferInfo.java b/core/src/main/java/haveno/core/api/model/OfferInfo.java index 537cc9ab26..76de24401a 100644 --- a/core/src/main/java/haveno/core/api/model/OfferInfo.java +++ b/core/src/main/java/haveno/core/api/model/OfferInfo.java @@ -80,6 +80,7 @@ public class OfferInfo implements Payload { private final long splitOutputTxFee; private final boolean isPrivateOffer; private final String challenge; + private final String extraInfo; public OfferInfo(OfferInfoBuilder builder) { this.id = builder.getId(); @@ -115,6 +116,7 @@ public class OfferInfo implements Payload { this.splitOutputTxFee = builder.getSplitOutputTxFee(); this.isPrivateOffer = builder.isPrivateOffer(); this.challenge = builder.getChallenge(); + this.extraInfo = builder.getExtraInfo(); } public static OfferInfo toOfferInfo(Offer offer) { @@ -184,7 +186,8 @@ public class OfferInfo implements Payload { .withProtocolVersion(offer.getOfferPayload().getProtocolVersion()) .withArbitratorSigner(offer.getOfferPayload().getArbitratorSigner() == null ? null : offer.getOfferPayload().getArbitratorSigner().getFullAddress()) .withIsPrivateOffer(offer.isPrivateOffer()) - .withChallenge(offer.getChallenge()); + .withChallenge(offer.getChallenge()) + .withExtraInfo(offer.getCombinedExtraInfo()); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -227,6 +230,7 @@ public class OfferInfo implements Payload { Optional.ofNullable(arbitratorSigner).ifPresent(builder::setArbitratorSigner); Optional.ofNullable(splitOutputTxHash).ifPresent(builder::setSplitOutputTxHash); Optional.ofNullable(challenge).ifPresent(builder::setChallenge); + Optional.ofNullable(extraInfo).ifPresent(builder::setExtraInfo); return builder.build(); } @@ -266,6 +270,7 @@ public class OfferInfo implements Payload { .withSplitOutputTxFee(proto.getSplitOutputTxFee()) .withIsPrivateOffer(proto.getIsPrivateOffer()) .withChallenge(proto.getChallenge()) + .withExtraInfo(proto.getExtraInfo()) .build(); } } diff --git a/core/src/main/java/haveno/core/api/model/builder/OfferInfoBuilder.java b/core/src/main/java/haveno/core/api/model/builder/OfferInfoBuilder.java index 36801cdbb6..23e403fcd2 100644 --- a/core/src/main/java/haveno/core/api/model/builder/OfferInfoBuilder.java +++ b/core/src/main/java/haveno/core/api/model/builder/OfferInfoBuilder.java @@ -65,6 +65,7 @@ public final class OfferInfoBuilder { private long splitOutputTxFee; private boolean isPrivateOffer; private String challenge; + private String extraInfo; public OfferInfoBuilder withId(String id) { this.id = id; @@ -246,6 +247,11 @@ public final class OfferInfoBuilder { return this; } + public OfferInfoBuilder withExtraInfo(String extraInfo) { + this.extraInfo = extraInfo; + return this; + } + public OfferInfo build() { return new OfferInfo(this); } diff --git a/core/src/main/java/haveno/core/offer/CreateOfferService.java b/core/src/main/java/haveno/core/offer/CreateOfferService.java index 35ece3b10e..508a3f44e3 100644 --- a/core/src/main/java/haveno/core/offer/CreateOfferService.java +++ b/core/src/main/java/haveno/core/offer/CreateOfferService.java @@ -103,7 +103,8 @@ public class CreateOfferService { double securityDepositPct, PaymentAccount paymentAccount, boolean isPrivateOffer, - boolean buyerAsTakerWithoutDeposit) { + boolean buyerAsTakerWithoutDeposit, + String extraInfo) { log.info("create and get offer with offerId={}, " + "currencyCode={}, " + "direction={}, " + @@ -114,7 +115,8 @@ public class CreateOfferService { "minAmount={}, " + "securityDepositPct={}, " + "isPrivateOffer={}, " + - "buyerAsTakerWithoutDeposit={}", + "buyerAsTakerWithoutDeposit={}, " + + "extraInfo={}", offerId, currencyCode, direction, @@ -125,7 +127,8 @@ public class CreateOfferService { minAmount, securityDepositPct, isPrivateOffer, - buyerAsTakerWithoutDeposit); + buyerAsTakerWithoutDeposit, + extraInfo); // verify buyer as taker security deposit boolean isBuyerMaker = offerUtil.isBuyOffer(direction); @@ -225,7 +228,8 @@ public class CreateOfferService { Version.TRADE_PROTOCOL_VERSION, null, null, - null); + null, + extraInfo); Offer offer = new Offer(offerPayload); offer.setPriceFeedService(priceFeedService); offer.setChallenge(challenge); diff --git a/core/src/main/java/haveno/core/offer/Offer.java b/core/src/main/java/haveno/core/offer/Offer.java index e84e4fa329..fac72f827d 100644 --- a/core/src/main/java/haveno/core/offer/Offer.java +++ b/core/src/main/java/haveno/core/offer/Offer.java @@ -421,7 +421,23 @@ public class Offer implements NetworkPayload, PersistablePayload { return ""; } - public String getExtraInfo() { + public String getCombinedExtraInfo() { + StringBuilder sb = new StringBuilder(); + if (getOfferExtraInfo() != null && !getOfferExtraInfo().isEmpty()) { + sb.append(getOfferExtraInfo()); + } + if (getPaymentAccountExtraInfo() != null && !getPaymentAccountExtraInfo().isEmpty()) { + if (sb.length() > 0) sb.append("\n\n"); + sb.append(getPaymentAccountExtraInfo()); + } + return sb.toString(); + } + + public String getOfferExtraInfo() { + return offerPayload.getExtraInfo(); + } + + public String getPaymentAccountExtraInfo() { if (getExtraDataMap() != null && getExtraDataMap().containsKey(OfferPayload.F2F_EXTRA_INFO)) return getExtraDataMap().get(OfferPayload.F2F_EXTRA_INFO); else if (getExtraDataMap() != null && getExtraDataMap().containsKey(OfferPayload.PAY_BY_MAIL_EXTRA_INFO)) diff --git a/core/src/main/java/haveno/core/offer/OfferPayload.java b/core/src/main/java/haveno/core/offer/OfferPayload.java index bd10719ec3..8da91b4b15 100644 --- a/core/src/main/java/haveno/core/offer/OfferPayload.java +++ b/core/src/main/java/haveno/core/offer/OfferPayload.java @@ -158,6 +158,8 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay private final boolean isPrivateOffer; @Nullable private final String challengeHash; + @Nullable + private final String extraInfo; /////////////////////////////////////////////////////////////////////////////////////////// @@ -201,7 +203,8 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay int protocolVersion, @Nullable NodeAddress arbitratorSigner, @Nullable byte[] arbitratorSignature, - @Nullable List reserveTxKeyImages) { + @Nullable List reserveTxKeyImages, + @Nullable String extraInfo) { this.id = id; this.date = date; this.ownerNodeAddress = ownerNodeAddress; @@ -240,6 +243,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay this.upperClosePrice = upperClosePrice; this.isPrivateOffer = isPrivateOffer; this.challengeHash = challengeHash; + this.extraInfo = extraInfo; } public byte[] getHash() { @@ -290,7 +294,8 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay protocolVersion, arbitratorSigner, null, - reserveTxKeyImages + reserveTxKeyImages, + null ); return signee.getHash(); @@ -387,6 +392,7 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay Optional.ofNullable(arbitratorSigner).ifPresent(e -> builder.setArbitratorSigner(arbitratorSigner.toProtoMessage())); Optional.ofNullable(arbitratorSignature).ifPresent(e -> builder.setArbitratorSignature(ByteString.copyFrom(e))); Optional.ofNullable(reserveTxKeyImages).ifPresent(builder::addAllReserveTxKeyImages); + Optional.ofNullable(extraInfo).ifPresent(builder::setExtraInfo); return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build(); } @@ -398,7 +404,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay null : new ArrayList<>(proto.getAcceptedCountryCodesList()); List reserveTxKeyImages = proto.getReserveTxKeyImagesList().isEmpty() ? null : new ArrayList<>(proto.getReserveTxKeyImagesList()); - String challengeHash = ProtoUtil.stringOrNullFromProto(proto.getChallengeHash()); Map extraDataMapMap = CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap(); @@ -434,12 +439,13 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay proto.getLowerClosePrice(), proto.getUpperClosePrice(), proto.getIsPrivateOffer(), - challengeHash, + ProtoUtil.stringOrNullFromProto(proto.getChallengeHash()), extraDataMapMap, proto.getProtocolVersion(), proto.hasArbitratorSigner() ? NodeAddress.fromProto(proto.getArbitratorSigner()) : null, ProtoUtil.byteArrayOrNullFromProto(proto.getArbitratorSignature()), - reserveTxKeyImages); + reserveTxKeyImages, + ProtoUtil.stringOrNullFromProto(proto.getExtraInfo())); } @Override @@ -481,14 +487,15 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay ",\r\n lowerClosePrice=" + lowerClosePrice + ",\r\n upperClosePrice=" + upperClosePrice + ",\r\n isPrivateOffer=" + isPrivateOffer + - ",\r\n challengeHash='" + challengeHash + '\'' + + ",\r\n challengeHash='" + challengeHash + ",\r\n arbitratorSigner=" + arbitratorSigner + ",\r\n arbitratorSignature=" + Utilities.bytesAsHexString(arbitratorSignature) + + ",\r\n extraInfo='" + extraInfo + "\r\n} "; } // For backward compatibility we need to ensure same order for json fields as with 1.7.5. and earlier versions. - // The json is used for the hash in the contract and change of oder would cause a different hash and + // The json is used for the hash in the contract and change of order would cause a different hash and // therefore a failure during trade. public static class JsonSerializer implements com.google.gson.JsonSerializer { @Override @@ -525,6 +532,8 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay object.add("protocolVersion", context.serialize(offerPayload.getProtocolVersion())); object.add("arbitratorSigner", context.serialize(offerPayload.getArbitratorSigner())); object.add("arbitratorSignature", context.serialize(offerPayload.getArbitratorSignature())); + object.add("extraInfo", context.serialize(offerPayload.getExtraInfo())); + // reserveTxKeyImages and challengeHash are purposely excluded because they are not relevant to existing trades and would break existing contracts return object; } } diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index b7cb7255f8..ab52d00b38 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -1788,7 +1788,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe protocolVersion, originalOfferPayload.getArbitratorSigner(), originalOfferPayload.getArbitratorSignature(), - originalOfferPayload.getReserveTxKeyImages()); + originalOfferPayload.getReserveTxKeyImages(), + originalOfferPayload.getExtraInfo()); // Save states from original data to use for the updated Offer.State originalOfferState = originalOffer.getState(); diff --git a/core/src/main/java/haveno/core/payment/F2FAccount.java b/core/src/main/java/haveno/core/payment/F2FAccount.java index b75718ec68..a16b4daf6c 100644 --- a/core/src/main/java/haveno/core/payment/F2FAccount.java +++ b/core/src/main/java/haveno/core/payment/F2FAccount.java @@ -93,7 +93,7 @@ public final class F2FAccount extends CountryBasedPaymentAccount { if (field.getId() == PaymentAccountFormField.FieldId.TRADE_CURRENCIES) field.setComponent(PaymentAccountFormField.Component.SELECT_ONE); if (field.getId() == PaymentAccountFormField.FieldId.CITY) field.setLabel(Res.get("payment.f2f.city")); if (field.getId() == PaymentAccountFormField.FieldId.CONTACT) field.setLabel(Res.get("payment.f2f.contact")); - if (field.getId() == PaymentAccountFormField.FieldId.EXTRA_INFO) field.setLabel(Res.get("payment.shared.extraInfo.prompt")); + if (field.getId() == PaymentAccountFormField.FieldId.EXTRA_INFO) field.setLabel(Res.get("payment.shared.extraInfo.prompt.paymentAccount")); return field; } } diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 26023eff08..c759cd61da 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -3028,7 +3028,10 @@ payment.f2f.city=City for 'Face to face' meeting payment.f2f.city.prompt=The city will be displayed with the offer payment.shared.optionalExtra=Optional additional information payment.shared.extraInfo=Additional information -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=Additional offer information +payment.shared.extraInfo.prompt.paymentAccount=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.prompt.offer=Define any special terms, conditions, or details you would like to be displayed with your offer. +payment.shared.extraInfo.noDeposit=Contact details and offer terms payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\n\ The main differences are:\n\ ● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n\ @@ -3042,7 +3045,7 @@ payment.f2f.info='Face to Face' trades have different rules and come with differ recommendations at: [HYPERLINK:https://docs.haveno.exchange/the-project/payment_methods/F2F] payment.f2f.info.openURL=Open web page payment.f2f.offerbook.tooltip.countryAndCity=Country and city: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Additional information: {0} +payment.shared.extraInfo.tooltip=Additional information: {0} payment.ifsc=IFS Code payment.ifsc.validation=IFSC format: XXXX0999999 diff --git a/core/src/main/resources/i18n/displayStrings_cs.properties b/core/src/main/resources/i18n/displayStrings_cs.properties index 1769788e97..32f326ca91 100644 --- a/core/src/main/resources/i18n/displayStrings_cs.properties +++ b/core/src/main/resources/i18n/displayStrings_cs.properties @@ -3028,7 +3028,10 @@ payment.f2f.city=Město pro setkání 'tváří v tvář' payment.f2f.city.prompt=Město se zobrazí s nabídkou payment.shared.optionalExtra=Volitelné další informace payment.shared.extraInfo=Další informace -payment.shared.extraInfo.prompt=Uveďte jakékoli speciální požadavky, podmínky a detaily, které chcete zobrazit u vašich nabídek s tímto platebním účtem. (Uživatelé uvidí tyto informace předtím, než akceptují vaši nabídku.) +payment.shared.extraInfo.offer=Další informace o nabídce +payment.shared.extraInfo.prompt.paymentAccount=Uveďte jakékoli speciální požadavky, podmínky a detaily, které chcete zobrazit u vašich nabídek s tímto platebním účtem. (Uživatelé uvidí tyto informace předtím, než akceptují vaši nabídku.) +payment.shared.extraInfo.prompt.offer=Definujte jakékoli speciální podmínky, podmínky nebo detaily, které chcete zobrazit u své nabídky. +payment.shared.extraInfo.noDeposit=Kontaktní údaje a podmínky nabídky payment.f2f.info=Obchody 'tváří v tvář' mají různá pravidla a přicházejí s jinými riziky než online transakce.\n\n\ Hlavní rozdíly jsou:\n\ ● Obchodní partneři si musí vyměňovat informace o místě a čase schůzky pomocí poskytnutých kontaktních údajů.\n\ @@ -3042,7 +3045,7 @@ payment.f2f.info=Obchody 'tváří v tvář' mají různá pravidla a přicháze na adrese: [HYPERLINK:https://docs.haveno.exchange/the-project/payment_methods/F2F] payment.f2f.info.openURL=Otevřít webovou stránku payment.f2f.offerbook.tooltip.countryAndCity=Země a město: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Další informace: {0} +payment.shared.extraInfo.tooltip=Další informace: {0} payment.ifsc=IFS kód payment.ifsc.validation=IFSC formát: XXXX0999999 diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index c6002f049a..ef8fb9afe9 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -2032,11 +2032,14 @@ payment.f2f.city=Stadt für ein "Angesicht zu Angesicht" Treffen payment.f2f.city.prompt=Die Stadt wird mit dem Angebot angezeigt payment.shared.optionalExtra=Freiwillige zusätzliche Informationen payment.shared.extraInfo=Zusätzliche Informationen -payment.shared.extraInfo.prompt=Gib spezielle Bedingungen, Abmachungen oder Details die bei ihren Angeboten unter diesem Zahlungskonto angezeigt werden sollen an. Nutzer werden diese Informationen vor der Annahme des Angebots sehen. +payment.shared.extraInfo.offer=Zusätzliche Angebotsinformationen +payment.shared.extraInfo.prompt.paymentAccount=Gib spezielle Bedingungen, Abmachungen oder Details die bei ihren Angeboten unter diesem Zahlungskonto angezeigt werden sollen an. Nutzer werden diese Informationen vor der Annahme des Angebots sehen. +payment.shared.extraInfo.prompt.offer=Definieren Sie alle speziellen Begriffe, Bedingungen oder Details, die Sie mit Ihrem Angebot anzeigen möchten. +payment.shared.extraInfo.noDeposit=Kontaktdaten und Angebotsbedingungen payment.f2f.info=Persönliche 'Face to Face' Trades haben unterschiedliche Regeln und sind mit anderen Risiken verbunden als gewöhnliche Online-Trades.\n\nDie Hauptunterschiede sind:\n● Die Trading Partner müssen die Kontaktdaten und Informationen über den Ort und die Uhrzeit des Treffens austauschen.\n● Die Trading Partner müssen ihre Laptops mitbringen und die Bestätigung der "gesendeten Zahlung" und der "erhaltenen Zahlung" am Treffpunkt vornehmen.\n● Wenn ein Ersteller eines Angebots spezielle "Allgemeine Geschäftsbedingungen" hat, muss er diese im Textfeld "Zusatzinformationen" des Kontos angeben.\n● Mit der Annahme eines Angebots erklärt sich der Käufer mit den vom Anbieter angegebenen "Allgemeinen Geschäftsbedingungen" einverstanden.\n● Im Konfliktfall kann der Mediator oder Arbitrator nicht viel tun, da es in der Regel schwierig ist zu bestimmen, was beim Treffen passiert ist. In solchen Fällen können die Monero auf unbestimmte Zeit oder bis zu einer Einigung der Trading Peers gesperrt werden.\n\nUm sicherzustellen, dass Sie die Besonderheiten der persönlichen 'Face to Face' Trades vollständig verstehen, lesen Sie bitte die Anweisungen und Empfehlungen unter: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Webseite öffnen payment.f2f.offerbook.tooltip.countryAndCity=Land und Stadt: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Zusätzliche Informationen: {0} +payment.shared.extraInfo.tooltip=Zusätzliche Informationen: {0} payment.japan.bank=Bank payment.japan.branch=Filiale diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index 303330e489..e5ab6b4537 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -2033,11 +2033,14 @@ payment.f2f.city=Ciudad para la reunión 'cara a cara' payment.f2f.city.prompt=La ciudad se mostrará con la oferta payment.shared.optionalExtra=Información adicional opcional payment.shared.extraInfo=Información adicional -payment.shared.extraInfo.prompt=Defina cualquier término especial, condiciones o detalles que quiera mostrar junto a sus ofertas para esta cuenta de pago (otros usuarios podrán ver esta información antes de aceptar las ofertas). +payment.shared.extraInfo.offer=Información adicional de la oferta +payment.shared.extraInfo.prompt.paymentAccount=Defina cualquier término especial, condiciones o detalles que quiera mostrar junto a sus ofertas para esta cuenta de pago (otros usuarios podrán ver esta información antes de aceptar las ofertas). +payment.shared.extraInfo.prompt.offer=Defina cualquier término, condición o detalle especial que le gustaría mostrar con su oferta. +payment.shared.extraInfo.noDeposit=Detalles de contacto y términos de la oferta payment.f2f.info=Los intercambios 'Cara a Cara' tienen diferentes reglas y riesgos que las transacciones en línea.\n\nLas principales diferencias son:\n● Los pares de intercambio necesitan intercambiar información acerca del punto de reunión y la hora usando los detalles de contacto proporcionados.\n● Los pares de intercambio tienen que traer sus portátiles y hacer la confirmación de 'pago enviado' y 'pago recibido' en el lugar de reunión.\n● Si un creador tiene 'términos y condiciones' especiales necesita declararlos en el campo de texto 'información adicional' en la cuenta.\n● Tomando una oferta el tomador está de acuerdo con los 'términos y condiciones' declarados por el creador.\n● En caso de disputa el árbitro no puede ayudar mucho ya que normalmente es complicado obtener evidencias no manipulables de lo que ha pasado en una reunión. En estos casos los fondos XMR pueden bloquearse indefinidamente o hasta que los pares lleguen a un acuerdo.\n\nPara asegurarse de que comprende las diferencias con los intercambios 'Cara a Cara' por favor lea las instrucciones y recomendaciones en: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Abrir paǵina web payment.f2f.offerbook.tooltip.countryAndCity=País y ciudad: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Información adicional: {0} +payment.shared.extraInfo.tooltip=Información adicional: {0} payment.japan.bank=Banco payment.japan.branch=Branch diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index 647b9dc735..cd739ed362 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -2007,11 +2007,14 @@ payment.f2f.city=شهر جهت ملاقات 'رو در رو' payment.f2f.city.prompt=نام شهر به همراه پیشنهاد نمایش داده خواهد شد payment.shared.optionalExtra=اطلاعات اضافی اختیاری payment.shared.extraInfo=اطلاعات اضافی -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=اطلاعات اضافی پیشنهاد +payment.shared.extraInfo.prompt.paymentAccount=هرگونه اصطلاحات، شرایط یا جزئیات خاصی که می‌خواهید همراه با پیشنهادات شما برای این حساب پرداخت نمایش داده شود را تعریف کنید (کاربران قبل از پذیرش پیشنهادات این اطلاعات را مشاهده خواهند کرد). +payment.shared.extraInfo.prompt.offer=هر اصطلاح، شرایط یا جزئیات خاصی که مایلید همراه با پیشنهاد خود نمایش داده شود را تعریف کنید. +payment.shared.extraInfo.noDeposit=جزئیات تماس و شرایط پیشنهاد payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=باز کردن صفحه وب payment.f2f.offerbook.tooltip.countryAndCity=Country and city: {0} / {1} -payment.f2f.offerbook.tooltip.extra=اطلاعات اضافی: {0} +payment.shared.extraInfo.tooltip=اطلاعات اضافی: {0} payment.japan.bank=بانک payment.japan.branch=Branch diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index 7ee0f6a420..858cbee06c 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -2034,11 +2034,14 @@ payment.f2f.city=Ville pour la rencontre en face à face payment.f2f.city.prompt=La ville sera affichée en même temps que l'ordre payment.shared.optionalExtra=Informations complémentaires facultatives payment.shared.extraInfo=Informations complémentaires -payment.shared.extraInfo.prompt=Définissez n'importe quels termes spécifiques, conditons ou détails que vous souhaiteriez voir affichés avec vos offres pour ce compte de paiement (les utilisateurs verront ces informations avant d'accepter les offres). +payment.shared.extraInfo.offer=Informations supplémentaires sur l'offre +payment.shared.extraInfo.prompt.paymentAccount=Définissez n'importe quels termes spécifiques, conditons ou détails que vous souhaiteriez voir affichés avec vos offres pour ce compte de paiement (les utilisateurs verront ces informations avant d'accepter les offres). +payment.shared.extraInfo.prompt.offer=Définissez tous les termes, conditions ou détails spéciaux que vous souhaitez afficher avec votre offre. +payment.shared.extraInfo.noDeposit=Coordonnées et conditions de l'offre payment.f2f.info=Les transactions en 'face à face' ont des règles différentes et comportent des risques différents de ceux des transactions en ligne.\n\nLes principales différences sont les suivantes:\n● Les pairs de trading doivent échanger des informations sur le lieu et l'heure de la réunion en utilisant les coordonnées de contanct qu'ils ont fournies.\n● Les pairs de trading doivent apporter leur ordinateur portable et faire la confirmation du 'paiement envoyé' et du 'paiement reçu' sur le lieu de la réunion.\n● Si un maker a des 'termes et conditions' spéciaux, il doit les indiquer dans le champ 'Informations supplémentaires' dans le compte.\n● En acceptant une offre, le taker accepte les 'termes et conditions' du maker.\n● En cas de litige, le médiateur ou l'arbitre ne peut pas beaucoup aider car il est généralement difficile d'obtenir des preuves irréfutables de ce qui s'est passé lors de la réunion. Dans ce cas, les fonds en XMR peuvent être bloqué s indéfiniment tant que les pairs ne parviennent pas à un accord.\n\nPour vous assurer de bien comprendre les spécificités des transactions 'face à face', veuillez lire les instructions et les recommandations à [LIEN:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Ouvrir la page web payment.f2f.offerbook.tooltip.countryAndCity=Pays et ville: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Informations complémentaires: {0} +payment.shared.extraInfo.tooltip=Informations complémentaires: {0} payment.japan.bank=Banque payment.japan.branch=Filiale diff --git a/core/src/main/resources/i18n/displayStrings_it.properties b/core/src/main/resources/i18n/displayStrings_it.properties index 495c2380f8..f4dff1e8f5 100644 --- a/core/src/main/resources/i18n/displayStrings_it.properties +++ b/core/src/main/resources/i18n/displayStrings_it.properties @@ -2010,11 +2010,14 @@ payment.f2f.city=Città per l'incontro 'Faccia a faccia' payment.f2f.city.prompt=La città verrà visualizzata con l'offerta payment.shared.optionalExtra=Ulteriori informazioni opzionali payment.shared.extraInfo=Informazioni aggiuntive -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=Informazioni aggiuntive sull'offerta +payment.shared.extraInfo.prompt.paymentAccount=Definisci eventuali termini, condizioni o dettagli speciali che desideri vengano visualizzati con le tue offerte per questo account di pagamento (gli utenti vedranno queste informazioni prima di accettare le offerte). +payment.shared.extraInfo.prompt.offer=Definisci eventuali termini, condizioni o dettagli speciali che desideri mostrare con la tua offerta. +payment.shared.extraInfo.noDeposit=Dettagli di contatto e termini dell'offerta payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Apri sito web payment.f2f.offerbook.tooltip.countryAndCity=Paese e città: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Ulteriori informazioni: {0} +payment.shared.extraInfo.tooltip=Ulteriori informazioni: {0} payment.japan.bank=Banca payment.japan.branch=Filiale diff --git a/core/src/main/resources/i18n/displayStrings_ja.properties b/core/src/main/resources/i18n/displayStrings_ja.properties index b31773063e..f4348c9e68 100644 --- a/core/src/main/resources/i18n/displayStrings_ja.properties +++ b/core/src/main/resources/i18n/displayStrings_ja.properties @@ -2032,11 +2032,14 @@ payment.f2f.city=「対面」で会うための市区町村 payment.f2f.city.prompt=オファーとともに市区町村が表示されます payment.shared.optionalExtra=オプションの追加情報 payment.shared.extraInfo=追加情報 -payment.shared.extraInfo.prompt=この支払いアカウントのオファーと一緒に表示したい特別な契約条件または詳細を定義して下さい(オファーを受ける前に、ユーザはこの情報を見れます)。 +payment.shared.extraInfo.offer=追加のオファー情報 +payment.shared.extraInfo.prompt.paymentAccount=この支払いアカウントのオファーと一緒に表示したい特別な契約条件または詳細を定義して下さい(オファーを受ける前に、ユーザはこの情報を見れます)。 +payment.shared.extraInfo.prompt.offer=提供内容と共に表示したい特別な用語、条件、または詳細を定義してください。 +payment.shared.extraInfo.noDeposit=連絡先詳細およびオファー条件 payment.f2f.info=「対面」トレードには違うルールがあり、オンライントレードとは異なるリスクを伴います。\n\n主な違いは以下の通りです。\n●取引者は、提供される連絡先の詳細を使用して、出会う場所と時間に関する情報を交換する必要があります。\n●取引者は自分のノートパソコンを持ってきて、集合場所で「送金」と「入金」の確認をする必要があります。\n●メイカーに特別な「取引条件」がある場合は、アカウントの「追加情報」テキストフィールドにその旨を記載する必要があります。\n●オファーを受けると、テイカーはメイカーの「トレード条件」に同意したものとします。\n●係争が発生した場合、集合場所で何が起きたのかについての改ざん防止証明を入手することは通常困難であるため、調停者や調停人はあまりサポートをできません。このような場合、XMRの資金は無期限に、または取引者が合意に達するまでロックされる可能性があります。\n\n「対面」トレードでの違いを完全に理解しているか確認するためには、次のURLにある手順と推奨事項をお読みください:[HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Webページを開く payment.f2f.offerbook.tooltip.countryAndCity=国と都市: {0} / {1} -payment.f2f.offerbook.tooltip.extra=追加情報: {0} +payment.shared.extraInfo.tooltip=追加情報: {0} payment.japan.bank=銀行 payment.japan.branch=支店 diff --git a/core/src/main/resources/i18n/displayStrings_pt-br.properties b/core/src/main/resources/i18n/displayStrings_pt-br.properties index 6ac9da556c..9a1f111b62 100644 --- a/core/src/main/resources/i18n/displayStrings_pt-br.properties +++ b/core/src/main/resources/i18n/displayStrings_pt-br.properties @@ -2017,11 +2017,14 @@ payment.f2f.city=Cidade para se encontrar 'Cara-a-cara' payment.f2f.city.prompt=A cidade será exibida na oferta payment.shared.optionalExtra=Informações adicionais opcionais payment.shared.extraInfo=Informações adicionais -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=Informações adicionais sobre a oferta +payment.shared.extraInfo.prompt.paymentAccount=Defina quaisquer termos, condições ou detalhes especiais que você gostaria que fossem exibidos com suas ofertas para esta conta de pagamento (os usuários verão estas informações antes de aceitar as ofertas). +payment.shared.extraInfo.prompt.offer=Defina quaisquer termos, condições ou detalhes especiais que você gostaria de exibir com sua oferta. +payment.shared.extraInfo.noDeposit=Detalhes de contato e termos da oferta payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Abrir site payment.f2f.offerbook.tooltip.countryAndCity=País e cidade: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Informações adicionais: {0} +payment.shared.extraInfo.tooltip=Informações adicionais: {0} payment.japan.bank=Banco payment.japan.branch=Ramo diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index 45cd1170dc..3165205bd5 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -2007,11 +2007,14 @@ payment.f2f.city=Cidade para o encontro 'Face à face' payment.f2f.city.prompt=A cidade será exibida com a oferta payment.shared.optionalExtra=Informação adicional opcional payment.shared.extraInfo=Informação adicional -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=Informações adicionais sobre a oferta +payment.shared.extraInfo.prompt.paymentAccount=Defina quaisquer termos especiais, condições ou detalhes que você gostaria de exibir com suas ofertas para esta conta de pagamento (os usuários verão essas informações antes de aceitar as ofertas). +payment.shared.extraInfo.prompt.offer=Defina quaisquer termos, condições ou detalhes especiais que você gostaria de exibir com sua oferta. +payment.shared.extraInfo.noDeposit=Detalhes de contato e termos da oferta payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Abrir página web payment.f2f.offerbook.tooltip.countryAndCity=País e cidade: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Informação adicional: {0} +payment.shared.extraInfo.tooltip=Informação adicional: {0} payment.japan.bank=Banco payment.japan.branch=Agência diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index ac05e10b83..0e693049c7 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -2008,11 +2008,14 @@ payment.f2f.city=Город для личной встречи payment.f2f.city.prompt=Город будет указан в предложении payment.shared.optionalExtra=Дополнительная необязательная информация payment.shared.extraInfo=Дополнительная информация -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=Дополнительная информация о предложении +payment.shared.extraInfo.prompt.paymentAccount=Определите любые специальные термины, условия или детали, которые вы хотите, чтобы отображались с вашими предложениями для этого платежного аккаунта (пользователи увидят эту информацию перед принятием предложений). +payment.shared.extraInfo.prompt.offer=Определите любые специальные условия, требования или детали, которые вы хотели бы указать в своем предложении. +payment.shared.extraInfo.noDeposit=Контактные данные и условия предложения payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Открыть веб-страницу payment.f2f.offerbook.tooltip.countryAndCity=Country and city: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Дополнительная информация: {0} +payment.shared.extraInfo.tooltip=Дополнительная информация: {0} payment.japan.bank=Банк payment.japan.branch=Branch diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index 5e25ee8149..5863219f9c 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -2008,11 +2008,14 @@ payment.f2f.city=เมืองสำหรับการประชุมแ payment.f2f.city.prompt=ชื่อเมืองจะแสดงพร้อมกับข้อเสนอ payment.shared.optionalExtra=ข้อมูลตัวเลือกเพิ่มเติม payment.shared.extraInfo=ข้อมูลเพิ่มเติม -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=ข้อมูลเพิ่มเติมเกี่ยวกับข้อเสนอ +payment.shared.extraInfo.prompt.paymentAccount=กำหนดคำศัพท์ เงื่อนไข หรือรายละเอียดพิเศษใดๆ ที่คุณต้องการให้แสดงพร้อมข้อเสนอของคุณสำหรับบัญชีการชำระเงินนี้ (ผู้ใช้จะเห็นข้อมูลนี้ก่อนที่จะยอมรับข้อเสนอ) +payment.shared.extraInfo.prompt.offer=กำหนดเงื่อนไขพิเศษ ข้อกำหนด หรือรายละเอียดใด ๆ ที่คุณต้องการแสดงพร้อมกับข้อเสนอของคุณ +payment.shared.extraInfo.noDeposit=รายละเอียดการติดต่อและเงื่อนไขข้อเสนอ payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=เปิดหน้าเว็บ payment.f2f.offerbook.tooltip.countryAndCity=Country and city: {0} / {1} -payment.f2f.offerbook.tooltip.extra=ข้อมูลเพิ่มเติม: {0} +payment.shared.extraInfo.tooltip=ข้อมูลเพิ่มเติม: {0} payment.japan.bank=ธนาคาร payment.japan.branch=Branch diff --git a/core/src/main/resources/i18n/displayStrings_tr.properties b/core/src/main/resources/i18n/displayStrings_tr.properties index 4ff0b4f610..d506f428a8 100644 --- a/core/src/main/resources/i18n/displayStrings_tr.properties +++ b/core/src/main/resources/i18n/displayStrings_tr.properties @@ -3015,7 +3015,10 @@ payment.f2f.city='Yüz yüze' buluşma için şehir payment.f2f.city.prompt=Şehir teklifle birlikte gösterilecektir payment.shared.optionalExtra=İsteğe bağlı ek bilgi payment.shared.extraInfo=Ek bilgi -payment.shared.extraInfo.prompt=Bu ödeme hesabınız için tekliflerinize eklemek istediğiniz özel şart, koşul veya detayları tanımlayın (kullanıcılar bu bilgileri teklifleri kabul etmeden önce görecektir). +payment.shared.extraInfo.offer=Ek teklif bilgileri +payment.shared.extraInfo.prompt.paymentAccount=Bu ödeme hesabınız için tekliflerinize eklemek istediğiniz özel şart, koşul veya detayları tanımlayın (kullanıcılar bu bilgileri teklifleri kabul etmeden önce görecektir). +payment.shared.extraInfo.prompt.offer=Teklifinizle birlikte göstermek istediğiniz özel terimleri, koşulları veya detayları tanımlayın. +payment.shared.extraInfo.noDeposit=İletişim detayları ve teklif şartları payment.f2f.info='Yüz Yüze' ticaretler farklı kurallara sahiptir ve çevrimiçi işlemlerden farklı riskler içerir.\n\n\ Başlıca farklar şunlardır:\n\ ● Ticaret eşleri, sağlanan iletişim bilgilerini kullanarak buluşma yeri ve zamanını paylaşmalıdır.\n\ @@ -3029,7 +3032,7 @@ payment.f2f.info='Yüz Yüze' ticaretler farklı kurallara sahiptir ve çevrimi ve tavsiyeleri okuyun: [HYPERLINK:https://docs.haveno.exchange/the-project/payment_methods/F2F] payment.f2f.info.openURL=Web sayfasını aç payment.f2f.offerbook.tooltip.countryAndCity=Ülke ve şehir: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Ek bilgi: {0} +payment.shared.extraInfo.tooltip=Ek bilgi: {0} payment.ifsc=IFS Kodu payment.ifsc.validation=IFSC formatı: XXXX0999999 diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index 7ea2eb9d27..5476c67d17 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -2010,11 +2010,14 @@ payment.f2f.city=Thành phố để gặp mặt trực tiếp payment.f2f.city.prompt=Thành phố sẽ được hiển thị cùng báo giá payment.shared.optionalExtra=Thông tin thêm tuỳ chọn. payment.shared.extraInfo=thông tin thêm -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=Thông tin bổ sung về ưu đãi +payment.shared.extraInfo.prompt.paymentAccount=Xác định bất kỳ điều khoản, điều kiện hoặc chi tiết đặc biệt nào bạn muốn hiển thị cùng với các ưu đãi của mình cho tài khoản thanh toán này (người dùng sẽ thấy thông tin này trước khi chấp nhận các ưu đãi). +payment.shared.extraInfo.prompt.offer=Xác định bất kỳ thuật ngữ, điều kiện hoặc chi tiết đặc biệt nào bạn muốn hiển thị cùng với đề nghị của mình. +payment.shared.extraInfo.noDeposit=Chi tiết liên hệ và điều khoản ưu đãi payment.f2f.info='Face to Face' trades have different rules and come with different risks than online transactions.\n\nThe main differences are:\n● The trading peers need to exchange information about the meeting location and time by using their provided contact details.\n● The trading peers need to bring their laptops and do the confirmation of 'payment sent' and 'payment received' at the meeting place.\n● If a maker has special 'terms and conditions' they must state those in the 'Additional information' text field in the account.\n● By taking an offer the taker agrees to the maker's stated 'terms and conditions'.\n● In case of a dispute the mediator or arbitrator cannot be of much assistance as it is usually difficult to get tamper-proof evidence of what happened at the meeting. In such cases the XMR funds might get locked indefinitely or until the trading peers come to an agreement.\n\nTo be sure you fully understand the differences with 'Face to Face' trades please read the instructions and recommendations at: [HYPERLINK:https://docs.haveno.exchange/trading-rules.html#f2f-trading] payment.f2f.info.openURL=Mở trang web payment.f2f.offerbook.tooltip.countryAndCity=Country and city: {0} / {1} -payment.f2f.offerbook.tooltip.extra=Thông tin thêm: {0} +payment.shared.extraInfo.tooltip=Thông tin thêm: {0} payment.japan.bank=Ngân hàng payment.japan.branch=Branch diff --git a/core/src/main/resources/i18n/displayStrings_zh-hans.properties b/core/src/main/resources/i18n/displayStrings_zh-hans.properties index 9f3e495ba7..2e5a0c9945 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hans.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hans.properties @@ -2017,11 +2017,14 @@ payment.f2f.city=“面对面”会议的城市 payment.f2f.city.prompt=城市将与报价一同显示 payment.shared.optionalExtra=可选的附加信息 payment.shared.extraInfo=附加信息 -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=附加报价信息 +payment.shared.extraInfo.prompt.paymentAccount=定义您希望在此支付账户的报价中显示的任何特殊术语、条件或细节(用户在接受报价之前将看到这些信息)。 +payment.shared.extraInfo.prompt.offer=定义您希望随您的报价一起显示的任何特殊条款、条件或详细信息。 +payment.shared.extraInfo.noDeposit=联系方式和优惠条款 payment.f2f.info=与网上交易相比,“面对面”交易有不同的规则,也有不同的风险。\n\n主要区别是:\n●交易伙伴需要使用他们提供的联系方式交换关于会面地点和时间的信息。\n●交易双方需要携带笔记本电脑,在会面地点确认“已发送付款”和“已收到付款”。\n●如果交易方有特殊的“条款和条件”,他们必须在账户的“附加信息”文本框中声明这些条款和条件。\n●在发生争议时,调解员或仲裁员不能提供太多帮助,因为通常很难获得有关会面上所发生情况的篡改证据。在这种情况下,XMR 资金可能会被无限期锁定,或者直到交易双方达成协议。\n\n为确保您完全理解“面对面”交易的不同之处,请阅读以下说明和建议:“https://docs.haveno.exchange/trading-rules.html#f2f-trading” payment.f2f.info.openURL=打开网页 payment.f2f.offerbook.tooltip.countryAndCity=国家或地区及城市:{0} / {1} -payment.f2f.offerbook.tooltip.extra=附加信息:{0} +payment.shared.extraInfo.tooltip=附加信息:{0} payment.japan.bank=银行 payment.japan.branch=分行 diff --git a/core/src/main/resources/i18n/displayStrings_zh-hant.properties b/core/src/main/resources/i18n/displayStrings_zh-hant.properties index c802eba7b8..5bca299cfc 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hant.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hant.properties @@ -2011,11 +2011,14 @@ payment.f2f.city=“面對面”會議的城市 payment.f2f.city.prompt=城市將與報價一同顯示 payment.shared.optionalExtra=可選的附加信息 payment.shared.extraInfo=附加信息 -payment.shared.extraInfo.prompt=Define any special terms, conditions, or details you would like to be displayed with your offers for this payment account (users will see this info before accepting offers). +payment.shared.extraInfo.offer=額外的優惠資訊 +payment.shared.extraInfo.prompt.paymentAccount=定義您希望在此付款帳戶的報價中顯示的任何特殊術語、條件或細節(用戶在接受報價之前將看到這些資訊)。 +payment.shared.extraInfo.prompt.offer=定義您希望在您的報價中顯示的任何特殊條款、條件或詳細資訊。 +payment.shared.extraInfo.noDeposit=聯絡詳情及優惠條款 payment.f2f.info=與網上交易相比,“面對面”交易有不同的規則,也有不同的風險。\n\n主要區別是:\n●交易夥伴需要使用他們提供的聯繫方式交換關於會面地點和時間的信息。\n●交易雙方需要攜帶筆記本電腦,在會面地點確認“已發送付款”和“已收到付款”。\n●如果交易方有特殊的“條款和條件”,他們必須在賬户的“附加信息”文本框中聲明這些條款和條件。\n●在發生爭議時,調解員或仲裁員不能提供太多幫助,因為通常很難獲得有關會面上所發生情況的篡改證據。在這種情況下,XMR 資金可能會被無限期鎖定,或者直到交易雙方達成協議。\n\n為確保您完全理解“面對面”交易的不同之處,請閲讀以下説明和建議:“https://docs.haveno.exchange/trading-rules.html#f2f-trading” payment.f2f.info.openURL=打開網頁 payment.f2f.offerbook.tooltip.countryAndCity=國家或地區及城市:{0} / {1} -payment.f2f.offerbook.tooltip.extra=附加信息:{0} +payment.shared.extraInfo.tooltip=附加信息:{0} payment.japan.bank=銀行 payment.japan.branch=分行 diff --git a/core/src/test/java/haveno/core/offer/OfferMaker.java b/core/src/test/java/haveno/core/offer/OfferMaker.java index 52084f209b..2f839e1a38 100644 --- a/core/src/test/java/haveno/core/offer/OfferMaker.java +++ b/core/src/test/java/haveno/core/offer/OfferMaker.java @@ -73,7 +73,8 @@ public class OfferMaker { 0, null, null, - null)); + null, + "My extra info")); public static final Maker btcUsdOffer = a(Offer); } diff --git a/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java index 7768522b23..a3ceba75db 100644 --- a/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java @@ -156,6 +156,7 @@ class GrpcOffersService extends OffersImplBase { req.getPaymentAccountId(), req.getIsPrivateOffer(), req.getBuyerAsTakerWithoutDeposit(), + req.getExtraInfo(), offer -> { // This result handling consumer's accept operation will return // the new offer to the gRPC client after async placement is done. diff --git a/desktop/src/main/java/haveno/desktop/components/paymentmethods/AustraliaPayidForm.java b/desktop/src/main/java/haveno/desktop/components/paymentmethods/AustraliaPayidForm.java index 234b5e88b0..615663bbbf 100644 --- a/desktop/src/main/java/haveno/desktop/components/paymentmethods/AustraliaPayidForm.java +++ b/desktop/src/main/java/haveno/desktop/components/paymentmethods/AustraliaPayidForm.java @@ -91,7 +91,7 @@ public class AustraliaPayidForm extends PaymentMethodForm { }); TextArea extraTextArea = addTopLabelTextArea(gridPane, ++gridRow, - Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt")).second; + Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt.paymentAccount")).second; extraTextArea.setMinHeight(70); ((JFXTextArea) extraTextArea).setLabelFloat(false); extraTextArea.textProperty().addListener((ov, oldValue, newValue) -> { diff --git a/desktop/src/main/java/haveno/desktop/components/paymentmethods/CashAppForm.java b/desktop/src/main/java/haveno/desktop/components/paymentmethods/CashAppForm.java index c0bb16f5e0..e1376c2643 100644 --- a/desktop/src/main/java/haveno/desktop/components/paymentmethods/CashAppForm.java +++ b/desktop/src/main/java/haveno/desktop/components/paymentmethods/CashAppForm.java @@ -79,7 +79,7 @@ public class CashAppForm extends PaymentMethodForm { }); TextArea extraTextArea = addTopLabelTextArea(gridPane, ++gridRow, - Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt")).second; + Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt.paymentAccount")).second; extraTextArea.setMinHeight(70); ((JFXTextArea) extraTextArea).setLabelFloat(false); extraTextArea.textProperty().addListener((ov, oldValue, newValue) -> { diff --git a/desktop/src/main/java/haveno/desktop/components/paymentmethods/F2FForm.java b/desktop/src/main/java/haveno/desktop/components/paymentmethods/F2FForm.java index aebd470d31..2a7e7f4f2a 100644 --- a/desktop/src/main/java/haveno/desktop/components/paymentmethods/F2FForm.java +++ b/desktop/src/main/java/haveno/desktop/components/paymentmethods/F2FForm.java @@ -65,7 +65,7 @@ public class F2FForm extends PaymentMethodForm { textArea.setMinHeight(70); textArea.setEditable(false); textArea.setId("text-area-disabled"); - textArea.setText(offer.getExtraInfo()); + textArea.setText(offer.getPaymentAccountExtraInfo()); return gridRow; } @@ -106,7 +106,7 @@ public class F2FForm extends PaymentMethodForm { }); TextArea extraTextArea = addTopLabelTextArea(gridPane, ++gridRow, - Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt")).second; + Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt.paymentAccount")).second; extraTextArea.setMinHeight(70); ((JFXTextArea) extraTextArea).setLabelFloat(false); //extraTextArea.setValidator(f2fValidator); diff --git a/desktop/src/main/java/haveno/desktop/components/paymentmethods/PayPalForm.java b/desktop/src/main/java/haveno/desktop/components/paymentmethods/PayPalForm.java index 8e0d48ee6e..83e4614a97 100644 --- a/desktop/src/main/java/haveno/desktop/components/paymentmethods/PayPalForm.java +++ b/desktop/src/main/java/haveno/desktop/components/paymentmethods/PayPalForm.java @@ -79,7 +79,7 @@ public class PayPalForm extends PaymentMethodForm { }); TextArea extraTextArea = addTopLabelTextArea(gridPane, ++gridRow, - Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt")).second; + Res.get("payment.shared.optionalExtra"), Res.get("payment.shared.extraInfo.prompt.paymentAccount")).second; extraTextArea.setMinHeight(70); ((JFXTextArea) extraTextArea).setLabelFloat(false); extraTextArea.textProperty().addListener((ov, oldValue, newValue) -> { diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java index bad2ee75f8..68c5edc733 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java @@ -105,6 +105,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel { protected final ObjectProperty price = new SimpleObjectProperty<>(); protected final ObjectProperty volume = new SimpleObjectProperty<>(); protected final ObjectProperty minVolume = new SimpleObjectProperty<>(); + protected final ObjectProperty extraInfo = new SimpleObjectProperty<>(); // Percentage value of buyer security deposit. E.g. 0.01 means 1% of trade amount protected final DoubleProperty securityDepositPct = new SimpleDoubleProperty(); @@ -305,7 +306,8 @@ public abstract class MutableOfferDataModel extends OfferDataModel { securityDepositPct.get(), paymentAccount, buyerAsTakerWithoutDeposit.get(), // private offer if buyer as taker without deposit - buyerAsTakerWithoutDeposit.get()); + buyerAsTakerWithoutDeposit.get(), + extraInfo.get()); } void onPlaceOffer(Offer offer, TransactionResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { @@ -583,6 +585,10 @@ public abstract class MutableOfferDataModel extends OfferDataModel { this.amount.set(amount); } + protected void setMinAmount(BigInteger minAmount) { + this.minAmount.set(minAmount); + } + protected void setPrice(Price price) { this.price.set(price); } @@ -595,6 +601,22 @@ public abstract class MutableOfferDataModel extends OfferDataModel { this.securityDepositPct.set(value); } + public void setMarketPriceAvailable(boolean marketPriceAvailable) { + this.marketPriceAvailable = marketPriceAvailable; + } + + public void setTriggerPrice(long triggerPrice) { + this.triggerPrice = triggerPrice; + } + + public void setReserveExactAmount(boolean reserveExactAmount) { + this.reserveExactAmount = reserveExactAmount; + } + + protected void setExtraInfo(String extraInfo) { + this.extraInfo.set(extraInfo); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Getters /////////////////////////////////////////////////////////////////////////////////////////// @@ -627,10 +649,6 @@ public abstract class MutableOfferDataModel extends OfferDataModel { return buyerAsTakerWithoutDeposit; } - protected void setMinAmount(BigInteger minAmount) { - this.minAmount.set(minAmount); - } - public ReadOnlyStringProperty getTradeCurrencyCode() { return tradeCurrencyCode; } @@ -670,10 +688,6 @@ public abstract class MutableOfferDataModel extends OfferDataModel { return totalToPay; } - public void setMarketPriceAvailable(boolean marketPriceAvailable) { - this.marketPriceAvailable = marketPriceAvailable; - } - public BigInteger getMaxMakerFee() { return HavenoUtils.multiply(amount.get(), buyerAsTakerWithoutDeposit.get() ? HavenoUtils.MAKER_FEE_FOR_TAKER_WITHOUT_DEPOSIT_PCT : HavenoUtils.MAKER_FEE_PCT); } @@ -687,11 +701,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel { return getSecurityDeposit().compareTo(Restrictions.getMinSecurityDeposit()) <= 0; } - public void setTriggerPrice(long triggerPrice) { - this.triggerPrice = triggerPrice; - } - - public void setReserveExactAmount(boolean reserveExactAmount) { - this.reserveExactAmount = reserveExactAmount; + public ReadOnlyObjectProperty getExtraInfo() { + return extraInfo; } } diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java index 0bcfa79050..35a2da8b60 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java @@ -44,6 +44,7 @@ import haveno.desktop.components.AutoTooltipLabel; import haveno.desktop.components.BalanceTextField; import haveno.desktop.components.BusyAnimation; import haveno.desktop.components.FundsTextField; +import haveno.desktop.components.HavenoTextArea; import haveno.desktop.components.InfoInputTextField; import haveno.desktop.components.InputTextField; import haveno.desktop.components.TitledGroupBg; @@ -75,6 +76,7 @@ import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.Separator; +import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.control.ToggleButton; import javafx.scene.control.Tooltip; @@ -126,7 +128,7 @@ public abstract class MutableOfferView> exten private ScrollPane scrollPane; protected GridPane gridPane; - private TitledGroupBg payFundsTitledGroupBg, setDepositTitledGroupBg, paymentTitledGroupBg; + private TitledGroupBg payFundsTitledGroupBg, setDepositTitledGroupBg, extraInfoTitledGroupBg, paymentTitledGroupBg; protected TitledGroupBg amountTitledGroupBg; private BusyAnimation waitingForFundsSpinner; private AutoTooltipButton nextButton, cancelButton1, cancelButton2, placeOfferButton, fundFromSavingsWalletButton; @@ -138,6 +140,7 @@ public abstract class MutableOfferView> exten private BalanceTextField balanceTextField; private ToggleButton reserveExactAmountSlider; private ToggleButton buyerAsTakerWithoutDepositSlider; + protected TextArea extraInfoTextArea; private FundsTextField totalToPayTextField; private Label amountDescriptionLabel, priceCurrencyLabel, priceDescriptionLabel, volumeDescriptionLabel, waitingForFundsLabel, marketBasedPriceLabel, percentagePriceDescriptionLabel, tradeFeeDescriptionLabel, @@ -156,10 +159,10 @@ public abstract class MutableOfferView> exten private ChangeListener amountFocusedListener, minAmountFocusedListener, volumeFocusedListener, securityDepositFocusedListener, priceFocusedListener, placeOfferCompletedListener, priceAsPercentageFocusedListener, getShowWalletFundedNotificationListener, - isMinSecurityDepositListener, buyerAsTakerWithoutDepositListener, triggerPriceFocusedListener; + isMinSecurityDepositListener, buyerAsTakerWithoutDepositListener, triggerPriceFocusedListener, extraInfoFocusedListener; private ChangeListener missingCoinListener; private ChangeListener tradeCurrencyCodeListener, errorMessageListener, - marketPriceMarginListener, volumeListener, securityDepositInXMRListener; + marketPriceMarginListener, volumeListener, securityDepositInXMRListener, extraInfoListener; private ChangeListener marketPriceAvailableListener; private EventHandler currencyComboBoxSelectionHandler, paymentAccountsComboBoxSelectionHandler; private OfferView.CloseHandler closeHandler; @@ -202,6 +205,8 @@ public abstract class MutableOfferView> exten addPaymentGroup(); addAmountPriceGroup(); addOptionsGroup(); + addExtraInfoGroup(); + addNextButtons(); addFundingGroup(); createListeners(); @@ -257,6 +262,8 @@ public abstract class MutableOfferView> exten triggerPriceInfoInputTextField.setContentForPopOver(popOverLabel, AwesomeIcon.SHIELD); buyerAsTakerWithoutDepositSlider.setSelected(model.dataModel.getBuyerAsTakerWithoutDeposit().get()); + + extraInfoTextArea.setText(model.dataModel.extraInfo.get()); } } @@ -389,6 +396,11 @@ public abstract class MutableOfferView> exten buyerAsTakerWithoutDepositSlider.setVisible(false); buyerAsTakerWithoutDepositSlider.setManaged(false); + extraInfoTitledGroupBg.setVisible(false); + extraInfoTitledGroupBg.setManaged(false); + extraInfoTextArea.setVisible(false); + extraInfoTextArea.setManaged(false); + updateQrCode(); model.onShowPayFundsScreen(() -> { @@ -571,6 +583,7 @@ public abstract class MutableOfferView> exten securityDepositLabel.textProperty().bind(model.securityDepositLabel); tradeFeeInXmrLabel.textProperty().bind(model.tradeFeeInXmrWithFiat); tradeFeeDescriptionLabel.textProperty().bind(model.tradeFeeDescription); + extraInfoTextArea.textProperty().bindBidirectional(model.extraInfo); // Validation amountTextField.validationResultProperty().bind(model.amountValidationResult); @@ -621,6 +634,7 @@ public abstract class MutableOfferView> exten tradeFeeDescriptionLabel.textProperty().unbind(); tradeFeeInXmrLabel.visibleProperty().unbind(); tradeFeeDescriptionLabel.visibleProperty().unbind(); + extraInfoTextArea.textProperty().unbindBidirectional(model.extraInfo); // Validation amountTextField.validationResultProperty().unbind(); @@ -694,11 +708,14 @@ public abstract class MutableOfferView> exten model.onFocusOutSecurityDepositTextField(oldValue, newValue); securityDepositInputTextField.setText(model.securityDeposit.get()); }; - triggerPriceFocusedListener = (o, oldValue, newValue) -> { model.onFocusOutTriggerPriceTextField(oldValue, newValue); triggerPriceInputTextField.setText(model.triggerPrice.get()); }; + extraInfoFocusedListener = (observable, oldValue, newValue) -> { + model.onFocusOutExtraInfoTextField(oldValue, newValue); + extraInfoTextArea.setText(model.extraInfo.get()); + }; errorMessageListener = (o, oldValue, newValue) -> { if (model.createOfferCanceled) return; @@ -822,6 +839,12 @@ public abstract class MutableOfferView> exten buyerAsTakerWithoutDepositListener = ((observable, oldValue, newValue) -> { updateSecurityDepositLabels(); }); + + extraInfoListener = (observable, oldValue, newValue) -> { + if (newValue != null && !newValue.equals("")) { + // no action + } + }; } private void updateSecurityDepositLabels() { @@ -881,6 +904,7 @@ public abstract class MutableOfferView> exten model.securityDepositInXMR.addListener(securityDepositInXMRListener); model.isMinSecurityDeposit.addListener(isMinSecurityDepositListener); model.getDataModel().buyerAsTakerWithoutDeposit.addListener(buyerAsTakerWithoutDepositListener); + model.getDataModel().extraInfo.addListener(extraInfoListener); // focus out amountTextField.focusedProperty().addListener(amountFocusedListener); @@ -890,6 +914,7 @@ public abstract class MutableOfferView> exten marketBasedPriceTextField.focusedProperty().addListener(priceAsPercentageFocusedListener); volumeTextField.focusedProperty().addListener(volumeFocusedListener); securityDepositInputTextField.focusedProperty().addListener(securityDepositFocusedListener); + extraInfoTextArea.focusedProperty().addListener(extraInfoFocusedListener); // notifications model.getDataModel().getShowWalletFundedNotification().addListener(getShowWalletFundedNotificationListener); @@ -914,6 +939,7 @@ public abstract class MutableOfferView> exten model.securityDepositInXMR.removeListener(securityDepositInXMRListener); model.isMinSecurityDeposit.removeListener(isMinSecurityDepositListener); model.getDataModel().buyerAsTakerWithoutDeposit.removeListener(buyerAsTakerWithoutDepositListener); + model.getDataModel().extraInfo.removeListener(extraInfoListener); // focus out amountTextField.focusedProperty().removeListener(amountFocusedListener); @@ -923,6 +949,7 @@ public abstract class MutableOfferView> exten marketBasedPriceTextField.focusedProperty().removeListener(priceAsPercentageFocusedListener); volumeTextField.focusedProperty().removeListener(volumeFocusedListener); securityDepositInputTextField.focusedProperty().removeListener(securityDepositFocusedListener); + extraInfoTextArea.focusedProperty().removeListener(extraInfoFocusedListener); // notifications model.getDataModel().getShowWalletFundedNotification().removeListener(getShowWalletFundedNotificationListener); @@ -1062,7 +1089,30 @@ public abstract class MutableOfferView> exten }); GridPane.setHalignment(buyerAsTakerWithoutDepositSlider, HPos.LEFT); GridPane.setMargin(buyerAsTakerWithoutDepositSlider, new Insets(0, 0, 0, 0)); + } + private void addExtraInfoGroup() { + + extraInfoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, + Res.get("payment.shared.optionalExtra"), 25 + heightAdjustment); + GridPane.setColumnSpan(extraInfoTitledGroupBg, 3); + + extraInfoTextArea = new HavenoTextArea(); + extraInfoTextArea.setPromptText(Res.get("payment.shared.extraInfo.prompt.offer")); + extraInfoTextArea.getStyleClass().add("text-area"); + extraInfoTextArea.setWrapText(true); + extraInfoTextArea.setPrefHeight(75); + extraInfoTextArea.setMinHeight(75); + extraInfoTextArea.setMaxHeight(75); + GridPane.setRowIndex(extraInfoTextArea, gridRow); + GridPane.setColumnSpan(extraInfoTextArea, GridPane.REMAINING); + GridPane.setColumnIndex(extraInfoTextArea, 0); + GridPane.setHalignment(extraInfoTextArea, HPos.LEFT); + GridPane.setMargin(extraInfoTextArea, new Insets(Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0)); + gridPane.getChildren().add(extraInfoTextArea); + } + + private void addNextButtons() { Tuple2 tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, Res.get("shared.nextStep"), Res.get("shared.cancel")); nextButton = (AutoTooltipButton) tuple.first; @@ -1105,16 +1155,26 @@ public abstract class MutableOfferView> exten protected void hideOptionsGroup() { setDepositTitledGroupBg.setVisible(false); setDepositTitledGroupBg.setManaged(false); - nextButton.setVisible(false); - nextButton.setManaged(false); - cancelButton1.setVisible(false); - cancelButton1.setManaged(false); securityDepositAndFeeBox.setVisible(false); securityDepositAndFeeBox.setManaged(false); buyerAsTakerWithoutDepositSlider.setVisible(false); buyerAsTakerWithoutDepositSlider.setManaged(false); } + protected void hideExtraInfoGroup() { + extraInfoTitledGroupBg.setVisible(false); + extraInfoTitledGroupBg.setManaged(false); + extraInfoTextArea.setVisible(false); + extraInfoTextArea.setManaged(false); + } + + protected void hideNextButtons() { + nextButton.setVisible(false); + nextButton.setManaged(false); + cancelButton1.setVisible(false); + cancelButton1.setManaged(false); + } + private VBox getSecurityDepositBox() { Tuple3 tuple = getEditableValueBoxWithInfo( Res.get("createOffer.securityDeposit.prompt")); diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java index d92a0322d2..2907fe8979 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java @@ -144,6 +144,7 @@ public abstract class MutableOfferViewModel ext final StringProperty waitingForFundsText = new SimpleStringProperty(""); final StringProperty triggerPriceDescription = new SimpleStringProperty(""); final StringProperty percentagePriceDescription = new SimpleStringProperty(""); + final StringProperty extraInfo = new SimpleStringProperty(""); final BooleanProperty isPlaceOfferButtonDisabled = new SimpleBooleanProperty(true); final BooleanProperty cancelButtonDisabled = new SimpleBooleanProperty(); @@ -166,6 +167,7 @@ public abstract class MutableOfferViewModel ext private ChangeListener priceStringListener, marketPriceMarginStringListener; private ChangeListener volumeStringListener; private ChangeListener securityDepositStringListener; + private ChangeListener extraInfoStringListener; private ChangeListener amountListener; private ChangeListener minAmountListener; @@ -238,6 +240,7 @@ public abstract class MutableOfferViewModel ext dataModel.calculateTotalToPay(); updateButtonDisableState(); updateSpinnerInfo(); + setExtraInfoToModel(); }, 100, TimeUnit.MILLISECONDS); } @@ -498,6 +501,14 @@ public abstract class MutableOfferViewModel ext updateButtonDisableState(); }; + extraInfoStringListener = (ov, oldValue, newValue) -> { + if (newValue != null) { + extraInfo.set(newValue); + } else { + extraInfo.set(""); + } + }; + isWalletFundedListener = (ov, oldValue, newValue) -> updateButtonDisableState(); /* feeFromFundingTxListener = (ov, oldValue, newValue) -> { updateButtonDisableState(); @@ -542,6 +553,7 @@ public abstract class MutableOfferViewModel ext dataModel.getUseMarketBasedPrice().addListener(useMarketBasedPriceListener); volume.addListener(volumeStringListener); securityDeposit.addListener(securityDepositStringListener); + extraInfo.addListener(extraInfoStringListener); // Binding with Bindings.createObjectBinding does not work because of bi-directional binding dataModel.getAmount().addListener(amountListener); @@ -550,6 +562,7 @@ public abstract class MutableOfferViewModel ext dataModel.getVolume().addListener(volumeListener); dataModel.getSecurityDepositPct().addListener(securityDepositAsDoubleListener); dataModel.getBuyerAsTakerWithoutDeposit().addListener(buyerAsTakerWithoutDepositListener); + dataModel.getExtraInfo().addListener(extraInfoStringListener); // dataModel.feeFromFundingTxProperty.addListener(feeFromFundingTxListener); dataModel.getIsXmrWalletFunded().addListener(isWalletFundedListener); @@ -565,6 +578,7 @@ public abstract class MutableOfferViewModel ext dataModel.getUseMarketBasedPrice().removeListener(useMarketBasedPriceListener); volume.removeListener(volumeStringListener); securityDeposit.removeListener(securityDepositStringListener); + extraInfo.removeListener(extraInfoStringListener); // Binding with Bindings.createObjectBinding does not work because of bi-directional binding dataModel.getAmount().removeListener(amountListener); @@ -827,6 +841,12 @@ public abstract class MutableOfferViewModel ext } } + public void onFocusOutExtraInfoTextField(boolean oldValue, boolean newValue) { + if (oldValue && !newValue) { + dataModel.setExtraInfo(extraInfo.get()); + } + } + void onFocusOutTriggerPriceTextField(boolean oldValue, boolean newValue) { if (oldValue && !newValue) { onTriggerPriceTextFieldChanged(); @@ -1233,6 +1253,14 @@ public abstract class MutableOfferViewModel ext } } + private void setExtraInfoToModel() { + if (extraInfo.get() != null && !extraInfo.get().isEmpty()) { + dataModel.setExtraInfo(extraInfo.get()); + } else { + dataModel.setExtraInfo(null); + } + } + private void validateAndSetSecurityDepositToModel() { // If the security deposit in the model is not valid percent String value = FormattingUtils.formatToPercent(dataModel.getSecurityDepositPct().get()); diff --git a/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java index 967e29b6e3..d82b854d2f 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -483,8 +483,6 @@ abstract class OfferBookViewModel extends ActivatableViewModel { if (countryCode != null) { result += "\n" + Res.get("payment.f2f.offerbook.tooltip.countryAndCity", CountryUtil.getNameByCode(countryCode), offer.getF2FCity()); - - result += "\n" + Res.get("payment.f2f.offerbook.tooltip.extra", offer.getExtraInfo()); } } else { if (countryCode != null) { @@ -514,6 +512,8 @@ abstract class OfferBookViewModel extends ActivatableViewModel { result += "\n" + Res.getWithCol("shared.acceptedBanks") + " " + Joiner.on(", ").join(acceptedBanks); } } + if (offer.getCombinedExtraInfo() != null && !offer.getCombinedExtraInfo().isEmpty()) + result += "\n" + Res.get("payment.shared.extraInfo.tooltip", offer.getCombinedExtraInfo()); } return result; } diff --git a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java index e0385bb5b3..dc11216f53 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java @@ -69,6 +69,7 @@ import static haveno.desktop.util.FormBuilder.add2ButtonsWithBox; import static haveno.desktop.util.FormBuilder.addAddressTextField; import static haveno.desktop.util.FormBuilder.addBalanceTextField; import static haveno.desktop.util.FormBuilder.addComboBoxTopLabelTextField; +import static haveno.desktop.util.FormBuilder.addCompactTopLabelTextArea; import static haveno.desktop.util.FormBuilder.addFundsTextfield; import static haveno.desktop.util.FormBuilder.addTitledGroupBg; import static haveno.desktop.util.FormBuilder.getEditableValueBox; @@ -98,6 +99,7 @@ import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.Separator; +import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.control.Tooltip; import javafx.scene.image.Image; @@ -125,6 +127,7 @@ public class TakeOfferView extends ActivatableViewAndModel paymentAccountsComboBox; + private TextArea extraInfoTextArea; private Label amountDescriptionLabel, paymentMethodLabel, priceCurrencyLabel, priceAsPercentageLabel, @@ -160,7 +164,7 @@ public class TakeOfferView extends ActivatableViewAndModel paymentAccountWarningDisplayed = new HashMap<>(); - private boolean offerDetailsWindowDisplayed, zelleWarningDisplayed, fasterPaymentsWarningDisplayed, + private boolean offerDetailsWindowDisplayed, extraInfoPopupDisplayed, zelleWarningDisplayed, fasterPaymentsWarningDisplayed, takeOfferFromUnsignedAccountWarningDisplayed, payByMailWarningDisplayed, cashAtAtmWarningDisplayed, australiaPayidWarningDisplayed, paypalWarningDisplayed, cashAppWarningDisplayed, F2FWarningDisplayed; private SimpleBooleanProperty errorPopupDisplayed; @@ -267,16 +271,11 @@ public class TakeOfferView extends ActivatableViewAndModel close(false)) .show(); + + if (offer.hasBuyerAsTakerWithoutDeposit() && offer.getCombinedExtraInfo() != null && !offer.getCombinedExtraInfo().isEmpty()) { + + // attach extra info text area + extraInfoTextArea = addCompactTopLabelTextArea(gridPane, ++lastGridRowNoFundingRequired, Res.get("payment.shared.extraInfo.noDeposit"), "").second; + extraInfoTextArea.setText(offer.getCombinedExtraInfo()); + extraInfoTextArea.getStyleClass().add("text-area"); + extraInfoTextArea.setWrapText(true); + extraInfoTextArea.setPrefHeight(75); + extraInfoTextArea.setMinHeight(75); + extraInfoTextArea.setMaxHeight(150); + extraInfoTextArea.setEditable(false); + GridPane.setRowIndex(extraInfoTextArea, lastGridRowNoFundingRequired); + GridPane.setColumnSpan(extraInfoTextArea, GridPane.REMAINING); + GridPane.setColumnIndex(extraInfoTextArea, 0); + + // move up take offer buttons + GridPane.setRowIndex(takeOfferBox, lastGridRowNoFundingRequired + 1); + GridPane.setMargin(takeOfferBox, new Insets(15, 0, 0, 0)); + } } @Override @@ -871,6 +890,7 @@ public class TakeOfferView extends ActivatableViewAndModel { + new GenericMessageWindow() + .preamble(Res.get("payment.tradingRestrictions")) + .instruction(offer.getCombinedExtraInfo()) + .actionButtonText(Res.get("shared.iConfirm")) + .closeButtonText(Res.get("shared.close")) + .width(Layout.INITIAL_WINDOW_WIDTH) + .onClose(() -> close(false)) + .show(); + }, 500, TimeUnit.MILLISECONDS); + } + } private void maybeShowTakeOfferFromUnsignedAccountWarning(Offer offer) { // warn if you are selling BTC to unsigned account (#5343) @@ -1151,108 +1186,6 @@ public class TakeOfferView extends ActivatableViewAndModel { - new GenericMessageWindow() - .preamble(Res.get("payment.tradingRestrictions")) - .instruction(offer.getExtraInfo()) - .actionButtonText(Res.get("shared.iConfirm")) - .closeButtonText(Res.get("shared.close")) - .width(Layout.INITIAL_WINDOW_WIDTH) - .onClose(() -> close(false)) - .show(); - }, 500, TimeUnit.MILLISECONDS); - } - } - - private void maybeShowCashAtAtmWarning(PaymentAccount paymentAccount, Offer offer) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.CASH_AT_ATM_ID) && - !cashAtAtmWarningDisplayed && !offer.getExtraInfo().isEmpty()) { - cashAtAtmWarningDisplayed = true; - UserThread.runAfter(() -> { - new GenericMessageWindow() - .preamble(Res.get("payment.tradingRestrictions")) - .instruction(offer.getExtraInfo()) - .actionButtonText(Res.get("shared.iConfirm")) - .closeButtonText(Res.get("shared.close")) - .width(Layout.INITIAL_WINDOW_WIDTH) - .onClose(() -> close(false)) - .show(); - }, 500, TimeUnit.MILLISECONDS); - } - } - - private void maybeShowAustraliaPayidWarning(PaymentAccount paymentAccount, Offer offer) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.AUSTRALIA_PAYID_ID) && - !australiaPayidWarningDisplayed && !offer.getExtraInfo().isEmpty()) { - australiaPayidWarningDisplayed = true; - UserThread.runAfter(() -> { - new GenericMessageWindow() - .preamble(Res.get("payment.tradingRestrictions")) - .instruction(offer.getExtraInfo()) - .actionButtonText(Res.get("shared.iConfirm")) - .closeButtonText(Res.get("shared.close")) - .width(Layout.INITIAL_WINDOW_WIDTH) - .onClose(() -> close(false)) - .show(); - }, 500, TimeUnit.MILLISECONDS); - } - } - - private void maybeShowPayPalWarning(PaymentAccount paymentAccount, Offer offer) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.PAYPAL_ID) && - !paypalWarningDisplayed && !offer.getExtraInfo().isEmpty()) { - paypalWarningDisplayed = true; - UserThread.runAfter(() -> { - new GenericMessageWindow() - .preamble(Res.get("payment.tradingRestrictions")) - .instruction(offer.getExtraInfo()) - .actionButtonText(Res.get("shared.iConfirm")) - .closeButtonText(Res.get("shared.close")) - .width(Layout.INITIAL_WINDOW_WIDTH) - .onClose(() -> close(false)) - .show(); - }, 500, TimeUnit.MILLISECONDS); - } - } - - private void maybeShowCashAppWarning(PaymentAccount paymentAccount, Offer offer) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.CASH_APP_ID) && - !cashAppWarningDisplayed && !offer.getExtraInfo().isEmpty()) { - cashAppWarningDisplayed = true; - UserThread.runAfter(() -> { - new GenericMessageWindow() - .preamble(Res.get("payment.tradingRestrictions")) - .instruction(offer.getExtraInfo()) - .actionButtonText(Res.get("shared.iConfirm")) - .closeButtonText(Res.get("shared.close")) - .width(Layout.INITIAL_WINDOW_WIDTH) - .onClose(() -> close(false)) - .show(); - }, 500, TimeUnit.MILLISECONDS); - } - } - - private void maybeShowF2FWarning(PaymentAccount paymentAccount, Offer offer) { - if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.F2F_ID) && - !F2FWarningDisplayed && !offer.getExtraInfo().isEmpty()) { - F2FWarningDisplayed = true; - UserThread.runAfter(() -> { - new GenericMessageWindow() - .preamble(Res.get("payment.tradingRestrictions")) - .instruction(offer.getExtraInfo()) - .actionButtonText(Res.get("shared.iConfirm")) - .closeButtonText(Res.get("shared.close")) - .width(Layout.INITIAL_WINDOW_WIDTH) - .onClose(() -> close(false)) - .show(); - }, 500, TimeUnit.MILLISECONDS); - } - } - private Tuple2 getTradeInputBox(HBox amountValueBox, String promptText) { Label descriptionLabel = new AutoTooltipLabel(promptText); descriptionLabel.setId("input-description-label"); diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/windows/OfferDetailsWindow.java b/desktop/src/main/java/haveno/desktop/main/overlays/windows/OfferDetailsWindow.java index 7732b7b70d..3ef8ca521b 100644 --- a/desktop/src/main/java/haveno/desktop/main/overlays/windows/OfferDetailsWindow.java +++ b/desktop/src/main/java/haveno/desktop/main/overlays/windows/OfferDetailsWindow.java @@ -177,19 +177,14 @@ public class OfferDetailsWindow extends Overlay { List acceptedCountryCodes = offer.getAcceptedCountryCodes(); boolean showAcceptedCountryCodes = acceptedCountryCodes != null && !acceptedCountryCodes.isEmpty(); boolean isF2F = offer.getPaymentMethod().equals(PaymentMethod.F2F); - boolean showExtraInfo = offer.getPaymentMethod().equals(PaymentMethod.F2F) || - offer.getPaymentMethod().equals(PaymentMethod.PAY_BY_MAIL) || - offer.getPaymentMethod().equals(PaymentMethod.AUSTRALIA_PAYID)|| - offer.getPaymentMethod().equals(PaymentMethod.PAYPAL)|| - offer.getPaymentMethod().equals(PaymentMethod.CASH_APP) || - offer.getPaymentMethod().equals(PaymentMethod.CASH_AT_ATM); + boolean showOfferExtraInfo = offer.getCombinedExtraInfo() != null && !offer.getCombinedExtraInfo().isEmpty(); if (!takeOfferHandlerOptional.isPresent()) rows++; if (showAcceptedBanks) rows++; if (showAcceptedCountryCodes) rows++; - if (showExtraInfo) + if (showOfferExtraInfo) rows++; if (isF2F) rows++; @@ -320,9 +315,9 @@ public class OfferDetailsWindow extends Overlay { if (isF2F) { addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("payment.f2f.city"), offer.getF2FCity()); } - if (showExtraInfo) { + if (showOfferExtraInfo) { TextArea textArea = addConfirmationLabelTextArea(gridPane, ++rowIndex, Res.get("payment.shared.extraInfo"), "", 0).second; - textArea.setText(offer.getExtraInfo()); + textArea.setText(offer.getCombinedExtraInfo()); textArea.setMaxHeight(200); textArea.sceneProperty().addListener((o, oldScene, newScene) -> { if (newScene != null) { diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/haveno/desktop/main/overlays/windows/TradeDetailsWindow.java index 0e3397ca54..004cc0a3f5 100644 --- a/desktop/src/main/java/haveno/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/haveno/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -38,6 +38,7 @@ import haveno.core.xmr.wallet.BtcWalletService; import haveno.desktop.components.HavenoTextArea; import haveno.desktop.main.MainView; import haveno.desktop.main.overlays.Overlay; +import haveno.desktop.util.CssTheme; import haveno.desktop.util.DisplayUtils; import static haveno.desktop.util.DisplayUtils.getAccountWitnessDescription; import static haveno.desktop.util.FormBuilder.add2ButtonsWithBox; @@ -47,6 +48,8 @@ import static haveno.desktop.util.FormBuilder.addLabelTxIdTextField; import static haveno.desktop.util.FormBuilder.addTitledGroupBg; import haveno.desktop.util.Layout; import haveno.network.p2p.NodeAddress; +import javafx.application.Platform; +import javafx.beans.binding.Bindings; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.value.ChangeListener; @@ -165,9 +168,12 @@ public class TradeDetailsWindow extends Overlay { // second group rows = 7; + + if (offer.getCombinedExtraInfo() != null && !offer.getCombinedExtraInfo().isEmpty()) + rows++; + PaymentAccountPayload buyerPaymentAccountPayload = null; PaymentAccountPayload sellerPaymentAccountPayload = null; - if (contract != null) { rows++; @@ -219,6 +225,29 @@ public class TradeDetailsWindow extends Overlay { addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradePeersOnion"), trade.getTradePeerNodeAddress().getFullAddress()); + if (offer.getCombinedExtraInfo() != null && !offer.getCombinedExtraInfo().isEmpty()) { + TextArea textArea = addConfirmationLabelTextArea(gridPane, ++rowIndex, Res.get("payment.shared.extraInfo.offer"), "", 0).second; + textArea.setText(offer.getCombinedExtraInfo()); + textArea.setMaxHeight(200); + textArea.sceneProperty().addListener((o, oldScene, newScene) -> { + if (newScene != null) { + // avoid javafx css warning + CssTheme.loadSceneStyles(newScene, CssTheme.CSS_THEME_LIGHT, false); + textArea.applyCss(); + var text = textArea.lookup(".text"); + + textArea.prefHeightProperty().bind(Bindings.createDoubleBinding(() -> { + return textArea.getFont().getSize() + text.getBoundsInLocal().getHeight(); + }, text.boundsInLocalProperty())); + + text.boundsInLocalProperty().addListener((observableBoundsAfter, boundsBefore, boundsAfter) -> { + Platform.runLater(() -> textArea.requestLayout()); + }); + } + }); + textArea.setEditable(false); + } + if (contract != null) { buyersAccountAge = getAccountWitnessDescription(accountAgeWitnessService, offer.getPaymentMethod(), buyerPaymentAccountPayload, contract.getBuyerPubKeyRing()); sellersAccountAge = getAccountWitnessDescription(accountAgeWitnessService, offer.getPaymentMethod(), sellerPaymentAccountPayload, contract.getSellerPubKeyRing()); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferDataModel.java index d7ab366b75..b9cd38efb5 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferDataModel.java @@ -166,6 +166,7 @@ class EditOfferDataModel extends MutableOfferDataModel { if (offer.isUseMarketBasedPrice()) { setMarketPriceMarginPct(offer.getMarketPriceMarginPct()); } + setExtraInfo(offer.getOfferExtraInfo()); } public void onStartEditOffer(ErrorMessageHandler errorMessageHandler) { @@ -216,7 +217,8 @@ class EditOfferDataModel extends MutableOfferDataModel { offerPayload.getProtocolVersion(), offerPayload.getArbitratorSigner(), offerPayload.getArbitratorSignature(), - offerPayload.getReserveTxKeyImages()); + offerPayload.getReserveTxKeyImages(), + newOfferPayload.getExtraInfo()); final Offer editedOffer = new Offer(editedPayload); editedOffer.setPriceFeedService(priceFeedService); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferView.java b/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferView.java index 60aa3c4dec..3752ab9dcb 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferView.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/editoffer/EditOfferView.java @@ -90,6 +90,7 @@ public class EditOfferView extends MutableOfferView { addBindings(); hideOptionsGroup(); + hideNextButtons(); // Lock amount field as it would require bigger changes to support increased amount values. amountTextField.setDisable(true); @@ -178,7 +179,7 @@ public class EditOfferView extends MutableOfferView { private void addConfirmEditGroup() { - int tmpGridRow = 4; + int tmpGridRow = 6; final Tuple4 editOfferTuple = addButtonBusyAnimationLabelAfterGroup(gridPane, tmpGridRow++, Res.get("editOffer.confirmEdit")); final HBox editOfferConfirmationBox = editOfferTuple.fourth; diff --git a/desktop/src/test/java/haveno/desktop/main/market/trades/TradesChartsViewModelTest.java b/desktop/src/test/java/haveno/desktop/main/market/trades/TradesChartsViewModelTest.java index 19c2359245..971c15bff9 100644 --- a/desktop/src/test/java/haveno/desktop/main/market/trades/TradesChartsViewModelTest.java +++ b/desktop/src/test/java/haveno/desktop/main/market/trades/TradesChartsViewModelTest.java @@ -94,6 +94,7 @@ public class TradesChartsViewModelTest { 0, null, null, + null, null); @BeforeEach diff --git a/desktop/src/test/java/haveno/desktop/main/offer/offerbook/OfferBookViewModelTest.java b/desktop/src/test/java/haveno/desktop/main/offer/offerbook/OfferBookViewModelTest.java index 3b648533c0..b7cc852ee1 100644 --- a/desktop/src/test/java/haveno/desktop/main/offer/offerbook/OfferBookViewModelTest.java +++ b/desktop/src/test/java/haveno/desktop/main/offer/offerbook/OfferBookViewModelTest.java @@ -632,6 +632,7 @@ public class OfferBookViewModelTest { 0, null, null, + null, null)); } } diff --git a/desktop/src/test/java/haveno/desktop/maker/OfferMaker.java b/desktop/src/test/java/haveno/desktop/maker/OfferMaker.java index ae6f73ac52..2496dbdbbd 100644 --- a/desktop/src/test/java/haveno/desktop/maker/OfferMaker.java +++ b/desktop/src/test/java/haveno/desktop/maker/OfferMaker.java @@ -111,6 +111,7 @@ public class OfferMaker { lookup.valueOf(protocolVersion, 0), getLocalHostNodeWithPort(99999), null, + null, null)); public static final Maker xmrUsdOffer = a(Offer); diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index f99a0feae5..75ad4a0658 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -527,6 +527,7 @@ message PostOfferRequest { string payment_account_id = 11; bool is_private_offer = 12; bool buyer_as_taker_without_deposit = 13; + string extra_info = 14; } message PostOfferReply { @@ -574,6 +575,7 @@ message OfferInfo { uint64 split_output_tx_fee = 31 [jstype = JS_STRING]; bool is_private_offer = 32; string challenge = 33; + string extra_info = 34; } message AvailabilityResultWithDescription { diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index b52274ae57..18962d0c56 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -657,6 +657,7 @@ message OfferPayload { NodeAddress arbitrator_signer = 36; bytes arbitrator_signature = 37; repeated string reserve_tx_key_images = 38; + string extra_info = 39; } enum OfferDirection {