Skip to content

Commit

Permalink
Merge branch 'haveno-dex:master' into haveno-reto
Browse files Browse the repository at this point in the history
  • Loading branch information
boldsuck authored Feb 5, 2025
2 parents 07d1e51 + 728cf22 commit 7282c21
Show file tree
Hide file tree
Showing 28 changed files with 416 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ public enum FormId {
AUSTRALIA_PAYID,
CASH_APP,
PAYPAL,
VENMO;
VENMO,
PAYSAFE;

public static PaymentAccountForm.FormId fromProto(protobuf.PaymentAccountForm.FormId formId) {
return ProtoUtil.enumFromProto(PaymentAccountForm.FormId.class, formId.name());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new CashAppAccount();
case PaymentMethod.VENMO_ID:
return new VenmoAccount();
case PaymentMethod.PAYSAFE_ID:
return new PaysafeAccount();

// Cannot be deleted as it would break old trade history entries
case PaymentMethod.OK_PAY_ID:
Expand Down
112 changes: 112 additions & 0 deletions core/src/main/java/haveno/core/payment/PaysafeAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* This file is part of Haveno.
*
* Haveno is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Haveno is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/

package haveno.core.payment;

import haveno.core.api.model.PaymentAccountFormField;
import haveno.core.locale.TraditionalCurrency;
import haveno.core.locale.TradeCurrency;
import haveno.core.payment.payload.PaymentAccountPayload;
import haveno.core.payment.payload.PaymentMethod;
import haveno.core.payment.payload.PaysafeAccountPayload;
import lombok.EqualsAndHashCode;
import org.jetbrains.annotations.NotNull;

import java.util.List;

@EqualsAndHashCode(callSuper = true)
public final class PaysafeAccount extends PaymentAccount {

private static final List<PaymentAccountFormField.FieldId> INPUT_FIELD_IDS = List.of(
PaymentAccountFormField.FieldId.ACCOUNT_NAME,
PaymentAccountFormField.FieldId.EMAIL,
PaymentAccountFormField.FieldId.TRADE_CURRENCIES,
PaymentAccountFormField.FieldId.SALT
);

// https://developer.paysafe.com/en/support/reference-information/codes/
public static final List<TradeCurrency> SUPPORTED_CURRENCIES = List.of(
new TraditionalCurrency("AED"),
new TraditionalCurrency("ARS"),
new TraditionalCurrency("AUD"),
new TraditionalCurrency("BGN"),
new TraditionalCurrency("BRL"),
new TraditionalCurrency("CAD"),
new TraditionalCurrency("CHF"),
new TraditionalCurrency("CZK"),
new TraditionalCurrency("DKK"),
new TraditionalCurrency("EGP"),
new TraditionalCurrency("EUR"),
new TraditionalCurrency("GBP"),
new TraditionalCurrency("GEL"),
new TraditionalCurrency("HUF"),
new TraditionalCurrency("ILS"),
new TraditionalCurrency("INR"),
new TraditionalCurrency("JPY"),
new TraditionalCurrency("ISK"),
new TraditionalCurrency("KWD"),
new TraditionalCurrency("KRW"),
new TraditionalCurrency("MXN"),
new TraditionalCurrency("NOK"),
new TraditionalCurrency("NZD"),
new TraditionalCurrency("PEN"),
new TraditionalCurrency("PHP"),
new TraditionalCurrency("PLN"),
new TraditionalCurrency("RON"),
new TraditionalCurrency("RSD"),
new TraditionalCurrency("RUB"),
new TraditionalCurrency("SAR"),
new TraditionalCurrency("SEK"),
new TraditionalCurrency("TRY"),
new TraditionalCurrency("USD"),
new TraditionalCurrency("UYU")
);

public PaysafeAccount() {
super(PaymentMethod.PAYSAFE);
}

@Override
protected PaymentAccountPayload createPayload() {
return new PaysafeAccountPayload(paymentMethod.getId(), id);
}

@Override
public @NotNull List<TradeCurrency> getSupportedCurrencies() {
return SUPPORTED_CURRENCIES;
}

@Override
public @NotNull List<PaymentAccountFormField.FieldId> getInputFieldIds() {
return INPUT_FIELD_IDS;
}

public void setEmail(String accountId) {
((PaysafeAccountPayload) paymentAccountPayload).setEmail(accountId);
}

public String getEmail() {
return ((PaysafeAccountPayload) paymentAccountPayload).getEmail();
}

@Override
protected PaymentAccountFormField getEmptyFormField(PaymentAccountFormField.FieldId fieldId) {
var field = super.getEmptyFormField(fieldId);
if (field.getId() == PaymentAccountFormField.FieldId.TRADE_CURRENCIES) field.setValue("");
return field;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import haveno.core.payment.CashAtAtmAccount;
import haveno.core.payment.PayByMailAccount;
import haveno.core.payment.PayPalAccount;
import haveno.core.payment.PaysafeAccount;
import haveno.core.payment.CashDepositAccount;
import haveno.core.payment.CelPayAccount;
import haveno.core.payment.ZelleAccount;
Expand Down Expand Up @@ -193,6 +194,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static final String CASH_APP_ID = "CASH_APP";
public static final String VENMO_ID = "VENMO";
public static final String PAYPAL_ID = "PAYPAL";
public static final String PAYSAFE_ID = "PAYSAFE";

public static PaymentMethod UPHOLD;
public static PaymentMethod MONEY_BEAM;
Expand Down Expand Up @@ -252,6 +254,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static PaymentMethod PAYPAL;
public static PaymentMethod CASH_APP;
public static PaymentMethod VENMO;
public static PaymentMethod PAYSAFE;

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -322,6 +325,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
DOMESTIC_WIRE_TRANSFER = new PaymentMethod(DOMESTIC_WIRE_TRANSFER_ID, 3 * DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(DomesticWireTransferAccount.SUPPORTED_CURRENCIES)),
PAYPAL = new PaymentMethod(PAYPAL_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(PayPalAccount.SUPPORTED_CURRENCIES)),
CASH_APP = new PaymentMethod(CASH_APP_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(CashAppAccount.SUPPORTED_CURRENCIES)),
PAYSAFE = new PaymentMethod(PaymentMethod.PAYSAFE_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(PaysafeAccount.SUPPORTED_CURRENCIES)),

// Japan
JAPAN_BANK = new PaymentMethod(JAPAN_BANK_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK, getAssetCodes(JapanBankAccount.SUPPORTED_CURRENCIES)),
Expand Down Expand Up @@ -364,7 +368,8 @@ public static List<PaymentMethod> getPaymentMethods() {
AUSTRALIA_PAYID_ID,
CASH_APP_ID,
PAYPAL_ID,
VENMO_ID);
VENMO_ID,
PAYSAFE_ID);
return paymentMethods.stream().filter(paymentMethod -> paymentMethodIds.contains(paymentMethod.getId())).collect(Collectors.toList());
}

Expand Down Expand Up @@ -588,7 +593,8 @@ public static boolean hasChargebackRisk(String id, String currencyCode) {
id.equals(PaymentMethod.UPHOLD_ID) ||
id.equals(PaymentMethod.CASH_APP_ID) ||
id.equals(PaymentMethod.PAYPAL_ID) ||
id.equals(PaymentMethod.VENMO_ID);
id.equals(PaymentMethod.VENMO_ID) ||
id.equals(PaymentMethod.PAYSAFE_ID);
}

public static boolean isRoundedForAtmCash(String id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* This file is part of Haveno.
*
* Haveno is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Haveno is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/

package haveno.core.payment.payload;

import com.google.protobuf.Message;
import haveno.core.locale.Res;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@EqualsAndHashCode(callSuper = true)
@ToString
@Setter
@Getter
@Slf4j
public final class PaysafeAccountPayload extends PaymentAccountPayload {
private String email = "";

public PaysafeAccountPayload(String paymentMethod, String id) {
super(paymentMethod, id);
}


///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////

private PaysafeAccountPayload(String paymentMethod,
String id,
String email,
long maxTradePeriod,
Map<String, String> excludeFromJsonDataMap) {
super(paymentMethod,
id,
maxTradePeriod,
excludeFromJsonDataMap);

this.email = email;
}

@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
.setPaysafeAccountPayload(protobuf.PaysafeAccountPayload.newBuilder().setEmail(email))
.build();
}

public static PaysafeAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new PaysafeAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getPaysafeAccountPayload().getEmail(),
proto.getMaxTradePeriod(),
new HashMap<>(proto.getExcludeFromJsonDataMap()));
}


///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////

@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.email") + " " + email;
}

