Expand ecash explorer capabilities

Add Fedimint discovery, dual SQLite/Postgres storage, richer review handling, and generated social imagery.
This commit is contained in:
michilis
2026-08-21 02:10:48 +02:00
parent aa1771ea20
commit 6f17b572b1
80 changed files with 7580 additions and 704 deletions
+38 -1
View File
@@ -26,13 +26,50 @@ function isDisallowedHost(hostname: string): boolean {
if (hostname === 'localhost' || hostname.endsWith('.localhost')) return true;
if (hostname.endsWith('.onion')) return true;
if (hostname.endsWith('.local')) return true;
if (hostname === '::1' || hostname === '[::1]') return true;
if (PRIVATE_IPV4.test(hostname)) return true;
if (isPrivateIpv6(hostname)) return true;
// A bare label with no dot cannot be a public host.
if (!hostname.includes('.') && !hostname.includes(':')) return true;
return false;
}
/**
* IPv6 forms that are loopback, link-local (fe80::/10), unique-local (fc00::/7) or an
* IPv4-mapped address whose IPv4 part is private. The URL parser brackets an IPv6
* hostname, so both spellings are accepted.
*/
function isPrivateIpv6(hostname: string): boolean {
const bare =
hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;
if (!bare.includes(':')) return false;
if (bare === '::' || bare === '::1') return true;
if (/^f[cd]/i.test(bare)) return true;
if (/^fe[89ab]/i.test(bare)) return true;
const mapped = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(bare);
if (mapped?.[1]) return PRIVATE_IPV4.test(mapped[1]) || mapped[1].startsWith('127.');
return false;
}
/**
* May the indexer fetch this URL? http(s) only, and never a private or local host.
*
* For URLs a mint *publishes* rather than the URL it lives at — its `icon_url` above
* all. Those never pass through `normalizeMintUrl`, so without this check a mint's
* /v1/info could point the indexer at a cloud metadata endpoint or anything else on
* the API host's own network. Callers that follow redirects must re-check every hop.
*/
export function isFetchableUrl(value: URL | string): boolean {
let u: URL;
try {
u = typeof value === 'string' ? new URL(value) : value;
} catch {
return false;
}
if (u.protocol !== 'https:' && u.protocol !== 'http:') return false;
const hostname = u.hostname.toLowerCase();
return hostname !== '' && !isDisallowedHost(hostname);
}
/**
* Normalize a mint URL as found in a Nostr `u` tag or typed by a user.
* Returns null when the input is not a usable public mint URL.