@thurinlabs/identity-kit 1.4.0 → 2.0.0

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.js CHANGED
@@ -2,619 +2,185 @@ import {
2
2
  ARWEAVE_GATEWAY,
3
3
  AUTHORIZATION_TYPES,
4
4
  CLAIM_CHECK_LABEL,
5
+ CLAIM_LIMIT,
6
+ CONTRACT_ERROR_TEXT,
5
7
  EIP712_NAME,
6
8
  EIP712_VERSION,
7
9
  ENS_HINT_KEY,
8
10
  ENS_TEXT_RESOLVER_ABI,
9
11
  FARCASTER_HUB,
10
- IDENTITY_ERROR_TEXT,
11
- IDENTITY_KINDS,
12
12
  IPFS_GATEWAY,
13
13
  IPFS_GATEWAYS,
14
14
  KNOWN_KINDS,
15
+ MAX_KIND_BYTES,
15
16
  MAX_RECORD_BYTES,
16
17
  NETWORKS,
17
18
  NFT_AVATAR_ABI,
19
+ OWNER_REVOKE_REASONS,
18
20
  REGISTRY_ABI,
19
21
  REGISTRY_ADDRESS,
20
- addPointer,
22
+ REVOKE_REASONS,
23
+ addRelease,
21
24
  attestTypedData,
22
25
  authorizationDigest,
23
26
  avatarFallbacks,
24
27
  avatarUrl,
25
28
  bytesToFingerprint,
26
29
  chainFor,
30
+ checkKindName,
31
+ checkRecordValue,
27
32
  claimCheckText,
28
33
  claimFateText,
29
34
  claimFates,
30
- decodeRecord,
35
+ claimSignature,
36
+ contractErrorName,
37
+ contractErrorText,
31
38
  displayUrl,
32
- encodeRecord,
39
+ encryptRefusalText,
40
+ encryptTo,
41
+ encryptionKeyFor,
33
42
  ensHintFor,
34
43
  ensHintValue,
35
44
  ensHintWrite,
36
45
  expiresSoon,
37
46
  expiresSoonText,
38
- fetchEFPGraph,
39
47
  fetchEnsHint,
40
48
  fetchRecords,
49
+ findOwners,
41
50
  fingerprintHash,
42
51
  fingerprintToBytes,
43
52
  formatClaimDate,
44
53
  getRegistry,
45
54
  hasEmailUserID,
46
55
  identifyProof,
47
- identityErrorKind,
48
56
  isNetworkName,
57
+ keyChangedText,
49
58
  keyIdOf,
50
59
  keyIdToBytes,
60
+ keyProblemText,
61
+ keyStanding,
51
62
  kindName,
52
- needsRpcProbe,
63
+ leanKey,
64
+ markCompromisedTypedData,
53
65
  nftAvatarImage,
54
66
  normalizeFingerprint,
67
+ pageRecords,
55
68
  parseNftAvatar,
56
69
  parsePgpKey,
57
- parsePointer,
58
70
  parseRecord,
71
+ parseReleases,
72
+ payloadText,
73
+ pickRecords,
59
74
  proofHref,
60
75
  proofSecondaryHref,
76
+ readClaims,
61
77
  reattestTypedData,
62
78
  recordKind,
63
79
  registryDomain,
64
- renderPointer,
80
+ renderReleases,
65
81
  revokeTypedData,
82
+ sameFingerprint,
66
83
  setRecordTypedData,
84
+ signatureEmail,
85
+ sshKeys,
86
+ statementText,
67
87
  stripEmailUserIDs,
68
88
  updateKeyTypedData,
69
89
  verifyAttestation,
70
90
  verifyClearsigned,
71
- verifyProof
72
- } from "./chunk-ZAQ2EPF5.js";
73
-
74
- // src/provider.tsx
75
- import { useMemo } from "react";
76
- import { WagmiProvider, createConfig, http, useConfig } from "wagmi";
77
- import { mainnet, sepolia, foundry } from "wagmi/chains";
78
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
79
-
80
- // src/context.ts
81
- import { createContext, useContext } from "react";
82
- var defaultConfig = {
83
- baseUrl: "https://thurin.id",
84
- network: "mainnet"
85
- };
86
- var IdentityKitContext = createContext(defaultConfig);
87
- function useIdentityKitConfig() {
88
- return useContext(IdentityKitContext);
89
- }
90
-
91
- // src/provider.tsx
92
- import { Fragment, jsx } from "react/jsx-runtime";
93
- var defaultQueryClient = new QueryClient({
94
- defaultOptions: {
95
- queries: {
96
- staleTime: 6e4,
97
- retry: 1
98
- }
99
- }
100
- });
101
- function createDefaultWagmiConfig(rpcUrl, network) {
102
- const url = rpcUrl || getRegistry(network).defaultRpcUrl;
103
- if (network === "sepolia") return createConfig({ chains: [sepolia], transports: { [sepolia.id]: http(url) } });
104
- if (network === "local") return createConfig({ chains: [foundry], transports: { [foundry.id]: http(url) } });
105
- return createConfig({ chains: [mainnet], transports: { [mainnet.id]: http(url) } });
106
- }
107
- function WagmiDetector({ children, rpcUrl, network }) {
108
- let hasWagmi = false;
109
- try {
110
- useConfig();
111
- hasWagmi = true;
112
- } catch {
113
- }
114
- const wagmiConfig = useMemo(() => createDefaultWagmiConfig(rpcUrl, network), [rpcUrl, network]);
115
- if (hasWagmi) {
116
- return /* @__PURE__ */ jsx(Fragment, { children });
117
- }
118
- return /* @__PURE__ */ jsx(WagmiProvider, { config: wagmiConfig, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: defaultQueryClient, children }) });
119
- }
120
- function IdentityKitProvider({
121
- children,
122
- rpcUrl,
123
- neynarApiKey,
124
- farcasterHub,
125
- baseUrl = "https://thurin.id",
126
- network = "mainnet",
127
- registryAddress
128
- }) {
129
- const config = useMemo(
130
- () => ({ rpcUrl, neynarApiKey, farcasterHub, baseUrl, network, registryAddress }),
131
- [rpcUrl, neynarApiKey, farcasterHub, baseUrl, network, registryAddress]
132
- );
133
- return /* @__PURE__ */ jsx(IdentityKitContext.Provider, { value: config, children: /* @__PURE__ */ jsx(WagmiDetector, { rpcUrl, network, children }) });
134
- }
135
-
136
- // src/components/ThurinCard/ThurinCard.tsx
137
- import { useEffect, useState } from "react";
138
-
139
- // src/hooks/useThurinIdentity.ts
140
- import { useBlockNumber, useEnsAddress, useEnsName } from "wagmi";
141
- import { normalize } from "viem/ens";
142
-
143
- // src/hooks/useAttestations.ts
144
- import { useReadContract, useReadContracts } from "wagmi";
145
- import { useQuery } from "@tanstack/react-query";
146
- import { hexToString } from "viem";
147
- function useAttestations(address) {
148
- const config = useIdentityKitConfig();
149
- const registry = getRegistry(config.network, config.registryAddress);
150
- const chain = chainFor(config.network);
151
- const owner = address;
152
- const { data: rows, isLoading: rowsLoading, isFetched: rowsFetched, error: rowsError, refetch: refetchRows } = useReadContract({
153
- address: registry.address,
154
- abi: REGISTRY_ABI,
155
- functionName: "attestationsOf",
156
- args: owner ? [owner] : void 0,
157
- chainId: chain.id,
158
- query: { enabled: !!owner }
159
- });
160
- const count = rows?.length ?? 0;
161
- const contracts = owner && rows ? rows.map((_, i) => ({
162
- address: registry.address,
163
- abi: REGISTRY_ABI,
164
- functionName: "getPayload",
165
- args: [owner, BigInt(i)],
166
- chainId: chain.id
167
- })) : [];
168
- const { data: payloads, isLoading: payloadsLoading, error: payloadsError, refetch: refetchPayloads } = useReadContracts({
169
- contracts,
170
- query: { enabled: contracts.length > 0 }
171
- });
172
- const payloadsReady = count === 0 || payloads !== void 0 && payloads.length === count;
173
- const { data: claims, isLoading: verifyLoading } = useQuery({
174
- queryKey: ["attestations", config.network, registry.address, address, count, payloadsReady],
175
- queryFn: async () => {
176
- if (!rows || !address) return [];
177
- const results = [];
178
- for (let i = 0; i < rows.length; i++) {
179
- const row = rows[i];
180
- const payload = payloads?.[i];
181
- let pgpSignature = null;
182
- let pgpPublicKey = null;
183
- if (payload && payload.status === "success") {
184
- const [sigHex, keyHex] = payload.result;
185
- pgpSignature = hexToString(sigHex);
186
- pgpPublicKey = hexToString(keyHex);
187
- }
188
- const fingerprint = bytesToFingerprint(row.fingerprint);
189
- const verification = pgpPublicKey && pgpSignature ? await verifyAttestation({ pgpPublicKey, pgpSignature, fingerprint, ethAddress: address }) : null;
190
- const revokedAt = Number(row.revokedAt);
191
- results.push({
192
- index: i,
193
- fingerprint,
194
- createdAt: Number(row.createdAt),
195
- revoked: revokedAt !== 0,
196
- revokedAt: revokedAt === 0 ? null : revokedAt,
197
- messageVersion: Number(row.messageVersion),
198
- pgpSignature,
199
- pgpPublicKey,
200
- verification
201
- });
202
- }
203
- return results;
204
- },
205
- enabled: !!rows && payloadsReady,
206
- staleTime: 3e5
207
- });
208
- const isLoading = rowsLoading || !!owner && !rowsFetched || payloadsLoading || verifyLoading || !!owner && rows !== void 0 && !payloadsReady;
209
- const activeClaims = (claims || []).filter((c) => !c.revoked);
210
- const verifiedClaims = activeClaims.filter((c) => c.verification?.verified);
211
- const currentFingerprint = verifiedClaims.length > 0 ? verifiedClaims[verifiedClaims.length - 1].fingerprint : null;
212
- return {
213
- claims: claims || [],
214
- totalClaims: count,
215
- activeClaims: activeClaims.length,
216
- currentFingerprint,
217
- isLoading,
218
- /** A registry read failed (the RPC may be down; useThurinIdentity finds out which). */
219
- error: rowsError ?? payloadsError ?? null,
220
- refetch: () => {
221
- if (owner) {
222
- refetchRows();
223
- if (contracts.length > 0) refetchPayloads();
224
- }
225
- }
226
- };
227
- }
228
-
229
- // src/hooks/useEFPGraph.ts
230
- import { useQuery as useQuery2 } from "@tanstack/react-query";
231
- function useEFPGraph(address) {
232
- const { data, isLoading } = useQuery2({
233
- queryKey: ["efp-graph", address],
234
- queryFn: () => fetchEFPGraph(address),
235
- enabled: !!address,
236
- staleTime: 3e5
237
- });
238
- return {
239
- efp: data ?? null,
240
- isLoading
241
- };
242
- }
243
-
244
- // src/hooks/usePGPProofs.ts
245
- import { useQuery as useQuery3 } from "@tanstack/react-query";
246
- function usePGPProofs(fingerprint, armoredKey) {
247
- const config = useIdentityKitConfig();
248
- const { data } = useQuery3({
249
- // The key is large; key the query on its length + fingerprint, which
250
- // changes whenever a different attestation's key is supplied.
251
- queryKey: ["pgp-proofs", fingerprint, armoredKey?.length ?? 0],
252
- queryFn: async () => {
253
- if (!fingerprint || !armoredKey) return { keyInfo: null, proofs: [] };
254
- const keyInfo = await parsePgpKey(armoredKey);
255
- if (!keyInfo) return { keyInfo: null, proofs: [] };
256
- const identified = keyInfo.notations.map((n) => identifyProof(n)).filter((p) => p !== null && p.provider !== "unknown");
257
- const proofs = await Promise.all(
258
- identified.map(async (proof) => {
259
- const result = await verifyProof(proof, fingerprint, { neynarApiKey: config.neynarApiKey, farcasterHub: config.farcasterHub });
260
- return {
261
- provider: proof.provider,
262
- label: proof.label,
263
- url: proof.url,
264
- displayUrl: displayUrl(proof),
265
- href: proofHref(proof),
266
- secondaryHref: proofSecondaryHref(proof),
267
- status: result.verified ? "verified" : "unverified",
268
- reason: result.reason
269
- };
270
- })
271
- );
272
- const byAccount = /* @__PURE__ */ new Map();
273
- for (const p of proofs) {
274
- const key = `${p.provider}:${p.displayUrl}`;
275
- const prev = byAccount.get(key);
276
- if (!prev || p.status === "verified" && prev.status !== "verified") {
277
- byAccount.set(key, p);
278
- }
279
- }
280
- return { keyInfo, proofs: [...byAccount.values()] };
281
- },
282
- enabled: !!fingerprint && !!armoredKey,
283
- staleTime: 3e5
284
- });
285
- return {
286
- keyInfo: data?.keyInfo ?? null,
287
- proofs: data?.proofs ?? [],
288
- // Report loading whenever a fingerprint is set but its proofs haven't
289
- // resolved yet. Using react-query's own isLoading leaves a gap while the
290
- // query is enabling (fingerprint just became known), during which the card
291
- // would briefly paint without proof badges and then pop them in.
292
- isLoading: !!fingerprint && !!armoredKey && data === void 0
293
- };
294
- }
295
-
296
- // src/hooks/useSafeAvatar.ts
297
- import { useEnsText, useReadContract as useReadContract2 } from "wagmi";
298
- import { useQuery as useQuery4 } from "@tanstack/react-query";
299
- function useSafeAvatar(name, chainId) {
300
- const { data: raw } = useEnsText({ name, key: "avatar", chainId, query: { enabled: !!name } });
301
- const direct = avatarUrl(raw);
302
- const nft = direct ? null : parseNftAvatar(raw);
303
- const { data: tokenUri } = useReadContract2({
304
- address: nft?.contract,
305
- abi: NFT_AVATAR_ABI,
306
- functionName: nft?.standard === "erc1155" ? "uri" : "tokenURI",
307
- args: nft ? [nft.tokenId] : void 0,
308
- chainId,
309
- query: { enabled: !!nft && nft.chainId === chainId }
310
- });
311
- const { data: image } = useQuery4({
312
- queryKey: ["thurin-nft-avatar", tokenUri, nft?.tokenId.toString()],
313
- queryFn: () => nftAvatarImage(tokenUri, nft.tokenId).catch(() => null),
314
- enabled: typeof tokenUri === "string" && !!nft
315
- });
316
- return direct ?? image ?? null;
317
- }
318
-
319
- // src/hooks/useThurinIdentity.ts
320
- function isAddress(value) {
321
- return /^0x[0-9a-fA-F]{40}$/.test(value);
322
- }
323
- function safeNormalize(name) {
324
- try {
325
- return normalize(name);
326
- } catch {
327
- return void 0;
328
- }
329
- }
330
- function useThurinIdentity(ensOrAddress) {
331
- const chain = chainFor(useIdentityKitConfig().network);
332
- const isAddr = ensOrAddress ? isAddress(ensOrAddress) : false;
333
- const ensInput = ensOrAddress && !isAddr ? safeNormalize(ensOrAddress) : void 0;
334
- const { data: resolvedAddress, error: ensError, isFetched: ensFetched, refetch: refetchEns } = useEnsAddress({
335
- name: ensInput,
336
- chainId: chain.id,
337
- query: { enabled: !!ensInput }
338
- });
339
- const address = isAddr ? ensOrAddress : resolvedAddress ?? null;
340
- const { data: ensName } = useEnsName({
341
- address,
342
- chainId: chain.id,
343
- query: { enabled: !!address }
344
- });
345
- const displayName = ensInput || ensName || null;
346
- const ensAvatar = useSafeAvatar(displayName ? safeNormalize(displayName) : void 0, chain.id);
347
- const {
348
- claims,
349
- totalClaims,
350
- activeClaims,
351
- currentFingerprint,
352
- isLoading: claimsLoading,
353
- error: claimsError,
354
- refetch: refetchClaims
355
- } = useAttestations(address);
356
- const currentClaim = [...claims].reverse().find(
357
- (c) => !c.revoked && c.verification?.verified && c.fingerprint === currentFingerprint
358
- );
359
- const {
360
- keyInfo: pgpKeyInfo,
361
- proofs,
362
- isLoading: proofsLoading
363
- } = usePGPProofs(currentFingerprint, currentClaim?.pgpPublicKey ?? null);
364
- const { efp, isLoading: efpLoading } = useEFPGraph(address);
365
- const lookup = { ensEmpty: !!ensInput && ensFetched && !resolvedAddress, ensFailed: !!ensError, claimsFailed: !!claimsError };
366
- const probeNeeded = needsRpcProbe(lookup);
367
- const probe = useBlockNumber({
368
- chainId: chain.id,
369
- scopeKey: `thurin-rpc-probe:${ensOrAddress ?? ""}`,
370
- query: { enabled: probeNeeded, retry: 0, staleTime: 0, gcTime: 0 }
371
- });
372
- const rpcAnswered = !probeNeeded || probe.isFetching ? void 0 : probe.isSuccess ? true : probe.isError ? false : void 0;
373
- const errorKind = identityErrorKind({ ...lookup, rpcAnswered });
374
- const probing = probeNeeded && rpcAnswered === void 0;
375
- const retry = () => {
376
- if (ensInput) refetchEns();
377
- refetchClaims();
378
- if (probeNeeded) probe.refetch();
379
- };
380
- return {
381
- address,
382
- ensName: displayName,
383
- ensAvatar,
384
- claims,
385
- totalClaims,
386
- activeClaims,
387
- currentFingerprint,
388
- pgpKeyInfo,
389
- proofs,
390
- efp,
391
- // "Not finished" counts as loading, including queries paused in a background tab: the card
392
- // must not render defaults (zeros) for an identity it hasn't looked up yet.
393
- isLoading: !!ensInput && !ensFetched || claimsLoading || proofsLoading || efpLoading || probing,
394
- error: errorKind ? new Error(IDENTITY_ERROR_TEXT[errorKind]) : null,
395
- errorKind,
396
- retry
397
- };
398
- }
399
-
400
- // src/components/ThurinCard/ThurinCard.tsx
401
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
402
- function ThurinLogo() {
403
- return /* @__PURE__ */ jsxs("svg", { className: "thurin-card-avatar-placeholder", viewBox: "0 0 100 100", xmlns: "http://www.w3.org/2000/svg", children: [
404
- /* @__PURE__ */ jsx2("circle", { cx: "50", cy: "50", r: "50", fill: "var(--thurin-surface-deep)" }),
405
- /* @__PURE__ */ jsx2("path", { d: "M25 80 Q25 25 50 25 Q75 25 75 50", fill: "none", stroke: "#7c9a3e", strokeWidth: "4", strokeLinecap: "round" }),
406
- /* @__PURE__ */ jsx2("path", { d: "M33 75 Q33 35 50 35 Q67 35 67 52", fill: "none", stroke: "#7c9a3e", strokeWidth: "4", strokeLinecap: "round" }),
407
- /* @__PURE__ */ jsx2("path", { d: "M41 70 Q41 45 50 45 Q59 45 59 55", fill: "none", stroke: "#c9a227", strokeWidth: "4", strokeLinecap: "round" }),
408
- /* @__PURE__ */ jsx2("path", { d: "M50 65 L50 53", fill: "none", stroke: "#c9a227", strokeWidth: "4", strokeLinecap: "round" })
409
- ] });
410
- }
411
- function Avatar({ src, alt }) {
412
- const [tries, setTries] = useState([]);
413
- useEffect(() => {
414
- setTries(src ? [src, ...avatarFallbacks(src)] : []);
415
- }, [src]);
416
- if (!tries.length) return /* @__PURE__ */ jsx2(ThurinLogo, {});
417
- return /* @__PURE__ */ jsx2("img", { className: "thurin-card-avatar", src: tries[0], alt, onError: () => setTries((t) => t.slice(1)) });
418
- }
419
- function ThurinCard({ ens, address, theme = "thurin" }) {
420
- const input = ens || address;
421
- const identity = useThurinIdentity(input);
422
- const config = useIdentityKitConfig();
423
- const profileUrl = identity.address ? `${config.baseUrl}/eth/${identity.address}` : ens ? `${config.baseUrl}/ens/${ens}` : null;
424
- if (identity.isLoading) {
425
- return /* @__PURE__ */ jsx2("div", { className: "thurin-card", "data-thurin-theme": theme, children: /* @__PURE__ */ jsx2("div", { className: "thurin-card-loading", children: "Loading identity..." }) });
426
- }
427
- const displayAddress = identity.address || null;
428
- if (identity.errorKind) {
429
- return /* @__PURE__ */ jsxs("div", { className: "thurin-card", "data-thurin-theme": theme, children: [
430
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-header", children: [
431
- /* @__PURE__ */ jsx2(ThurinLogo, {}),
432
- /* @__PURE__ */ jsx2("div", { children: /* @__PURE__ */ jsx2("div", { className: "thurin-card-name", children: identity.ensName || ens || address }) })
433
- ] }),
434
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-error", role: "status", children: [
435
- identity.error?.message,
436
- identity.errorKind !== "not-found" && /* @__PURE__ */ jsx2("button", { type: "button", className: "thurin-card-retry", onClick: identity.retry, children: "Try again" })
437
- ] }),
438
- profileUrl && identity.errorKind !== "not-found" && /* @__PURE__ */ jsx2("a", { className: "thurin-card-link", href: profileUrl, target: "_blank", rel: "noopener noreferrer", children: "View on Thurin" })
439
- ] });
440
- }
441
- const verifiedProofs = identity.proofs.filter((p) => p.status === "verified").length;
442
- const hasVerifiedPgp = identity.claims.some((c) => c.verification?.verified && !c.revoked);
443
- return /* @__PURE__ */ jsxs("div", { className: "thurin-card", "data-thurin-theme": theme, children: [
444
- /* @__PURE__ */ jsxs("a", { className: "thurin-card-header", href: profileUrl || void 0, target: "_blank", rel: "noopener noreferrer", children: [
445
- /* @__PURE__ */ jsx2(Avatar, { src: identity.ensAvatar, alt: identity.ensName || "" }),
446
- /* @__PURE__ */ jsxs("div", { children: [
447
- identity.ensName && /* @__PURE__ */ jsx2("div", { className: "thurin-card-name", children: identity.ensName }),
448
- displayAddress && /* @__PURE__ */ jsx2("div", { className: "thurin-card-address", children: displayAddress })
449
- ] })
450
- ] }),
451
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-stats", children: [
452
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-stat", children: [
453
- /* @__PURE__ */ jsx2("span", { className: "thurin-card-stat-value", children: identity.activeClaims }),
454
- /* @__PURE__ */ jsx2("span", { className: "thurin-card-stat-label", children: "Attestations" })
455
- ] }),
456
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-stat", children: [
457
- /* @__PURE__ */ jsx2("span", { className: "thurin-card-stat-value", children: verifiedProofs }),
458
- /* @__PURE__ */ jsx2("span", { className: "thurin-card-stat-label", children: "Proofs" })
459
- ] }),
460
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-stat", children: [
461
- /* @__PURE__ */ jsx2("span", { className: "thurin-card-stat-value", children: identity.efp ? identity.efp.followers : "\u2013" }),
462
- /* @__PURE__ */ jsx2("span", { className: "thurin-card-stat-label", children: "Followers" })
463
- ] })
464
- ] }),
465
- /* @__PURE__ */ jsxs("div", { className: "thurin-card-badges", children: [
466
- hasVerifiedPgp && /* @__PURE__ */ jsx2("span", { className: "thurin-card-badge thurin-card-badge--verified", children: "PGP Verified" }),
467
- identity.efp?.hasEfp && /* @__PURE__ */ jsx2("span", { className: "thurin-card-badge thurin-card-badge--verified", children: "EFP" }),
468
- identity.proofs.map((p, i) => /* @__PURE__ */ jsx2(
469
- "span",
470
- {
471
- className: `thurin-card-badge thurin-card-badge--${p.status === "verified" ? "verified" : "unverified"}`,
472
- children: p.label
473
- },
474
- i
475
- ))
476
- ] }),
477
- profileUrl && /* @__PURE__ */ jsx2(
478
- "a",
479
- {
480
- className: "thurin-card-link",
481
- href: profileUrl,
482
- target: "_blank",
483
- rel: "noopener noreferrer",
484
- children: "View on Thurin"
485
- }
486
- )
487
- ] });
488
- }
489
-
490
- // src/hooks/useEnsHint.ts
491
- import { useEnsText as useEnsText2 } from "wagmi";
492
- import { normalize as normalize2 } from "viem/ens";
493
- function safeNormalize2(name) {
494
- try {
495
- return normalize2(name);
496
- } catch {
497
- return void 0;
498
- }
499
- }
500
- function useEnsHint(name, verifiedFingerprint) {
501
- const chain = chainFor(useIdentityKitConfig().network);
502
- const ensName = name ? safeNormalize2(name) : void 0;
503
- const { data, isLoading, refetch } = useEnsText2({
504
- name: ensName,
505
- key: ENS_HINT_KEY,
506
- chainId: chain.id,
507
- query: { enabled: !!ensName }
508
- });
509
- return { ...ensHintFor(data ?? null, verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => {
510
- void refetch();
511
- } };
512
- }
513
-
514
- // src/hooks/useRecords.ts
515
- import { useReadContracts as useReadContracts2 } from "wagmi";
516
- import { useQuery as useQuery5 } from "@tanstack/react-query";
517
- function useRecords(address, index, kinds = IDENTITY_KINDS, armoredKey) {
518
- const config = useIdentityKitConfig();
519
- const registry = getRegistry(config.network, config.registryAddress);
520
- const chain = chainFor(config.network);
521
- const owner = address;
522
- const enabled = !!owner && index !== void 0 && index !== null;
523
- const contracts = enabled ? kinds.map((kind) => ({ address: registry.address, abi: REGISTRY_ABI, functionName: "record", args: [owner, BigInt(index), recordKind(kind)], chainId: chain.id })) : [];
524
- const { data: raw, isLoading: readLoading, refetch } = useReadContracts2({ contracts, query: { enabled: contracts.length > 0 } });
525
- const texts = (raw ?? []).map((r) => r.status === "success" ? decodeRecord(r.result) : "");
526
- const { data: records, isLoading: parseLoading } = useQuery5({
527
- queryKey: ["records", config.network, registry.address, address, index, kinds.join(","), texts.join(" "), armoredKey ?? ""],
528
- queryFn: async () => {
529
- const out = [];
530
- for (let i = 0; i < kinds.length; i++) if (texts[i]) out.push(await parseRecord(kinds[i], texts[i], { armoredKey: armoredKey ?? void 0 }));
531
- return out;
532
- },
533
- enabled: enabled && raw !== void 0
534
- });
535
- return { records: records ?? [], isLoading: enabled && (readLoading || parseLoading), refetch: () => {
536
- void refetch();
537
- } };
538
- }
91
+ verifyProof,
92
+ verifyStatementSignature
93
+ } from "./chunk-AAJWERE2.js";
539
94
  export {
540
95
  ARWEAVE_GATEWAY,
541
96
  AUTHORIZATION_TYPES,
542
97
  CLAIM_CHECK_LABEL,
98
+ CLAIM_LIMIT,
99
+ CONTRACT_ERROR_TEXT,
543
100
  EIP712_NAME,
544
101
  EIP712_VERSION,
545
102
  ENS_HINT_KEY,
546
103
  ENS_TEXT_RESOLVER_ABI,
547
104
  FARCASTER_HUB,
548
- IDENTITY_ERROR_TEXT,
549
- IDENTITY_KINDS,
550
105
  IPFS_GATEWAY,
551
106
  IPFS_GATEWAYS,
552
- IdentityKitProvider,
553
107
  KNOWN_KINDS,
108
+ MAX_KIND_BYTES,
554
109
  MAX_RECORD_BYTES,
555
110
  NETWORKS,
556
111
  NFT_AVATAR_ABI,
112
+ OWNER_REVOKE_REASONS,
557
113
  REGISTRY_ABI,
558
114
  REGISTRY_ADDRESS,
559
- ThurinCard,
560
- addPointer,
115
+ REVOKE_REASONS,
116
+ addRelease,
561
117
  attestTypedData,
562
118
  authorizationDigest,
563
119
  avatarFallbacks,
564
120
  avatarUrl,
565
121
  bytesToFingerprint,
566
122
  chainFor,
123
+ checkKindName,
124
+ checkRecordValue,
567
125
  claimCheckText,
568
126
  claimFateText,
569
127
  claimFates,
570
- decodeRecord,
128
+ claimSignature,
129
+ contractErrorName,
130
+ contractErrorText,
571
131
  displayUrl,
572
- encodeRecord,
132
+ encryptRefusalText,
133
+ encryptTo,
134
+ encryptionKeyFor,
573
135
  ensHintFor,
574
136
  ensHintValue,
575
137
  ensHintWrite,
576
138
  expiresSoon,
577
139
  expiresSoonText,
578
- fetchEFPGraph,
579
140
  fetchEnsHint,
580
141
  fetchRecords,
142
+ findOwners,
581
143
  fingerprintHash,
582
144
  fingerprintToBytes,
583
145
  formatClaimDate,
584
146
  getRegistry,
585
147
  hasEmailUserID,
586
148
  identifyProof,
587
- identityErrorKind,
588
149
  isNetworkName,
150
+ keyChangedText,
589
151
  keyIdOf,
590
152
  keyIdToBytes,
153
+ keyProblemText,
154
+ keyStanding,
591
155
  kindName,
592
- needsRpcProbe,
156
+ leanKey,
157
+ markCompromisedTypedData,
593
158
  nftAvatarImage,
594
159
  normalizeFingerprint,
160
+ pageRecords,
595
161
  parseNftAvatar,
596
162
  parsePgpKey,
597
- parsePointer,
598
163
  parseRecord,
164
+ parseReleases,
165
+ payloadText,
166
+ pickRecords,
599
167
  proofHref,
600
168
  proofSecondaryHref,
169
+ readClaims,
601
170
  reattestTypedData,
602
171
  recordKind,
603
172
  registryDomain,
604
- renderPointer,
173
+ renderReleases,
605
174
  revokeTypedData,
175
+ sameFingerprint,
606
176
  setRecordTypedData,
177
+ signatureEmail,
178
+ sshKeys,
179
+ statementText,
607
180
  stripEmailUserIDs,
608
181
  updateKeyTypedData,
609
- useAttestations,
610
- useEFPGraph,
611
- useEnsHint,
612
- usePGPProofs,
613
- useRecords,
614
- useSafeAvatar,
615
- useThurinIdentity,
616
182
  verifyAttestation,
617
183
  verifyClearsigned,
618
- verifyProof
184
+ verifyProof,
185
+ verifyStatementSignature
619
186
  };
620
- //# sourceMappingURL=index.js.map