@Override
public String getPaymentDetailsForTradePopup() {
return getPaymentDetails();
}

@Override
public byte[] getAgeWitnessInputData() {
return super.getAgeWitnessInputData(email.getBytes(StandardCharsets.UTF_8));
}
}
3 changes: 3 additions & 0 deletions core/src/main/java/haveno/core/proto/CoreProtoResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import haveno.core.payment.payload.OKPayAccountPayload;
import haveno.core.payment.payload.PaxumAccountPayload;
import haveno.core.payment.payload.PaymentAccountPayload;
import haveno.core.payment.payload.PaysafeAccountPayload;
import haveno.core.payment.payload.PayPalAccountPayload;
import haveno.core.payment.payload.PayseraAccountPayload;
import haveno.core.payment.payload.PaytmAccountPayload;
Expand Down Expand Up @@ -239,6 +240,8 @@ public PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return VenmoAccountPayload.fromProto(proto);
case PAYPAL_ACCOUNT_PAYLOAD:
return PayPalAccountPayload.fromProto(proto);
case PAYSAFE_ACCOUNT_PAYLOAD:
return PaysafeAccountPayload.fromProto(proto);

default:
throw new ProtobufferRuntimeException("Unknown proto message case(PB.PaymentAccountPayload). messageCase=" + messageCase);
Expand Down
11 changes: 8 additions & 3 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2980,8 +2980,8 @@ payment.usPostalMoneyOrder.info=Trading using US Postal Money Orders (USPMO) on
- XMR buyers must send the USPMO to the XMR seller with Delivery Confirmation.\n\
\n\
In the event mediation is necessary, or if there is a trade dispute, you will be required to send the photos to the Haveno mediator or refund agent, together with the USPMO Serial Number, Post Office Number, and dollar amount, so they can verify the details on the US Post Office website.\n\n\
Failure to provide the required information to the Mediator or Arbitrator will result in losing the dispute case.\n\n\
In all dispute cases, the USPMO sender bears 100% of the burden of responsibility in providing evidence/proof to the Mediator or Arbitrator.\n\n\
Failure to provide the required information to the arbitrator will result in losing the dispute case.\n\n\
In all dispute cases, the USPMO sender bears 100% of the burden of responsibility in providing evidence/proof to the arbitrator.\n\n\
If you do not understand these requirements, do not trade using USPMO on Haveno.

