mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-02-26 17:31:27 -05:00
support additional info on all offers
This commit is contained in:
parent
a6af1550a4
commit
6c6c6e2dd5
@ -425,6 +425,7 @@ public class CoreApi {
|
||||
String paymentAccountId,
|
||||
boolean isPrivateOffer,
|
||||
boolean buyerAsTakerWithoutDeposit,
|
||||
String extraInfo,
|
||||
Consumer<Offer> 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) {
|
||||
|
@ -178,6 +178,7 @@ public class CoreOffersService {
|
||||
String paymentAccountId,
|
||||
boolean isPrivateOffer,
|
||||
boolean buyerAsTakerWithoutDeposit,
|
||||
String extraInfo,
|
||||
Consumer<Offer> 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) {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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<String> reserveTxKeyImages) {
|
||||
@Nullable List<String> 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<String> reserveTxKeyImages = proto.getReserveTxKeyImagesList().isEmpty() ?
|
||||
null : new ArrayList<>(proto.getReserveTxKeyImagesList());
|
||||
String challengeHash = ProtoUtil.stringOrNullFromProto(proto.getChallengeHash());
|
||||
Map<String, String> 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<OfferPayload> {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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=支店
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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=分行
|
||||
|
@ -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=分行
|
||||
|
@ -73,7 +73,8 @@ public class OfferMaker {
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
null,
|
||||
"My extra info"));
|
||||
|
||||
public static final Maker<Offer> btcUsdOffer = a(Offer);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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) -> {
|
||||
|
@ -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) -> {
|
||||
|
@ -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);
|
||||
|
@ -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) -> {
|
||||
|
@ -105,6 +105,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
|
||||
protected final ObjectProperty<Price> price = new SimpleObjectProperty<>();
|
||||
protected final ObjectProperty<Volume> volume = new SimpleObjectProperty<>();
|
||||
protected final ObjectProperty<Volume> minVolume = new SimpleObjectProperty<>();
|
||||
protected final ObjectProperty<String> 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<String> getExtraInfo() {
|
||||
return extraInfo;
|
||||
}
|
||||
}
|
||||
|
@ -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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> exten
|
||||
private ChangeListener<Boolean> amountFocusedListener, minAmountFocusedListener, volumeFocusedListener,
|
||||
securityDepositFocusedListener, priceFocusedListener, placeOfferCompletedListener,
|
||||
priceAsPercentageFocusedListener, getShowWalletFundedNotificationListener,
|
||||
isMinSecurityDepositListener, buyerAsTakerWithoutDepositListener, triggerPriceFocusedListener;
|
||||
isMinSecurityDepositListener, buyerAsTakerWithoutDepositListener, triggerPriceFocusedListener, extraInfoFocusedListener;
|
||||
private ChangeListener<BigInteger> missingCoinListener;
|
||||
private ChangeListener<String> tradeCurrencyCodeListener, errorMessageListener,
|
||||
marketPriceMarginListener, volumeListener, securityDepositInXMRListener;
|
||||
marketPriceMarginListener, volumeListener, securityDepositInXMRListener, extraInfoListener;
|
||||
private ChangeListener<Number> marketPriceAvailableListener;
|
||||
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler, paymentAccountsComboBoxSelectionHandler;
|
||||
private OfferView.CloseHandler closeHandler;
|
||||
@ -202,6 +205,8 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
|
||||
addPaymentGroup();
|
||||
addAmountPriceGroup();
|
||||
addOptionsGroup();
|
||||
addExtraInfoGroup();
|
||||
addNextButtons();
|
||||
addFundingGroup();
|
||||
|
||||
createListeners();
|
||||
@ -257,6 +262,8 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> 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<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++gridRow,
|
||||
Res.get("shared.nextStep"), Res.get("shared.cancel"));
|
||||
nextButton = (AutoTooltipButton) tuple.first;
|
||||
@ -1105,16 +1155,26 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> 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<HBox, InfoInputTextField, Label> tuple = getEditableValueBoxWithInfo(
|
||||
Res.get("createOffer.securityDeposit.prompt"));
|
||||
|
@ -144,6 +144,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> 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<M extends MutableOfferDataModel> ext
|
||||
private ChangeListener<String> priceStringListener, marketPriceMarginStringListener;
|
||||
private ChangeListener<String> volumeStringListener;
|
||||
private ChangeListener<String> securityDepositStringListener;
|
||||
private ChangeListener<String> extraInfoStringListener;
|
||||
|
||||
private ChangeListener<BigInteger> amountListener;
|
||||
private ChangeListener<BigInteger> minAmountListener;
|
||||
@ -238,6 +240,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
dataModel.calculateTotalToPay();
|
||||
updateButtonDisableState();
|
||||
updateSpinnerInfo();
|
||||
setExtraInfoToModel();
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@ -498,6 +501,14 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> 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<M extends MutableOfferDataModel> 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<M extends MutableOfferDataModel> 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<M extends MutableOfferDataModel> 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<M extends MutableOfferDataModel> 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<M extends MutableOfferDataModel> 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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<AnchorPane, TakeOffer
|
||||
private GridPane gridPane;
|
||||
private TitledGroupBg noFundingRequiredTitledGroupBg;
|
||||
private Label noFundingRequiredLabel;
|
||||
private int lastGridRowNoFundingRequired;
|
||||
private TitledGroupBg payFundsTitledGroupBg;
|
||||
private TitledGroupBg advancedOptionsGroup;
|
||||
private VBox priceAsPercentageInputBox, amountRangeBox;
|
||||
@ -132,6 +135,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
priceAsPercentageValueCurrencyBox, minAmountValueCurrencyBox, advancedOptionsBox,
|
||||
takeOfferBox, buttonBox, firstRowHBox;
|
||||
private ComboBox<PaymentAccount> paymentAccountsComboBox;
|
||||
private TextArea extraInfoTextArea;
|
||||
private Label amountDescriptionLabel,
|
||||
paymentMethodLabel,
|
||||
priceCurrencyLabel, priceAsPercentageLabel,
|
||||
@ -160,7 +164,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
|
||||
private int gridRow = 0;
|
||||
private final HashMap<String, Boolean> 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<AnchorPane, TakeOffer
|
||||
|
||||
balanceTextField.setTargetAmount(model.dataModel.getTotalToPay().get());
|
||||
|
||||
maybeShowExtraInfoPopup(model.dataModel.getOffer());
|
||||
maybeShowTakeOfferFromUnsignedAccountWarning(model.dataModel.getOffer());
|
||||
maybeShowZelleWarning(lastPaymentAccount);
|
||||
maybeShowFasterPaymentsWarning(lastPaymentAccount);
|
||||
maybeShowAccountWarning(lastPaymentAccount, model.dataModel.isBuyOffer());
|
||||
maybeShowPayByMailWarning(lastPaymentAccount, model.dataModel.getOffer());
|
||||
maybeShowCashAtAtmWarning(lastPaymentAccount, model.dataModel.getOffer());
|
||||
maybeShowAustraliaPayidWarning(lastPaymentAccount, model.dataModel.getOffer());
|
||||
maybeShowPayPalWarning(lastPaymentAccount, model.dataModel.getOffer());
|
||||
maybeShowCashAppWarning(lastPaymentAccount, model.dataModel.getOffer());
|
||||
maybeShowF2FWarning(lastPaymentAccount, model.dataModel.getOffer());
|
||||
|
||||
if (!model.isRange()) {
|
||||
nextButton.setVisible(false);
|
||||
@ -358,6 +357,26 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
new Popup().warning(Res.get("takeOffer.noPriceFeedAvailable"))
|
||||
.onClose(() -> 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<AnchorPane, TakeOffer
|
||||
noFundingRequiredLabel.setPadding(new Insets(Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0));
|
||||
GridPane.setHalignment(noFundingRequiredLabel, HPos.LEFT);
|
||||
gridPane.getChildren().add(noFundingRequiredLabel);
|
||||
lastGridRowNoFundingRequired = gridRow;
|
||||
|
||||
// funding title
|
||||
payFundsTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 3,
|
||||
@ -1121,6 +1141,21 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void maybeShowExtraInfoPopup(Offer offer) {
|
||||
if (offer.getCombinedExtraInfo() != null && !offer.getCombinedExtraInfo().isEmpty() && !extraInfoPopupDisplayed) {
|
||||
extraInfoPopupDisplayed = true;
|
||||
UserThread.runAfter(() -> {
|
||||
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<AnchorPane, TakeOffer
|
||||
OfferViewUtil.showPaymentAccountWarning(msgKey, paymentAccountWarningDisplayed);
|
||||
}
|
||||
|
||||
private void maybeShowPayByMailWarning(PaymentAccount paymentAccount, Offer offer) {
|
||||
if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.PAY_BY_MAIL_ID) &&
|
||||
!payByMailWarningDisplayed && !offer.getExtraInfo().isEmpty()) {
|
||||
payByMailWarningDisplayed = 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 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<Label, VBox> getTradeInputBox(HBox amountValueBox, String promptText) {
|
||||
Label descriptionLabel = new AutoTooltipLabel(promptText);
|
||||
descriptionLabel.setId("input-description-label");
|
||||
|
@ -177,19 +177,14 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||
List<String> 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<OfferDetailsWindow> {
|
||||
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) {
|
||||
|
@ -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<TradeDetailsWindow> {
|
||||
|
||||
// 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<TradeDetailsWindow> {
|
||||
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());
|
||||
|
@ -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);
|
||||
|
@ -90,6 +90,7 @@ public class EditOfferView extends MutableOfferView<EditOfferViewModel> {
|
||||
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<EditOfferViewModel> {
|
||||
|
||||
private void addConfirmEditGroup() {
|
||||
|
||||
int tmpGridRow = 4;
|
||||
int tmpGridRow = 6;
|
||||
final Tuple4<Button, BusyAnimation, Label, HBox> editOfferTuple = addButtonBusyAnimationLabelAfterGroup(gridPane, tmpGridRow++, Res.get("editOffer.confirmEdit"));
|
||||
|
||||
final HBox editOfferConfirmationBox = editOfferTuple.fourth;
|
||||
|
@ -94,6 +94,7 @@ public class TradesChartsViewModelTest {
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
@BeforeEach
|
||||
|
@ -632,6 +632,7 @@ public class OfferBookViewModelTest {
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ public class OfferMaker {
|
||||
lookup.valueOf(protocolVersion, 0),
|
||||
getLocalHostNodeWithPort(99999),
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
|
||||
public static final Maker<Offer> xmrUsdOffer = a(Offer);
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user