@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.
package/dist/core.cjs CHANGED
@@ -59,10 +59,10 @@
59
59
 
60
60
 
61
61
 
62
- var _chunkYTO7Z5SIcjs = require('./chunk-YTO7Z5SI.cjs');
63
62
 
64
63
 
65
64
 
65
+ var _chunkOIE72R6Jcjs = require('./chunk-OIE72R6J.cjs');
66
66
 
67
67
 
68
68
 
@@ -121,5 +121,11 @@ var _chunkYTO7Z5SIcjs = require('./chunk-YTO7Z5SI.cjs');
121
121
 
122
122
 
123
123
 
124
- exports.ARWEAVE_GATEWAY = _chunkYTO7Z5SIcjs.ARWEAVE_GATEWAY; exports.AUTHORIZATION_TYPES = _chunkYTO7Z5SIcjs.AUTHORIZATION_TYPES; exports.EIP712_NAME = _chunkYTO7Z5SIcjs.EIP712_NAME; exports.EIP712_VERSION = _chunkYTO7Z5SIcjs.EIP712_VERSION; exports.ENS_HINT_KEY = _chunkYTO7Z5SIcjs.ENS_HINT_KEY; exports.ENS_TEXT_RESOLVER_ABI = _chunkYTO7Z5SIcjs.ENS_TEXT_RESOLVER_ABI; exports.IDENTITY_ERROR_TEXT = _chunkYTO7Z5SIcjs.IDENTITY_ERROR_TEXT; exports.IDENTITY_KINDS = _chunkYTO7Z5SIcjs.IDENTITY_KINDS; exports.IPFS_GATEWAY = _chunkYTO7Z5SIcjs.IPFS_GATEWAY; exports.KNOWN_KINDS = _chunkYTO7Z5SIcjs.KNOWN_KINDS; exports.MAX_RECORD_BYTES = _chunkYTO7Z5SIcjs.MAX_RECORD_BYTES; exports.NETWORKS = _chunkYTO7Z5SIcjs.NETWORKS; exports.NFT_AVATAR_ABI = _chunkYTO7Z5SIcjs.NFT_AVATAR_ABI; exports.REGISTRY_ABI = _chunkYTO7Z5SIcjs.REGISTRY_ABI; exports.REGISTRY_ADDRESS = _chunkYTO7Z5SIcjs.REGISTRY_ADDRESS; exports.addPointer = _chunkYTO7Z5SIcjs.addPointer; exports.attestTypedData = _chunkYTO7Z5SIcjs.attestTypedData; exports.authorizationDigest = _chunkYTO7Z5SIcjs.authorizationDigest; exports.avatarUrl = _chunkYTO7Z5SIcjs.avatarUrl; exports.bytesToFingerprint = _chunkYTO7Z5SIcjs.bytesToFingerprint; exports.chainFor = _chunkYTO7Z5SIcjs.chainFor; exports.decodeRecord = _chunkYTO7Z5SIcjs.decodeRecord; exports.displayUrl = _chunkYTO7Z5SIcjs.displayUrl; exports.encodeRecord = _chunkYTO7Z5SIcjs.encodeRecord; exports.ensHintFor = _chunkYTO7Z5SIcjs.ensHintFor; exports.ensHintValue = _chunkYTO7Z5SIcjs.ensHintValue; exports.ensHintWrite = _chunkYTO7Z5SIcjs.ensHintWrite; exports.fetchEFPGraph = _chunkYTO7Z5SIcjs.fetchEFPGraph; exports.fetchEnsHint = _chunkYTO7Z5SIcjs.fetchEnsHint; exports.fetchRecords = _chunkYTO7Z5SIcjs.fetchRecords; exports.fingerprintHash = _chunkYTO7Z5SIcjs.fingerprintHash; exports.fingerprintToBytes = _chunkYTO7Z5SIcjs.fingerprintToBytes; exports.getRegistry = _chunkYTO7Z5SIcjs.getRegistry; exports.hasEmailUserID = _chunkYTO7Z5SIcjs.hasEmailUserID; exports.identifyProof = _chunkYTO7Z5SIcjs.identifyProof; exports.identityErrorKind = _chunkYTO7Z5SIcjs.identityErrorKind; exports.isNetworkName = _chunkYTO7Z5SIcjs.isNetworkName; exports.keyIdOf = _chunkYTO7Z5SIcjs.keyIdOf; exports.keyIdToBytes = _chunkYTO7Z5SIcjs.keyIdToBytes; exports.kindName = _chunkYTO7Z5SIcjs.kindName; exports.needsRpcProbe = _chunkYTO7Z5SIcjs.needsRpcProbe; exports.nftAvatarImage = _chunkYTO7Z5SIcjs.nftAvatarImage; exports.normalizeFingerprint = _chunkYTO7Z5SIcjs.normalizeFingerprint; exports.parseNftAvatar = _chunkYTO7Z5SIcjs.parseNftAvatar; exports.parsePgpKey = _chunkYTO7Z5SIcjs.parsePgpKey; exports.parsePointer = _chunkYTO7Z5SIcjs.parsePointer; exports.parseRecord = _chunkYTO7Z5SIcjs.parseRecord; exports.proofHref = _chunkYTO7Z5SIcjs.proofHref; exports.proofSecondaryHref = _chunkYTO7Z5SIcjs.proofSecondaryHref; exports.reattestTypedData = _chunkYTO7Z5SIcjs.reattestTypedData; exports.recordKind = _chunkYTO7Z5SIcjs.recordKind; exports.registryDomain = _chunkYTO7Z5SIcjs.registryDomain; exports.renderPointer = _chunkYTO7Z5SIcjs.renderPointer; exports.revokeTypedData = _chunkYTO7Z5SIcjs.revokeTypedData; exports.setRecordTypedData = _chunkYTO7Z5SIcjs.setRecordTypedData; exports.stripEmailUserIDs = _chunkYTO7Z5SIcjs.stripEmailUserIDs; exports.updateKeyTypedData = _chunkYTO7Z5SIcjs.updateKeyTypedData; exports.verifyAttestation = _chunkYTO7Z5SIcjs.verifyAttestation; exports.verifyClearsigned = _chunkYTO7Z5SIcjs.verifyClearsigned; exports.verifyProof = _chunkYTO7Z5SIcjs.verifyProof;
124
+
125
+
126
+
127
+
128
+
129
+
130
+ exports.ARWEAVE_GATEWAY = _chunkOIE72R6Jcjs.ARWEAVE_GATEWAY; exports.AUTHORIZATION_TYPES = _chunkOIE72R6Jcjs.AUTHORIZATION_TYPES; exports.EIP712_NAME = _chunkOIE72R6Jcjs.EIP712_NAME; exports.EIP712_VERSION = _chunkOIE72R6Jcjs.EIP712_VERSION; exports.ENS_HINT_KEY = _chunkOIE72R6Jcjs.ENS_HINT_KEY; exports.ENS_TEXT_RESOLVER_ABI = _chunkOIE72R6Jcjs.ENS_TEXT_RESOLVER_ABI; exports.FARCASTER_HUB = _chunkOIE72R6Jcjs.FARCASTER_HUB; exports.IDENTITY_ERROR_TEXT = _chunkOIE72R6Jcjs.IDENTITY_ERROR_TEXT; exports.IDENTITY_KINDS = _chunkOIE72R6Jcjs.IDENTITY_KINDS; exports.IPFS_GATEWAY = _chunkOIE72R6Jcjs.IPFS_GATEWAY; exports.IPFS_GATEWAYS = _chunkOIE72R6Jcjs.IPFS_GATEWAYS; exports.KNOWN_KINDS = _chunkOIE72R6Jcjs.KNOWN_KINDS; exports.MAX_RECORD_BYTES = _chunkOIE72R6Jcjs.MAX_RECORD_BYTES; exports.NETWORKS = _chunkOIE72R6Jcjs.NETWORKS; exports.NFT_AVATAR_ABI = _chunkOIE72R6Jcjs.NFT_AVATAR_ABI; exports.REGISTRY_ABI = _chunkOIE72R6Jcjs.REGISTRY_ABI; exports.REGISTRY_ADDRESS = _chunkOIE72R6Jcjs.REGISTRY_ADDRESS; exports.addPointer = _chunkOIE72R6Jcjs.addPointer; exports.attestTypedData = _chunkOIE72R6Jcjs.attestTypedData; exports.authorizationDigest = _chunkOIE72R6Jcjs.authorizationDigest; exports.avatarFallbacks = _chunkOIE72R6Jcjs.avatarFallbacks; exports.avatarUrl = _chunkOIE72R6Jcjs.avatarUrl; exports.bytesToFingerprint = _chunkOIE72R6Jcjs.bytesToFingerprint; exports.chainFor = _chunkOIE72R6Jcjs.chainFor; exports.decodeRecord = _chunkOIE72R6Jcjs.decodeRecord; exports.displayUrl = _chunkOIE72R6Jcjs.displayUrl; exports.encodeRecord = _chunkOIE72R6Jcjs.encodeRecord; exports.ensHintFor = _chunkOIE72R6Jcjs.ensHintFor; exports.ensHintValue = _chunkOIE72R6Jcjs.ensHintValue; exports.ensHintWrite = _chunkOIE72R6Jcjs.ensHintWrite; exports.fetchEFPGraph = _chunkOIE72R6Jcjs.fetchEFPGraph; exports.fetchEnsHint = _chunkOIE72R6Jcjs.fetchEnsHint; exports.fetchRecords = _chunkOIE72R6Jcjs.fetchRecords; exports.fingerprintHash = _chunkOIE72R6Jcjs.fingerprintHash; exports.fingerprintToBytes = _chunkOIE72R6Jcjs.fingerprintToBytes; exports.getRegistry = _chunkOIE72R6Jcjs.getRegistry; exports.hasEmailUserID = _chunkOIE72R6Jcjs.hasEmailUserID; exports.identifyProof = _chunkOIE72R6Jcjs.identifyProof; exports.identityErrorKind = _chunkOIE72R6Jcjs.identityErrorKind; exports.isNetworkName = _chunkOIE72R6Jcjs.isNetworkName; exports.keyIdOf = _chunkOIE72R6Jcjs.keyIdOf; exports.keyIdToBytes = _chunkOIE72R6Jcjs.keyIdToBytes; exports.kindName = _chunkOIE72R6Jcjs.kindName; exports.needsRpcProbe = _chunkOIE72R6Jcjs.needsRpcProbe; exports.nftAvatarImage = _chunkOIE72R6Jcjs.nftAvatarImage; exports.normalizeFingerprint = _chunkOIE72R6Jcjs.normalizeFingerprint; exports.parseNftAvatar = _chunkOIE72R6Jcjs.parseNftAvatar; exports.parsePgpKey = _chunkOIE72R6Jcjs.parsePgpKey; exports.parsePointer = _chunkOIE72R6Jcjs.parsePointer; exports.parseRecord = _chunkOIE72R6Jcjs.parseRecord; exports.proofHref = _chunkOIE72R6Jcjs.proofHref; exports.proofSecondaryHref = _chunkOIE72R6Jcjs.proofSecondaryHref; exports.reattestTypedData = _chunkOIE72R6Jcjs.reattestTypedData; exports.recordKind = _chunkOIE72R6Jcjs.recordKind; exports.registryDomain = _chunkOIE72R6Jcjs.registryDomain; exports.renderPointer = _chunkOIE72R6Jcjs.renderPointer; exports.revokeTypedData = _chunkOIE72R6Jcjs.revokeTypedData; exports.setRecordTypedData = _chunkOIE72R6Jcjs.setRecordTypedData; exports.stripEmailUserIDs = _chunkOIE72R6Jcjs.stripEmailUserIDs; exports.updateKeyTypedData = _chunkOIE72R6Jcjs.updateKeyTypedData; exports.verifyAttestation = _chunkOIE72R6Jcjs.verifyAttestation; exports.verifyClearsigned = _chunkOIE72R6Jcjs.verifyClearsigned; exports.verifyProof = _chunkOIE72R6Jcjs.verifyProof;
125
131
  //# sourceMappingURL=core.cjs.map
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ben/code/thurinlabs/identity-kit/dist/core.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,i6GAAC","file":"/home/ben/code/thurinlabs/identity-kit/dist/core.cjs"}
1
+ {"version":3,"sources":["/home/ben/code/thurinlabs/identity-kit/dist/core.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,glHAAC","file":"/home/ben/code/thurinlabs/identity-kit/dist/core.cjs"}
package/dist/core.d.cts CHANGED
@@ -90,7 +90,10 @@ interface ThurinIdentity {
90
90
  type Theme = 'thurin' | 'dark' | 'light';
91
91
  interface IdentityKitConfig {
92
92
  rpcUrl?: string;
93
+ /** Optional: read Farcaster proofs through Neynar's hub with this key. Not needed since 1.3.7. */
93
94
  neynarApiKey?: string;
95
+ /** A Farcaster node's HTTP API for Farcaster proofs. Default: Quilibrium's public Hypersnap node (keyless). */
96
+ farcasterHub?: string;
94
97
  baseUrl?: string;
95
98
  /** Which PGPRegistry deployment to read: 'mainnet' (default) or 'sepolia'. */
96
99
  network?: 'mainnet' | 'sepolia' | 'local';
@@ -1715,7 +1718,24 @@ declare function identifyProof(notation: Notation): Proof | null;
1715
1718
  declare function displayUrl(proof: Proof): string;
1716
1719
  declare function proofHref(proof: Proof): string | null;
1717
1720
  declare function proofSecondaryHref(proof: Proof): string | null;
1718
- declare function verifyProof(proof: Proof, fingerprint: string, neynarApiKey?: string): Promise<PGPVerification>;
1721
+ /**
1722
+ * Farcaster proofs are read from a Farcaster node's HTTP API (`/v1/userNameProofByName`,
1723
+ * `/v1/castsByFid`). The default is Quilibrium's public Hypersnap node, which needs no key and
1724
+ * allows browser requests; it sees the visitor's IP and which account was checked. Point
1725
+ * `farcasterHub` at your own node to avoid that, or pass a Neynar key to use Neynar's hub.
1726
+ */
1727
+ declare const FARCASTER_HUB = "https://haatz.quilibrium.com";
1728
+ interface ProofOptions {
1729
+ /** A Farcaster node's HTTP API base URL. Default: FARCASTER_HUB (keyless). */
1730
+ farcasterHub?: string;
1731
+ /** Optional: read Farcaster through Neynar's hub with this key instead. */
1732
+ neynarApiKey?: string;
1733
+ }
1734
+ /**
1735
+ * Check one proof. The third argument is options; a plain string is still accepted as a
1736
+ * Neynar API key (the pre-1.3.7 signature).
1737
+ */
1738
+ declare function verifyProof(proof: Proof, fingerprint: string, opts?: ProofOptions | string): Promise<PGPVerification>;
1719
1739
 
1720
1740
  declare function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null>;
1721
1741
  /**
@@ -1807,20 +1827,29 @@ declare const IDENTITY_ERROR_TEXT: Record<IdentityErrorKind, string>;
1807
1827
  * chooses; loading an ordinary https:// link would tell that owner's server the IP and time of
1808
1828
  * everyone who views the card. So only images the owner can't watch load: content-addressed
1809
1829
  * ones (IPFS, Arweave, inline data, or an NFT whose metadata and image are content-addressed)
1810
- * through one public gateway, and euc.li, ENS Labs' host behind the ENS app's avatar upload
1830
+ * through public gateways, and euc.li, ENS Labs' host behind the ENS app's avatar upload
1811
1831
  * (most avatars; ENS Labs sees the view, the name's owner doesn't). Anything else: no avatar.
1812
1832
  */
1813
- declare const IPFS_GATEWAY = "https://ipfs.io/ipfs/";
1833
+ /**
1834
+ * Public IPFS gateways, tried in order: when an image fails to load, the next one is used.
1835
+ * Any single public gateway can stop serving (ipfs.io and dweb.link went "service worker only"
1836
+ * in 2026), so there is always a fallback. The gateway sees the viewer's IP and the avatar.
1837
+ */
1838
+ declare const IPFS_GATEWAYS: readonly ["https://ipfs.filebase.io/ipfs/", "https://gateway.pinata.cloud/ipfs/"];
1839
+ /** The first gateway in IPFS_GATEWAYS (kept for code that imported it before 1.3.6). */
1840
+ declare const IPFS_GATEWAY: string;
1814
1841
  declare const ARWEAVE_GATEWAY = "https://arweave.net/";
1815
1842
  /** An image URL safe to load for `uri`, or null if loading it would reach a host the owner picked. */
1816
1843
  declare function avatarUrl(uri: unknown): string | null;
1844
+ /** The same content through the other IPFS gateways, for retrying a failed load. [] for non-IPFS URLs. */
1845
+ declare function avatarFallbacks(url: string | null | undefined): string[];
1817
1846
  interface NftAvatar {
1818
1847
  chainId: number;
1819
1848
  standard: 'erc721' | 'erc1155';
1820
1849
  contract: `0x${string}`;
1821
1850
  tokenId: bigint;
1822
1851
  }
1823
- /** `eip155:1/erc721:0x…/123` (or erc1155) → its parts; null for anything else. */
1852
+ /** `eip155:1/erc721:0x…/123` (or erc1155; any case, as records in the wild vary) → its parts; null otherwise. */
1824
1853
  declare function parseNftAvatar(raw: unknown): NftAvatar | null;
1825
1854
  declare const NFT_AVATAR_ABI: readonly [{
1826
1855
  readonly type: "function";
@@ -1866,4 +1895,4 @@ declare function keyIdOf(fingerprint: string): Hex;
1866
1895
  /** A 16-hex long key ID (spaces/0x tolerated) → `bytes8`. */
1867
1896
  declare function keyIdToBytes(keyId: string): Hex | null;
1868
1897
 
1869
- export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, type AttestAuthorization, type Attestation, type AuthorizationAction, type EFPGraph, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, type EnsHint, type EnsHintState, type EnsTextReader, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, type IdentityErrorKind, type IdentityKitConfig, type IdentityLookupState, KNOWN_KINDS, type KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, type NetworkName, type NftAvatar, type Notation, type PGPKeyInfo, type PGPVerification, type ParsedRecord, type PointerEntry, type PointerRecord, type Proof, type ProofResult, REGISTRY_ABI, REGISTRY_ADDRESS, type ReattestAuthorization, type RecordData, type RecordReader, type RegistryDeployment, type RevokeAuthorization, type SetRecordAuthorization, type StrippedKey, type SubkeyInfo, type Theme, type ThurinIdentity, type UpdateKeyAuthorization, addPointer, attestTypedData, authorizationDigest, avatarUrl, bytesToFingerprint, chainFor, decodeRecord, displayUrl, encodeRecord, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint, fetchRecords, fingerprintHash, fingerprintToBytes, getRegistry, hasEmailUserID, identifyProof, identityErrorKind, isNetworkName, keyIdOf, keyIdToBytes, kindName, needsRpcProbe, nftAvatarImage, normalizeFingerprint, parseNftAvatar, parsePgpKey, parsePointer, parseRecord, proofHref, proofSecondaryHref, reattestTypedData, recordKind, registryDomain, renderPointer, revokeTypedData, setRecordTypedData, stripEmailUserIDs, updateKeyTypedData, verifyAttestation, verifyClearsigned, verifyProof };
1898
+ export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, type AttestAuthorization, type Attestation, type AuthorizationAction, type EFPGraph, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, type EnsHint, type EnsHintState, type EnsTextReader, FARCASTER_HUB, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, IPFS_GATEWAYS, type IdentityErrorKind, type IdentityKitConfig, type IdentityLookupState, KNOWN_KINDS, type KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, type NetworkName, type NftAvatar, type Notation, type PGPKeyInfo, type PGPVerification, type ParsedRecord, type PointerEntry, type PointerRecord, type Proof, type ProofOptions, type ProofResult, REGISTRY_ABI, REGISTRY_ADDRESS, type ReattestAuthorization, type RecordData, type RecordReader, type RegistryDeployment, type RevokeAuthorization, type SetRecordAuthorization, type StrippedKey, type SubkeyInfo, type Theme, type ThurinIdentity, type UpdateKeyAuthorization, addPointer, attestTypedData, authorizationDigest, avatarFallbacks, avatarUrl, bytesToFingerprint, chainFor, decodeRecord, displayUrl, encodeRecord, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint, fetchRecords, fingerprintHash, fingerprintToBytes, getRegistry, hasEmailUserID, identifyProof, identityErrorKind, isNetworkName, keyIdOf, keyIdToBytes, kindName, needsRpcProbe, nftAvatarImage, normalizeFingerprint, parseNftAvatar, parsePgpKey, parsePointer, parseRecord, proofHref, proofSecondaryHref, reattestTypedData, recordKind, registryDomain, renderPointer, revokeTypedData, setRecordTypedData, stripEmailUserIDs, updateKeyTypedData, verifyAttestation, verifyClearsigned, verifyProof };
package/dist/core.d.ts CHANGED
@@ -90,7 +90,10 @@ interface ThurinIdentity {
90
90
  type Theme = 'thurin' | 'dark' | 'light';
91
91
  interface IdentityKitConfig {
92
92
  rpcUrl?: string;
93
+ /** Optional: read Farcaster proofs through Neynar's hub with this key. Not needed since 1.3.7. */
93
94
  neynarApiKey?: string;
95
+ /** A Farcaster node's HTTP API for Farcaster proofs. Default: Quilibrium's public Hypersnap node (keyless). */
96
+ farcasterHub?: string;
94
97
  baseUrl?: string;
95
98
  /** Which PGPRegistry deployment to read: 'mainnet' (default) or 'sepolia'. */
96
99
  network?: 'mainnet' | 'sepolia' | 'local';
@@ -1715,7 +1718,24 @@ declare function identifyProof(notation: Notation): Proof | null;
1715
1718
  declare function displayUrl(proof: Proof): string;
1716
1719
  declare function proofHref(proof: Proof): string | null;
1717
1720
  declare function proofSecondaryHref(proof: Proof): string | null;
1718
- declare function verifyProof(proof: Proof, fingerprint: string, neynarApiKey?: string): Promise<PGPVerification>;
1721
+ /**
1722
+ * Farcaster proofs are read from a Farcaster node's HTTP API (`/v1/userNameProofByName`,
1723
+ * `/v1/castsByFid`). The default is Quilibrium's public Hypersnap node, which needs no key and
1724
+ * allows browser requests; it sees the visitor's IP and which account was checked. Point
1725
+ * `farcasterHub` at your own node to avoid that, or pass a Neynar key to use Neynar's hub.
1726
+ */
1727
+ declare const FARCASTER_HUB = "https://haatz.quilibrium.com";
1728
+ interface ProofOptions {
1729
+ /** A Farcaster node's HTTP API base URL. Default: FARCASTER_HUB (keyless). */
1730
+ farcasterHub?: string;
1731
+ /** Optional: read Farcaster through Neynar's hub with this key instead. */
1732
+ neynarApiKey?: string;
1733
+ }
1734
+ /**
1735
+ * Check one proof. The third argument is options; a plain string is still accepted as a
1736
+ * Neynar API key (the pre-1.3.7 signature).
1737
+ */
1738
+ declare function verifyProof(proof: Proof, fingerprint: string, opts?: ProofOptions | string): Promise<PGPVerification>;
1719
1739
 
1720
1740
  declare function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null>;
1721
1741
  /**
@@ -1807,20 +1827,29 @@ declare const IDENTITY_ERROR_TEXT: Record<IdentityErrorKind, string>;
1807
1827
  * chooses; loading an ordinary https:// link would tell that owner's server the IP and time of
1808
1828
  * everyone who views the card. So only images the owner can't watch load: content-addressed
1809
1829
  * ones (IPFS, Arweave, inline data, or an NFT whose metadata and image are content-addressed)
1810
- * through one public gateway, and euc.li, ENS Labs' host behind the ENS app's avatar upload
1830
+ * through public gateways, and euc.li, ENS Labs' host behind the ENS app's avatar upload
1811
1831
  * (most avatars; ENS Labs sees the view, the name's owner doesn't). Anything else: no avatar.
1812
1832
  */
1813
- declare const IPFS_GATEWAY = "https://ipfs.io/ipfs/";
1833
+ /**
1834
+ * Public IPFS gateways, tried in order: when an image fails to load, the next one is used.
1835
+ * Any single public gateway can stop serving (ipfs.io and dweb.link went "service worker only"
1836
+ * in 2026), so there is always a fallback. The gateway sees the viewer's IP and the avatar.
1837
+ */
1838
+ declare const IPFS_GATEWAYS: readonly ["https://ipfs.filebase.io/ipfs/", "https://gateway.pinata.cloud/ipfs/"];
1839
+ /** The first gateway in IPFS_GATEWAYS (kept for code that imported it before 1.3.6). */
1840
+ declare const IPFS_GATEWAY: string;
1814
1841
  declare const ARWEAVE_GATEWAY = "https://arweave.net/";
1815
1842
  /** An image URL safe to load for `uri`, or null if loading it would reach a host the owner picked. */
1816
1843
  declare function avatarUrl(uri: unknown): string | null;
1844
+ /** The same content through the other IPFS gateways, for retrying a failed load. [] for non-IPFS URLs. */
1845
+ declare function avatarFallbacks(url: string | null | undefined): string[];
1817
1846
  interface NftAvatar {
1818
1847
  chainId: number;
1819
1848
  standard: 'erc721' | 'erc1155';
1820
1849
  contract: `0x${string}`;
1821
1850
  tokenId: bigint;
1822
1851
  }
1823
- /** `eip155:1/erc721:0x…/123` (or erc1155) → its parts; null for anything else. */
1852
+ /** `eip155:1/erc721:0x…/123` (or erc1155; any case, as records in the wild vary) → its parts; null otherwise. */
1824
1853
  declare function parseNftAvatar(raw: unknown): NftAvatar | null;
1825
1854
  declare const NFT_AVATAR_ABI: readonly [{
1826
1855
  readonly type: "function";
@@ -1866,4 +1895,4 @@ declare function keyIdOf(fingerprint: string): Hex;
1866
1895
  /** A 16-hex long key ID (spaces/0x tolerated) → `bytes8`. */
1867
1896
  declare function keyIdToBytes(keyId: string): Hex | null;
1868
1897
 
1869
- export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, type AttestAuthorization, type Attestation, type AuthorizationAction, type EFPGraph, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, type EnsHint, type EnsHintState, type EnsTextReader, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, type IdentityErrorKind, type IdentityKitConfig, type IdentityLookupState, KNOWN_KINDS, type KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, type NetworkName, type NftAvatar, type Notation, type PGPKeyInfo, type PGPVerification, type ParsedRecord, type PointerEntry, type PointerRecord, type Proof, type ProofResult, REGISTRY_ABI, REGISTRY_ADDRESS, type ReattestAuthorization, type RecordData, type RecordReader, type RegistryDeployment, type RevokeAuthorization, type SetRecordAuthorization, type StrippedKey, type SubkeyInfo, type Theme, type ThurinIdentity, type UpdateKeyAuthorization, addPointer, attestTypedData, authorizationDigest, avatarUrl, bytesToFingerprint, chainFor, decodeRecord, displayUrl, encodeRecord, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint, fetchRecords, fingerprintHash, fingerprintToBytes, getRegistry, hasEmailUserID, identifyProof, identityErrorKind, isNetworkName, keyIdOf, keyIdToBytes, kindName, needsRpcProbe, nftAvatarImage, normalizeFingerprint, parseNftAvatar, parsePgpKey, parsePointer, parseRecord, proofHref, proofSecondaryHref, reattestTypedData, recordKind, registryDomain, renderPointer, revokeTypedData, setRecordTypedData, stripEmailUserIDs, updateKeyTypedData, verifyAttestation, verifyClearsigned, verifyProof };
1898
+ export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, type AttestAuthorization, type Attestation, type AuthorizationAction, type EFPGraph, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, type EnsHint, type EnsHintState, type EnsTextReader, FARCASTER_HUB, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, IPFS_GATEWAYS, type IdentityErrorKind, type IdentityKitConfig, type IdentityLookupState, KNOWN_KINDS, type KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, type NetworkName, type NftAvatar, type Notation, type PGPKeyInfo, type PGPVerification, type ParsedRecord, type PointerEntry, type PointerRecord, type Proof, type ProofOptions, type ProofResult, REGISTRY_ABI, REGISTRY_ADDRESS, type ReattestAuthorization, type RecordData, type RecordReader, type RegistryDeployment, type RevokeAuthorization, type SetRecordAuthorization, type StrippedKey, type SubkeyInfo, type Theme, type ThurinIdentity, type UpdateKeyAuthorization, addPointer, attestTypedData, authorizationDigest, avatarFallbacks, avatarUrl, bytesToFingerprint, chainFor, decodeRecord, displayUrl, encodeRecord, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint, fetchRecords, fingerprintHash, fingerprintToBytes, getRegistry, hasEmailUserID, identifyProof, identityErrorKind, isNetworkName, keyIdOf, keyIdToBytes, kindName, needsRpcProbe, nftAvatarImage, normalizeFingerprint, parseNftAvatar, parsePgpKey, parsePointer, parseRecord, proofHref, proofSecondaryHref, reattestTypedData, recordKind, registryDomain, renderPointer, revokeTypedData, setRecordTypedData, stripEmailUserIDs, updateKeyTypedData, verifyAttestation, verifyClearsigned, verifyProof };
package/dist/core.js CHANGED
@@ -5,9 +5,11 @@ import {
5
5
  EIP712_VERSION,
6
6
  ENS_HINT_KEY,
7
7
  ENS_TEXT_RESOLVER_ABI,
8
+ FARCASTER_HUB,
8
9
  IDENTITY_ERROR_TEXT,
9
10
  IDENTITY_KINDS,
10
11
  IPFS_GATEWAY,
12
+ IPFS_GATEWAYS,
11
13
  KNOWN_KINDS,
12
14
  MAX_RECORD_BYTES,
13
15
  NETWORKS,
@@ -17,6 +19,7 @@ import {
17
19
  addPointer,
18
20
  attestTypedData,
19
21
  authorizationDigest,
22
+ avatarFallbacks,
20
23
  avatarUrl,
21
24
  bytesToFingerprint,
22
25
  chainFor,
@@ -59,7 +62,7 @@ import {
59
62
  verifyAttestation,
60
63
  verifyClearsigned,
61
64
  verifyProof
62
- } from "./chunk-CF64QQZO.js";
65
+ } from "./chunk-ROQWHCHP.js";
63
66
  export {
64
67
  ARWEAVE_GATEWAY,
65
68
  AUTHORIZATION_TYPES,
@@ -67,9 +70,11 @@ export {
67
70
  EIP712_VERSION,
68
71
  ENS_HINT_KEY,
69
72
  ENS_TEXT_RESOLVER_ABI,
73
+ FARCASTER_HUB,
70
74
  IDENTITY_ERROR_TEXT,
71
75
  IDENTITY_KINDS,
72
76
  IPFS_GATEWAY,
77
+ IPFS_GATEWAYS,
73
78
  KNOWN_KINDS,
74
79
  MAX_RECORD_BYTES,
75
80
  NETWORKS,
@@ -79,6 +84,7 @@ export {
79
84
  addPointer,
80
85
  attestTypedData,
81
86
  authorizationDigest,
87
+ avatarFallbacks,
82
88
  avatarUrl,
83
89
  bytesToFingerprint,
84
90
  chainFor,
@@ -30400,17 +30400,21 @@ ${prettyStateOverride(stateOverride)}`;
30400
30400
  children,
30401
30401
  rpcUrl,
30402
30402
  neynarApiKey,
30403
+ farcasterHub,
30403
30404
  baseUrl = "https://thurin.id",
30404
30405
  network = "mainnet",
30405
30406
  registryAddress
30406
30407
  }) {
30407
30408
  const config = (0, import_react8.useMemo)(
30408
- () => ({ rpcUrl, neynarApiKey, baseUrl, network, registryAddress }),
30409
- [rpcUrl, neynarApiKey, baseUrl, network, registryAddress]
30409
+ () => ({ rpcUrl, neynarApiKey, farcasterHub, baseUrl, network, registryAddress }),
30410
+ [rpcUrl, neynarApiKey, farcasterHub, baseUrl, network, registryAddress]
30410
30411
  );
30411
30412
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IdentityKitContext.Provider, { value: config, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WagmiDetector, { rpcUrl, network, children }) });
30412
30413
  }
30413
30414
 
30415
+ // src/components/ThurinCard/ThurinCard.tsx
30416
+ var import_react9 = __toESM(require_react(), 1);
30417
+
30414
30418
  // src/core/identityError.ts
30415
30419
  function needsRpcProbe(s2) {
30416
30420
  return s2.ensEmpty || s2.ensFailed || s2.claimsFailed;
@@ -31637,29 +31641,27 @@ ${prettyStateOverride(stateOverride)}`;
31637
31641
  return { verified: false, reason: `DNS fetch failed: ${err.message}` };
31638
31642
  }
31639
31643
  }
31644
+ var FARCASTER_HUB = "https://haatz.quilibrium.com";
31640
31645
  var NEYNAR_HUB = "https://hub-api.neynar.com";
31641
- async function resolveFid(username, apiKey) {
31642
- const resp = await fetch(
31643
- `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,
31644
- { headers: { "x-api-key": apiKey } }
31645
- );
31646
- if (!resp.ok) return null;
31647
- const data = await resp.json();
31648
- return data.fid ?? null;
31649
- }
31650
- async function verifyFarcaster(proof, fingerprint, neynarApiKey) {
31651
- if (!neynarApiKey) {
31652
- return { verified: false, reason: "Farcaster verification requires a Neynar API key" };
31653
- }
31646
+ function farcasterSource(opts) {
31647
+ if (opts.farcasterHub) return { base: opts.farcasterHub.replace(/\/+$/, ""), headers: {} };
31648
+ if (opts.neynarApiKey) return { base: NEYNAR_HUB, headers: { "x-api-key": opts.neynarApiKey } };
31649
+ return { base: FARCASTER_HUB, headers: {} };
31650
+ }
31651
+ async function verifyFarcaster(proof, fingerprint, opts = {}) {
31652
+ const { base, headers } = farcasterSource(opts);
31653
+ const host = base.replace(/^https?:\/\//, "");
31654
31654
  try {
31655
- const fid = await resolveFid(proof.user, neynarApiKey);
31655
+ const nameResp = await fetch(`${base}/v1/userNameProofByName?name=${encodeURIComponent(proof.user)}`, { headers });
31656
+ if (nameResp.status === 404) return { verified: false, reason: `Could not resolve Farcaster user "${proof.user}"` };
31657
+ if (!nameResp.ok) return { verified: false, reason: `Couldn't check: the Farcaster node (${host}) returned ${nameResp.status}` };
31658
+ const fid = (await nameResp.json()).fid;
31656
31659
  if (!fid) return { verified: false, reason: `Could not resolve Farcaster user "${proof.user}"` };
31657
- const headers = { "x-api-key": neynarApiKey };
31658
31660
  let pageToken = "";
31659
31661
  for (let page = 0; page < 5; page++) {
31660
- const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ""}`;
31662
+ const url = `${base}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ""}`;
31661
31663
  const resp = await fetch(url, { headers });
31662
- if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` };
31664
+ if (!resp.ok) return { verified: false, reason: `Couldn't check: the Farcaster node (${host}) returned ${resp.status}` };
31663
31665
  const data = await resp.json();
31664
31666
  for (const msg of data.messages || []) {
31665
31667
  if (msg.hash && msg.hash.startsWith(proof.castHash)) {
@@ -31674,7 +31676,7 @@ ${prettyStateOverride(stateOverride)}`;
31674
31676
  }
31675
31677
  return { verified: false, reason: "Cast not found" };
31676
31678
  } catch (err) {
31677
- return { verified: false, reason: `Farcaster fetch failed: ${err.message}` };
31679
+ return { verified: false, reason: `Couldn't check: the Farcaster node (${host}) didn't answer (${err.message})` };
31678
31680
  }
31679
31681
  }
31680
31682
  async function verifyCodeberg(proof, fingerprint) {
@@ -31727,10 +31729,10 @@ ${prettyStateOverride(stateOverride)}`;
31727
31729
  codeberg: verifyCodeberg,
31728
31730
  mastodon: verifyMastodon
31729
31731
  };
31730
- async function verifyProof(proof, fingerprint, neynarApiKey) {
31732
+ async function verifyProof(proof, fingerprint, opts) {
31731
31733
  const fn2 = verifiers[proof.provider];
31732
31734
  if (!fn2) return { verified: false, reason: "Unknown provider" };
31733
- return fn2(proof, fingerprint, neynarApiKey);
31735
+ return fn2(proof, fingerprint, typeof opts === "string" ? { neynarApiKey: opts } : opts ?? {});
31734
31736
  }
31735
31737
 
31736
31738
  // src/hooks/usePGPProofs.ts
@@ -31747,7 +31749,7 @@ ${prettyStateOverride(stateOverride)}`;
31747
31749
  const identified = keyInfo.notations.map((n2) => identifyProof(n2)).filter((p2) => p2 !== null && p2.provider !== "unknown");
31748
31750
  const proofs = await Promise.all(
31749
31751
  identified.map(async (proof) => {
31750
- const result = await verifyProof(proof, fingerprint, config.neynarApiKey);
31752
+ const result = await verifyProof(proof, fingerprint, { neynarApiKey: config.neynarApiKey, farcasterHub: config.farcasterHub });
31751
31753
  return {
31752
31754
  provider: proof.provider,
31753
31755
  label: proof.label,
@@ -31785,7 +31787,8 @@ ${prettyStateOverride(stateOverride)}`;
31785
31787
  }
31786
31788
 
31787
31789
  // src/core/avatar.ts
31788
- var IPFS_GATEWAY = "https://ipfs.io/ipfs/";
31790
+ var IPFS_GATEWAYS = ["https://ipfs.filebase.io/ipfs/", "https://gateway.pinata.cloud/ipfs/"];
31791
+ var IPFS_GATEWAY = IPFS_GATEWAYS[0];
31789
31792
  var ARWEAVE_GATEWAY = "https://arweave.net/";
31790
31793
  function avatarUrl(uri) {
31791
31794
  if (typeof uri !== "string") return null;
@@ -31800,9 +31803,14 @@ ${prettyStateOverride(stateOverride)}`;
31800
31803
  if (m2) return IPFS_GATEWAY + m2[1];
31801
31804
  return null;
31802
31805
  }
31806
+ function avatarFallbacks(url) {
31807
+ if (!url || !url.startsWith(IPFS_GATEWAYS[0])) return [];
31808
+ const path = url.slice(IPFS_GATEWAYS[0].length);
31809
+ return IPFS_GATEWAYS.slice(1).map((g2) => g2 + path);
31810
+ }
31803
31811
  function parseNftAvatar(raw) {
31804
- const m2 = typeof raw === "string" && raw.trim().match(/^eip155:(\d+)\/(erc721|erc1155):(0x[0-9a-fA-F]{40})\/(\d+)$/);
31805
- return m2 ? { chainId: Number(m2[1]), standard: m2[2], contract: m2[3], tokenId: BigInt(m2[4]) } : null;
31812
+ const m2 = typeof raw === "string" && raw.trim().match(/^eip155:(\d+)\/(erc721|erc1155):(0x[0-9a-fA-F]{40})\/(\d+)$/i);
31813
+ return m2 ? { chainId: Number(m2[1]), standard: m2[2].toLowerCase(), contract: m2[3], tokenId: BigInt(m2[4]) } : null;
31806
31814
  }
31807
31815
  var NFT_AVATAR_ABI = [
31808
31816
  { type: "function", name: "tokenURI", stateMutability: "view", inputs: [{ type: "uint256" }], outputs: [{ type: "string" }] },
@@ -31816,9 +31824,17 @@ ${prettyStateOverride(stateOverride)}`;
31816
31824
  else {
31817
31825
  const url = uri.startsWith("data:") ? null : avatarUrl(uri);
31818
31826
  if (!url) return null;
31819
- const res = await fetchFn(url);
31820
- if (!res.ok) return null;
31821
- meta = await res.json();
31827
+ for (const candidate of [url, ...avatarFallbacks(url)]) {
31828
+ try {
31829
+ const res = await fetchFn(candidate);
31830
+ if (res.ok) {
31831
+ meta = await res.json();
31832
+ break;
31833
+ }
31834
+ } catch {
31835
+ }
31836
+ }
31837
+ if (!meta) return null;
31822
31838
  }
31823
31839
  return avatarUrl(meta?.image ?? meta?.image_url);
31824
31840
  }
@@ -31936,6 +31952,14 @@ ${prettyStateOverride(stateOverride)}`;
31936
31952
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M50 65 L50 53", fill: "none", stroke: "#c9a227", strokeWidth: "4", strokeLinecap: "round" })
31937
31953
  ] });
31938
31954
  }
31955
+ function Avatar({ src, alt }) {
31956
+ const [tries, setTries] = (0, import_react9.useState)([]);
31957
+ (0, import_react9.useEffect)(() => {
31958
+ setTries(src ? [src, ...avatarFallbacks(src)] : []);
31959
+ }, [src]);
31960
+ if (!tries.length) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ThurinLogo, {});
31961
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { className: "thurin-card-avatar", src: tries[0], alt, onError: () => setTries((t2) => t2.slice(1)) });
31962
+ }
31939
31963
  function ThurinCard({ ens, address, theme = "thurin" }) {
31940
31964
  const input = ens || address;
31941
31965
  const identity = useThurinIdentity(input);
@@ -31962,14 +31986,7 @@ ${prettyStateOverride(stateOverride)}`;
31962
31986
  const hasVerifiedPgp = identity.claims.some((c2) => c2.verification?.verified && !c2.revoked);
31963
31987
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "thurin-card", "data-thurin-theme": theme, children: [
31964
31988
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("a", { className: "thurin-card-header", href: profileUrl || void 0, target: "_blank", rel: "noopener noreferrer", children: [
31965
- identity.ensAvatar ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
31966
- "img",
31967
- {
31968
- className: "thurin-card-avatar",
31969
- src: identity.ensAvatar,
31970
- alt: identity.ensName || ""
31971
- }
31972
- ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ThurinLogo, {}),
31989
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { src: identity.ensAvatar, alt: identity.ensName || "" }),
31973
31990
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
31974
31991
  identity.ensName && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "thurin-card-name", children: identity.ensName }),
31975
31992
  displayAddress && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "thurin-card-address", children: displayAddress })
@@ -32036,6 +32053,7 @@ ${prettyStateOverride(stateOverride)}`;
32036
32053
  const theme = el2.dataset.theme || "thurin";
32037
32054
  const rpcUrl = el2.dataset.rpcUrl;
32038
32055
  const neynarApiKey = el2.dataset.neynarKey;
32056
+ const farcasterHub = el2.dataset.farcasterHub;
32039
32057
  const baseUrl = el2.dataset.baseUrl;
32040
32058
  const network = isNetworkName(el2.dataset.network) ? el2.dataset.network : "mainnet";
32041
32059
  const registryAddress = el2.dataset.registryAddress;
@@ -32048,7 +32066,7 @@ ${prettyStateOverride(stateOverride)}`;
32048
32066
  shadow.appendChild(container);
32049
32067
  const root = (0, import_client.createRoot)(container);
32050
32068
  const render = (t2) => root.render(
32051
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IdentityKitProvider, { rpcUrl, neynarApiKey, network, registryAddress, baseUrl, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ThurinCard, { ...props, theme: t2 }) })
32069
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IdentityKitProvider, { rpcUrl, neynarApiKey, farcasterHub, network, registryAddress, baseUrl, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ThurinCard, { ...props, theme: t2 }) })
32052
32070
  );
32053
32071
  render(theme);
32054
32072
  new MutationObserver(() => {