payment.payByMail.info=Trading using Pay by Mail on Haveno requires that you understand the following:\n\
Expand Down Expand Up @@ -3040,7 +3040,7 @@ payment.f2f.info='Face to Face' trades have different rules and come with differ
● 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 \
● In case of a dispute the 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\n\
To be sure you fully understand the differences with 'Face to Face' trades please read the instructions and \
Expand All @@ -3067,6 +3067,9 @@ payment.amazonGiftCard.info=To pay with Amazon eGift Card, you will need to send
- try to use creative, believable text for the gift card''s message (e.g., "Happy birthday Susan!") along with the trade ID (and use trader chat \
to tell your trading peer the reference text you picked so they can verify your payment)\n\
- Amazon eGift Cards can only be redeemed on the Amazon website they were purchased on (e.g., a gift card purchased on amazon.it can only be redeemed on amazon.it)
payment.paysafe.info=For your protection, we strongly discourage using Paysafecard PINs for payment.\n\n\
Transactions made via PINs cannot be independently verified for dispute resolution. If an issue arises, recovering funds may not be possible.\n\n\
To ensure transaction security with dispute resolution, always use payment methods that provide verifiable records.

# We use constants from the code so we do not use our normal naming convention
# dynamic values are not recognized by IntelliJ
Expand Down Expand Up @@ -3302,6 +3305,8 @@ CASH_APP_SHORT=Cash App
# suppress inspection "UnusedProperty"
VENMO_SHORT=Venmo
PAYPAL_SHORT=PayPal
# suppress inspection "UnusedProperty"
PAYSAFE=Paysafe


