@thurinlabs/identity-kit 1.3.5 → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1627,29 +1627,27 @@ async function verifyDNS(proof, fingerprint) {
1627
1627
  return { verified: false, reason: `DNS fetch failed: ${err.message}` };
1628
1628
  }
1629
1629
  }
1630
+ var FARCASTER_HUB = "https://haatz.quilibrium.com";
1630
1631
  var NEYNAR_HUB = "https://hub-api.neynar.com";
1631
- async function resolveFid(username, apiKey) {
1632
- const resp = await fetch(
1633
- `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,
1634
- { headers: { "x-api-key": apiKey } }
1635
- );
1636
- if (!resp.ok) return null;
1637
- const data = await resp.json();
1638
- return data.fid ?? null;
1632
+ function farcasterSource(opts) {
1633
+ if (opts.farcasterHub) return { base: opts.farcasterHub.replace(/\/+$/, ""), headers: {} };
1634
+ if (opts.neynarApiKey) return { base: NEYNAR_HUB, headers: { "x-api-key": opts.neynarApiKey } };
1635
+ return { base: FARCASTER_HUB, headers: {} };
1639
1636
  }
1640
- async function verifyFarcaster(proof, fingerprint, neynarApiKey) {
1641
- if (!neynarApiKey) {
1642
- return { verified: false, reason: "Farcaster verification requires a Neynar API key" };
1643
- }
1637
+ async function verifyFarcaster(proof, fingerprint, opts = {}) {
1638
+ const { base, headers } = farcasterSource(opts);
1639
+ const host = base.replace(/^https?:\/\//, "");
1644
1640
  try {
1645
- const fid = await resolveFid(proof.user, neynarApiKey);
1641
+ const nameResp = await fetch(`${base}/v1/userNameProofByName?name=${encodeURIComponent(proof.user)}`, { headers });
1642
+ if (nameResp.status === 404) return { verified: false, reason: `Could not resolve Farcaster user "${proof.user}"` };
1643
+ if (!nameResp.ok) return { verified: false, reason: `Couldn't check: the Farcaster node (${host}) returned ${nameResp.status}` };
1644
+ const fid = (await nameResp.json()).fid;
1646
1645
  if (!fid) return { verified: false, reason: `Could not resolve Farcaster user "${proof.user}"` };
1647
- const headers = { "x-api-key": neynarApiKey };
1648
1646
  let pageToken = "";
1649
1647
  for (let page = 0; page < 5; page++) {
1650
- const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ""}`;
1648
+ const url = `${base}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ""}`;
1651
1649
  const resp = await fetch(url, { headers });
1652
- if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` };
1650
+ if (!resp.ok) return { verified: false, reason: `Couldn't check: the Farcaster node (${host}) returned ${resp.status}` };
1653
1651
  const data = await resp.json();
1654
1652
  for (const msg of data.messages || []) {
1655
1653
  if (msg.hash && msg.hash.startsWith(proof.castHash)) {
@@ -1664,7 +1662,7 @@ async function verifyFarcaster(proof, fingerprint, neynarApiKey) {
1664
1662
  }
1665
1663
  return { verified: false, reason: "Cast not found" };
1666
1664
  } catch (err) {
1667
- return { verified: false, reason: `Farcaster fetch failed: ${err.message}` };
1665
+ return { verified: false, reason: `Couldn't check: the Farcaster node (${host}) didn't answer (${err.message})` };
1668
1666
  }
1669
1667
  }
