Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add payment method "Cash by mail" #5092

Merged
merged 5 commits into from Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/src/main/java/bisq/core/offer/Offer.java
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,11 @@ public String getF2FCity() {
return "";
}

public String getF2FExtraInfo() {
public String getExtraInfo() {
if (getExtraDataMap() != null && getExtraDataMap().containsKey(OfferPayload.F2F_EXTRA_INFO))
return getExtraDataMap().get(OfferPayload.F2F_EXTRA_INFO);
else if (getExtraDataMap() != null && getExtraDataMap().containsKey(OfferPayload.CASH_BY_MAIL_EXTRA_INFO))
return getExtraDataMap().get(OfferPayload.CASH_BY_MAIL_EXTRA_INFO);
else
return "";
}
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/bisq/core/offer/OfferPayload.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public static protobuf.OfferPayload.Direction toProtoMessage(Direction direction
// Only used in payment method F2F
public static final String F2F_CITY = "f2fCity";
public static final String F2F_EXTRA_INFO = "f2fExtraInfo";
public static final String CASH_BY_MAIL_EXTRA_INFO = "cashByMailExtraInfo";

// Comma separated list of ordinal of a bisq.common.app.Capability. E.g. ordinal of
// Capability.SIGNED_ACCOUNT_AGE_WITNESS is 11 and Capability.MEDIATION is 12 so if we want to signal that maker
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/bisq/core/offer/OfferUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import bisq.core.locale.Res;
import bisq.core.monetary.Price;
import bisq.core.monetary.Volume;
import bisq.core.payment.CashByMailAccount;
import bisq.core.payment.F2FAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.provider.fee.FeeService;
Expand Down Expand Up @@ -329,6 +330,10 @@ public Map<String, String> getExtraDataMap(PaymentAccount paymentAccount,
extraDataMap.put(F2F_EXTRA_INFO, ((F2FAccount) paymentAccount).getExtraInfo());
}

if (paymentAccount instanceof CashByMailAccount) {
extraDataMap.put(CASH_BY_MAIL_EXTRA_INFO, ((CashByMailAccount) paymentAccount).getExtraInfo());
}

extraDataMap.put(CAPABILITIES, Capabilities.app.toStringList());

if (currencyCode.equals("XMR") && direction == Direction.SELL) {
Expand Down
58 changes: 58 additions & 0 deletions core/src/main/java/bisq/core/payment/CashByMailAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.payment;

import bisq.core.payment.payload.CashByMailAccountPayload;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;

public final class CashByMailAccount extends PaymentAccount {

public CashByMailAccount() {
super(PaymentMethod.CASH_BY_MAIL);
}

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

public void setPostalAddress(String postalAddress) {
((CashByMailAccountPayload) paymentAccountPayload).setPostalAddress(postalAddress);
}

public String getPostalAddress() {
return ((CashByMailAccountPayload) paymentAccountPayload).getPostalAddress();
}

public void setContact(String contact) {
((CashByMailAccountPayload) paymentAccountPayload).setContact(contact);
}

public String getContact() {
return ((CashByMailAccountPayload) paymentAccountPayload).getContact();
}

public void setExtraInfo(String extraInfo) {
((CashByMailAccountPayload) paymentAccountPayload).setExtraInfo(extraInfo);
}

public String getExtraInfo() {
return ((CashByMailAccountPayload) paymentAccountPayload).getExtraInfo();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new HalCashAccount();
case PaymentMethod.F2F_ID:
return new F2FAccount();
case PaymentMethod.CASH_BY_MAIL_ID:
return new CashByMailAccount();
case PaymentMethod.PROMPT_PAY_ID:
return new PromptPayAccount();
case PaymentMethod.ADVANCED_CASH_ID:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.payment.payload;

import bisq.core.locale.Res;

import com.google.protobuf.Message;

import org.apache.commons.lang3.ArrayUtils;

import java.nio.charset.StandardCharsets;

import java.util.HashMap;
import java.util.Map;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

@EqualsAndHashCode(callSuper = true)
@ToString
@Setter
@Getter
@Slf4j
public final class CashByMailAccountPayload extends PaymentAccountPayload implements PayloadWithHolderName {
private String postalAddress = "";
private String contact = "";
private String extraInfo = "";

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


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

private CashByMailAccountPayload(String paymentMethod, String id,
String postalAddress,
String contact,
String extraInfo,
long maxTradePeriod,
Map<String, String> excludeFromJsonDataMap) {
super(paymentMethod,
id,
maxTradePeriod,
excludeFromJsonDataMap);
this.postalAddress = postalAddress;
this.contact = contact;
this.extraInfo = extraInfo;
}

@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
.setCashByMailAccountPayload(protobuf.CashByMailAccountPayload.newBuilder()
.setPostalAddress(postalAddress)
.setContact(contact)
.setExtraInfo(extraInfo))
.build();
}

public static CashByMailAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new CashByMailAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getCashByMailAccountPayload().getPostalAddress(),
proto.getCashByMailAccountPayload().getContact(),
proto.getCashByMailAccountPayload().getExtraInfo(),
proto.getMaxTradePeriod(),
new HashMap<>(proto.getExcludeFromJsonDataMap()));
}


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

@Override
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.account.owner") + " " + contact + ", " +
Res.getWithCol("payment.postal.address") + " " + postalAddress + ", " +
Res.getWithCol("payment.shared.extraInfo") + " " + extraInfo;
}

@Override
public String getPaymentDetailsForTradePopup() {
return Res.getWithCol("payment.account.owner") + " " + contact + "\n" +
Res.getWithCol("payment.postal.address") + " " + postalAddress;
}

@Override
public byte[] getAgeWitnessInputData() {
// We use here the contact because the address alone seems to be too weak
return super.getAgeWitnessInputData(ArrayUtils.addAll(contact.getBytes(StandardCharsets.UTF_8),
postalAddress.getBytes(StandardCharsets.UTF_8)));
}

@Override
public String getOwnerId() {
return contact;
}
@Override
public String getHolderName() {
return contact;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload pro
public String getPaymentDetails() {
return Res.get(paymentMethodId) + " - " + Res.getWithCol("payment.f2f.contact") + " " + contact + ", " +
Res.getWithCol("payment.f2f.city") + " " + city +
", " + Res.getWithCol("payment.f2f.extra") + " " + extraInfo;
", " + Res.getWithCol("payment.shared.extraInfo") + " " + extraInfo;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static final String TRANSFERWISE_ID = "TRANSFERWISE";
public static final String AMAZON_GIFT_CARD_ID = "AMAZON_GIFT_CARD";
public static final String BLOCK_CHAINS_INSTANT_ID = "BLOCK_CHAINS_INSTANT";
public static final String CASH_BY_MAIL_ID = "CASH_BY_MAIL";

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -135,6 +136,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme
public static PaymentMethod TRANSFERWISE;
public static PaymentMethod AMAZON_GIFT_CARD;
public static PaymentMethod BLOCK_CHAINS_INSTANT;
public static PaymentMethod CASH_BY_MAIL;

// Cannot be deleted as it would break old trade history entries
@Deprecated
Expand Down Expand Up @@ -171,6 +173,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme

// Global
CASH_DEPOSIT = new PaymentMethod(CASH_DEPOSIT_ID, 4 * DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
CASH_BY_MAIL = new PaymentMethod(CASH_BY_MAIL_ID, 8 * DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
MONEY_GRAM = new PaymentMethod(MONEY_GRAM_ID, 4 * DAY, DEFAULT_TRADE_LIMIT_MID_RISK),
WESTERN_UNION = new PaymentMethod(WESTERN_UNION_ID, 4 * DAY, DEFAULT_TRADE_LIMIT_MID_RISK),
NATIONAL_BANK = new PaymentMethod(NATIONAL_BANK_ID, 4 * DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK),
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/bisq/core/proto/CoreProtoResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import bisq.core.payment.payload.AmazonGiftCardAccountPayload;
import bisq.core.payment.payload.AustraliaPayidPayload;
import bisq.core.payment.payload.CashAppAccountPayload;
import bisq.core.payment.payload.CashByMailAccountPayload;
import bisq.core.payment.payload.CashDepositAccountPayload;
import bisq.core.payment.payload.ChaseQuickPayAccountPayload;
import bisq.core.payment.payload.ClearXchangeAccountPayload;
Expand Down Expand Up @@ -146,6 +147,8 @@ public PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return HalCashAccountPayload.fromProto(proto);
case U_S_POSTAL_MONEY_ORDER_ACCOUNT_PAYLOAD:
return USPostalMoneyOrderAccountPayload.fromProto(proto);
case CASH_BY_MAIL_ACCOUNT_PAYLOAD:
return CashByMailAccountPayload.fromProto(proto);
case PROMPT_PAY_ACCOUNT_PAYLOAD:
return PromptPayAccountPayload.fromProto(proto);
case ADVANCED_CASH_ACCOUNT_PAYLOAD:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ private enum PaymentMethodMapper {
ADVANCED_CASH,
BLOCK_CHAINS_INSTANT,
TRANSFERWISE,
AMAZON_GIFT_CARD
AMAZON_GIFT_CARD,
CASH_BY_MAIL
}

@Getter
Expand Down
32 changes: 28 additions & 4 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,10 @@ portfolio.pending.step2_buyer.amazonGiftCard=Please purchase an Amazon eGift Car
# suppress inspection "TrailingSpacesInProperty"
portfolio.pending.step2_buyer.postal=Please send {0} by \"US Postal Money Order\" to the BTC seller.\n\n
# suppress inspection "TrailingSpacesInProperty"
portfolio.pending.step2_buyer.cashByMail=Please send {0} using \"Cash by Mail\" to the BTC seller. \
Specific instructions are in the trade contract, or if unclear you may ask questions via trader chat.\
See more details about Cash by Mail on the Bisq wiki [HYPERLINK:https://bisq.wiki/Cash_by_Mail].\n\n
# suppress inspection "TrailingSpacesInProperty"
portfolio.pending.step2_buyer.pay=Please pay {0} via the specified payment method to the BTC seller. You''ll find the seller's account details on the next screen.\n\n
# suppress inspection "TrailingSpacesInProperty"
portfolio.pending.step2_buyer.f2f=Please contact the BTC seller by the provided contact and arrange a meeting to pay {0}.\n\n
Expand Down Expand Up @@ -753,6 +757,8 @@ has already sufficient blockchain confirmations.\nThe payment amount has to be {
You can copy & paste your {4} address from the main screen after closing that popup.
portfolio.pending.step3_seller.postal={0}Please check if you have received {1} with \"US Postal Money Order\" from the BTC buyer.
# suppress inspection "TrailingSpacesInProperty"
portfolio.pending.step3_seller.cashByMail={0}Please check if you have received {1} with \"Cash by Mail\" from the BTC buyer.
# suppress inspection "TrailingSpacesInProperty"
portfolio.pending.step3_seller.bank=Your trading partner has confirmed that they have initiated the {0} payment.\n\n\
Please go to your online banking web page and check if you have received {1} from the BTC buyer.
portfolio.pending.step3_seller.cash=Because the payment is done via Cash Deposit the BTC buyer has to write \"NO REFUND\" on the paper receipt, tear it in 2 parts and send you a photo by email.\n\n\
Expand Down Expand Up @@ -3305,14 +3311,29 @@ Failure to provide the required information to the Mediator or Arbitrator will r
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\
If you do not understand these requirements, do not trade using USPMO on Bisq.

payment.cashByMail.info=Trading using cash-by-mail (CBM) on Bisq requires that you understand the following:\n\
\n\
● BTC buyer should package cash in a tamper-evident cash bag.\n\
● BTC buyer should film or take high-resolution photos of the cash packaging process with the address & tracking number already affixed to packaging.\n\
● BTC buyer should send the cash package to the BTC seller with Delivery Confirmation and appropriate Insurance.\n\
● BTC seller should film the opening of the package, making sure that the tracking number provided by the sender is visible in the video.\n\
● Offer maker must state any special terms or conditions in the 'Additional Information' field of the payment account.\n\
● Offer taker agrees to the offer maker's terms and conditions by taking the offer.\n\
● MEDIATORS CANNOT MAKE JUDGEMENTS IN CBM DISPUTES. But they can help with smaller problems such as technical difficulties not related to scam attempts.\n\
\n\
To be sure you fully understand the requirements of cash-by-mail trades, please see: [HYPERLINK:https://bisq.wiki/Cash_by_Mail]\n\
\n\
If you do not understand these requirements, do not trade using CBM on Bisq.

payment.cashByMail.contact=Contact info
payment.cashByMail.contact.prompt=Your contact information such as name or nym
payment.f2f.contact=Contact info
payment.f2f.contact.prompt=How would you like to be contacted by the trading peer? (email address, phone number,...)
payment.f2f.city=City for 'Face to face' meeting
payment.f2f.city.prompt=The city will be displayed with the offer
payment.f2f.optionalExtra=Optional additional information
payment.f2f.extra=Additional information

payment.f2f.extra.prompt=The maker can define 'terms and conditions' or add a public contact information. It will be displayed with the offer.
payment.shared.optionalExtra=Optional additional information
payment.shared.extraInfo=Additional information
payment.shared.extraInfo.prompt=The maker can define 'terms and conditions' or add a public contact information. It will be displayed with the offer.
This conversation was marked as resolved.
Show resolved Hide resolved
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\
Expand Down Expand Up @@ -3356,6 +3377,7 @@ SAME_BANK=Transfer with same bank
SPECIFIC_BANKS=Transfers with specific banks
US_POSTAL_MONEY_ORDER=US Postal Money Order
CASH_DEPOSIT=Cash Deposit
CASH_BY_MAIL=Cash By Mail
MONEY_GRAM=MoneyGram
WESTERN_UNION=Western Union
F2F=Face to face (in person)
Expand All @@ -3373,6 +3395,8 @@ US_POSTAL_MONEY_ORDER_SHORT=US Money Order
# suppress inspection "UnusedProperty"
CASH_DEPOSIT_SHORT=Cash Deposit
# suppress inspection "UnusedProperty"
CASH_BY_MAIL_SHORT=CashByMail
# suppress inspection "UnusedProperty"
MONEY_GRAM_SHORT=MoneyGram
# suppress inspection "UnusedProperty"
WESTERN_UNION_SHORT=Western Union
Expand Down
Loading