@thurinlabs/identity-kit 1.3.2 → 1.3.4

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
@@ -50,7 +50,16 @@
50
50
 
51
51
 
52
52
 
53
- var _chunkHUJD6LYZcjs = require('./chunk-HUJD6LYZ.cjs');
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+ var _chunkYTO7Z5SIcjs = require('./chunk-YTO7Z5SI.cjs');
54
63
 
55
64
  // src/provider.tsx
56
65
  var _react = require('react');
@@ -80,7 +89,7 @@ var defaultQueryClient = new (0, _reactquery.QueryClient)({
80
89
  }
81
90
  });
82
91
  function createDefaultWagmiConfig(rpcUrl, network) {
83
- const url = rpcUrl || _chunkHUJD6LYZcjs.getRegistry.call(void 0, network).defaultRpcUrl;
92
+ const url = rpcUrl || _chunkYTO7Z5SIcjs.getRegistry.call(void 0, network).defaultRpcUrl;
84
93
  if (network === "sepolia") return _wagmi.createConfig.call(void 0, { chains: [_chains.sepolia], transports: { [_chains.sepolia.id]: _wagmi.http.call(void 0, url) } });
85
94
  if (network === "local") return _wagmi.createConfig.call(void 0, { chains: [_chains.foundry], transports: { [_chains.foundry.id]: _wagmi.http.call(void 0, url) } });
86
95
  return _wagmi.createConfig.call(void 0, { chains: [_chains.mainnet], transports: { [_chains.mainnet.id]: _wagmi.http.call(void 0, url) } });
@@ -115,6 +124,7 @@ function IdentityKitProvider({
115
124
 
116
125
  // src/hooks/useThurinIdentity.ts
117
126
 
127
+
118
128
  var _ens = require('viem/ens');
119
129
 
120
130
  // src/hooks/useAttestations.ts
@@ -123,12 +133,12 @@ var _ens = require('viem/ens');
123
133
  var _viem = require('viem');
124
134
  function useAttestations(address) {
125
135
  const config = useIdentityKitConfig();
126
- const registry = _chunkHUJD6LYZcjs.getRegistry.call(void 0, config.network, config.registryAddress);
127
- const chain = _chunkHUJD6LYZcjs.chainFor.call(void 0, config.network);
136
+ const registry = _chunkYTO7Z5SIcjs.getRegistry.call(void 0, config.network, config.registryAddress);
137
+ const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, config.network);
128
138
  const owner = address;
129
- const { data: rows, isLoading: rowsLoading } = _wagmi.useReadContract.call(void 0, {
139
+ const { data: rows, isLoading: rowsLoading, isFetched: rowsFetched, error: rowsError, refetch: refetchRows } = _wagmi.useReadContract.call(void 0, {
130
140
  address: registry.address,
131
- abi: _chunkHUJD6LYZcjs.REGISTRY_ABI,
141
+ abi: _chunkYTO7Z5SIcjs.REGISTRY_ABI,
132
142
  functionName: "attestationsOf",
133
143
  args: owner ? [owner] : void 0,
134
144
  chainId: chain.id,
@@ -137,12 +147,12 @@ function useAttestations(address) {
137
147
  const count = _nullishCoalesce(_optionalChain([rows, 'optionalAccess', _2 => _2.length]), () => ( 0));
138
148
  const contracts = owner && rows ? rows.map((_, i) => ({
139
149
  address: registry.address,
140
- abi: _chunkHUJD6LYZcjs.REGISTRY_ABI,
150
+ abi: _chunkYTO7Z5SIcjs.REGISTRY_ABI,
141
151
  functionName: "getPayload",
142
152
  args: [owner, BigInt(i)],
143
153
  chainId: chain.id
144
154
  })) : [];
145
- const { data: payloads, isLoading: payloadsLoading } = _wagmi.useReadContracts.call(void 0, {
155
+ const { data: payloads, isLoading: payloadsLoading, error: payloadsError, refetch: refetchPayloads } = _wagmi.useReadContracts.call(void 0, {
146
156
  contracts,
147
157
  query: { enabled: contracts.length > 0 }
148
158
  });
@@ -162,8 +172,8 @@ function useAttestations(address) {
162
172
  pgpSignature = _viem.hexToString.call(void 0, sigHex);
163
173
  pgpPublicKey = _viem.hexToString.call(void 0, keyHex);
164
174
  }
165
- const fingerprint = _chunkHUJD6LYZcjs.bytesToFingerprint.call(void 0, row.fingerprint);
166
- const verification = pgpPublicKey && pgpSignature ? await _chunkHUJD6LYZcjs.verifyAttestation.call(void 0, { pgpPublicKey, pgpSignature, fingerprint, ethAddress: address }) : null;
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;
167
177
  const revokedAt = Number(row.revokedAt);
168
178
  results.push({
169
179
  index: i,
@@ -182,7 +192,7 @@ function useAttestations(address) {
182
192
  enabled: !!rows && payloadsReady,
183
193
  staleTime: 3e5
184
194
  });
185
- const isLoading = rowsLoading || payloadsLoading || verifyLoading || !!owner && rows !== void 0 && !payloadsReady;
195
+ const isLoading = rowsLoading || !!owner && !rowsFetched || payloadsLoading || verifyLoading || !!owner && rows !== void 0 && !payloadsReady;
186
196
  const activeClaims = (claims || []).filter((c) => !c.revoked);
187
197
  const verifiedClaims = activeClaims.filter((c) => _optionalChain([c, 'access', _4 => _4.verification, 'optionalAccess', _5 => _5.verified]));
188
198
  const currentFingerprint = verifiedClaims.length > 0 ? verifiedClaims[verifiedClaims.length - 1].fingerprint : null;
@@ -191,7 +201,15 @@ function useAttestations(address) {
191
201
  totalClaims: count,
192
202
  activeClaims: activeClaims.length,
193
203
  currentFingerprint,
194
- isLoading
204
+ isLoading,
205
+ /** A registry read failed (the RPC may be down; useThurinIdentity finds out which). */
206
+ error: _nullishCoalesce(_nullishCoalesce(rowsError, () => ( payloadsError)), () => ( null)),
207
+ refetch: () => {
208
+ if (owner) {
209
+ refetchRows();
210
+ if (contracts.length > 0) refetchPayloads();
211
+ }
212
+ }
195
213
  };
196
214
  }
197
215
 
@@ -200,7 +218,7 @@ function useAttestations(address) {
200
218
  function useEFPGraph(address) {
201
219
  const { data, isLoading } = _reactquery.useQuery.call(void 0, {
202
220
  queryKey: ["efp-graph", address],
203
- queryFn: () => _chunkHUJD6LYZcjs.fetchEFPGraph.call(void 0, address),
221
+ queryFn: () => _chunkYTO7Z5SIcjs.fetchEFPGraph.call(void 0, address),
204
222
  enabled: !!address,
205
223
  staleTime: 3e5
206
224
  });
@@ -220,19 +238,19 @@ function usePGPProofs(fingerprint, armoredKey) {
220
238
  queryKey: ["pgp-proofs", fingerprint, _nullishCoalesce(_optionalChain([armoredKey, 'optionalAccess', _6 => _6.length]), () => ( 0))],
221
239
  queryFn: async () => {
222
240
  if (!fingerprint || !armoredKey) return { keyInfo: null, proofs: [] };
223
- const keyInfo = await _chunkHUJD6LYZcjs.parsePgpKey.call(void 0, armoredKey);
241
+ const keyInfo = await _chunkYTO7Z5SIcjs.parsePgpKey.call(void 0, armoredKey);
224
242
  if (!keyInfo) return { keyInfo: null, proofs: [] };
225
- const identified = keyInfo.notations.map((n) => _chunkHUJD6LYZcjs.identifyProof.call(void 0, n)).filter((p) => p !== null && p.provider !== "unknown");
243
+ const identified = keyInfo.notations.map((n) => _chunkYTO7Z5SIcjs.identifyProof.call(void 0, n)).filter((p) => p !== null && p.provider !== "unknown");
226
244
  const proofs = await Promise.all(
227
245
  identified.map(async (proof) => {
228
- const result = await _chunkHUJD6LYZcjs.verifyProof.call(void 0, proof, fingerprint, config.neynarApiKey);
246
+ const result = await _chunkYTO7Z5SIcjs.verifyProof.call(void 0, proof, fingerprint, config.neynarApiKey);
229
247
  return {
230
248
  provider: proof.provider,
231
249
  label: proof.label,
232
250
  url: proof.url,
233
- displayUrl: _chunkHUJD6LYZcjs.displayUrl.call(void 0, proof),
234
- href: _chunkHUJD6LYZcjs.proofHref.call(void 0, proof),
235
- secondaryHref: _chunkHUJD6LYZcjs.proofSecondaryHref.call(void 0, proof),
251
+ displayUrl: _chunkYTO7Z5SIcjs.displayUrl.call(void 0, proof),
252
+ href: _chunkYTO7Z5SIcjs.proofHref.call(void 0, proof),
253
+ secondaryHref: _chunkYTO7Z5SIcjs.proofSecondaryHref.call(void 0, proof),
236
254
  status: result.verified ? "verified" : "unverified",
237
255
  reason: result.reason
238
256
  };
@@ -262,6 +280,29 @@ function usePGPProofs(fingerprint, armoredKey) {
262
280
  };
263
281
  }
264
282
 
283
+ // src/hooks/useSafeAvatar.ts
284
+
285
+
286
+ function useSafeAvatar(name, chainId) {
287
+ 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);
290
+ const { data: tokenUri } = _wagmi.useReadContract.call(void 0, {
291
+ address: _optionalChain([nft, 'optionalAccess', _9 => _9.contract]),
292
+ abi: _chunkYTO7Z5SIcjs.NFT_AVATAR_ABI,
293
+ functionName: _optionalChain([nft, 'optionalAccess', _10 => _10.standard]) === "erc1155" ? "uri" : "tokenURI",
294
+ args: nft ? [nft.tokenId] : void 0,
295
+ chainId,
296
+ query: { enabled: !!nft && nft.chainId === chainId }
297
+ });
298
+ const { data: image } = _reactquery.useQuery.call(void 0, {
299
+ 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),
301
+ enabled: typeof tokenUri === "string" && !!nft
302
+ });
303
+ return _nullishCoalesce(_nullishCoalesce(direct, () => ( image)), () => ( null));
304
+ }
305
+
265
306
  // src/hooks/useThurinIdentity.ts
266
307
  function isAddress(value) {
267
308
  return /^0x[0-9a-fA-F]{40}$/.test(value);
@@ -274,10 +315,10 @@ function safeNormalize(name) {
274
315
  }
275
316
  }
276
317
  function useThurinIdentity(ensOrAddress) {
277
- const chain = _chunkHUJD6LYZcjs.chainFor.call(void 0, useIdentityKitConfig().network);
318
+ const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, useIdentityKitConfig().network);
278
319
  const isAddr = ensOrAddress ? isAddress(ensOrAddress) : false;
279
320
  const ensInput = ensOrAddress && !isAddr ? safeNormalize(ensOrAddress) : void 0;
280
- const { data: resolvedAddress } = _wagmi.useEnsAddress.call(void 0, {
321
+ const { data: resolvedAddress, error: ensError, isFetched: ensFetched, refetch: refetchEns } = _wagmi.useEnsAddress.call(void 0, {
281
322
  name: ensInput,
282
323
  chainId: chain.id,
283
324
  query: { enabled: !!ensInput }
@@ -289,31 +330,47 @@ function useThurinIdentity(ensOrAddress) {
289
330
  query: { enabled: !!address }
290
331
  });
291
332
  const displayName = ensInput || ensName || null;
292
- const { data: ensAvatar } = _wagmi.useEnsAvatar.call(void 0, {
293
- name: displayName ? safeNormalize(displayName) : void 0,
294
- chainId: chain.id,
295
- query: { enabled: !!displayName }
296
- });
333
+ const ensAvatar = useSafeAvatar(displayName ? safeNormalize(displayName) : void 0, chain.id);
297
334
  const {
298
335
  claims,
299
336
  totalClaims,
300
337
  activeClaims,
301
338
  currentFingerprint,
302
- isLoading: claimsLoading
339
+ isLoading: claimsLoading,
340
+ error: claimsError,
341
+ refetch: refetchClaims
303
342
  } = useAttestations(address);
304
343
  const currentClaim = [...claims].reverse().find(
305
- (c) => !c.revoked && _optionalChain([c, 'access', _9 => _9.verification, 'optionalAccess', _10 => _10.verified]) && c.fingerprint === currentFingerprint
344
+ (c) => !c.revoked && _optionalChain([c, 'access', _14 => _14.verification, 'optionalAccess', _15 => _15.verified]) && c.fingerprint === currentFingerprint
306
345
  );
307
346
  const {
308
347
  keyInfo: pgpKeyInfo,
309
348
  proofs,
310
349
  isLoading: proofsLoading
311
- } = usePGPProofs(currentFingerprint, _nullishCoalesce(_optionalChain([currentClaim, 'optionalAccess', _11 => _11.pgpPublicKey]), () => ( null)));
350
+ } = usePGPProofs(currentFingerprint, _nullishCoalesce(_optionalChain([currentClaim, 'optionalAccess', _16 => _16.pgpPublicKey]), () => ( null)));
312
351
  const { efp, isLoading: efpLoading } = useEFPGraph(address);
352
+ 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
361
+ });
362
+ 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 probing = probeNeeded && rpcAnswered === void 0;
365
+ const retry = () => {
366
+ if (ensInput) refetchEns();
367
+ refetchClaims();
368
+ if (probeNeeded) probe.refetch();
369
+ };
313
370
  return {
314
371
  address,
315
372
  ensName: displayName,
316
- ensAvatar: _nullishCoalesce(ensAvatar, () => ( null)),
373
+ ensAvatar,
317
374
  claims,
318
375
  totalClaims,
319
376
  activeClaims,
@@ -321,8 +378,12 @@ function useThurinIdentity(ensOrAddress) {
321
378
  pgpKeyInfo,
322
379
  proofs,
323
380
  efp,
324
- isLoading: claimsLoading || proofsLoading || efpLoading,
325
- error: null
381
+ // "Not finished" counts as loading, including queries paused in a background tab: the card
382
+ // must not render defaults (zeros) for an identity it hasn't looked up yet.
383
+ isLoading: !!ensInput && !ensFetched || claimsLoading || proofsLoading || efpLoading || probing,
384
+ error: errorKind ? new Error(_chunkYTO7Z5SIcjs.IDENTITY_ERROR_TEXT[errorKind]) : null,
385
+ errorKind,
386
+ retry
326
387
  };
327
388
  }
328
389
 
@@ -346,8 +407,21 @@ function ThurinCard({ ens, address, theme = "thurin" }) {
346
407
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "thurin-card", "data-thurin-theme": theme, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "thurin-card-loading", children: "Loading identity..." }) });
347
408
  }
348
409
  const displayAddress = identity.address || null;
410
+ if (identity.errorKind) {
411
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card", "data-thurin-theme": theme, children: [
412
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card-header", children: [
413
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ThurinLogo, {}),
414
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "thurin-card-name", children: identity.ensName || ens || address }) })
415
+ ] }),
416
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card-error", role: "status", children: [
417
+ _optionalChain([identity, 'access', _17 => _17.error, 'optionalAccess', _18 => _18.message]),
418
+ identity.errorKind !== "not-found" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "thurin-card-retry", onClick: identity.retry, children: "Try again" })
419
+ ] }),
420
+ profileUrl && identity.errorKind !== "not-found" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { className: "thurin-card-link", href: profileUrl, target: "_blank", rel: "noopener noreferrer", children: "View on Thurin" })
421
+ ] });
422
+ }
349
423
  const verifiedProofs = identity.proofs.filter((p) => p.status === "verified").length;
