omit a paynym contact whose payment code does not parse rather than keeping it with a null code or failing the whole paynym response

This commit is contained in:
Craig Raw
2026-09-15 12:52:33 +02:00
parent b91f7993d5
commit 94ebb84934
4 changed files with 43 additions and 11 deletions
+1 -1
Submodule drongo updated: eb3cf3e577...9a8c659b49
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static com.sparrowwallet.drongo.bip47.PaymentCode.SEGWIT_SCRIPT_TYPES;
import static com.sparrowwallet.drongo.bip47.PaymentCode.V1_SCRIPT_TYPES;
@@ -70,16 +71,13 @@ public class PayNym {
return V1_SCRIPT_TYPES;
}
public static PayNym fromString(String strPaymentCode, String nymId, String nymName, boolean segwit, List<PayNym> following, List<PayNym> followers) {
PaymentCode paymentCode;
public static Optional<PayNym> fromString(String strPaymentCode, String nymId, String nymName, boolean segwit, List<PayNym> following, List<PayNym> followers) {
try {
paymentCode = new PaymentCode(strPaymentCode);
return Optional.of(new PayNym(new PaymentCode(strPaymentCode), nymId, nymName, segwit, following, followers));
} catch(InvalidPaymentCodeException e) {
log.error("Error creating PayNym from payment code " + strPaymentCode, e);
paymentCode = null;
return Optional.empty();
}
return new PayNym(paymentCode, nymId, nymName, segwit, following, followers);
}
public static PayNym fromWallet(Wallet bip47Wallet) {
@@ -206,13 +206,14 @@ public class PayNymService {
}
List<Map<String, Object>> followingMaps = (List<Map<String, Object>>)nymMap.get("following");
List<PayNym> following = followingMaps.stream().map(followingMap -> {
return PayNym.fromString((String)followingMap.get("code"), (String)followingMap.get("nymId"), (String)followingMap.get("nymName"), (Boolean)followingMap.get("segwit"), Collections.emptyList(), Collections.emptyList());
//An entry whose payment code does not parse is omitted rather than failing the whole PayNym
List<PayNym> following = followingMaps.stream().flatMap(followingMap -> {
return PayNym.fromString((String)followingMap.get("code"), (String)followingMap.get("nymId"), (String)followingMap.get("nymName"), (Boolean)followingMap.get("segwit"), Collections.emptyList(), Collections.emptyList()).stream();
}).collect(Collectors.toList());
List<Map<String, Object>> followersMaps = (List<Map<String, Object>>)nymMap.get("followers");
List<PayNym> followers = followersMaps.stream().map(followerMap -> {
return PayNym.fromString((String)followerMap.get("code"), (String)followerMap.get("nymId"), (String)followerMap.get("nymName"), (Boolean)followerMap.get("segwit"), Collections.emptyList(), Collections.emptyList());
List<PayNym> followers = followersMaps.stream().flatMap(followerMap -> {
return PayNym.fromString((String)followerMap.get("code"), (String)followerMap.get("nymId"), (String)followerMap.get("nymName"), (Boolean)followerMap.get("segwit"), Collections.emptyList(), Collections.emptyList()).stream();
}).collect(Collectors.toList());
return new PayNym(code, (String)nymMap.get("nymID"), (String)nymMap.get("nymName"), (Boolean)nymMap.get("segwit"), following, followers);
@@ -0,0 +1,33 @@
package com.sparrowwallet.sparrow.paynym;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* A contact entry in a PayNym response whose payment code does not parse is omitted, rather than becoming a PayNym with no payment code that the contact
* lists and search then dereference.
*/
public class PayNymTest {
private static final String PAYMENT_CODE = "PM8TJTLJbPRGxSbc8EJi42Wrr6QbNSaSSVJ5Y3E4pbCYiTHUskHg13935Ubb7q8tx9GVbh2UuRnBc3WSyJHhUrw8KhprKnn9eDznYGieTzFcwQRya4GA";
@Test
public void parsesAValidPaymentCode() {
Optional<PayNym> payNym = PayNym.fromString(PAYMENT_CODE, "id", "+name", true, Collections.emptyList(), Collections.emptyList());
assertTrue(payNym.isPresent());
assertEquals(PAYMENT_CODE, payNym.get().paymentCode().toString());
}
@Test
public void omitsAnUnparseablePaymentCode() {
assertTrue(PayNym.fromString("not-a-payment-code", "id", "+name", true, Collections.emptyList(), Collections.emptyList()).isEmpty());
//Valid Base58 with a corrupted checksum
String corrupted = PAYMENT_CODE.substring(0, PAYMENT_CODE.length() - 1) + (PAYMENT_CODE.endsWith("A") ? "B" : "A");
assertTrue(PayNym.fromString(corrupted, "id", "+name", true, Collections.emptyList(), Collections.emptyList()).isEmpty());
}
}