@thurinlabs/identity-kit 1.3.4 → 1.3.6

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/index.cjs CHANGED
@@ -59,7 +59,9 @@
59
59
 
60
60
 
61
61
 
62
- var _chunkYTO7Z5SIcjs = require('./chunk-YTO7Z5SI.cjs');
62
+
63
+
64
+ var _chunkI3Y63ZPKcjs = require('./chunk-I3Y63ZPK.cjs');
63
65
 
64
66
  // src/provider.tsx
65
67
  var _react = require('react');
@@ -89,7 +91,7 @@ var defaultQueryClient = new (0, _reactquery.QueryClient)({
89
91
  }
90
92
  });
91
93
  function createDefaultWagmiConfig(rpcUrl, network) {
92
- const url = rpcUrl || _chunkYTO7Z5SIcjs.getRegistry.call(void 0, network).defaultRpcUrl;
94
+ const url = rpcUrl || _chunkI3Y63ZPKcjs.getRegistry.call(void 0, network).defaultRpcUrl;
93
95
  if (network === "sepolia") return _wagmi.createConfig.call(void 0, { chains: [_chains.sepolia], transports: { [_chains.sepolia.id]: _wagmi.http.call(void 0, url) } });
94
96
  if (network === "local") return _wagmi.createConfig.call(void 0, { chains: [_chains.foundry], transports: { [_chains.foundry.id]: _wagmi.http.call(void 0, url) } });
95
97
  return _wagmi.createConfig.call(void 0, { chains: [_chains.mainnet], transports: { [_chains.mainnet.id]: _wagmi.http.call(void 0, url) } });
@@ -122,8 +124,10 @@ function IdentityKitProvider({
122
124
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IdentityKitContext.Provider, { value: config, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WagmiDetector, { rpcUrl, network, children }) });
123
125
  }
124
126
 
125
- // src/hooks/useThurinIdentity.ts
127
+ // src/components/ThurinCard/ThurinCard.tsx
128
+
126
129
 
130
+ // src/hooks/useThurinIdentity.ts
127
131
 
128
132
  var _ens = require('viem/ens');
129
133
 
@@ -133,12 +137,12 @@ var _ens = require('viem/ens');
133
137
  var _viem = require('viem');
134
138
  function useAttestations(address) {
135
139
  const config = useIdentityKitConfig();
136
- const registry = _chunkYTO7Z5SIcjs.getRegistry.call(void 0, config.network, config.registryAddress);
137
- const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, config.network);
140
+ const registry = _chunkI3Y63ZPKcjs.getRegistry.call(void 0, config.network, config.registryAddress);
141
+ const chain = _chunkI3Y63ZPKcjs.chainFor.call(void 0, config.network);
138
142
  const owner = address;