####################################################################
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/resources/i18n/displayStrings_cs.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3065,6 +3065,10 @@ payment.amazonGiftCard.info=Chcete-li platit dárkovou kartou Amazon eGift, bude
- Na kartě do zprávy pro příjemce můžete přidat i vlastní originální text (např. "Happy birthday Susan!") spolu s ID obchodu (v takovém případě \
o tom informujte protistranu pomocí obchodovacího chatu, aby mohli s jistotou ověřit, že obdržená dárková karta pochází od vás.)\n\
- Karty Amazon eGift lze uplatnit pouze na té stránce Amazon, na které byly také koupeny (např. karta koupená na amazon.it může být uplatněna zase jen na amazon.it).
payment.paysafe.info=Pro vaši ochranu důrazně nedoporučujeme používat Paysafecard PINy pro platby.\n\n\
Transakce provedené pomocí PINů nelze nezávisle ověřit pro řešení sporů. Pokud nastane problém, obnova prostředků nemusí být možná.\n\n\
Pro zajištění bezpečnosti transakcí a podpory řešení sporů vždy používejte platební metody, které poskytují ověřitelné záznamy.


# We use constants from the code so we do not use our normal naming convention
# dynamic values are not recognized by IntelliJ
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/resources/i18n/displayStrings_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,9 @@ payment.australia.payid=PayID
payment.payid=PayIDs wie E-Mail Adressen oder Telefonnummern die mit Finanzinstitutionen verbunden sind.
payment.payid.info=Eine PayID wie eine Telefonnummer, E-Mail Adresse oder Australische Business Number (ABN) mit der Sie sicher Ihre Bank, Kreditgenossenschaft oder Bausparkassenkonto verlinken können. Sie müssen bereits eine PayID mit Ihrer Australischen Finanzinstitution erstellt haben. Beide Institutionen, die die sendet und die die empfängt, müssen PayID unterstützen. Weitere informationen finden Sie unter [HYPERLINK:https://payid.com.au/faqs/]
payment.amazonGiftCard.info=Um mit einer Amazon eGift Geschenkkarte zu bezahlen, müssen Sie eine Amazon eGift Geschenkkarte über Ihr Amazon-Konto an den XMR-Verkäufer senden. \n\nHaveno zeigt die E-Mail-Adresse oder Telefonnummer des XMR-Verkäufers an, an die die Geschenkkarte gesendet werden soll, und Sie müssen die Handels-ID in das Nachrichtenfeld der Geschenkkarte eintragen. Bitte lesen Sie das Wiki [HYPERLINK:https://haveno.exchange/wiki/Amazon_eGift_card] für weitere Details und empfohlene Vorgehensweisen. \n\nDrei wichtige Hinweise:\n- Versuchen Sie Geschenkkarten mit Beträgen von 100 USD oder weniger zu versenden, weil Amazon größere Geschenkkarten gerne als betrügerisch kennzeichnet\n- Versuchen Sie einen kreativen, glaubwürdigen Text für die Nachricht der Geschenkkarten zu verwenden (z.B. "Alles Gute zum Geburtstag Susi!"), zusammen mit der Handels-ID (und verwenden Sie den Handels-Chat, um Ihrem Handelspartner den von Ihnen gewählten Referenztext mitzuteilen, damit er Ihre Zahlung überprüfen kann)\n- Amazon Geschenkkarten können nur auf der Amazon-Website eingelöst werden, auf der sie gekauft wurden (z. B. kann eine auf amazon.it gekaufte Geschenkkarte nur auf amazon.it eingelöst werden)
payment.paysafe.info=Zum Schutz Ihrer Sicherheit raten wir dringend davon ab, Paysafecard-PINs für Zahlungen zu verwenden.\n\n\
Transaktionen, die über PINs durchgeführt werden, können nicht unabhängig zur Streitbeilegung überprüft werden. Wenn ein Problem auftritt, kann die Rückerstattung von Geldern möglicherweise nicht möglich sein.\n\n\
Um die Transaktionssicherheit mit Streitbeilegung zu gewährleisten, verwenden Sie immer Zahlungsmethoden, die überprüfbare Aufzeichnungen bieten.


# We use constants from the code so we do not use our normal naming convention
Expand Down
Loading

0 comments on commit 7282c21

Please sign in to comment.