From 1aec2eb638f0651b6d1114db2bf98ed231968802 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 11 Jun 2026 09:11:01 +0200 Subject: [PATCH] change url separator to semicolon --- scripts/resolver/snrc-resolve.py | 22 +++++++++------ scripts/resolver/test_snrc_resolve.py | 39 ++++++++++++++------------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/scripts/resolver/snrc-resolve.py b/scripts/resolver/snrc-resolve.py index f3de0cdff..8b5f21e70 100755 --- a/scripts/resolver/snrc-resolve.py +++ b/scripts/resolver/snrc-resolve.py @@ -19,7 +19,7 @@ and returns a flat JSON document with these fields: `simplexContact` and `simplexChannel` are arrays so a name can advertise multiple SMP servers for redundancy. Clients SHOULD try the URLs in the order returned. The on-chain text record stores them as a single -comma-separated string; this resolver splits and trims into a list. +`LINK_SEPARATOR` (`;`)-joined string; this resolver splits and trims into a list. All keys are valid Haskell record-field identifiers (lowercase initial, no dots), so consumers can derive aeson FromJSON instances directly @@ -372,16 +372,22 @@ TEXT_KEYS = [ ] -def split_csv(value: str) -> list: - """Split a comma-separated text record into an ordered list of entries. +# Separator that joins the SMP-server URL list inside a simplex.contact / +# simplex.channel text record. MUST match SIMPLEX_LINK_SEPARATOR in the dApp +# (ens-app-v3 src/constants/simplex.ts) — the two sides decode the same record. +LINK_SEPARATOR = ";" + + +def split_links(value: str) -> list: + """Split a separator-joined text record into an ordered list of entries. Trims whitespace around each element and drops empties so trailing - commas, doubled commas, and all-whitespace inputs all yield clean + separators, doubled separators, and all-whitespace inputs all yield clean output. Single-value records yield a 1-element list; empty inputs yield `[]`. Used for `simplex.contact` / `simplex.channel`, which - store one-or-more SMP-server URLs as a single comma-joined string. + store one-or-more SMP-server URLs as a single `LINK_SEPARATOR`-joined string. """ - return [item.strip() for item in value.split(",") if item.strip()] + return [item.strip() for item in value.split(LINK_SEPARATOR) if item.strip()] def resolve(name: str): @@ -429,8 +435,8 @@ def resolve(name: str): "nickname": nickname, "website": texts.get("url", ""), "location": texts.get("location", ""), - "simplexContact": split_csv(texts.get("simplex.contact", "")), - "simplexChannel": split_csv(texts.get("simplex.channel", "")), + "simplexContact": split_links(texts.get("simplex.contact", "")), + "simplexChannel": split_links(texts.get("simplex.channel", "")), "eth": addr_multicoin(resolver_addr, node, COIN_ETH), "btc": addr_multicoin(resolver_addr, node, COIN_BTC), "xmr": addr_multicoin(resolver_addr, node, COIN_XMR), diff --git a/scripts/resolver/test_snrc_resolve.py b/scripts/resolver/test_snrc_resolve.py index 107c0e90d..64e924c06 100644 --- a/scripts/resolver/test_snrc_resolve.py +++ b/scripts/resolver/test_snrc_resolve.py @@ -17,28 +17,29 @@ snrc = importlib.util.module_from_spec(_SPEC) _SPEC.loader.exec_module(snrc) -class SplitCsvTests(unittest.TestCase): - """`split_csv` decodes the multi-URL convention for simplex.contact / +class SplitLinksTests(unittest.TestCase): + """`split_links` decodes the multi-URL convention for simplex.contact / simplex.channel text records. Reuses the same rule the dApp's - `parseSimplexUrls` will use, so the two sides round-trip cleanly.""" + `parseSimplexUrls` uses (separator `;`), so the two sides round-trip + cleanly.""" def test_empty_string_yields_empty_list(self): - self.assertEqual(snrc.split_csv(""), []) + self.assertEqual(snrc.split_links(""), []) def test_whitespace_only_yields_empty_list(self): - self.assertEqual(snrc.split_csv(" "), []) - self.assertEqual(snrc.split_csv(" , , "), []) + self.assertEqual(snrc.split_links(" "), []) + self.assertEqual(snrc.split_links(" ; ; "), []) def test_single_url_yields_singleton_list(self): self.assertEqual( - snrc.split_csv("https://smp16.simplex.im/a#H1"), + snrc.split_links("https://smp16.simplex.im/a#H1"), ["https://smp16.simplex.im/a#H1"], ) - def test_two_urls_split_on_comma(self): + def test_two_urls_split_on_separator(self): self.assertEqual( - snrc.split_csv( - "https://smp16.simplex.im/a#H1,https://smp19.simplex.im/a#H1" + snrc.split_links( + "https://smp16.simplex.im/a#H1;https://smp19.simplex.im/a#H1" ), [ "https://smp16.simplex.im/a#H1", @@ -46,10 +47,10 @@ class SplitCsvTests(unittest.TestCase): ], ) - def test_whitespace_around_commas_is_trimmed(self): + def test_whitespace_around_separators_is_trimmed(self): self.assertEqual( - snrc.split_csv( - " https://smp16.simplex.im/a#H1 ,\thttps://smp19.simplex.im/a#H1 " + snrc.split_links( + " https://smp16.simplex.im/a#H1 ;\thttps://smp19.simplex.im/a#H1 " ), [ "https://smp16.simplex.im/a#H1", @@ -57,16 +58,16 @@ class SplitCsvTests(unittest.TestCase): ], ) - def test_trailing_comma_does_not_produce_empty_entry(self): + def test_trailing_separator_does_not_produce_empty_entry(self): self.assertEqual( - snrc.split_csv("https://smp16.simplex.im/a#H1,"), + snrc.split_links("https://smp16.simplex.im/a#H1;"), ["https://smp16.simplex.im/a#H1"], ) - def test_doubled_comma_does_not_produce_empty_entry(self): + def test_doubled_separator_does_not_produce_empty_entry(self): self.assertEqual( - snrc.split_csv( - "https://smp16.simplex.im/a#H1,,https://smp19.simplex.im/a#H1" + snrc.split_links( + "https://smp16.simplex.im/a#H1;;https://smp19.simplex.im/a#H1" ), [ "https://smp16.simplex.im/a#H1", @@ -76,7 +77,7 @@ class SplitCsvTests(unittest.TestCase): def test_order_is_preserved(self): self.assertEqual( - snrc.split_csv("c,a,b"), + snrc.split_links("c;a;b"), ["c", "a", "b"], )