139
143
  const { data: rows, isLoading: rowsLoading, isFetched: rowsFetched, error: rowsError, refetch: refetchRows } = _wagmi.useReadContract.call(void 0, {
140
144
  address: registry.address,
141
- abi: _chunkYTO7Z5SIcjs.REGISTRY_ABI,
145
+ abi: _chunkI3Y63ZPKcjs.REGISTRY_ABI,
142
146
  functionName: "attestationsOf",
143
147
  args: owner ? [owner] : void 0,
144
148
  chainId: chain.id,
@@ -147,7 +151,7 @@ function useAttestations(address) {
147
151
  const count = _nullishCoalesce(_optionalChain([rows, 'optionalAccess', _2 => _2.length]), () => ( 0));
148
152
  const contracts = owner && rows ? rows.map((_, i) => ({
149
153
  address: registry.address,
150
- abi: _chunkYTO7Z5SIcjs.REGISTRY_ABI,
154
+ abi: _chunkI3Y63ZPKcjs.REGISTRY_ABI,
151
155
  functionName: "getPayload",
152
156
  args: [owner, BigInt(i)],
153
157
  chainId: chain.id
@@ -172,8 +176,8 @@ function useAttestations(address) {
172
176
  pgpSignature = _viem.hexToString.call(void 0, sigHex);
173
177
  pgpPublicKey = _viem.hexToString.call(void 0, keyHex);
174
178
  }
175
- const fingerprint = _chunkYTO7Z5SIcjs.bytesToFingerprint.call(void 0, row.fingerprint);
176
- const verification = pgpPublicKey && pgpSignature ? await _chunkYTO7Z5SIcjs.verifyAttestation.call(void 0, { pgpPublicKey, pgpSignature, fingerprint, ethAddress: address }) : null;
179
+ const fingerprint = _chunkI3Y63ZPKcjs.bytesToFingerprint.call(void 0, row.fingerprint);
180
+ const verification = pgpPublicKey && pgpSignature ? await _chunkI3Y63ZPKcjs.verifyAttestation.call(void 0, { pgpPublicKey, pgpSignature, fingerprint, ethAddress: address }) : null;
177
181
  const revokedAt = Number(row.revokedAt);
178
182
  results.push({
179
183
  index: i,
@@ -218,7 +222,7 @@ function useAttestations(address) {
218
222
  function useEFPGraph(address) {
219
223
  const { data, isLoading } = _reactquery.useQuery.call(void 0, {
220
224
  queryKey: ["efp-graph", address],
221
- queryFn: () => _chunkYTO7Z5SIcjs.fetchEFPGraph.call(void 0, address),
225
+ queryFn: () => _chunkI3Y63ZPKcjs.fetchEFPGraph.call(void 0, address),
222
226
  enabled: !!address,
223
227
  staleTime: 3e5
224
228
  });
@@ -238,19 +242,19 @@ function usePGPProofs(fingerprint, armoredKey) {
238
242
  queryKey: ["pgp-proofs", fingerprint, _nullishCoalesce(_optionalChain([armoredKey, 'optionalAccess', _6 => _6.length]), () => ( 0))],
239
243
  queryFn: async () => {
240
244
  if (!fingerprint || !armoredKey) return { keyInfo: null, proofs: [] };
241
- const keyInfo = await _chunkYTO7Z5SIcjs.parsePgpKey.call(void 0, armoredKey);
245
+ const keyInfo = await _chunkI3Y63ZPKcjs.parsePgpKey.call(void 0, armoredKey);
242
246
  if (!keyInfo) return { keyInfo: null, proofs: [] };
243
- const identified = keyInfo.notations.map((n) => _chunkYTO7Z5SIcjs.identifyProof.call(void 0, n)).filter((p) => p !== null && p.provider !== "unknown");
247
+ const identified = keyInfo.notations.map((n) => _chunkI3Y63ZPKcjs.identifyProof.call(void 0, n)).filter((p) => p !== null && p.provider !== "unknown");
244
248
  const proofs = await Promise.all(
245
249
  identified.map(async (proof) => {
246
- const result = await _chunkYTO7Z5SIcjs.verifyProof.call(void 0, proof, fingerprint, config.neynarApiKey);
250
+ const result = await _chunkI3Y63ZPKcjs.verifyProof.call(void 0, proof, fingerprint, config.neynarApiKey);
247
251
  return {
248
252
  provider: proof.provider,
249
253
  label: proof.label,
250
254
  url: proof.url,
251
- displayUrl: _chunkYTO7Z5SIcjs.displayUrl.call(void 0, proof),
252
- href: _chunkYTO7Z5SIcjs.proofHref.call(void 0, proof),
253
- secondaryHref: _chunkYTO7Z5SIcjs.proofSecondaryHref.call(void 0, proof),
255
+ displayUrl: _chunkI3Y63ZPKcjs.displayUrl.call(void 0, proof),
256
+ href: _chunkI3Y63ZPKcjs.proofHref.call(void 0, proof),
257
+ secondaryHref: _chunkI3Y63ZPKcjs.proofSecondaryHref.call(void 0, proof),
254
258
  status: result.verified ? "verified" : "unverified",
255
259
  reason: result.reason
256
260
  };
@@ -285,11 +289,11 @@ function usePGPProofs(fingerprint, armoredKey) {
285
289
 
286
290
  function useSafeAvatar(name, chainId) {
287
291
  const { data: raw } = _wagmi.useEnsText.call(void 0, { name, key: "avatar", chainId, query: { enabled: !!name } });
288
- const direct = _chunkYTO7Z5SIcjs.avatarUrl.call(void 0, raw);
289
- const nft = direct ? null : _chunkYTO7Z5SIcjs.parseNftAvatar.call(void 0, raw);
292
+ const direct = _chunkI3Y63ZPKcjs.avatarUrl.call(void 0, raw);
293
+ const nft = direct ? null : _chunkI3Y63ZPKcjs.parseNftAvatar.call(void 0, raw);
290
294
  const { data: tokenUri } = _wagmi.useReadContract.call(void 0, {
291
295
  address: _optionalChain([nft, 'optionalAccess', _9 => _9.contract]),
292
- abi: _chunkYTO7Z5SIcjs.NFT_AVATAR_ABI,
296
+ abi: _chunkI3Y63ZPKcjs.NFT_AVATAR_ABI,
293
297
  functionName: _optionalChain([nft, 'optionalAccess', _10 => _10.standard]) === "erc1155" ? "uri" : "tokenURI",
294
298
  args: nft ? [nft.tokenId] : void 0,
295
299
  chainId,
@@ -297,7 +301,7 @@ function useSafeAvatar(name, chainId) {
297
301
  });
298
302
  const { data: image } = _reactquery.useQuery.call(void 0, {
299
303
  queryKey: ["thurin-nft-avatar", tokenUri, _optionalChain([nft, 'optionalAccess', _11 => _11.tokenId, 'access', _12 => _12.toString, 'call', _13 => _13()])],
300
- queryFn: () => _chunkYTO7Z5SIcjs.nftAvatarImage.call(void 0, tokenUri, nft.tokenId).catch(() => null),
304
+ queryFn: () => _chunkI3Y63ZPKcjs.nftAvatarImage.call(void 0, tokenUri, nft.tokenId).catch(() => null),
301
305
  enabled: typeof tokenUri === "string" && !!nft
302
306
  });
303
307
  return _nullishCoalesce(_nullishCoalesce(direct, () => ( image)), () => ( null));
@@ -315,7 +319,7 @@ function safeNormalize(name) {
315
319
  }
316
320
  }
317
321
  function useThurinIdentity(ensOrAddress) {
318
- const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, useIdentityKitConfig().network);
322
+ const chain = _chunkI3Y63ZPKcjs.chainFor.call(void 0, useIdentityKitConfig().network);
319
323
  const isAddr = ensOrAddress ? isAddress(ensOrAddress) : false;
320
324
  const ensInput = ensOrAddress && !isAddr ? safeNormalize(ensOrAddress) : void 0;
321
325
  const { data: resolvedAddress, error: ensError, isFetched: ensFetched, refetch: refetchEns } = _wagmi.useEnsAddress.call(void 0, {
@@ -350,17 +354,14 @@ function useThurinIdentity(ensOrAddress) {
350
354
  } = usePGPProofs(currentFingerprint, _nullishCoalesce(_optionalChain([currentClaim, 'optionalAccess', _16 => _16.pgpPublicKey]), () => ( null)));
351
355
  const { efp, isLoading: efpLoading } = useEFPGraph(address);
352
356
  const lookup = { ensEmpty: !!ensInput && ensFetched && !resolvedAddress, ensFailed: !!ensError, claimsFailed: !!claimsError };
353
- const probeNeeded = _chunkYTO7Z5SIcjs.needsRpcProbe.call(void 0, lookup);
354
- const client = _wagmi.usePublicClient.call(void 0, { chainId: chain.id });
355
- const probe = _reactquery.useQuery.call(void 0, {
356
- queryKey: ["thurin-rpc-probe", chain.id, ensOrAddress],
357
- queryFn: () => client.getBlockNumber(),
358
- enabled: probeNeeded && !!client,
359
- retry: 0,
360
- staleTime: 0
357
+ const probeNeeded = _chunkI3Y63ZPKcjs.needsRpcProbe.call(void 0, lookup);
358
+ const probe = _wagmi.useBlockNumber.call(void 0, {
359
+ chainId: chain.id,
360
+ scopeKey: `thurin-rpc-probe:${_nullishCoalesce(ensOrAddress, () => ( ""))}`,
361
+ query: { enabled: probeNeeded, retry: 0, staleTime: 0, gcTime: 0 }
361
362
  });
362
363
  const rpcAnswered = !probeNeeded || probe.isFetching ? void 0 : probe.isSuccess ? true : probe.isError ? false : void 0;
363
- const errorKind = _chunkYTO7Z5SIcjs.identityErrorKind.call(void 0, { ...lookup, rpcAnswered });
364
+ const errorKind = _chunkI3Y63ZPKcjs.identityErrorKind.call(void 0, { ...lookup, rpcAnswered });
364
365
  const probing = probeNeeded && rpcAnswered === void 0;
365
366
  const retry = () => {
366
367
  if (ensInput) refetchEns();
@@ -381,7 +382,7 @@ function useThurinIdentity(ensOrAddress) {
381
382
  // "Not finished" counts as loading, including queries paused in a background tab: the card
382
383
  // must not render defaults (zeros) for an identity it hasn't looked up yet.
383
384
  isLoading: !!ensInput && !ensFetched || claimsLoading || proofsLoading || efpLoading || probing,
384
- error: errorKind ? new Error(_chunkYTO7Z5SIcjs.IDENTITY_ERROR_TEXT[errorKind]) : null,
385
+ error: errorKind ? new Error(_chunkI3Y63ZPKcjs.IDENTITY_ERROR_TEXT[errorKind]) : null,
385
386
  errorKind,
386
387
  retry
387
388
  };
@@ -398,6 +399,14 @@ function ThurinLogo() {
398
399
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M50 65 L50 53", fill: "none", stroke: "#c9a227", strokeWidth: "4", strokeLinecap: "round" })
399
400
  ] });
400
401
  }
402
+ function Avatar({ src, alt }) {
403
+ const [tries, setTries] = _react.useState.call(void 0, []);
404
+ _react.useEffect.call(void 0, () => {
405
+ setTries(src ? [src, ..._chunkI3Y63ZPKcjs.avatarFallbacks.call(void 0, src)] : []);
406
+ }, [src]);
407
+ if (!tries.length) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ThurinLogo, {});
408
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { className: "thurin-card-avatar", src: tries[0], alt, onError: () => setTries((t) => t.slice(1)) });
409
+ }
401
410
  function ThurinCard({ ens, address, theme = "thurin" }) {
402
411
  const input = ens || address;
403
412
  const identity = useThurinIdentity(input);
@@ -424,14 +433,7 @@ function ThurinCard({ ens, address, theme = "thurin" }) {
424
433
  const hasVerifiedPgp = identity.claims.some((c) => _optionalChain([c, 'access', _19 => _19.verification, 'optionalAccess', _20 => _20.verified]) && !c.revoked);
425
434
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card", "data-thurin-theme": theme, children: [
426
435
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "a", { className: "thurin-card-header", href: profileUrl || void 0, target: "_blank", rel: "noopener noreferrer", children: [
427
- identity.ensAvatar ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
428
- "img",
429
- {
430
- className: "thurin-card-avatar",
431
- src: identity.ensAvatar,
432
- alt: identity.ensName || ""
433
- }
434
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ThurinLogo, {}),
436
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Avatar, { src: identity.ensAvatar, alt: identity.ensName || "" }),
435
437
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
436
438
  identity.ensName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "thurin-card-name", children: identity.ensName }),
437
439
  displayAddress && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "thurin-card-address", children: displayAddress })
@@ -487,15 +489,15 @@ function safeNormalize2(name) {
487
489
  }
488
490
  }
489
491
  function useEnsHint(name, verifiedFingerprint) {
490
- const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, useIdentityKitConfig().network);
492
+ const chain = _chunkI3Y63ZPKcjs.chainFor.call(void 0, useIdentityKitConfig().network);
491
493
  const ensName = name ? safeNormalize2(name) : void 0;
492
494
  const { data, isLoading, refetch } = _wagmi.useEnsText.call(void 0, {
493
495
  name: ensName,
494
- key: _chunkYTO7Z5SIcjs.ENS_HINT_KEY,
496
+ key: _chunkI3Y63ZPKcjs.ENS_HINT_KEY,
495
497
  chainId: chain.id,
496
498
  query: { enabled: !!ensName }
497
499
  });
498
- return { ..._chunkYTO7Z5SIcjs.ensHintFor.call(void 0, _nullishCoalesce(data, () => ( null)), verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => {
500
+ return { ..._chunkI3Y63ZPKcjs.ensHintFor.call(void 0, _nullishCoalesce(data, () => ( null)), verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => {
499
501
  void refetch();
500
502
  } };
501
503
  }
@@ -503,20 +505,20 @@ function useEnsHint(name, verifiedFingerprint) {
503
505
  // src/hooks/useRecords.ts
504
506
 
505
507
 
506
- function useRecords(address, index, kinds = _chunkYTO7Z5SIcjs.IDENTITY_KINDS, armoredKey) {
508
+ function useRecords(address, index, kinds = _chunkI3Y63ZPKcjs.IDENTITY_KINDS, armoredKey) {
507
509
  const config = useIdentityKitConfig();
508
- const registry = _chunkYTO7Z5SIcjs.getRegistry.call(void 0, config.network, config.registryAddress);
509
- const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, config.network);
510
+ const registry = _chunkI3Y63ZPKcjs.getRegistry.call(void 0, config.network, config.registryAddress);
511
+ const chain = _chunkI3Y63ZPKcjs.chainFor.call(void 0, config.network);
510
512
  const owner = address;
511
513
  const enabled = !!owner && index !== void 0 && index !== null;
512
- const contracts = enabled ? kinds.map((kind) => ({ address: registry.address, abi: _chunkYTO7Z5SIcjs.REGISTRY_ABI, functionName: "record", args: [owner, BigInt(index), _chunkYTO7Z5SIcjs.recordKind.call(void 0, kind)], chainId: chain.id })) : [];
514
+ const contracts = enabled ? kinds.map((kind) => ({ address: registry.address, abi: _chunkI3Y63ZPKcjs.REGISTRY_ABI, functionName: "record", args: [owner, BigInt(index), _chunkI3Y63ZPKcjs.recordKind.call(void 0, kind)], chainId: chain.id })) : [];
513
515
  const { data: raw, isLoading: readLoading, refetch } = _wagmi.useReadContracts.call(void 0, { contracts, query: { enabled: contracts.length > 0 } });
514
- const texts = (_nullishCoalesce(raw, () => ( []))).map((r) => r.status === "success" ? _chunkYTO7Z5SIcjs.decodeRecord.call(void 0, r.result) : "");
516
+ const texts = (_nullishCoalesce(raw, () => ( []))).map((r) => r.status === "success" ? _chunkI3Y63ZPKcjs.decodeRecord.call(void 0, r.result) : "");
515
517
  const { data: records, isLoading: parseLoading } = _reactquery.useQuery.call(void 0, {
516
518
  queryKey: ["records", config.network, registry.address, address, index, kinds.join(","), texts.join(" "), _nullishCoalesce(armoredKey, () => ( ""))],
517
519
  queryFn: async () => {
518
520
  const out = [];
519
- for (let i = 0; i < kinds.length; i++) if (texts[i]) out.push(await _chunkYTO7Z5SIcjs.parseRecord.call(void 0, kinds[i], texts[i], { armoredKey: _nullishCoalesce(armoredKey, () => ( void 0)) }));
521
+ for (let i = 0; i < kinds.length; i++) if (texts[i]) out.push(await _chunkI3Y63ZPKcjs.parseRecord.call(void 0, kinds[i], texts[i], { armoredKey: _nullishCoalesce(armoredKey, () => ( void 0)) }));
520
522
  return out;
521
523
  },
522
524
  enabled: enabled && raw !== void 0
@@ -595,5 +597,7 @@ function useRecords(address, index, kinds = _chunkYTO7Z5SIcjs.IDENTITY_KINDS, ar
595
597
 
596
598
 
597
599
 
598
- 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.IdentityKitProvider = IdentityKitProvider; 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.ThurinCard = ThurinCard; 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.useAttestations = useAttestations; exports.useEFPGraph = useEFPGraph; exports.useEnsHint = useEnsHint; exports.usePGPProofs = usePGPProofs; exports.useRecords = useRecords; exports.useSafeAvatar = useSafeAvatar; exports.useThurinIdentity = useThurinIdentity; exports.verifyAttestation = _chunkYTO7Z5SIcjs.verifyAttestation; exports.verifyClearsigned = _chunkYTO7Z5SIcjs.verifyClearsigned; exports.verifyProof = _chunkYTO7Z5SIcjs.verifyProof;
600
+
601
+
602
+ exports.ARWEAVE_GATEWAY = _chunkI3Y63ZPKcjs.ARWEAVE_GATEWAY; exports.AUTHORIZATION_TYPES = _chunkI3Y63ZPKcjs.AUTHORIZATION_TYPES; exports.EIP712_NAME = _chunkI3Y63ZPKcjs.EIP712_NAME; exports.EIP712_VERSION = _chunkI3Y63ZPKcjs.EIP712_VERSION; exports.ENS_HINT_KEY = _chunkI3Y63ZPKcjs.ENS_HINT_KEY; exports.ENS_TEXT_RESOLVER_ABI = _chunkI3Y63ZPKcjs.ENS_TEXT_RESOLVER_ABI; exports.IDENTITY_ERROR_TEXT = _chunkI3Y63ZPKcjs.IDENTITY_ERROR_TEXT; exports.IDENTITY_KINDS = _chunkI3Y63ZPKcjs.IDENTITY_KINDS; exports.IPFS_GATEWAY = _chunkI3Y63ZPKcjs.IPFS_GATEWAY; exports.IPFS_GATEWAYS = _chunkI3Y63ZPKcjs.IPFS_GATEWAYS; exports.IdentityKitProvider = IdentityKitProvider; exports.KNOWN_KINDS = _chunkI3Y63ZPKcjs.KNOWN_KINDS; exports.MAX_RECORD_BYTES = _chunkI3Y63ZPKcjs.MAX_RECORD_BYTES; exports.NETWORKS = _chunkI3Y63ZPKcjs.NETWORKS; exports.NFT_AVATAR_ABI = _chunkI3Y63ZPKcjs.NFT_AVATAR_ABI; exports.REGISTRY_ABI = _chunkI3Y63ZPKcjs.REGISTRY_ABI; exports.REGISTRY_ADDRESS = _chunkI3Y63ZPKcjs.REGISTRY_ADDRESS; exports.ThurinCard = ThurinCard; exports.addPointer = _chunkI3Y63ZPKcjs.addPointer; exports.attestTypedData = _chunkI3Y63ZPKcjs.attestTypedData; exports.authorizationDigest = _chunkI3Y63ZPKcjs.authorizationDigest; exports.avatarFallbacks = _chunkI3Y63ZPKcjs.avatarFallbacks; exports.avatarUrl = _chunkI3Y63ZPKcjs.avatarUrl; exports.bytesToFingerprint = _chunkI3Y63ZPKcjs.bytesToFingerprint; exports.chainFor = _chunkI3Y63ZPKcjs.chainFor; exports.decodeRecord = _chunkI3Y63ZPKcjs.decodeRecord; exports.displayUrl = _chunkI3Y63ZPKcjs.displayUrl; exports.encodeRecord = _chunkI3Y63ZPKcjs.encodeRecord; exports.ensHintFor = _chunkI3Y63ZPKcjs.ensHintFor; exports.ensHintValue = _chunkI3Y63ZPKcjs.ensHintValue; exports.ensHintWrite = _chunkI3Y63ZPKcjs.ensHintWrite; exports.fetchEFPGraph = _chunkI3Y63ZPKcjs.fetchEFPGraph; exports.fetchEnsHint = _chunkI3Y63ZPKcjs.fetchEnsHint; exports.fetchRecords = _chunkI3Y63ZPKcjs.fetchRecords; exports.fingerprintHash = _chunkI3Y63ZPKcjs.fingerprintHash; exports.fingerprintToBytes = _chunkI3Y63ZPKcjs.fingerprintToBytes; exports.getRegistry = _chunkI3Y63ZPKcjs.getRegistry; exports.hasEmailUserID = _chunkI3Y63ZPKcjs.hasEmailUserID; exports.identifyProof = _chunkI3Y63ZPKcjs.identifyProof; exports.identityErrorKind = _chunkI3Y63ZPKcjs.identityErrorKind; exports.isNetworkName = _chunkI3Y63ZPKcjs.isNetworkName; exports.keyIdOf = _chunkI3Y63ZPKcjs.keyIdOf; exports.keyIdToBytes = _chunkI3Y63ZPKcjs.keyIdToBytes; exports.kindName = _chunkI3Y63ZPKcjs.kindName; exports.needsRpcProbe = _chunkI3Y63ZPKcjs.needsRpcProbe; exports.nftAvatarImage = _chunkI3Y63ZPKcjs.nftAvatarImage; exports.normalizeFingerprint = _chunkI3Y63ZPKcjs.normalizeFingerprint; exports.parseNftAvatar = _chunkI3Y63ZPKcjs.parseNftAvatar; exports.parsePgpKey = _chunkI3Y63ZPKcjs.parsePgpKey; exports.parsePointer = _chunkI3Y63ZPKcjs.parsePointer; exports.parseRecord = _chunkI3Y63ZPKcjs.parseRecord; exports.proofHref = _chunkI3Y63ZPKcjs.proofHref; exports.proofSecondaryHref = _chunkI3Y63ZPKcjs.proofSecondaryHref; exports.reattestTypedData = _chunkI3Y63ZPKcjs.reattestTypedData; exports.recordKind = _chunkI3Y63ZPKcjs.recordKind; exports.registryDomain = _chunkI3Y63ZPKcjs.registryDomain; exports.renderPointer = _chunkI3Y63ZPKcjs.renderPointer; exports.revokeTypedData = _chunkI3Y63ZPKcjs.revokeTypedData; exports.setRecordTypedData = _chunkI3Y63ZPKcjs.setRecordTypedData; exports.stripEmailUserIDs = _chunkI3Y63ZPKcjs.stripEmailUserIDs; exports.updateKeyTypedData = _chunkI3Y63ZPKcjs.updateKeyTypedData; exports.useAttestations = useAttestations; exports.useEFPGraph = useEFPGraph; exports.useEnsHint = useEnsHint; exports.usePGPProofs = usePGPProofs; exports.useRecords = useRecords; exports.useSafeAvatar = useSafeAvatar; exports.useThurinIdentity = useThurinIdentity; exports.verifyAttestation = _chunkI3Y63ZPKcjs.verifyAttestation; exports.verifyClearsigned = _chunkI3Y63ZPKcjs.verifyClearsigned; exports.verifyProof = _chunkI3Y63ZPKcjs.verifyProof;
599
603
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ben/code/thurinlabs/identity-kit/dist/index.cjs","../src/provider.tsx","../src/context.ts","../src/hooks/useThurinIdentity.ts","../src/hooks/useAttestations.ts","../src/hooks/useEFPGraph.ts","../src/hooks/usePGPProofs.ts","../src/hooks/useSafeAvatar.ts","../src/components/ThurinCard/ThurinCard.tsx","../src/hooks/useEnsHint.ts","../src/hooks/useRecords.ts"],"names":["useQuery","jsx","safeNormalize","normalize"],"mappings":"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AACA,sBAAA;AACE,wBAAA;AACA,wBAAA;AACF,MAAA;AACA,sBAAA;AACE,wBAAA;AAIA,wBAAA;AACF,MAAA;AACF,IAAA;AAEA,oBAAA;AACG,MAAA;AAGc,sBAAA;AAGL,MAAA;AACP,QAAA;AAAA,QAAA;AAEY,UAAA;AAEV,UAAA;AAAE,QAAA;AAHE,QAAA;AAKR,MAAA;AACH,IAAA;AAGE,IAAA;AAAC,MAAA;AAAA,MAAA;AACW,QAAA;AACJ,QAAA;AACC,QAAA;AACH,QAAA;AACL,QAAA;AAAA,MAAA;AAED,IAAA;AAEJ,EAAA;AAEJ;ARiVqB;AACA;AS9dZ;AACA;AAKAC;AACH,EAAA;AAASC,IAAAA;AAAwB,EAAA;AAAS,IAAA;AAAU,EAAA;AAC1D;AAO2B;AACX,EAAA;AACE,EAAA;AACF,EAAA;AACN,IAAA;AACD,IAAA;AACU,IAAA;AACN,IAAA;AACV,EAAA;AACW,EAAA;AAAgH,IAAA;AAAI,EAAA;AAClI;AT4dqB;AACA;AUtfZ;AACAH;AAUkB;AACV,EAAA;AACE,EAAA;AACH,EAAA;AACA,EAAA;AACI,EAAA;AAEA,EAAA;AAGC,EAAA;AAEJ,EAAA;AACD,EAAA;AACD,IAAA;AACF,IAAA;AACsB,MAAA;AAChB,MAAA;AACN,MAAA;AACT,IAAA;AACS,IAAA;AACV,EAAA;AAEiB,EAAA;AAAkG,IAAA;AAAI,EAAA;AAC1H;AV4eqB;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/ben/code/thurinlabs/identity-kit/dist/index.cjs","sourcesContent":[null,"import { type ReactNode, useMemo } from 'react'\nimport { WagmiProvider, createConfig, http, useConfig } from 'wagmi'\nimport { mainnet, sepolia, foundry } from 'wagmi/chains'\nimport { getRegistry } from './core/contract'\nimport type { NetworkName } from './core/contract'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { IdentityKitContext } from './context'\nimport type { IdentityKitConfig } from './core/types'\n\nconst defaultQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 60_000,\n retry: 1,\n },\n },\n})\n\nexport { chainFor } from './core/contract'\n\nfunction createDefaultWagmiConfig(rpcUrl: string | undefined, network: NetworkName) {\n const url = rpcUrl || getRegistry(network).defaultRpcUrl\n // Spelled out per network: wagmi types `transports` by the exact chain ids.\n if (network === 'sepolia') return createConfig({ chains: [sepolia], transports: { [sepolia.id]: http(url) } })\n if (network === 'local') return createConfig({ chains: [foundry], transports: { [foundry.id]: http(url) } })\n return createConfig({ chains: [mainnet], transports: { [mainnet.id]: http(url) } })\n}\n\nfunction WagmiDetector({ children, rpcUrl, network }: { children: ReactNode; rpcUrl?: string; network: NetworkName }) {\n // Try to use existing wagmi config\n let hasWagmi = false\n try {\n useConfig()\n hasWagmi = true\n } catch {\n // No WagmiProvider above us\n }\n\n const wagmiConfig = useMemo(() => createDefaultWagmiConfig(rpcUrl, network), [rpcUrl, network])\n\n if (hasWagmi) {\n return <>{children}</>\n }\n\n return (\n <WagmiProvider config={wagmiConfig}>\n <QueryClientProvider client={defaultQueryClient}>\n {children}\n </QueryClientProvider>\n </WagmiProvider>\n )\n}\n\nexport interface IdentityKitProviderProps extends IdentityKitConfig {\n children: ReactNode\n}\n\nexport function IdentityKitProvider({\n children,\n rpcUrl,\n neynarApiKey,\n baseUrl = 'https://thurin.id',\n network = 'mainnet',\n registryAddress,\n}: IdentityKitProviderProps) {\n const config = useMemo(\n () => ({ rpcUrl, neynarApiKey, baseUrl, network, registryAddress }),\n [rpcUrl, neynarApiKey, baseUrl, network, registryAddress],\n )\n\n return (\n <IdentityKitContext.Provider value={config}>\n <WagmiDetector rpcUrl={rpcUrl} network={network}>\n {children}\n </WagmiDetector>\n </IdentityKitContext.Provider>\n )\n}\n","import { createContext, useContext } from 'react'\nimport type { IdentityKitConfig } from './core/types'\n\nconst defaultConfig: IdentityKitConfig = {\n baseUrl: 'https://thurin.id',\n network: 'mainnet',\n}\n\nexport const IdentityKitContext = createContext<IdentityKitConfig>(defaultConfig)\n\nexport function useIdentityKitConfig(): IdentityKitConfig {\n return useContext(IdentityKitContext)\n}\n","import { useEnsAddress, useEnsName, usePublicClient } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { identityErrorKind, needsRpcProbe, IDENTITY_ERROR_TEXT } from '../core/identityError'\nimport { useIdentityKitConfig } from '../context'\nimport { chainFor } from '../provider'\nimport { normalize } from 'viem/ens'\nimport { useAttestations } from './useAttestations'\nimport { useEFPGraph } from './useEFPGraph'\nimport { usePGPProofs } from './usePGPProofs'\nimport { useSafeAvatar } from './useSafeAvatar'\nimport type { ThurinIdentity } from '../core/types'\n\nfunction isAddress(value: string): boolean {\n return /^0x[0-9a-fA-F]{40}$/.test(value)\n}\n\nfunction safeNormalize(name: string): string | undefined {\n try {\n return normalize(name)\n } catch {\n return undefined\n }\n}\n\nexport function useThurinIdentity(ensOrAddress: string | undefined | null): ThurinIdentity {\n const chain = chainFor(useIdentityKitConfig().network)\n const isAddr = ensOrAddress ? isAddress(ensOrAddress) : false\n const ensInput = ensOrAddress && !isAddr ? safeNormalize(ensOrAddress) : undefined\n\n // Resolve ENS → address\n const { data: resolvedAddress, error: ensError, isFetched: ensFetched, refetch: refetchEns } = useEnsAddress({\n name: ensInput,\n chainId: chain.id,\n query: { enabled: !!ensInput },\n })\n\n const address = isAddr ? ensOrAddress! : resolvedAddress ?? null\n\n // Reverse resolve address → ENS\n const { data: ensName } = useEnsName({\n address: address as `0x${string}` | undefined,\n chainId: chain.id,\n query: { enabled: !!address },\n })\n\n const displayName = ensInput || ensName || null\n\n const ensAvatar = useSafeAvatar(displayName ? safeNormalize(displayName) : undefined, chain.id)\n\n // On-chain attestations\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\n error: claimsError,\n refetch: refetchClaims,\n } = useAttestations(address)\n\n // PGP proofs come from the key stored in the current attestation — the\n // latest claim that is active and whose signature verified (the same rule\n // useAttestations uses to pick currentFingerprint).\n const currentClaim = [...claims].reverse().find(\n (c) => !c.revoked && c.verification?.verified && c.fingerprint === currentFingerprint,\n )\n const {\n keyInfo: pgpKeyInfo,\n proofs,\n isLoading: proofsLoading,\n } = usePGPProofs(currentFingerprint, currentClaim?.pgpPublicKey ?? null)\n\n // EFP social graph\n const { efp, isLoading: efpLoading } = useEFPGraph(address)\n\n // An empty ENS result or a failed read might just be a dead RPC; ask it for the block\n // number before saying anything about the identity (core/identityError.ts).\n const lookup = { ensEmpty: !!ensInput && ensFetched && !resolvedAddress, ensFailed: !!ensError, claimsFailed: !!claimsError }\n const probeNeeded = needsRpcProbe(lookup)\n const client = usePublicClient({ chainId: chain.id })\n const probe = useQuery({\n queryKey: ['thurin-rpc-probe', chain.id, ensOrAddress],\n queryFn: () => client!.getBlockNumber(),\n enabled: probeNeeded && !!client,\n retry: 0,\n staleTime: 0,\n })\n const rpcAnswered = !probeNeeded || probe.isFetching ? undefined : probe.isSuccess ? true : probe.isError ? false : undefined\n const errorKind = identityErrorKind({ ...lookup, rpcAnswered })\n const probing = probeNeeded && rpcAnswered === undefined\n const retry = () => {\n if (ensInput) refetchEns()\n refetchClaims()\n if (probeNeeded) probe.refetch()\n }\n\n return {\n address,\n ensName: displayName,\n ensAvatar,\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n pgpKeyInfo,\n proofs,\n efp,\n // \"Not finished\" counts as loading, including queries paused in a background tab: the card\n // must not render defaults (zeros) for an identity it hasn't looked up yet.\n isLoading: (!!ensInput && !ensFetched) || claimsLoading || proofsLoading || efpLoading || probing,\n error: errorKind ? new Error(IDENTITY_ERROR_TEXT[errorKind]) : null,\n errorKind,\n retry,\n }\n}\n","import { useReadContract, useReadContracts } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { hexToString } from 'viem'\nimport { REGISTRY_ABI, getRegistry } from '../core/contract'\nimport { bytesToFingerprint } from '../core/fingerprint'\nimport { chainFor } from '../provider'\nimport { verifyAttestation } from '../core/pgp'\nimport { useIdentityKitConfig } from '../context'\nimport type { Attestation } from '../core/types'\n\n/**\n * On-chain attestations for an address, read straight from the v2 registry:\n * `attestationsOf` for the history, `getPayload` for each stored signature + key.\n * No event logs, so any RPC works. Each claim is verified off-chain.\n */\nexport function useAttestations(address: string | undefined | null) {\n const config = useIdentityKitConfig()\n const registry = getRegistry(config.network, config.registryAddress)\n const chain = chainFor(config.network)\n const owner = address as `0x${string}` | undefined\n\n const { data: rows, isLoading: rowsLoading, isFetched: rowsFetched, error: rowsError, refetch: refetchRows } = useReadContract({\n address: registry.address,\n abi: REGISTRY_ABI,\n functionName: 'attestationsOf',\n args: owner ? [owner] : undefined,\n chainId: chain.id,\n query: { enabled: !!owner },\n })\n\n const count = rows?.length ?? 0\n\n const contracts = owner && rows\n ? rows.map((_, i) => ({\n address: registry.address,\n abi: REGISTRY_ABI,\n functionName: 'getPayload' as const,\n args: [owner, BigInt(i)] as const,\n chainId: chain.id,\n }))\n : []\n\n const { data: payloads, isLoading: payloadsLoading, error: payloadsError, refetch: refetchPayloads } = useReadContracts({\n contracts,\n query: { enabled: contracts.length > 0 },\n })\n\n const payloadsReady = count === 0 || (payloads !== undefined && payloads.length === count)\n\n const { data: claims, isLoading: verifyLoading } = useQuery({\n queryKey: ['attestations', config.network, registry.address, address, count, payloadsReady],\n queryFn: async (): Promise<Attestation[]> => {\n if (!rows || !address) return []\n const results: Attestation[] = []\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const payload = payloads?.[i]\n let pgpSignature: string | null = null\n let pgpPublicKey: string | null = null\n if (payload && payload.status === 'success') {\n const [sigHex, keyHex] = payload.result as readonly [`0x${string}`, `0x${string}`]\n pgpSignature = hexToString(sigHex)\n pgpPublicKey = hexToString(keyHex)\n }\n\n const fingerprint = bytesToFingerprint(row.fingerprint)\n const verification = pgpPublicKey && pgpSignature\n ? await verifyAttestation({ pgpPublicKey, pgpSignature, fingerprint, ethAddress: address })\n : null\n\n const revokedAt = Number(row.revokedAt)\n results.push({\n index: i,\n fingerprint,\n createdAt: Number(row.createdAt),\n revoked: revokedAt !== 0,\n revokedAt: revokedAt === 0 ? null : revokedAt,\n messageVersion: Number(row.messageVersion),\n pgpSignature,\n pgpPublicKey,\n verification,\n })\n }\n return results\n },\n enabled: !!rows && payloadsReady,\n staleTime: 300_000,\n })\n\n // Not fetched yet counts as loading (a paused query in a background tab is not \"no claims\").\n const isLoading = rowsLoading || (!!owner && !rowsFetched) || payloadsLoading || verifyLoading || (!!owner && rows !== undefined && !payloadsReady)\n\n const activeClaims = (claims || []).filter((c) => !c.revoked)\n // The current identity is the latest claim that is both active and has a\n // verified signature binding the key to this address. A claim whose signature\n // has not verified must not surface the key's proofs or user data.\n const verifiedClaims = activeClaims.filter((c) => c.verification?.verified)\n const currentFingerprint = verifiedClaims.length > 0\n ? verifiedClaims[verifiedClaims.length - 1].fingerprint\n : null\n\n return {\n claims: claims || [],\n totalClaims: count,\n activeClaims: activeClaims.length,\n currentFingerprint,\n isLoading,\n /** A registry read failed (the RPC may be down; useThurinIdentity finds out which). */\n error: (rowsError ?? payloadsError ?? null) as Error | null,\n refetch: () => { if (owner) { refetchRows(); if (contracts.length > 0) refetchPayloads() } },\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { fetchEFPGraph } from '../core/efp'\nimport type { EFPGraph } from '../core/types'\n\nexport function useEFPGraph(address: string | undefined | null) {\n const { data, isLoading } = useQuery<EFPGraph | null>({\n queryKey: ['efp-graph', address],\n queryFn: () => fetchEFPGraph(address!),\n enabled: !!address,\n staleTime: 300_000,\n })\n\n return {\n efp: data ?? null,\n isLoading,\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { parsePgpKey } from '../core/pgp'\nimport { identifyProof, verifyProof, displayUrl, proofHref, proofSecondaryHref } from '../core/proofs'\nimport { useIdentityKitConfig } from '../context'\nimport type { PGPKeyInfo, ProofResult } from '../core/types'\n\n/**\n * Proofs for an identity, read from the PGP key stored in its on-chain\n * attestation. No keyserver is consulted: keys.openpgp.org only serves user\n * IDs whose email is verified and drops non-email user IDs entirely, so it can\n * never carry the published (non-email) identity that holds the notations.\n *\n * @param fingerprint the attested fingerprint (proofs must name it)\n * @param armoredKey the attestation's `pgpPublicKey`\n */\nexport function usePGPProofs(fingerprint: string | undefined | null, armoredKey: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data } = useQuery({\n // The key is large; key the query on its length + fingerprint, which\n // changes whenever a different attestation's key is supplied.\n queryKey: ['pgp-proofs', fingerprint, armoredKey?.length ?? 0],\n queryFn: async (): Promise<{ keyInfo: PGPKeyInfo | null; proofs: ProofResult[] }> => {\n if (!fingerprint || !armoredKey) return { keyInfo: null, proofs: [] }\n\n const keyInfo = await parsePgpKey(armoredKey)\n if (!keyInfo) return { keyInfo: null, proofs: [] }\n\n // Identify proofs from notations. Drop unrecognized targets (provider\n // 'unknown') so the card doesn't render \"Unknown\" badges for platforms\n // Thurin has no verifier for — matching the explorer's behavior.\n const identified = keyInfo.notations\n .map((n) => identifyProof(n))\n .filter((p): p is NonNullable<typeof p> => p !== null && p.provider !== 'unknown')\n\n // Verify all proofs in parallel\n const proofs: ProofResult[] = await Promise.all(\n identified.map(async (proof) => {\n const result = await verifyProof(proof, fingerprint, config.neynarApiKey)\n return {\n provider: proof.provider,\n label: proof.label,\n url: proof.url,\n displayUrl: displayUrl(proof),\n href: proofHref(proof),\n secondaryHref: proofSecondaryHref(proof),\n status: result.verified ? 'verified' as const : 'unverified' as const,\n reason: result.reason,\n }\n }),\n )\n\n // Collapse proofs that resolve to the same account — the same target is\n // often listed under both proof@thurin.id and proof@ariadne.id (and can\n // be reached via more than one proof URL). Key by provider + display\n // identity, preferring a verified result.\n const byAccount = new Map<string, ProofResult>()\n for (const p of proofs) {\n const key = `${p.provider}:${p.displayUrl}`\n const prev = byAccount.get(key)\n if (!prev || (p.status === 'verified' && prev.status !== 'verified')) {\n byAccount.set(key, p)\n }\n }\n\n return { keyInfo, proofs: [...byAccount.values()] }\n },\n enabled: !!fingerprint && !!armoredKey,\n staleTime: 300_000,\n })\n\n return {\n keyInfo: data?.keyInfo ?? null,\n proofs: data?.proofs ?? [],\n // Report loading whenever a fingerprint is set but its proofs haven't\n // resolved yet. Using react-query's own isLoading leaves a gap while the\n // query is enabling (fingerprint just became known), during which the card\n // would briefly paint without proof badges and then pop them in.\n isLoading: !!fingerprint && !!armoredKey && data === undefined,\n }\n}\n","import { useEnsText, useReadContract } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { avatarUrl, parseNftAvatar, nftAvatarImage, NFT_AVATAR_ABI } from '../core/avatar'\n\n/**\n * The avatar to show for a normalized ENS name, or null. Reads the raw `avatar` record and\n * loads only what `avatarUrl` allows (see core/avatar.ts); wagmi's useEnsAvatar would fetch\n * whatever host the name's owner chose.\n */\nexport function useSafeAvatar(name: string | undefined, chainId: number): string | null {\n const { data: raw } = useEnsText({ name, key: 'avatar', chainId, query: { enabled: !!name } })\n const direct = avatarUrl(raw)\n const nft = direct ? null : parseNftAvatar(raw)\n const { data: tokenUri } = useReadContract({\n address: nft?.contract,\n abi: NFT_AVATAR_ABI,\n functionName: nft?.standard === 'erc1155' ? 'uri' : 'tokenURI',\n args: nft ? [nft.tokenId] : undefined,\n chainId,\n query: { enabled: !!nft && nft.chainId === chainId },\n })\n const { data: image } = useQuery({\n queryKey: ['thurin-nft-avatar', tokenUri, nft?.tokenId.toString()],\n queryFn: () => nftAvatarImage(tokenUri as string, nft!.tokenId).catch(() => null),\n enabled: typeof tokenUri === 'string' && !!nft,\n })\n return direct ?? image ?? null\n}\n","import { useThurinIdentity } from '../../hooks/useThurinIdentity'\nimport { useIdentityKitConfig } from '../../context'\nimport type { Theme } from '../../core/types'\nimport '../../themes/index.css'\nimport './ThurinCard.css'\n\nfunction ThurinLogo() {\n return (\n <svg className=\"thurin-card-avatar-placeholder\" viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"var(--thurin-surface-deep)\" />\n <path d=\"M25 80 Q25 25 50 25 Q75 25 75 50\" fill=\"none\" stroke=\"#7c9a3e\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n <path d=\"M33 75 Q33 35 50 35 Q67 35 67 52\" fill=\"none\" stroke=\"#7c9a3e\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n <path d=\"M41 70 Q41 45 50 45 Q59 45 59 55\" fill=\"none\" stroke=\"#c9a227\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n <path d=\"M50 65 L50 53\" fill=\"none\" stroke=\"#c9a227\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n </svg>\n )\n}\n\nexport interface ThurinCardProps {\n ens?: string\n address?: string\n theme?: Theme\n}\n\nexport function ThurinCard({ ens, address, theme = 'thurin' }: ThurinCardProps) {\n const input = ens || address\n const identity = useThurinIdentity(input)\n const config = useIdentityKitConfig()\n\n const profileUrl = identity.address\n ? `${config.baseUrl}/eth/${identity.address}`\n : ens\n ? `${config.baseUrl}/ens/${ens}`\n : null\n\n if (identity.isLoading) {\n return (\n <div className=\"thurin-card\" data-thurin-theme={theme}>\n <div className=\"thurin-card-loading\">Loading identity...</div>\n </div>\n )\n }\n\n const displayAddress = identity.address || null\n\n // A failed lookup says so, instead of rendering zeros that read as facts.\n if (identity.errorKind) {\n return (\n <div className=\"thurin-card\" data-thurin-theme={theme}>\n <div className=\"thurin-card-header\">\n <ThurinLogo />\n <div>\n <div className=\"thurin-card-name\">{identity.ensName || ens || address}</div>\n </div>\n </div>\n <div className=\"thurin-card-error\" role=\"status\">\n {identity.error?.message}\n {identity.errorKind !== 'not-found' && (\n <button type=\"button\" className=\"thurin-card-retry\" onClick={identity.retry}>Try again</button>\n )}\n </div>\n {profileUrl && identity.errorKind !== 'not-found' && (\n <a className=\"thurin-card-link\" href={profileUrl} target=\"_blank\" rel=\"noopener noreferrer\">View on Thurin</a>\n )}\n </div>\n )\n }\n\n const verifiedProofs = identity.proofs.filter((p) => p.status === 'verified').length\n const hasVerifiedPgp = identity.claims.some((c) => c.verification?.verified && !c.revoked)\n\n return (\n <div className=\"thurin-card\" data-thurin-theme={theme}>\n <a className=\"thurin-card-header\" href={profileUrl || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n {identity.ensAvatar ? (\n <img\n className=\"thurin-card-avatar\"\n src={identity.ensAvatar}\n alt={identity.ensName || ''}\n />\n ) : (\n <ThurinLogo />\n )}\n <div>\n {identity.ensName && (\n <div className=\"thurin-card-name\">{identity.ensName}</div>\n )}\n {displayAddress && (\n <div className=\"thurin-card-address\">{displayAddress}</div>\n )}\n </div>\n </a>\n\n <div className=\"thurin-card-stats\">\n <div className=\"thurin-card-stat\">\n <span className=\"thurin-card-stat-value\">{identity.activeClaims}</span>\n <span className=\"thurin-card-stat-label\">Attestations</span>\n </div>\n <div className=\"thurin-card-stat\">\n <span className=\"thurin-card-stat-value\">{verifiedProofs}</span>\n <span className=\"thurin-card-stat-label\">Proofs</span>\n </div>\n <div className=\"thurin-card-stat\">\n <span className=\"thurin-card-stat-value\">\n {/* EFP answers separately; a null graph means it didn't, so don't claim zero. */}\n {identity.efp ? identity.efp.followers : '–'}\n </span>\n <span className=\"thurin-card-stat-label\">Followers</span>\n </div>\n </div>\n\n <div className=\"thurin-card-badges\">\n {hasVerifiedPgp && (\n <span className=\"thurin-card-badge thurin-card-badge--verified\">PGP Verified</span>\n )}\n {identity.efp?.hasEfp && (\n <span className=\"thurin-card-badge thurin-card-badge--verified\">EFP</span>\n )}\n {identity.proofs.map((p, i) => (\n <span\n key={i}\n className={`thurin-card-badge thurin-card-badge--${p.status === 'verified' ? 'verified' : 'unverified'}`}\n >\n {p.label}\n </span>\n ))}\n </div>\n\n {profileUrl && (\n <a\n className=\"thurin-card-link\"\n href={profileUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on Thurin\n </a>\n )}\n </div>\n )\n}\n","import { useEnsText } from 'wagmi'\nimport { normalize } from 'viem/ens'\nimport { useIdentityKitConfig } from '../context'\nimport { chainFor } from '../provider'\nimport { ENS_HINT_KEY, ensHintFor, type EnsHint } from '../core/ensHint'\n\nfunction safeNormalize(name: string): string | undefined {\n try { return normalize(name) } catch { return undefined }\n}\n\n/**\n * A name's `id.thurin` record against the fingerprint the registry verifies for its\n * address. `state` is `match`, `unset`, or `mismatch`; the last one is the signal worth\n * showing — a name advertising a key its address has not claimed.\n */\nexport function useEnsHint(name: string | undefined | null, verifiedFingerprint: string | null | undefined): EnsHint & { isLoading: boolean; refetch: () => void } {\n const chain = chainFor(useIdentityKitConfig().network)\n const ensName = name ? safeNormalize(name) : undefined\n const { data, isLoading, refetch } = useEnsText({\n name: ensName,\n key: ENS_HINT_KEY,\n chainId: chain.id,\n query: { enabled: !!ensName },\n })\n return { ...ensHintFor(data ?? null, verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => { void refetch() } }\n}\n","import { useReadContracts } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { REGISTRY_ABI, getRegistry } from '../core/contract'\nimport { chainFor } from '../provider'\nimport { useIdentityKitConfig } from '../context'\nimport { IDENTITY_KINDS, decodeRecord, parseRecord, recordKind, type ParsedRecord } from '../core/records'\n\n/**\n * The records on one claim, for the kinds given (default: the kinds an identity page shows),\n * read in one multicall and parsed. Kinds with no record are left out.\n */\nexport function useRecords(address: string | undefined | null, index: number | undefined | null, kinds: readonly string[] = IDENTITY_KINDS, armoredKey?: string | null) {\n const config = useIdentityKitConfig()\n const registry = getRegistry(config.network, config.registryAddress)\n const chain = chainFor(config.network)\n const owner = address as `0x${string}` | undefined\n const enabled = !!owner && index !== undefined && index !== null\n\n const contracts = enabled\n ? kinds.map(kind => ({ address: registry.address, abi: REGISTRY_ABI, functionName: 'record' as const, args: [owner!, BigInt(index!), recordKind(kind)] as const, chainId: chain.id }))\n : []\n const { data: raw, isLoading: readLoading, refetch } = useReadContracts({ contracts, query: { enabled: contracts.length > 0 } })\n\n const texts = (raw ?? []).map(r => (r.status === 'success' ? decodeRecord(r.result as `0x${string}`) : ''))\n const { data: records, isLoading: parseLoading } = useQuery({\n queryKey: ['records', config.network, registry.address, address, index, kinds.join(','), texts.join(' '), armoredKey ?? ''],\n queryFn: async (): Promise<ParsedRecord[]> => {\n const out: ParsedRecord[] = []\n for (let i = 0; i < kinds.length; i++) if (texts[i]) out.push(await parseRecord(kinds[i], texts[i], { armoredKey: armoredKey ?? undefined }))\n return out\n },\n enabled: enabled && raw !== undefined,\n })\n\n return { records: records ?? [], isLoading: enabled && (readLoading || parseLoading), refetch: () => { void refetch() } }\n}\n"]}
1
+ {"version":3,"sources":["/home/ben/code/thurinlabs/identity-kit/dist/index.cjs","../src/provider.tsx","../src/context.ts","../src/components/ThurinCard/ThurinCard.tsx","../src/hooks/useThurinIdentity.ts","../src/hooks/useAttestations.ts","../src/hooks/useEFPGraph.ts","../src/hooks/usePGPProofs.ts","../src/hooks/useSafeAvatar.ts","../src/hooks/useEnsHint.ts","../src/hooks/useRecords.ts"],"names":["useQuery","jsx","safeNormalize","normalize"],"mappings":"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AAA;AACE,wBAAA;AACA,wBAAA;AACF,MAAA;AACA,sBAAA;AACE,wBAAA;AAIA,wBAAA;AACF,MAAA;AACF,IAAA;AAEA,oBAAA;AACG,MAAA;AAGc,sBAAA;AAGL,MAAA;AACP,QAAA;AAAA,QAAA;AAEY,UAAA;AAEV,UAAA;AAAE,QAAA;AAHE,QAAA;AAKR,MAAA;AACH,IAAA;AAGE,IAAA;AAAC,MAAA;AAAA,MAAA;AACW,QAAA;AACJ,QAAA;AACC,QAAA;AACH,QAAA;AACL,QAAA;AAAA,MAAA;AAED,IAAA;AAEJ,EAAA;AAEJ;AHiVqB;AACA;ASheZ;AACA;AAKAC;AACH,EAAA;AAASC,IAAAA;AAAwB,EAAA;AAAS,IAAA;AAAU,EAAA;AAC1D;AAO2B;AACX,EAAA;AACE,EAAA;AACF,EAAA;AACN,IAAA;AACD,IAAA;AACU,IAAA;AACN,IAAA;AACV,EAAA;AACW,EAAA;AAAgH,IAAA;AAAI,EAAA;AAClI;AT8dqB;AACA;AUxfZ;AACAH;AAUkB;AACV,EAAA;AACE,EAAA;AACH,EAAA;AACA,EAAA;AACI,EAAA;AAEA,EAAA;AAGC,EAAA;AAEJ,EAAA;AACD,EAAA;AACD,IAAA;AACF,IAAA;AACsB,MAAA;AAChB,MAAA;AACN,MAAA;AACT,IAAA;AACS,IAAA;AACV,EAAA;AAEiB,EAAA;AAAkG,IAAA;AAAI,EAAA;AAC1H;AV8eqB;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/ben/code/thurinlabs/identity-kit/dist/index.cjs","sourcesContent":[null,"import { type ReactNode, useMemo } from 'react'\nimport { WagmiProvider, createConfig, http, useConfig } from 'wagmi'\nimport { mainnet, sepolia, foundry } from 'wagmi/chains'\nimport { getRegistry } from './core/contract'\nimport type { NetworkName } from './core/contract'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { IdentityKitContext } from './context'\nimport type { IdentityKitConfig } from './core/types'\n\nconst defaultQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 60_000,\n retry: 1,\n },\n },\n})\n\nexport { chainFor } from './core/contract'\n\nfunction createDefaultWagmiConfig(rpcUrl: string | undefined, network: NetworkName) {\n const url = rpcUrl || getRegistry(network).defaultRpcUrl\n // Spelled out per network: wagmi types `transports` by the exact chain ids.\n if (network === 'sepolia') return createConfig({ chains: [sepolia], transports: { [sepolia.id]: http(url) } })\n if (network === 'local') return createConfig({ chains: [foundry], transports: { [foundry.id]: http(url) } })\n return createConfig({ chains: [mainnet], transports: { [mainnet.id]: http(url) } })\n}\n\nfunction WagmiDetector({ children, rpcUrl, network }: { children: ReactNode; rpcUrl?: string; network: NetworkName }) {\n // Try to use existing wagmi config\n let hasWagmi = false\n try {\n useConfig()\n hasWagmi = true\n } catch {\n // No WagmiProvider above us\n }\n\n const wagmiConfig = useMemo(() => createDefaultWagmiConfig(rpcUrl, network), [rpcUrl, network])\n\n if (hasWagmi) {\n return <>{children}</>\n }\n\n return (\n <WagmiProvider config={wagmiConfig}>\n <QueryClientProvider client={defaultQueryClient}>\n {children}\n </QueryClientProvider>\n </WagmiProvider>\n )\n}\n\nexport interface IdentityKitProviderProps extends IdentityKitConfig {\n children: ReactNode\n}\n\nexport function IdentityKitProvider({\n children,\n rpcUrl,\n neynarApiKey,\n baseUrl = 'https://thurin.id',\n network = 'mainnet',\n registryAddress,\n}: IdentityKitProviderProps) {\n const config = useMemo(\n () => ({ rpcUrl, neynarApiKey, baseUrl, network, registryAddress }),\n [rpcUrl, neynarApiKey, baseUrl, network, registryAddress],\n )\n\n return (\n <IdentityKitContext.Provider value={config}>\n <WagmiDetector rpcUrl={rpcUrl} network={network}>\n {children}\n </WagmiDetector>\n </IdentityKitContext.Provider>\n )\n}\n","import { createContext, useContext } from 'react'\nimport type { IdentityKitConfig } from './core/types'\n\nconst defaultConfig: IdentityKitConfig = {\n baseUrl: 'https://thurin.id',\n network: 'mainnet',\n}\n\nexport const IdentityKitContext = createContext<IdentityKitConfig>(defaultConfig)\n\nexport function useIdentityKitConfig(): IdentityKitConfig {\n return useContext(IdentityKitContext)\n}\n","import { useEffect, useState } from 'react'\nimport { useThurinIdentity } from '../../hooks/useThurinIdentity'\nimport { avatarFallbacks } from '../../core/avatar'\nimport { useIdentityKitConfig } from '../../context'\nimport type { Theme } from '../../core/types'\nimport '../../themes/index.css'\nimport './ThurinCard.css'\n\nfunction ThurinLogo() {\n return (\n <svg className=\"thurin-card-avatar-placeholder\" viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"50\" cy=\"50\" r=\"50\" fill=\"var(--thurin-surface-deep)\" />\n <path d=\"M25 80 Q25 25 50 25 Q75 25 75 50\" fill=\"none\" stroke=\"#7c9a3e\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n <path d=\"M33 75 Q33 35 50 35 Q67 35 67 52\" fill=\"none\" stroke=\"#7c9a3e\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n <path d=\"M41 70 Q41 45 50 45 Q59 45 59 55\" fill=\"none\" stroke=\"#c9a227\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n <path d=\"M50 65 L50 53\" fill=\"none\" stroke=\"#c9a227\" strokeWidth=\"4\" strokeLinecap=\"round\"/>\n </svg>\n )\n}\n\n// The avatar, retried through the other IPFS gateways if one fails, then the logo.\nfunction Avatar({ src, alt }: { src: string | null; alt: string }) {\n const [tries, setTries] = useState<string[]>([])\n useEffect(() => { setTries(src ? [src, ...avatarFallbacks(src)] : []) }, [src])\n if (!tries.length) return <ThurinLogo />\n return <img className=\"thurin-card-avatar\" src={tries[0]} alt={alt} onError={() => setTries((t) => t.slice(1))} />\n}\n\nexport interface ThurinCardProps {\n ens?: string\n address?: string\n theme?: Theme\n}\n\nexport function ThurinCard({ ens, address, theme = 'thurin' }: ThurinCardProps) {\n const input = ens || address\n const identity = useThurinIdentity(input)\n const config = useIdentityKitConfig()\n\n const profileUrl = identity.address\n ? `${config.baseUrl}/eth/${identity.address}`\n : ens\n ? `${config.baseUrl}/ens/${ens}`\n : null\n\n if (identity.isLoading) {\n return (\n <div className=\"thurin-card\" data-thurin-theme={theme}>\n <div className=\"thurin-card-loading\">Loading identity...</div>\n </div>\n )\n }\n\n const displayAddress = identity.address || null\n\n // A failed lookup says so, instead of rendering zeros that read as facts.\n if (identity.errorKind) {\n return (\n <div className=\"thurin-card\" data-thurin-theme={theme}>\n <div className=\"thurin-card-header\">\n <ThurinLogo />\n <div>\n <div className=\"thurin-card-name\">{identity.ensName || ens || address}</div>\n </div>\n </div>\n <div className=\"thurin-card-error\" role=\"status\">\n {identity.error?.message}\n {identity.errorKind !== 'not-found' && (\n <button type=\"button\" className=\"thurin-card-retry\" onClick={identity.retry}>Try again</button>\n )}\n </div>\n {profileUrl && identity.errorKind !== 'not-found' && (\n <a className=\"thurin-card-link\" href={profileUrl} target=\"_blank\" rel=\"noopener noreferrer\">View on Thurin</a>\n )}\n </div>\n )\n }\n\n const verifiedProofs = identity.proofs.filter((p) => p.status === 'verified').length\n const hasVerifiedPgp = identity.claims.some((c) => c.verification?.verified && !c.revoked)\n\n return (\n <div className=\"thurin-card\" data-thurin-theme={theme}>\n <a className=\"thurin-card-header\" href={profileUrl || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n <Avatar src={identity.ensAvatar} alt={identity.ensName || ''} />\n <div>\n {identity.ensName && (\n <div className=\"thurin-card-name\">{identity.ensName}</div>\n )}\n {displayAddress && (\n <div className=\"thurin-card-address\">{displayAddress}</div>\n )}\n </div>\n </a>\n\n <div className=\"thurin-card-stats\">\n <div className=\"thurin-card-stat\">\n <span className=\"thurin-card-stat-value\">{identity.activeClaims}</span>\n <span className=\"thurin-card-stat-label\">Attestations</span>\n </div>\n <div className=\"thurin-card-stat\">\n <span className=\"thurin-card-stat-value\">{verifiedProofs}</span>\n <span className=\"thurin-card-stat-label\">Proofs</span>\n </div>\n <div className=\"thurin-card-stat\">\n <span className=\"thurin-card-stat-value\">\n {/* EFP answers separately; a null graph means it didn't, so don't claim zero. */}\n {identity.efp ? identity.efp.followers : '–'}\n </span>\n <span className=\"thurin-card-stat-label\">Followers</span>\n </div>\n </div>\n\n <div className=\"thurin-card-badges\">\n {hasVerifiedPgp && (\n <span className=\"thurin-card-badge thurin-card-badge--verified\">PGP Verified</span>\n )}\n {identity.efp?.hasEfp && (\n <span className=\"thurin-card-badge thurin-card-badge--verified\">EFP</span>\n )}\n {identity.proofs.map((p, i) => (\n <span\n key={i}\n className={`thurin-card-badge thurin-card-badge--${p.status === 'verified' ? 'verified' : 'unverified'}`}\n >\n {p.label}\n </span>\n ))}\n </div>\n\n {profileUrl && (\n <a\n className=\"thurin-card-link\"\n href={profileUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on Thurin\n </a>\n )}\n </div>\n )\n}\n","import { useBlockNumber, useEnsAddress, useEnsName } from 'wagmi'\nimport { identityErrorKind, needsRpcProbe, IDENTITY_ERROR_TEXT } from '../core/identityError'\nimport { useIdentityKitConfig } from '../context'\nimport { chainFor } from '../provider'\nimport { normalize } from 'viem/ens'\nimport { useAttestations } from './useAttestations'\nimport { useEFPGraph } from './useEFPGraph'\nimport { usePGPProofs } from './usePGPProofs'\nimport { useSafeAvatar } from './useSafeAvatar'\nimport type { ThurinIdentity } from '../core/types'\n\nfunction isAddress(value: string): boolean {\n return /^0x[0-9a-fA-F]{40}$/.test(value)\n}\n\nfunction safeNormalize(name: string): string | undefined {\n try {\n return normalize(name)\n } catch {\n return undefined\n }\n}\n\nexport function useThurinIdentity(ensOrAddress: string | undefined | null): ThurinIdentity {\n const chain = chainFor(useIdentityKitConfig().network)\n const isAddr = ensOrAddress ? isAddress(ensOrAddress) : false\n const ensInput = ensOrAddress && !isAddr ? safeNormalize(ensOrAddress) : undefined\n\n // Resolve ENS → address\n const { data: resolvedAddress, error: ensError, isFetched: ensFetched, refetch: refetchEns } = useEnsAddress({\n name: ensInput,\n chainId: chain.id,\n query: { enabled: !!ensInput },\n })\n\n const address = isAddr ? ensOrAddress! : resolvedAddress ?? null\n\n // Reverse resolve address → ENS\n const { data: ensName } = useEnsName({\n address: address as `0x${string}` | undefined,\n chainId: chain.id,\n query: { enabled: !!address },\n })\n\n const displayName = ensInput || ensName || null\n\n const ensAvatar = useSafeAvatar(displayName ? safeNormalize(displayName) : undefined, chain.id)\n\n // On-chain attestations\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\n error: claimsError,\n refetch: refetchClaims,\n } = useAttestations(address)\n\n // PGP proofs come from the key stored in the current attestation — the\n // latest claim that is active and whose signature verified (the same rule\n // useAttestations uses to pick currentFingerprint).\n const currentClaim = [...claims].reverse().find(\n (c) => !c.revoked && c.verification?.verified && c.fingerprint === currentFingerprint,\n )\n const {\n keyInfo: pgpKeyInfo,\n proofs,\n isLoading: proofsLoading,\n } = usePGPProofs(currentFingerprint, currentClaim?.pgpPublicKey ?? null)\n\n // EFP social graph\n const { efp, isLoading: efpLoading } = useEFPGraph(address)\n\n // An empty ENS result or a failed read might just be a dead RPC; ask it for the block\n // number before saying anything about the identity (core/identityError.ts).\n const lookup = { ensEmpty: !!ensInput && ensFetched && !resolvedAddress, ensFailed: !!ensError, claimsFailed: !!claimsError }\n const probeNeeded = needsRpcProbe(lookup)\n // useBlockNumber, not usePublicClient: the latter attaches every public action to the client,\n // which put ~360 KB more into the standalone embed (1.3.4). Own scope per identity and no\n // caching, so an earlier answer can't make a dead RPC look alive.\n const probe = useBlockNumber({\n chainId: chain.id,\n scopeKey: `thurin-rpc-probe:${ensOrAddress ?? ''}`,\n query: { enabled: probeNeeded, retry: 0, staleTime: 0, gcTime: 0 },\n })\n const rpcAnswered = !probeNeeded || probe.isFetching ? undefined : probe.isSuccess ? true : probe.isError ? false : undefined\n const errorKind = identityErrorKind({ ...lookup, rpcAnswered })\n const probing = probeNeeded && rpcAnswered === undefined\n const retry = () => {\n if (ensInput) refetchEns()\n refetchClaims()\n if (probeNeeded) probe.refetch()\n }\n\n return {\n address,\n ensName: displayName,\n ensAvatar,\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n pgpKeyInfo,\n proofs,\n efp,\n // \"Not finished\" counts as loading, including queries paused in a background tab: the card\n // must not render defaults (zeros) for an identity it hasn't looked up yet.\n isLoading: (!!ensInput && !ensFetched) || claimsLoading || proofsLoading || efpLoading || probing,\n error: errorKind ? new Error(IDENTITY_ERROR_TEXT[errorKind]) : null,\n errorKind,\n retry,\n }\n}\n","import { useReadContract, useReadContracts } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { hexToString } from 'viem'\nimport { REGISTRY_ABI, getRegistry } from '../core/contract'\nimport { bytesToFingerprint } from '../core/fingerprint'\nimport { chainFor } from '../provider'\nimport { verifyAttestation } from '../core/pgp'\nimport { useIdentityKitConfig } from '../context'\nimport type { Attestation } from '../core/types'\n\n/**\n * On-chain attestations for an address, read straight from the v2 registry:\n * `attestationsOf` for the history, `getPayload` for each stored signature + key.\n * No event logs, so any RPC works. Each claim is verified off-chain.\n */\nexport function useAttestations(address: string | undefined | null) {\n const config = useIdentityKitConfig()\n const registry = getRegistry(config.network, config.registryAddress)\n const chain = chainFor(config.network)\n const owner = address as `0x${string}` | undefined\n\n const { data: rows, isLoading: rowsLoading, isFetched: rowsFetched, error: rowsError, refetch: refetchRows } = useReadContract({\n address: registry.address,\n abi: REGISTRY_ABI,\n functionName: 'attestationsOf',\n args: owner ? [owner] : undefined,\n chainId: chain.id,\n query: { enabled: !!owner },\n })\n\n const count = rows?.length ?? 0\n\n const contracts = owner && rows\n ? rows.map((_, i) => ({\n address: registry.address,\n abi: REGISTRY_ABI,\n functionName: 'getPayload' as const,\n args: [owner, BigInt(i)] as const,\n chainId: chain.id,\n }))\n : []\n\n const { data: payloads, isLoading: payloadsLoading, error: payloadsError, refetch: refetchPayloads } = useReadContracts({\n contracts,\n query: { enabled: contracts.length > 0 },\n })\n\n const payloadsReady = count === 0 || (payloads !== undefined && payloads.length === count)\n\n const { data: claims, isLoading: verifyLoading } = useQuery({\n queryKey: ['attestations', config.network, registry.address, address, count, payloadsReady],\n queryFn: async (): Promise<Attestation[]> => {\n if (!rows || !address) return []\n const results: Attestation[] = []\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n const payload = payloads?.[i]\n let pgpSignature: string | null = null\n let pgpPublicKey: string | null = null\n if (payload && payload.status === 'success') {\n const [sigHex, keyHex] = payload.result as readonly [`0x${string}`, `0x${string}`]\n pgpSignature = hexToString(sigHex)\n pgpPublicKey = hexToString(keyHex)\n }\n\n const fingerprint = bytesToFingerprint(row.fingerprint)\n const verification = pgpPublicKey && pgpSignature\n ? await verifyAttestation({ pgpPublicKey, pgpSignature, fingerprint, ethAddress: address })\n : null\n\n const revokedAt = Number(row.revokedAt)\n results.push({\n index: i,\n fingerprint,\n createdAt: Number(row.createdAt),\n revoked: revokedAt !== 0,\n revokedAt: revokedAt === 0 ? null : revokedAt,\n messageVersion: Number(row.messageVersion),\n pgpSignature,\n pgpPublicKey,\n verification,\n })\n }\n return results\n },\n enabled: !!rows && payloadsReady,\n staleTime: 300_000,\n })\n\n // Not fetched yet counts as loading (a paused query in a background tab is not \"no claims\").\n const isLoading = rowsLoading || (!!owner && !rowsFetched) || payloadsLoading || verifyLoading || (!!owner && rows !== undefined && !payloadsReady)\n\n const activeClaims = (claims || []).filter((c) => !c.revoked)\n // The current identity is the latest claim that is both active and has a\n // verified signature binding the key to this address. A claim whose signature\n // has not verified must not surface the key's proofs or user data.\n const verifiedClaims = activeClaims.filter((c) => c.verification?.verified)\n const currentFingerprint = verifiedClaims.length > 0\n ? verifiedClaims[verifiedClaims.length - 1].fingerprint\n : null\n\n return {\n claims: claims || [],\n totalClaims: count,\n activeClaims: activeClaims.length,\n currentFingerprint,\n isLoading,\n /** A registry read failed (the RPC may be down; useThurinIdentity finds out which). */\n error: (rowsError ?? payloadsError ?? null) as Error | null,\n refetch: () => { if (owner) { refetchRows(); if (contracts.length > 0) refetchPayloads() } },\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { fetchEFPGraph } from '../core/efp'\nimport type { EFPGraph } from '../core/types'\n\nexport function useEFPGraph(address: string | undefined | null) {\n const { data, isLoading } = useQuery<EFPGraph | null>({\n queryKey: ['efp-graph', address],\n queryFn: () => fetchEFPGraph(address!),\n enabled: !!address,\n staleTime: 300_000,\n })\n\n return {\n efp: data ?? null,\n isLoading,\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { parsePgpKey } from '../core/pgp'\nimport { identifyProof, verifyProof, displayUrl, proofHref, proofSecondaryHref } from '../core/proofs'\nimport { useIdentityKitConfig } from '../context'\nimport type { PGPKeyInfo, ProofResult } from '../core/types'\n\n/**\n * Proofs for an identity, read from the PGP key stored in its on-chain\n * attestation. No keyserver is consulted: keys.openpgp.org only serves user\n * IDs whose email is verified and drops non-email user IDs entirely, so it can\n * never carry the published (non-email) identity that holds the notations.\n *\n * @param fingerprint the attested fingerprint (proofs must name it)\n * @param armoredKey the attestation's `pgpPublicKey`\n */\nexport function usePGPProofs(fingerprint: string | undefined | null, armoredKey: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data } = useQuery({\n // The key is large; key the query on its length + fingerprint, which\n // changes whenever a different attestation's key is supplied.\n queryKey: ['pgp-proofs', fingerprint, armoredKey?.length ?? 0],\n queryFn: async (): Promise<{ keyInfo: PGPKeyInfo | null; proofs: ProofResult[] }> => {\n if (!fingerprint || !armoredKey) return { keyInfo: null, proofs: [] }\n\n const keyInfo = await parsePgpKey(armoredKey)\n if (!keyInfo) return { keyInfo: null, proofs: [] }\n\n // Identify proofs from notations. Drop unrecognized targets (provider\n // 'unknown') so the card doesn't render \"Unknown\" badges for platforms\n // Thurin has no verifier for — matching the explorer's behavior.\n const identified = keyInfo.notations\n .map((n) => identifyProof(n))\n .filter((p): p is NonNullable<typeof p> => p !== null && p.provider !== 'unknown')\n\n // Verify all proofs in parallel\n const proofs: ProofResult[] = await Promise.all(\n identified.map(async (proof) => {\n const result = await verifyProof(proof, fingerprint, config.neynarApiKey)\n return {\n provider: proof.provider,\n label: proof.label,\n url: proof.url,\n displayUrl: displayUrl(proof),\n href: proofHref(proof),\n secondaryHref: proofSecondaryHref(proof),\n status: result.verified ? 'verified' as const : 'unverified' as const,\n reason: result.reason,\n }\n }),\n )\n\n // Collapse proofs that resolve to the same account — the same target is\n // often listed under both proof@thurin.id and proof@ariadne.id (and can\n // be reached via more than one proof URL). Key by provider + display\n // identity, preferring a verified result.\n const byAccount = new Map<string, ProofResult>()\n for (const p of proofs) {\n const key = `${p.provider}:${p.displayUrl}`\n const prev = byAccount.get(key)\n if (!prev || (p.status === 'verified' && prev.status !== 'verified')) {\n byAccount.set(key, p)\n }\n }\n\n return { keyInfo, proofs: [...byAccount.values()] }\n },\n enabled: !!fingerprint && !!armoredKey,\n staleTime: 300_000,\n })\n\n return {\n keyInfo: data?.keyInfo ?? null,\n proofs: data?.proofs ?? [],\n // Report loading whenever a fingerprint is set but its proofs haven't\n // resolved yet. Using react-query's own isLoading leaves a gap while the\n // query is enabling (fingerprint just became known), during which the card\n // would briefly paint without proof badges and then pop them in.\n isLoading: !!fingerprint && !!armoredKey && data === undefined,\n }\n}\n","import { useEnsText, useReadContract } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { avatarUrl, parseNftAvatar, nftAvatarImage, NFT_AVATAR_ABI } from '../core/avatar'\n\n/**\n * The avatar to show for a normalized ENS name, or null. Reads the raw `avatar` record and\n * loads only what `avatarUrl` allows (see core/avatar.ts); wagmi's useEnsAvatar would fetch\n * whatever host the name's owner chose.\n */\nexport function useSafeAvatar(name: string | undefined, chainId: number): string | null {\n const { data: raw } = useEnsText({ name, key: 'avatar', chainId, query: { enabled: !!name } })\n const direct = avatarUrl(raw)\n const nft = direct ? null : parseNftAvatar(raw)\n const { data: tokenUri } = useReadContract({\n address: nft?.contract,\n abi: NFT_AVATAR_ABI,\n functionName: nft?.standard === 'erc1155' ? 'uri' : 'tokenURI',\n args: nft ? [nft.tokenId] : undefined,\n chainId,\n query: { enabled: !!nft && nft.chainId === chainId },\n })\n const { data: image } = useQuery({\n queryKey: ['thurin-nft-avatar', tokenUri, nft?.tokenId.toString()],\n queryFn: () => nftAvatarImage(tokenUri as string, nft!.tokenId).catch(() => null),\n enabled: typeof tokenUri === 'string' && !!nft,\n })\n return direct ?? image ?? null\n}\n","import { useEnsText } from 'wagmi'\nimport { normalize } from 'viem/ens'\nimport { useIdentityKitConfig } from '../context'\nimport { chainFor } from '../provider'\nimport { ENS_HINT_KEY, ensHintFor, type EnsHint } from '../core/ensHint'\n\nfunction safeNormalize(name: string): string | undefined {\n try { return normalize(name) } catch { return undefined }\n}\n\n/**\n * A name's `id.thurin` record against the fingerprint the registry verifies for its\n * address. `state` is `match`, `unset`, or `mismatch`; the last one is the signal worth\n * showing — a name advertising a key its address has not claimed.\n */\nexport function useEnsHint(name: string | undefined | null, verifiedFingerprint: string | null | undefined): EnsHint & { isLoading: boolean; refetch: () => void } {\n const chain = chainFor(useIdentityKitConfig().network)\n const ensName = name ? safeNormalize(name) : undefined\n const { data, isLoading, refetch } = useEnsText({\n name: ensName,\n key: ENS_HINT_KEY,\n chainId: chain.id,\n query: { enabled: !!ensName },\n })\n return { ...ensHintFor(data ?? null, verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => { void refetch() } }\n}\n","import { useReadContracts } from 'wagmi'\nimport { useQuery } from '@tanstack/react-query'\nimport { REGISTRY_ABI, getRegistry } from '../core/contract'\nimport { chainFor } from '../provider'\nimport { useIdentityKitConfig } from '../context'\nimport { IDENTITY_KINDS, decodeRecord, parseRecord, recordKind, type ParsedRecord } from '../core/records'\n\n/**\n * The records on one claim, for the kinds given (default: the kinds an identity page shows),\n * read in one multicall and parsed. Kinds with no record are left out.\n */\nexport function useRecords(address: string | undefined | null, index: number | undefined | null, kinds: readonly string[] = IDENTITY_KINDS, armoredKey?: string | null) {\n const config = useIdentityKitConfig()\n const registry = getRegistry(config.network, config.registryAddress)\n const chain = chainFor(config.network)\n const owner = address as `0x${string}` | undefined\n const enabled = !!owner && index !== undefined && index !== null\n\n const contracts = enabled\n ? kinds.map(kind => ({ address: registry.address, abi: REGISTRY_ABI, functionName: 'record' as const, args: [owner!, BigInt(index!), recordKind(kind)] as const, chainId: chain.id }))\n : []\n const { data: raw, isLoading: readLoading, refetch } = useReadContracts({ contracts, query: { enabled: contracts.length > 0 } })\n\n const texts = (raw ?? []).map(r => (r.status === 'success' ? decodeRecord(r.result as `0x${string}`) : ''))\n const { data: records, isLoading: parseLoading } = useQuery({\n queryKey: ['records', config.network, registry.address, address, index, kinds.join(','), texts.join(' '), armoredKey ?? ''],\n queryFn: async (): Promise<ParsedRecord[]> => {\n const out: ParsedRecord[] = []\n for (let i = 0; i < kinds.length; i++) if (texts[i]) out.push(await parseRecord(kinds[i], texts[i], { armoredKey: armoredKey ?? undefined }))\n return out\n },\n enabled: enabled && raw !== undefined,\n })\n\n return { records: records ?? [], isLoading: enabled && (readLoading || parseLoading), refetch: () => { void refetch() } }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { IdentityKitConfig, Theme, ThurinIdentity, Attestation, EFPGraph, PGPKeyInfo, ProofResult, EnsHint, ParsedRecord } from './core.cjs';
4
- export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, IdentityErrorKind, IdentityLookupState, KNOWN_KINDS, KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, NetworkName, NftAvatar, Notation, PGPVerification, PointerEntry, PointerRecord, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RecordData, RecordReader, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, 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 } from './core.cjs';
4
+ export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, IPFS_GATEWAYS, IdentityErrorKind, IdentityLookupState, KNOWN_KINDS, KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, NetworkName, NftAvatar, Notation, PGPVerification, PointerEntry, PointerRecord, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RecordData, RecordReader, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, 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 } from './core.cjs';
5
5
  import 'viem';
6
6
 
7
7
  interface IdentityKitProviderProps extends IdentityKitConfig {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { IdentityKitConfig, Theme, ThurinIdentity, Attestation, EFPGraph, PGPKeyInfo, ProofResult, EnsHint, ParsedRecord } from './core.js';
4
- export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, IdentityErrorKind, IdentityLookupState, KNOWN_KINDS, KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, NetworkName, NftAvatar, Notation, PGPVerification, PointerEntry, PointerRecord, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RecordData, RecordReader, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, 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 } from './core.js';
4
+ export { ARWEAVE_GATEWAY, AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, IDENTITY_ERROR_TEXT, IDENTITY_KINDS, IPFS_GATEWAY, IPFS_GATEWAYS, IdentityErrorKind, IdentityLookupState, KNOWN_KINDS, KnownKind, MAX_RECORD_BYTES, NETWORKS, NFT_AVATAR_ABI, NetworkName, NftAvatar, Notation, PGPVerification, PointerEntry, PointerRecord, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RecordData, RecordReader, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, 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 } from './core.js';
5
5
  import 'viem';
6
6
 
7
7
  interface IdentityKitProviderProps extends IdentityKitConfig {
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  IDENTITY_ERROR_TEXT,
9
9
  IDENTITY_KINDS,
10
10
  IPFS_GATEWAY,
11
+ IPFS_GATEWAYS,
11
12
  KNOWN_KINDS,
12
13
  MAX_RECORD_BYTES,
13
14
  NETWORKS,
@@ -17,6 +18,7 @@ import {
17
18
  addPointer,
18
19
  attestTypedData,
19
20
  authorizationDigest,
21
+ avatarFallbacks,
20
22
  avatarUrl,
21
23
  bytesToFingerprint,
22
24
  chainFor,
@@ -59,7 +61,7 @@ import {
59
61
  verifyAttestation,
60
62
  verifyClearsigned,
61
63
  verifyProof
62
- } from "./chunk-CF64QQZO.js";
64
+ } from "./chunk-HDBHNN4I.js";
63
65
 
64
66
  // src/provider.tsx
65
67
  import { useMemo } from "react";
@@ -122,9 +124,11 @@ function IdentityKitProvider({
122
124
  return /* @__PURE__ */ jsx(IdentityKitContext.Provider, { value: config, children: /* @__PURE__ */ jsx(WagmiDetector, { rpcUrl, network, children }) });
123
125
  }
124
126
 
127
+ // src/components/ThurinCard/ThurinCard.tsx
128
+ import { useEffect, useState } from "react";
129
+
125
130
  // src/hooks/useThurinIdentity.ts
126
- import { useEnsAddress, useEnsName, usePublicClient } from "wagmi";
127
- import { useQuery as useQuery5 } from "@tanstack/react-query";
131
+ import { useBlockNumber, useEnsAddress, useEnsName } from "wagmi";
128
132
  import { normalize } from "viem/ens";
129
133
 
130
134
  // src/hooks/useAttestations.ts
@@ -351,13 +355,10 @@ function useThurinIdentity(ensOrAddress) {
351
355
  const { efp, isLoading: efpLoading } = useEFPGraph(address);
352
356
  const lookup = { ensEmpty: !!ensInput && ensFetched && !resolvedAddress, ensFailed: !!ensError, claimsFailed: !!claimsError };
353
357
  const probeNeeded = needsRpcProbe(lookup);
354
- const client = usePublicClient({ chainId: chain.id });
355
- const probe = useQuery5({
356
- queryKey: ["thurin-rpc-probe", chain.id, ensOrAddress],
357
- queryFn: () => client.getBlockNumber(),
358
- enabled: probeNeeded && !!client,
359
- retry: 0,
360
- staleTime: 0
358
+ const probe = useBlockNumber({
359
+ chainId: chain.id,
360
+ scopeKey: `thurin-rpc-probe:${ensOrAddress ?? ""}`,
361
+ query: { enabled: probeNeeded, retry: 0, staleTime: 0, gcTime: 0 }
361
362
  });
362
363
  const rpcAnswered = !probeNeeded || probe.isFetching ? void 0 : probe.isSuccess ? true : probe.isError ? false : void 0;
363
364
  const errorKind = identityErrorKind({ ...lookup, rpcAnswered });
@@ -398,6 +399,14 @@ function ThurinLogo() {
398
399
  /* @__PURE__ */ jsx2("path", { d: "M50 65 L50 53", fill: "none", stroke: "#c9a227", strokeWidth: "4", strokeLinecap: "round" })
399
400
  ] });
400
401
  }
402
+ function Avatar({ src, alt }) {
403
+ const [tries, setTries] = useState([]);
404
+ useEffect(() => {
405
+ setTries(src ? [src, ...avatarFallbacks(src)] : []);
406
+ }, [src]);
407
+ if (!tries.length) return /* @__PURE__ */ jsx2(ThurinLogo, {});
408
+ return /* @__PURE__ */ jsx2("img", { className: "thurin-card-avatar", src: tries[0], alt, onError: () => setTries((t) => t.slice(1)) });
409
+ }
401
410
  function ThurinCard({ ens, address, theme = "thurin" }) {
402
411
  const input = ens || address;
403
412
  const identity = useThurinIdentity(input);
@@ -424,14 +433,7 @@ function ThurinCard({ ens, address, theme = "thurin" }) {
424
433
  const hasVerifiedPgp = identity.claims.some((c) => c.verification?.verified && !c.revoked);
425
434
  return /* @__PURE__ */ jsxs("div", { className: "thurin-card", "data-thurin-theme": theme, children: [
426
435
  /* @__PURE__ */ jsxs("a", { className: "thurin-card-header", href: profileUrl || void 0, target: "_blank", rel: "noopener noreferrer", children: [
427
- identity.ensAvatar ? /* @__PURE__ */ jsx2(
428
- "img",
429
- {
430
- className: "thurin-card-avatar",
431
- src: identity.ensAvatar,
432
- alt: identity.ensName || ""
433
- }
434
- ) : /* @__PURE__ */ jsx2(ThurinLogo, {}),
436
+ /* @__PURE__ */ jsx2(Avatar, { src: identity.ensAvatar, alt: identity.ensName || "" }),
435
437
  /* @__PURE__ */ jsxs("div", { children: [
436
438
  identity.ensName && /* @__PURE__ */ jsx2("div", { className: "thurin-card-name", children: identity.ensName }),
437
439
  displayAddress && /* @__PURE__ */ jsx2("div", { className: "thurin-card-address", children: displayAddress })
@@ -502,7 +504,7 @@ function useEnsHint(name, verifiedFingerprint) {
502
504
 
503
505
  // src/hooks/useRecords.ts
504
506
  import { useReadContracts as useReadContracts2 } from "wagmi";
505
- import { useQuery as useQuery6 } from "@tanstack/react-query";
507
+ import { useQuery as useQuery5 } from "@tanstack/react-query";
506
508
  function useRecords(address, index, kinds = IDENTITY_KINDS, armoredKey) {
507
509
  const config = useIdentityKitConfig();
508
510
  const registry = getRegistry(config.network, config.registryAddress);
@@ -512,7 +514,7 @@ function useRecords(address, index, kinds = IDENTITY_KINDS, armoredKey) {
512
514
  const contracts = enabled ? kinds.map((kind) => ({ address: registry.address, abi: REGISTRY_ABI, functionName: "record", args: [owner, BigInt(index), recordKind(kind)], chainId: chain.id })) : [];
513
515
  const { data: raw, isLoading: readLoading, refetch } = useReadContracts2({ contracts, query: { enabled: contracts.length > 0 } });
514
516
  const texts = (raw ?? []).map((r) => r.status === "success" ? decodeRecord(r.result) : "");
515
- const { data: records, isLoading: parseLoading } = useQuery6({
517
+ const { data: records, isLoading: parseLoading } = useQuery5({
516
518
  queryKey: ["records", config.network, registry.address, address, index, kinds.join(","), texts.join(" "), armoredKey ?? ""],
517
519
  queryFn: async () => {
518
520
  const out = [];
@@ -535,6 +537,7 @@ export {
535
537
  IDENTITY_ERROR_TEXT,
536
538
  IDENTITY_KINDS,
537
539
  IPFS_GATEWAY,
540
+ IPFS_GATEWAYS,
538
541
  IdentityKitProvider,
539
542
  KNOWN_KINDS,
540
543
  MAX_RECORD_BYTES,
@@ -546,6 +549,7 @@ export {
546
549
  addPointer,
547
550
  attestTypedData,
548
551
  authorizationDigest,
552
+ avatarFallbacks,
549
553
  avatarUrl,
550
554
  bytesToFingerprint,
551
555
  chainFor,