1670
1668
  async function verifyCodeberg(proof, fingerprint) {
@@ -1717,14 +1715,15 @@ var verifiers = {
1717
1715
  codeberg: verifyCodeberg,
1718
1716
  mastodon: verifyMastodon
1719
1717
  };
1720
- async function verifyProof(proof, fingerprint, neynarApiKey) {
1718
+ async function verifyProof(proof, fingerprint, opts) {
1721
1719
  const fn = verifiers[proof.provider];
1722
1720
  if (!fn) return { verified: false, reason: "Unknown provider" };
1723
- return fn(proof, fingerprint, neynarApiKey);
1721
+ return fn(proof, fingerprint, typeof opts === "string" ? { neynarApiKey: opts } : opts ?? {});
1724
1722
  }
1725
1723
 
1726
1724
  // src/core/avatar.ts
1727
- var IPFS_GATEWAY = "https://ipfs.io/ipfs/";
1725
+ var IPFS_GATEWAYS = ["https://ipfs.filebase.io/ipfs/", "https://gateway.pinata.cloud/ipfs/"];
1726
+ var IPFS_GATEWAY = IPFS_GATEWAYS[0];
1728
1727
  var ARWEAVE_GATEWAY = "https://arweave.net/";
1729
1728
  function avatarUrl(uri) {
1730
1729
  if (typeof uri !== "string") return null;
@@ -1739,9 +1738,14 @@ function avatarUrl(uri) {
1739
1738
  if (m) return IPFS_GATEWAY + m[1];
1740
1739
  return null;
1741
1740
  }
1741
+ function avatarFallbacks(url) {
1742
+ if (!url || !url.startsWith(IPFS_GATEWAYS[0])) return [];
1743
+ const path = url.slice(IPFS_GATEWAYS[0].length);
1744
+ return IPFS_GATEWAYS.slice(1).map((g) => g + path);
1745
+ }
1742
1746
  function parseNftAvatar(raw) {
1743
- const m = typeof raw === "string" && raw.trim().match(/^eip155:(\d+)\/(erc721|erc1155):(0x[0-9a-fA-F]{40})\/(\d+)$/);
1744
- return m ? { chainId: Number(m[1]), standard: m[2], contract: m[3], tokenId: BigInt(m[4]) } : null;
1747
+ const m = typeof raw === "string" && raw.trim().match(/^eip155:(\d+)\/(erc721|erc1155):(0x[0-9a-fA-F]{40})\/(\d+)$/i);
1748
+ return m ? { chainId: Number(m[1]), standard: m[2].toLowerCase(), contract: m[3], tokenId: BigInt(m[4]) } : null;
1745
1749
  }
1746
1750
  var NFT_AVATAR_ABI = [
1747
1751
  { type: "function", name: "tokenURI", stateMutability: "view", inputs: [{ type: "uint256" }], outputs: [{ type: "string" }] },
@@ -1755,9 +1759,17 @@ async function nftAvatarImage(tokenUri, tokenId, fetchFn = fetch) {
1755
1759
  else {
1756
1760
  const url = uri.startsWith("data:") ? null : avatarUrl(uri);
1757
1761
  if (!url) return null;
1758
- const res = await fetchFn(url);
1759
- if (!res.ok) return null;
1760
- meta = await res.json();
1762
+ for (const candidate of [url, ...avatarFallbacks(url)]) {
1763
+ try {
1764
+ const res = await fetchFn(candidate);
1765
+ if (res.ok) {
1766
+ meta = await res.json();
1767
+ break;
1768
+ }
1769
+ } catch {
1770
+ }
1771
+ }
1772
+ if (!meta) return null;
1761
1773
  }
1762
1774
  return avatarUrl(meta?.image ?? meta?.image_url);
1763
1775
  }
@@ -2053,10 +2065,13 @@ export {
2053
2065
  displayUrl,
2054
2066
  proofHref,
2055
2067
  proofSecondaryHref,
2068
+ FARCASTER_HUB,
2056
2069
  verifyProof,
2070
+ IPFS_GATEWAYS,
2057
2071
  IPFS_GATEWAY,
2058
2072
  ARWEAVE_GATEWAY,
2059
2073
  avatarUrl,
2074
+ avatarFallbacks,
2060
2075
  parseNftAvatar,
2061
2076
  NFT_AVATAR_ABI,
2062
2077
  nftAvatarImage,
@@ -2089,4 +2104,4 @@ export {
2089
2104
  parseRecord,
2090
2105
  fetchRecords
2091
2106
  };
2092
- //# sourceMappingURL=chunk-CF64QQZO.js.map
2107
+ //# sourceMappingURL=chunk-ROQWHCHP.js.map