350
- const hasVerifiedPgp = identity.claims.some((c) => _optionalChain([c, 'access', _12 => _12.verification, 'optionalAccess', _13 => _13.verified]) && !c.revoked);
424
+ const hasVerifiedPgp = identity.claims.some((c) => _optionalChain([c, 'access', _19 => _19.verification, 'optionalAccess', _20 => _20.verified]) && !c.revoked);
351
425
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card", "data-thurin-theme": theme, children: [
352
426
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "a", { className: "thurin-card-header", href: profileUrl || void 0, target: "_blank", rel: "noopener noreferrer", children: [
353
427
  identity.ensAvatar ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -373,13 +447,13 @@ function ThurinCard({ ens, address, theme = "thurin" }) {
373
447
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-stat-label", children: "Proofs" })
374
448
  ] }),
375
449
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card-stat", children: [
376
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-stat-value", children: _nullishCoalesce(_optionalChain([identity, 'access', _14 => _14.efp, 'optionalAccess', _15 => _15.followers]), () => ( 0)) }),
450
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-stat-value", children: identity.efp ? identity.efp.followers : "\u2013" }),
377
451
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-stat-label", children: "Followers" })
378
452
  ] })
379
453
  ] }),
380
454
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "thurin-card-badges", children: [
381
455
  hasVerifiedPgp && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-badge thurin-card-badge--verified", children: "PGP Verified" }),
382
- _optionalChain([identity, 'access', _16 => _16.efp, 'optionalAccess', _17 => _17.hasEfp]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-badge thurin-card-badge--verified", children: "EFP" }),
456
+ _optionalChain([identity, 'access', _21 => _21.efp, 'optionalAccess', _22 => _22.hasEfp]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "thurin-card-badge thurin-card-badge--verified", children: "EFP" }),
383
457
  identity.proofs.map((p, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
384
458
  "span",
385
459
  {
@@ -413,15 +487,15 @@ function safeNormalize2(name) {
413
487
  }
414
488
  }
415
489
  function useEnsHint(name, verifiedFingerprint) {
416
- const chain = _chunkHUJD6LYZcjs.chainFor.call(void 0, useIdentityKitConfig().network);
490
+ const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, useIdentityKitConfig().network);
417
491
  const ensName = name ? safeNormalize2(name) : void 0;
418
492
  const { data, isLoading, refetch } = _wagmi.useEnsText.call(void 0, {
419
493
  name: ensName,
420
- key: _chunkHUJD6LYZcjs.ENS_HINT_KEY,
494
+ key: _chunkYTO7Z5SIcjs.ENS_HINT_KEY,
421
495
  chainId: chain.id,
422
496
  query: { enabled: !!ensName }
423
497
  });
424
- return { ..._chunkHUJD6LYZcjs.ensHintFor.call(void 0, _nullishCoalesce(data, () => ( null)), verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => {
498
+ return { ..._chunkYTO7Z5SIcjs.ensHintFor.call(void 0, _nullishCoalesce(data, () => ( null)), verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => {
425
499
  void refetch();
426
500
  } };
427
501
  }
@@ -429,20 +503,20 @@ function useEnsHint(name, verifiedFingerprint) {
429
503
  // src/hooks/useRecords.ts
430
504
 
431
505
 
432
- function useRecords(address, index, kinds = _chunkHUJD6LYZcjs.IDENTITY_KINDS, armoredKey) {
506
+ function useRecords(address, index, kinds = _chunkYTO7Z5SIcjs.IDENTITY_KINDS, armoredKey) {
433
507
  const config = useIdentityKitConfig();
434
- const registry = _chunkHUJD6LYZcjs.getRegistry.call(void 0, config.network, config.registryAddress);
435
- const chain = _chunkHUJD6LYZcjs.chainFor.call(void 0, config.network);
508
+ const registry = _chunkYTO7Z5SIcjs.getRegistry.call(void 0, config.network, config.registryAddress);
509
+ const chain = _chunkYTO7Z5SIcjs.chainFor.call(void 0, config.network);
436
510
  const owner = address;
437
511
  const enabled = !!owner && index !== void 0 && index !== null;
438
- const contracts = enabled ? kinds.map((kind) => ({ address: registry.address, abi: _chunkHUJD6LYZcjs.REGISTRY_ABI, functionName: "record", args: [owner, BigInt(index), _chunkHUJD6LYZcjs.recordKind.call(void 0, kind)], chainId: chain.id })) : [];
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 })) : [];
439
513
  const { data: raw, isLoading: readLoading, refetch } = _wagmi.useReadContracts.call(void 0, { contracts, query: { enabled: contracts.length > 0 } });
440
- const texts = (_nullishCoalesce(raw, () => ( []))).map((r) => r.status === "success" ? _chunkHUJD6LYZcjs.decodeRecord.call(void 0, r.result) : "");
514
+ const texts = (_nullishCoalesce(raw, () => ( []))).map((r) => r.status === "success" ? _chunkYTO7Z5SIcjs.decodeRecord.call(void 0, r.result) : "");
441
515
  const { data: records, isLoading: parseLoading } = _reactquery.useQuery.call(void 0, {
442
516
  queryKey: ["records", config.network, registry.address, address, index, kinds.join(","), texts.join(" "), _nullishCoalesce(armoredKey, () => ( ""))],
443
517
  queryFn: async () => {
444
518
  const out = [];
445
- for (let i = 0; i < kinds.length; i++) if (texts[i]) out.push(await _chunkHUJD6LYZcjs.parseRecord.call(void 0, kinds[i], texts[i], { armoredKey: _nullishCoalesce(armoredKey, () => ( void 0)) }));
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)) }));
446
520
  return out;
447
521
  },
448
522
  enabled: enabled && raw !== void 0
@@ -511,5 +585,15 @@ function useRecords(address, index, kinds = _chunkHUJD6LYZcjs.IDENTITY_KINDS, ar
511
585
 
512
586
 
513
587
 
514
- exports.AUTHORIZATION_TYPES = _chunkHUJD6LYZcjs.AUTHORIZATION_TYPES; exports.EIP712_NAME = _chunkHUJD6LYZcjs.EIP712_NAME; exports.EIP712_VERSION = _chunkHUJD6LYZcjs.EIP712_VERSION; exports.ENS_HINT_KEY = _chunkHUJD6LYZcjs.ENS_HINT_KEY; exports.ENS_TEXT_RESOLVER_ABI = _chunkHUJD6LYZcjs.ENS_TEXT_RESOLVER_ABI; exports.IDENTITY_KINDS = _chunkHUJD6LYZcjs.IDENTITY_KINDS; exports.IdentityKitProvider = IdentityKitProvider; exports.KNOWN_KINDS = _chunkHUJD6LYZcjs.KNOWN_KINDS; exports.MAX_RECORD_BYTES = _chunkHUJD6LYZcjs.MAX_RECORD_BYTES; exports.NETWORKS = _chunkHUJD6LYZcjs.NETWORKS; exports.REGISTRY_ABI = _chunkHUJD6LYZcjs.REGISTRY_ABI; exports.REGISTRY_ADDRESS = _chunkHUJD6LYZcjs.REGISTRY_ADDRESS; exports.ThurinCard = ThurinCard; exports.addPointer = _chunkHUJD6LYZcjs.addPointer; exports.attestTypedData = _chunkHUJD6LYZcjs.attestTypedData; exports.authorizationDigest = _chunkHUJD6LYZcjs.authorizationDigest; exports.bytesToFingerprint = _chunkHUJD6LYZcjs.bytesToFingerprint; exports.chainFor = _chunkHUJD6LYZcjs.chainFor; exports.decodeRecord = _chunkHUJD6LYZcjs.decodeRecord; exports.displayUrl = _chunkHUJD6LYZcjs.displayUrl; exports.encodeRecord = _chunkHUJD6LYZcjs.encodeRecord; exports.ensHintFor = _chunkHUJD6LYZcjs.ensHintFor; exports.ensHintValue = _chunkHUJD6LYZcjs.ensHintValue; exports.ensHintWrite = _chunkHUJD6LYZcjs.ensHintWrite; exports.fetchEFPGraph = _chunkHUJD6LYZcjs.fetchEFPGraph; exports.fetchEnsHint = _chunkHUJD6LYZcjs.fetchEnsHint; exports.fetchRecords = _chunkHUJD6LYZcjs.fetchRecords; exports.fingerprintHash = _chunkHUJD6LYZcjs.fingerprintHash; exports.fingerprintToBytes = _chunkHUJD6LYZcjs.fingerprintToBytes; exports.getRegistry = _chunkHUJD6LYZcjs.getRegistry; exports.hasEmailUserID = _chunkHUJD6LYZcjs.hasEmailUserID; exports.identifyProof = _chunkHUJD6LYZcjs.identifyProof; exports.isNetworkName = _chunkHUJD6LYZcjs.isNetworkName; exports.keyIdOf = _chunkHUJD6LYZcjs.keyIdOf; exports.keyIdToBytes = _chunkHUJD6LYZcjs.keyIdToBytes; exports.kindName = _chunkHUJD6LYZcjs.kindName; exports.normalizeFingerprint = _chunkHUJD6LYZcjs.normalizeFingerprint; exports.parsePgpKey = _chunkHUJD6LYZcjs.parsePgpKey; exports.parsePointer = _chunkHUJD6LYZcjs.parsePointer; exports.parseRecord = _chunkHUJD6LYZcjs.parseRecord; exports.proofHref = _chunkHUJD6LYZcjs.proofHref; exports.proofSecondaryHref = _chunkHUJD6LYZcjs.proofSecondaryHref; exports.reattestTypedData = _chunkHUJD6LYZcjs.reattestTypedData; exports.recordKind = _chunkHUJD6LYZcjs.recordKind; exports.registryDomain = _chunkHUJD6LYZcjs.registryDomain; exports.renderPointer = _chunkHUJD6LYZcjs.renderPointer; exports.revokeTypedData = _chunkHUJD6LYZcjs.revokeTypedData; exports.setRecordTypedData = _chunkHUJD6LYZcjs.setRecordTypedData; exports.stripEmailUserIDs = _chunkHUJD6LYZcjs.stripEmailUserIDs; exports.updateKeyTypedData = _chunkHUJD6LYZcjs.updateKeyTypedData; exports.useAttestations = useAttestations; exports.useEFPGraph = useEFPGraph; exports.useEnsHint = useEnsHint; exports.usePGPProofs = usePGPProofs; exports.useRecords = useRecords; exports.useThurinIdentity = useThurinIdentity; exports.verifyAttestation = _chunkHUJD6LYZcjs.verifyAttestation; exports.verifyClearsigned = _chunkHUJD6LYZcjs.verifyClearsigned; exports.verifyProof = _chunkHUJD6LYZcjs.verifyProof;
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
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;
515
599
  //# 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/components/ThurinCard/ThurinCard.tsx","../src/hooks/useEnsHint.ts","../src/hooks/useRecords.ts"],"names":["useQuery","jsx","safeNormalize","normalize"],"mappings":"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","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, useEnsAvatar } from 'wagmi'\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 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 } = 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 { data: ensAvatar } = useEnsAvatar({\n name: displayName ? safeNormalize(displayName) : undefined,\n chainId: chain.id,\n query: { enabled: !!displayName },\n })\n\n // On-chain attestations\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\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 return {\n address,\n ensName: displayName,\n ensAvatar: ensAvatar ?? null,\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n pgpKeyInfo,\n proofs,\n efp,\n isLoading: claimsLoading || proofsLoading || efpLoading,\n error: null,\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 } = 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 } = 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 const isLoading = rowsLoading || 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 }\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 { 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 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 {identity.efp?.followers ?? 0}\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/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"]}
package/dist/index.css CHANGED
@@ -164,4 +164,22 @@
164
164
  color: var(--thurin-text-muted);
165
165
  font-size: 14px;
166
166
  }
167
+ .thurin-card-error {
168
+ margin: 12px 0;
169
+ font-size: 13px;
170
+ line-height: 1.5;
171
+ color: var(--thurin-text-muted);
172
+ }
173
+ .thurin-card-retry {
174
+ display: inline;
175
+ margin-left: 8px;
176
+ padding: 0;
177
+ background: none;
178
+ border: none;
179
+ font: inherit;
180
+ color: var(--thurin-primary);
181
+ text-decoration: underline;
182
+ text-underline-offset: 3px;
183
+ cursor: pointer;
184
+ }
167
185
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/themes/index.css","../src/components/ThurinCard/ThurinCard.css"],"sourcesContent":["[data-thurin-theme=\"thurin\"] {\n --thurin-bg: #1a1a12;\n --thurin-surface: #252518;\n --thurin-surface-deep: #151510;\n --thurin-border: #3a3a2a;\n --thurin-text: #faf9f5;\n --thurin-text-muted: #a8a598;\n --thurin-heading: #7c9a3e;\n --thurin-primary: #7c9a3e;\n --thurin-primary-dim: #5c7a2e;\n --thurin-secondary: #c9a227;\n --thurin-success: #7c9a3e;\n --thurin-error: #d44a4a;\n}\n\n[data-thurin-theme=\"dark\"] {\n --thurin-bg: #141010;\n --thurin-surface: #1e1918;\n --thurin-surface-deep: #110e0c;\n --thurin-border: #352a22;\n --thurin-text: #ede5d8;\n --thurin-text-muted: #a09080;\n --thurin-heading: #f0ece4;\n --thurin-primary: #c9a227;\n --thurin-primary-dim: #8a7020;\n --thurin-secondary: #d4a04a;\n --thurin-success: #7c9a3e;\n --thurin-error: #d44a4a;\n}\n\n[data-thurin-theme=\"light\"] {\n --thurin-bg: #faf9f5;\n --thurin-surface: #f0efe8;\n --thurin-surface-deep: #e8e7e0;\n --thurin-border: #d0cfc4;\n --thurin-text: #2a2a22;\n --thurin-text-muted: #6b6960;\n --thurin-heading: #5a7228;\n --thurin-primary: #5a7228;\n --thurin-primary-dim: #7c9a3e;\n --thurin-secondary: #a8861e;\n --thurin-success: #5a7228;\n --thurin-error: #b83a3a;\n}\n",".thurin-card {\n font-family: 'Crimson Pro', Georgia, serif;\n background: var(--thurin-surface);\n border: 1px solid var(--thurin-border);\n border-radius: 8px;\n padding: 20px;\n color: var(--thurin-text);\n max-width: 380px;\n width: 100%;\n}\n\n.thurin-card * {\n box-sizing: border-box;\n}\n\n.thurin-card-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 16px;\n text-decoration: none;\n color: inherit;\n cursor: pointer;\n}\n\n.thurin-card-header:hover .thurin-card-name {\n color: var(--thurin-primary);\n}\n\n.thurin-card-avatar {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n border: 2px solid var(--thurin-border);\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.thurin-card-avatar-placeholder {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n border: 2px solid var(--thurin-border);\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.thurin-card-name {\n font-family: 'Cinzel', serif;\n font-size: 18px;\n font-weight: 700;\n color: var(--thurin-heading);\n line-height: 1.2;\n}\n\n.thurin-card-address {\n font-family: 'Share Tech Mono', monospace;\n font-size: 11px;\n color: var(--thurin-text-muted);\n margin-top: 2px;\n word-break: break-all;\n}\n\n.thurin-card-stats {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.thurin-card-stat {\n text-align: center;\n padding: 8px 4px;\n background: var(--thurin-surface-deep);\n border-radius: 4px;\n}\n\n.thurin-card-stat-value {\n font-family: 'Cinzel', serif;\n font-size: 20px;\n font-weight: 700;\n color: var(--thurin-heading);\n display: block;\n}\n\n.thurin-card-stat-label {\n font-family: 'Share Tech Mono', monospace;\n font-size: 10px;\n color: var(--thurin-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.thurin-card-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-bottom: 16px;\n}\n\n.thurin-card-badge {\n font-family: 'Share Tech Mono', monospace;\n font-size: 11px;\n padding: 3px 8px;\n border-radius: 3px;\n border: 1px solid;\n}\n\n.thurin-card-badge--verified {\n color: var(--thurin-success);\n border-color: var(--thurin-success);\n}\n\n.thurin-card-badge--unverified {\n color: var(--thurin-text-muted);\n border-color: var(--thurin-border);\n}\n\n.thurin-card-link {\n display: block;\n text-align: right;\n font-size: 12px;\n color: var(--thurin-text-muted);\n text-decoration: none;\n}\n\n.thurin-card-link:hover {\n color: var(--thurin-primary);\n}\n\n.thurin-card-loading {\n text-align: center;\n padding: 24px;\n color: var(--thurin-text-muted);\n font-size: 14px;\n}\n"],"mappings":";AAAA,CAAC;AACC,eAAa;AACb,oBAAkB;AAClB,yBAAuB;AACvB,mBAAiB;AACjB,iBAAe;AACf,uBAAqB;AACrB,oBAAkB;AAClB,oBAAkB;AAClB,wBAAsB;AACtB,sBAAoB;AACpB,oBAAkB;AAClB,kBAAgB;AAClB;AAEA,CAAC;AACC,eAAa;AACb,oBAAkB;AAClB,yBAAuB;AACvB,mBAAiB;AACjB,iBAAe;AACf,uBAAqB;AACrB,oBAAkB;AAClB,oBAAkB;AAClB,wBAAsB;AACtB,sBAAoB;AACpB,oBAAkB;AAClB,kBAAgB;AAClB;AAEA,CAAC;AACC,eAAa;AACb,oBAAkB;AAClB,yBAAuB;AACvB,mBAAiB;AACjB,iBAAe;AACf,uBAAqB;AACrB,oBAAkB;AAClB,oBAAkB;AAClB,wBAAsB;AACtB,sBAAoB;AACpB,oBAAkB;AAClB,kBAAgB;AAClB;;;AC3CA,CAAC;AACC;AAAA,IAAa,aAAa;AAAA,IAAE,OAAO;AAAA,IAAE;AACrC,cAAY,IAAI;AAChB,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe;AACf,WAAS;AACT,SAAO,IAAI;AACX,aAAW;AACX,SAAO;AACT;AAEA,CAXC,YAWY;AACX,cAAY;AACd;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,OAAK;AACL,iBAAe;AACf,mBAAiB;AACjB,SAAO;AACP,UAAQ;AACV;AAEA,CAVC,kBAUkB,OAAO,CAAC;AACzB,SAAO,IAAI;AACb;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,iBAAe;AACf,UAAQ,IAAI,MAAM,IAAI;AACtB,cAAY;AACZ,eAAa;AACf;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,iBAAe;AACf,UAAQ,IAAI,MAAM,IAAI;AACtB,eAAa;AACb,YAAU;AACZ;AAEA,CAtB2B;AAuBzB,eAAa,QAAQ,EAAE;AACvB,aAAW;AACX,eAAa;AACb,SAAO,IAAI;AACX,eAAa;AACf;AAEA,CAAC;AACC,eAAa,iBAAiB,EAAE;AAChC,aAAW;AACX,SAAO,IAAI;AACX,cAAY;AACZ,cAAY;AACd;AAEA,CAAC;AACC,WAAS;AACT,yBAAuB,OAAO,CAAC,EAAE;AACjC,OAAK;AACL,iBAAe;AACjB;AAEA,CAAC;AACC,cAAY;AACZ,WAAS,IAAI;AACb,cAAY,IAAI;AAChB,iBAAe;AACjB;AAEA,CAAC;AACC,eAAa,QAAQ,EAAE;AACvB,aAAW;AACX,eAAa;AACb,SAAO,IAAI;AACX,WAAS;AACX;AAEA,CAAC;AACC,eAAa,iBAAiB,EAAE;AAChC,aAAW;AACX,SAAO,IAAI;AACX,kBAAgB;AAChB,kBAAgB;AAClB;AAEA,CAAC;AACC,WAAS;AACT,aAAW;AACX,OAAK;AACL,iBAAe;AACjB;AAEA,CAAC;AACC,eAAa,iBAAiB,EAAE;AAChC,aAAW;AACX,WAAS,IAAI;AACb,iBAAe;AACf,UAAQ,IAAI;AACd;AAEA,CAAC;AACC,SAAO,IAAI;AACX,gBAAc,IAAI;AACpB;AAEA,CAAC;AACC,SAAO,IAAI;AACX,gBAAc,IAAI;AACpB;AAEA,CAAC;AACC,WAAS;AACT,cAAY;AACZ,aAAW;AACX,SAAO,IAAI;AACX,mBAAiB;AACnB;AAEA,CARC,gBAQgB;AACf,SAAO,IAAI;AACb;AAEA,CAAC;AACC,cAAY;AACZ,WAAS;AACT,SAAO,IAAI;AACX,aAAW;AACb;","names":[]}
1
+ {"version":3,"sources":["../src/themes/index.css","../src/components/ThurinCard/ThurinCard.css"],"sourcesContent":["[data-thurin-theme=\"thurin\"] {\n --thurin-bg: #1a1a12;\n --thurin-surface: #252518;\n --thurin-surface-deep: #151510;\n --thurin-border: #3a3a2a;\n --thurin-text: #faf9f5;\n --thurin-text-muted: #a8a598;\n --thurin-heading: #7c9a3e;\n --thurin-primary: #7c9a3e;\n --thurin-primary-dim: #5c7a2e;\n --thurin-secondary: #c9a227;\n --thurin-success: #7c9a3e;\n --thurin-error: #d44a4a;\n}\n\n[data-thurin-theme=\"dark\"] {\n --thurin-bg: #141010;\n --thurin-surface: #1e1918;\n --thurin-surface-deep: #110e0c;\n --thurin-border: #352a22;\n --thurin-text: #ede5d8;\n --thurin-text-muted: #a09080;\n --thurin-heading: #f0ece4;\n --thurin-primary: #c9a227;\n --thurin-primary-dim: #8a7020;\n --thurin-secondary: #d4a04a;\n --thurin-success: #7c9a3e;\n --thurin-error: #d44a4a;\n}\n\n[data-thurin-theme=\"light\"] {\n --thurin-bg: #faf9f5;\n --thurin-surface: #f0efe8;\n --thurin-surface-deep: #e8e7e0;\n --thurin-border: #d0cfc4;\n --thurin-text: #2a2a22;\n --thurin-text-muted: #6b6960;\n --thurin-heading: #5a7228;\n --thurin-primary: #5a7228;\n --thurin-primary-dim: #7c9a3e;\n --thurin-secondary: #a8861e;\n --thurin-success: #5a7228;\n --thurin-error: #b83a3a;\n}\n",".thurin-card {\n font-family: 'Crimson Pro', Georgia, serif;\n background: var(--thurin-surface);\n border: 1px solid var(--thurin-border);\n border-radius: 8px;\n padding: 20px;\n color: var(--thurin-text);\n max-width: 380px;\n width: 100%;\n}\n\n.thurin-card * {\n box-sizing: border-box;\n}\n\n.thurin-card-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 16px;\n text-decoration: none;\n color: inherit;\n cursor: pointer;\n}\n\n.thurin-card-header:hover .thurin-card-name {\n color: var(--thurin-primary);\n}\n\n.thurin-card-avatar {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n border: 2px solid var(--thurin-border);\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.thurin-card-avatar-placeholder {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n border: 2px solid var(--thurin-border);\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.thurin-card-name {\n font-family: 'Cinzel', serif;\n font-size: 18px;\n font-weight: 700;\n color: var(--thurin-heading);\n line-height: 1.2;\n}\n\n.thurin-card-address {\n font-family: 'Share Tech Mono', monospace;\n font-size: 11px;\n color: var(--thurin-text-muted);\n margin-top: 2px;\n word-break: break-all;\n}\n\n.thurin-card-stats {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.thurin-card-stat {\n text-align: center;\n padding: 8px 4px;\n background: var(--thurin-surface-deep);\n border-radius: 4px;\n}\n\n.thurin-card-stat-value {\n font-family: 'Cinzel', serif;\n font-size: 20px;\n font-weight: 700;\n color: var(--thurin-heading);\n display: block;\n}\n\n.thurin-card-stat-label {\n font-family: 'Share Tech Mono', monospace;\n font-size: 10px;\n color: var(--thurin-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.thurin-card-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-bottom: 16px;\n}\n\n.thurin-card-badge {\n font-family: 'Share Tech Mono', monospace;\n font-size: 11px;\n padding: 3px 8px;\n border-radius: 3px;\n border: 1px solid;\n}\n\n.thurin-card-badge--verified {\n color: var(--thurin-success);\n border-color: var(--thurin-success);\n}\n\n.thurin-card-badge--unverified {\n color: var(--thurin-text-muted);\n border-color: var(--thurin-border);\n}\n\n.thurin-card-link {\n display: block;\n text-align: right;\n font-size: 12px;\n color: var(--thurin-text-muted);\n text-decoration: none;\n}\n\n.thurin-card-link:hover {\n color: var(--thurin-primary);\n}\n\n.thurin-card-loading {\n text-align: center;\n padding: 24px;\n color: var(--thurin-text-muted);\n font-size: 14px;\n}\n\n.thurin-card-error {\n margin: 12px 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--thurin-text-muted);\n}\n\n.thurin-card-retry {\n display: inline;\n margin-left: 8px;\n padding: 0;\n background: none;\n border: none;\n font: inherit;\n color: var(--thurin-primary);\n text-decoration: underline;\n text-underline-offset: 3px;\n cursor: pointer;\n}\n"],"mappings":"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","names":[]}