@thurinlabs/identity-kit 1.2.0 → 1.2.1
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/README.md +1 -1
- package/dist/{chunk-JBWSRWL5.cjs → chunk-DC72HPXJ.cjs} +3 -24
- package/dist/chunk-DC72HPXJ.cjs.map +1 -0
- package/dist/{chunk-Y4E5MMGR.js → chunk-FN5VSB3U.js} +1 -22
- package/dist/chunk-FN5VSB3U.js.map +1 -0
- package/dist/core.cjs +2 -6
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -3
- package/dist/core.d.ts +1 -3
- package/dist/core.js +1 -5
- package/dist/embed.global.js.map +1 -1
- package/dist/index.cjs +20 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-JBWSRWL5.cjs.map +0 -1
- package/dist/chunk-Y4E5MMGR.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var _chunkJBWSRWL5cjs = require('./chunk-JBWSRWL5.cjs');
|
|
41
|
+
var _chunkDC72HPXJcjs = require('./chunk-DC72HPXJ.cjs');
|
|
44
42
|
|
|
45
43
|
// src/provider.tsx
|
|
46
44
|
var _react = require('react');
|
|
@@ -70,7 +68,7 @@ var defaultQueryClient = new (0, _reactquery.QueryClient)({
|
|
|
70
68
|
}
|
|
71
69
|
});
|
|
72
70
|
function createDefaultWagmiConfig(rpcUrl, network) {
|
|
73
|
-
const url = rpcUrl ||
|
|
71
|
+
const url = rpcUrl || _chunkDC72HPXJcjs.getRegistry.call(void 0, network).defaultRpcUrl;
|
|
74
72
|
if (network === "sepolia") return _wagmi.createConfig.call(void 0, { chains: [_chains.sepolia], transports: { [_chains.sepolia.id]: _wagmi.http.call(void 0, url) } });
|
|
75
73
|
if (network === "local") return _wagmi.createConfig.call(void 0, { chains: [_chains.foundry], transports: { [_chains.foundry.id]: _wagmi.http.call(void 0, url) } });
|
|
76
74
|
return _wagmi.createConfig.call(void 0, { chains: [_chains.mainnet], transports: { [_chains.mainnet.id]: _wagmi.http.call(void 0, url) } });
|
|
@@ -113,12 +111,12 @@ var _ens = require('viem/ens');
|
|
|
113
111
|
var _viem = require('viem');
|
|
114
112
|
function useAttestations(address) {
|
|
115
113
|
const config = useIdentityKitConfig();
|
|
116
|
-
const registry =
|
|
117
|
-
const chain =
|
|
114
|
+
const registry = _chunkDC72HPXJcjs.getRegistry.call(void 0, config.network, config.registryAddress);
|
|
115
|
+
const chain = _chunkDC72HPXJcjs.chainFor.call(void 0, config.network);
|
|
118
116
|
const owner = address;
|
|
119
117
|
const { data: rows, isLoading: rowsLoading } = _wagmi.useReadContract.call(void 0, {
|
|
120
118
|
address: registry.address,
|
|
121
|
-
abi:
|
|
119
|
+
abi: _chunkDC72HPXJcjs.REGISTRY_ABI,
|
|
122
120
|
functionName: "attestationsOf",
|
|
123
121
|
args: owner ? [owner] : void 0,
|
|
124
122
|
chainId: chain.id,
|
|
@@ -127,7 +125,7 @@ function useAttestations(address) {
|
|
|
127
125
|
const count = _nullishCoalesce(_optionalChain([rows, 'optionalAccess', _2 => _2.length]), () => ( 0));
|
|
128
126
|
const contracts = owner && rows ? rows.map((_, i) => ({
|
|
129
127
|
address: registry.address,
|
|
130
|
-
abi:
|
|
128
|
+
abi: _chunkDC72HPXJcjs.REGISTRY_ABI,
|
|
131
129
|
functionName: "getPayload",
|
|
132
130
|
args: [owner, BigInt(i)],
|
|
133
131
|
chainId: chain.id
|
|
@@ -152,8 +150,8 @@ function useAttestations(address) {
|
|
|
152
150
|
pgpSignature = _viem.hexToString.call(void 0, sigHex);
|
|
153
151
|
pgpPublicKey = _viem.hexToString.call(void 0, keyHex);
|
|
154
152
|
}
|
|
155
|
-
const fingerprint =
|
|
156
|
-
const verification = pgpPublicKey && pgpSignature ? await
|
|
153
|
+
const fingerprint = _chunkDC72HPXJcjs.bytesToFingerprint.call(void 0, row.fingerprint);
|
|
154
|
+
const verification = pgpPublicKey && pgpSignature ? await _chunkDC72HPXJcjs.verifyAttestation.call(void 0, { pgpPublicKey, pgpSignature, fingerprint, ethAddress: address }) : null;
|
|
157
155
|
const revokedAt = Number(row.revokedAt);
|
|
158
156
|
results.push({
|
|
159
157
|
index: i,
|
|
@@ -190,7 +188,7 @@ function useAttestations(address) {
|
|
|
190
188
|
function useEFPGraph(address) {
|
|
191
189
|
const { data, isLoading } = _reactquery.useQuery.call(void 0, {
|
|
192
190
|
queryKey: ["efp-graph", address],
|
|
193
|
-
queryFn: () =>
|
|
191
|
+
queryFn: () => _chunkDC72HPXJcjs.fetchEFPGraph.call(void 0, address),
|
|
194
192
|
enabled: !!address,
|
|
195
193
|
staleTime: 3e5
|
|
196
194
|
});
|
|
@@ -210,19 +208,19 @@ function usePGPProofs(fingerprint, armoredKey) {
|
|
|
210
208
|
queryKey: ["pgp-proofs", fingerprint, _nullishCoalesce(_optionalChain([armoredKey, 'optionalAccess', _6 => _6.length]), () => ( 0))],
|
|
211
209
|
queryFn: async () => {
|
|
212
210
|
if (!fingerprint || !armoredKey) return { keyInfo: null, proofs: [] };
|
|
213
|
-
const keyInfo = await
|
|
211
|
+
const keyInfo = await _chunkDC72HPXJcjs.parsePgpKey.call(void 0, armoredKey);
|
|
214
212
|
if (!keyInfo) return { keyInfo: null, proofs: [] };
|
|
215
|
-
const identified = keyInfo.notations.map((n) =>
|
|
213
|
+
const identified = keyInfo.notations.map((n) => _chunkDC72HPXJcjs.identifyProof.call(void 0, n)).filter((p) => p !== null && p.provider !== "unknown");
|
|
216
214
|
const proofs = await Promise.all(
|
|
217
215
|
identified.map(async (proof) => {
|
|
218
|
-
const result = await
|
|
216
|
+
const result = await _chunkDC72HPXJcjs.verifyProof.call(void 0, proof, fingerprint, config.neynarApiKey);
|
|
219
217
|
return {
|
|
220
218
|
provider: proof.provider,
|
|
221
219
|
label: proof.label,
|
|
222
220
|
url: proof.url,
|
|
223
|
-
displayUrl:
|
|
224
|
-
href:
|
|
225
|
-
secondaryHref:
|
|
221
|
+
displayUrl: _chunkDC72HPXJcjs.displayUrl.call(void 0, proof),
|
|
222
|
+
href: _chunkDC72HPXJcjs.proofHref.call(void 0, proof),
|
|
223
|
+
secondaryHref: _chunkDC72HPXJcjs.proofSecondaryHref.call(void 0, proof),
|
|
226
224
|
status: result.verified ? "verified" : "unverified",
|
|
227
225
|
reason: result.reason
|
|
228
226
|
};
|
|
@@ -264,7 +262,7 @@ function safeNormalize(name) {
|
|
|
264
262
|
}
|
|
265
263
|
}
|
|
266
264
|
function useThurinIdentity(ensOrAddress) {
|
|
267
|
-
const chain =
|
|
265
|
+
const chain = _chunkDC72HPXJcjs.chainFor.call(void 0, useIdentityKitConfig().network);
|
|
268
266
|
const isAddr = ensOrAddress ? isAddress(ensOrAddress) : false;
|
|
269
267
|
const ensInput = ensOrAddress && !isAddr ? safeNormalize(ensOrAddress) : void 0;
|
|
270
268
|
const { data: resolvedAddress } = _wagmi.useEnsAddress.call(void 0, {
|
|
@@ -403,15 +401,15 @@ function safeNormalize2(name) {
|
|
|
403
401
|
}
|
|
404
402
|
}
|
|
405
403
|
function useEnsHint(name, verifiedFingerprint) {
|
|
406
|
-
const chain =
|
|
404
|
+
const chain = _chunkDC72HPXJcjs.chainFor.call(void 0, useIdentityKitConfig().network);
|
|
407
405
|
const ensName = name ? safeNormalize2(name) : void 0;
|
|
408
406
|
const { data, isLoading, refetch } = _wagmi.useEnsText.call(void 0, {
|
|
409
407
|
name: ensName,
|
|
410
|
-
key:
|
|
408
|
+
key: _chunkDC72HPXJcjs.ENS_HINT_KEY,
|
|
411
409
|
chainId: chain.id,
|
|
412
410
|
query: { enabled: !!ensName }
|
|
413
411
|
});
|
|
414
|
-
return { ...
|
|
412
|
+
return { ..._chunkDC72HPXJcjs.ensHintFor.call(void 0, _nullishCoalesce(data, () => ( null)), verifiedFingerprint), isLoading: !!ensName && isLoading, refetch: () => {
|
|
415
413
|
void refetch();
|
|
416
414
|
} };
|
|
417
415
|
}
|
|
@@ -462,7 +460,5 @@ function useEnsHint(name, verifiedFingerprint) {
|
|
|
462
460
|
|
|
463
461
|
|
|
464
462
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
exports.AUTHORIZATION_TYPES = _chunkJBWSRWL5cjs.AUTHORIZATION_TYPES; exports.EIP712_NAME = _chunkJBWSRWL5cjs.EIP712_NAME; exports.EIP712_VERSION = _chunkJBWSRWL5cjs.EIP712_VERSION; exports.ENS_HINT_KEY = _chunkJBWSRWL5cjs.ENS_HINT_KEY; exports.ENS_TEXT_RESOLVER_ABI = _chunkJBWSRWL5cjs.ENS_TEXT_RESOLVER_ABI; exports.IdentityKitProvider = IdentityKitProvider; exports.NETWORKS = _chunkJBWSRWL5cjs.NETWORKS; exports.REGISTRY_ABI = _chunkJBWSRWL5cjs.REGISTRY_ABI; exports.REGISTRY_ADDRESS = _chunkJBWSRWL5cjs.REGISTRY_ADDRESS; exports.ThurinCard = ThurinCard; exports.attestTypedData = _chunkJBWSRWL5cjs.attestTypedData; exports.authorizationDigest = _chunkJBWSRWL5cjs.authorizationDigest; exports.bytesToFingerprint = _chunkJBWSRWL5cjs.bytesToFingerprint; exports.chainFor = _chunkJBWSRWL5cjs.chainFor; exports.displayUrl = _chunkJBWSRWL5cjs.displayUrl; exports.ensHintFor = _chunkJBWSRWL5cjs.ensHintFor; exports.ensHintValue = _chunkJBWSRWL5cjs.ensHintValue; exports.ensHintWrite = _chunkJBWSRWL5cjs.ensHintWrite; exports.fetchEFPGraph = _chunkJBWSRWL5cjs.fetchEFPGraph; exports.fetchEnsHint = _chunkJBWSRWL5cjs.fetchEnsHint; exports.fetchKeyByFingerprint = _chunkJBWSRWL5cjs.fetchKeyByFingerprint; exports.fetchKeyByKeyId = _chunkJBWSRWL5cjs.fetchKeyByKeyId; exports.fingerprintHash = _chunkJBWSRWL5cjs.fingerprintHash; exports.fingerprintToBytes = _chunkJBWSRWL5cjs.fingerprintToBytes; exports.getRegistry = _chunkJBWSRWL5cjs.getRegistry; exports.hasEmailUserID = _chunkJBWSRWL5cjs.hasEmailUserID; exports.identifyProof = _chunkJBWSRWL5cjs.identifyProof; exports.isNetworkName = _chunkJBWSRWL5cjs.isNetworkName; exports.keyIdOf = _chunkJBWSRWL5cjs.keyIdOf; exports.keyIdToBytes = _chunkJBWSRWL5cjs.keyIdToBytes; exports.normalizeFingerprint = _chunkJBWSRWL5cjs.normalizeFingerprint; exports.parsePgpKey = _chunkJBWSRWL5cjs.parsePgpKey; exports.proofHref = _chunkJBWSRWL5cjs.proofHref; exports.proofSecondaryHref = _chunkJBWSRWL5cjs.proofSecondaryHref; exports.reattestTypedData = _chunkJBWSRWL5cjs.reattestTypedData; exports.recordKind = _chunkJBWSRWL5cjs.recordKind; exports.registryDomain = _chunkJBWSRWL5cjs.registryDomain; exports.revokeTypedData = _chunkJBWSRWL5cjs.revokeTypedData; exports.setRecordTypedData = _chunkJBWSRWL5cjs.setRecordTypedData; exports.stripEmailUserIDs = _chunkJBWSRWL5cjs.stripEmailUserIDs; exports.updateKeyTypedData = _chunkJBWSRWL5cjs.updateKeyTypedData; exports.useAttestations = useAttestations; exports.useEFPGraph = useEFPGraph; exports.useEnsHint = useEnsHint; exports.usePGPProofs = usePGPProofs; exports.useThurinIdentity = useThurinIdentity; exports.verifyAttestation = _chunkJBWSRWL5cjs.verifyAttestation; exports.verifyProof = _chunkJBWSRWL5cjs.verifyProof;
|
|
463
|
+
exports.AUTHORIZATION_TYPES = _chunkDC72HPXJcjs.AUTHORIZATION_TYPES; exports.EIP712_NAME = _chunkDC72HPXJcjs.EIP712_NAME; exports.EIP712_VERSION = _chunkDC72HPXJcjs.EIP712_VERSION; exports.ENS_HINT_KEY = _chunkDC72HPXJcjs.ENS_HINT_KEY; exports.ENS_TEXT_RESOLVER_ABI = _chunkDC72HPXJcjs.ENS_TEXT_RESOLVER_ABI; exports.IdentityKitProvider = IdentityKitProvider; exports.NETWORKS = _chunkDC72HPXJcjs.NETWORKS; exports.REGISTRY_ABI = _chunkDC72HPXJcjs.REGISTRY_ABI; exports.REGISTRY_ADDRESS = _chunkDC72HPXJcjs.REGISTRY_ADDRESS; exports.ThurinCard = ThurinCard; exports.attestTypedData = _chunkDC72HPXJcjs.attestTypedData; exports.authorizationDigest = _chunkDC72HPXJcjs.authorizationDigest; exports.bytesToFingerprint = _chunkDC72HPXJcjs.bytesToFingerprint; exports.chainFor = _chunkDC72HPXJcjs.chainFor; exports.displayUrl = _chunkDC72HPXJcjs.displayUrl; exports.ensHintFor = _chunkDC72HPXJcjs.ensHintFor; exports.ensHintValue = _chunkDC72HPXJcjs.ensHintValue; exports.ensHintWrite = _chunkDC72HPXJcjs.ensHintWrite; exports.fetchEFPGraph = _chunkDC72HPXJcjs.fetchEFPGraph; exports.fetchEnsHint = _chunkDC72HPXJcjs.fetchEnsHint; exports.fingerprintHash = _chunkDC72HPXJcjs.fingerprintHash; exports.fingerprintToBytes = _chunkDC72HPXJcjs.fingerprintToBytes; exports.getRegistry = _chunkDC72HPXJcjs.getRegistry; exports.hasEmailUserID = _chunkDC72HPXJcjs.hasEmailUserID; exports.identifyProof = _chunkDC72HPXJcjs.identifyProof; exports.isNetworkName = _chunkDC72HPXJcjs.isNetworkName; exports.keyIdOf = _chunkDC72HPXJcjs.keyIdOf; exports.keyIdToBytes = _chunkDC72HPXJcjs.keyIdToBytes; exports.normalizeFingerprint = _chunkDC72HPXJcjs.normalizeFingerprint; exports.parsePgpKey = _chunkDC72HPXJcjs.parsePgpKey; exports.proofHref = _chunkDC72HPXJcjs.proofHref; exports.proofSecondaryHref = _chunkDC72HPXJcjs.proofSecondaryHref; exports.reattestTypedData = _chunkDC72HPXJcjs.reattestTypedData; exports.recordKind = _chunkDC72HPXJcjs.recordKind; exports.registryDomain = _chunkDC72HPXJcjs.registryDomain; exports.revokeTypedData = _chunkDC72HPXJcjs.revokeTypedData; exports.setRecordTypedData = _chunkDC72HPXJcjs.setRecordTypedData; exports.stripEmailUserIDs = _chunkDC72HPXJcjs.stripEmailUserIDs; exports.updateKeyTypedData = _chunkDC72HPXJcjs.updateKeyTypedData; exports.useAttestations = useAttestations; exports.useEFPGraph = useEFPGraph; exports.useEnsHint = useEnsHint; exports.usePGPProofs = usePGPProofs; exports.useThurinIdentity = useThurinIdentity; exports.verifyAttestation = _chunkDC72HPXJcjs.verifyAttestation; exports.verifyProof = _chunkDC72HPXJcjs.verifyProof;
|
|
468
464
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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"],"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"]}
|
|
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"],"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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { IdentityKitConfig, Theme, ThurinIdentity, Attestation, EFPGraph, PGPKeyInfo, ProofResult, EnsHint } from './core.cjs';
|
|
4
|
-
export { AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, NETWORKS, NetworkName, Notation, PGPVerification, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, UpdateKeyAuthorization, attestTypedData, authorizationDigest, bytesToFingerprint, chainFor, displayUrl, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint,
|
|
4
|
+
export { AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, NETWORKS, NetworkName, Notation, PGPVerification, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, UpdateKeyAuthorization, attestTypedData, authorizationDigest, bytesToFingerprint, chainFor, displayUrl, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint, fingerprintHash, fingerprintToBytes, getRegistry, hasEmailUserID, identifyProof, isNetworkName, keyIdOf, keyIdToBytes, normalizeFingerprint, parsePgpKey, proofHref, proofSecondaryHref, reattestTypedData, recordKind, registryDomain, revokeTypedData, setRecordTypedData, stripEmailUserIDs, updateKeyTypedData, verifyAttestation, verifyProof } from './core.cjs';
|
|
5
5
|
import 'viem';
|
|
6
6
|
|
|
7
7
|
interface IdentityKitProviderProps extends IdentityKitConfig {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { IdentityKitConfig, Theme, ThurinIdentity, Attestation, EFPGraph, PGPKeyInfo, ProofResult, EnsHint } from './core.js';
|
|
4
|
-
export { AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, NETWORKS, NetworkName, Notation, PGPVerification, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, UpdateKeyAuthorization, attestTypedData, authorizationDigest, bytesToFingerprint, chainFor, displayUrl, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint,
|
|
4
|
+
export { AUTHORIZATION_TYPES, AttestAuthorization, AuthorizationAction, EIP712_NAME, EIP712_VERSION, ENS_HINT_KEY, ENS_TEXT_RESOLVER_ABI, EnsHintState, EnsTextReader, NETWORKS, NetworkName, Notation, PGPVerification, Proof, REGISTRY_ABI, REGISTRY_ADDRESS, ReattestAuthorization, RegistryDeployment, RevokeAuthorization, SetRecordAuthorization, StrippedKey, SubkeyInfo, UpdateKeyAuthorization, attestTypedData, authorizationDigest, bytesToFingerprint, chainFor, displayUrl, ensHintFor, ensHintValue, ensHintWrite, fetchEFPGraph, fetchEnsHint, fingerprintHash, fingerprintToBytes, getRegistry, hasEmailUserID, identifyProof, isNetworkName, keyIdOf, keyIdToBytes, normalizeFingerprint, parsePgpKey, proofHref, proofSecondaryHref, reattestTypedData, recordKind, registryDomain, revokeTypedData, setRecordTypedData, stripEmailUserIDs, updateKeyTypedData, verifyAttestation, verifyProof } from './core.js';
|
|
5
5
|
import 'viem';
|
|
6
6
|
|
|
7
7
|
interface IdentityKitProviderProps extends IdentityKitConfig {
|
package/dist/index.js
CHANGED
|
@@ -17,8 +17,6 @@ import {
|
|
|
17
17
|
ensHintWrite,
|
|
18
18
|
fetchEFPGraph,
|
|
19
19
|
fetchEnsHint,
|
|
20
|
-
fetchKeyByFingerprint,
|
|
21
|
-
fetchKeyByKeyId,
|
|
22
20
|
fingerprintHash,
|
|
23
21
|
fingerprintToBytes,
|
|
24
22
|
getRegistry,
|
|
@@ -40,7 +38,7 @@ import {
|
|
|
40
38
|
updateKeyTypedData,
|
|
41
39
|
verifyAttestation,
|
|
42
40
|
verifyProof
|
|
43
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-FN5VSB3U.js";
|
|
44
42
|
|
|
45
43
|
// src/provider.tsx
|
|
46
44
|
import { useMemo } from "react";
|
|
@@ -436,8 +434,6 @@ export {
|
|
|
436
434
|
ensHintWrite,
|
|
437
435
|
fetchEFPGraph,
|
|
438
436
|
fetchEnsHint,
|
|
439
|
-
fetchKeyByFingerprint,
|
|
440
|
-
fetchKeyByKeyId,
|
|
441
437
|
fingerprintHash,
|
|
442
438
|
fingerprintToBytes,
|
|
443
439
|
getRegistry,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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"],"sourcesContent":["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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAyB,eAAe;AACxC,SAAS,eAAe,cAAc,MAAM,iBAAiB;AAC7D,SAAS,SAAS,SAAS,eAAe;AAG1C,SAAS,aAAa,2BAA2B;;;ACLjD,SAAS,eAAe,kBAAkB;AAG1C,IAAM,gBAAmC;AAAA,EACvC,SAAS;AAAA,EACT,SAAS;AACX;AAEO,IAAM,qBAAqB,cAAiC,aAAa;AAEzE,SAAS,uBAA0C;AACxD,SAAO,WAAW,kBAAkB;AACtC;;;AD6BW;AAhCX,IAAM,qBAAqB,IAAI,YAAY;AAAA,EACzC,gBAAgB;AAAA,IACd,SAAS;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IACT;AAAA,EACF;AACF,CAAC;AAID,SAAS,yBAAyB,QAA4B,SAAsB;AAClF,QAAM,MAAM,UAAU,YAAY,OAAO,EAAE;AAE3C,MAAI,YAAY,UAAW,QAAO,aAAa,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;AAC7G,MAAI,YAAY,QAAS,QAAO,aAAa,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;AAC3G,SAAO,aAAa,EAAE,QAAQ,CAAC,OAAO,GAAG,YAAY,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE,EAAE,CAAC;AACpF;AAEA,SAAS,cAAc,EAAE,UAAU,QAAQ,QAAQ,GAAmE;AAEpH,MAAI,WAAW;AACf,MAAI;AACF,cAAU;AACV,eAAW;AAAA,EACb,QAAQ;AAAA,EAER;AAEA,QAAM,cAAc,QAAQ,MAAM,yBAAyB,QAAQ,OAAO,GAAG,CAAC,QAAQ,OAAO,CAAC;AAE9F,MAAI,UAAU;AACZ,WAAO,gCAAG,UAAS;AAAA,EACrB;AAEA,SACE,oBAAC,iBAAc,QAAQ,aACrB,8BAAC,uBAAoB,QAAQ,oBAC1B,UACH,GACF;AAEJ;AAMO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV;AACF,GAA6B;AAC3B,QAAM,SAAS;AAAA,IACb,OAAO,EAAE,QAAQ,cAAc,SAAS,SAAS,gBAAgB;AAAA,IACjE,CAAC,QAAQ,cAAc,SAAS,SAAS,eAAe;AAAA,EAC1D;AAEA,SACE,oBAAC,mBAAmB,UAAnB,EAA4B,OAAO,QAClC,8BAAC,iBAAc,QAAgB,SAC5B,UACH,GACF;AAEJ;;;AE7EA,SAAS,eAAe,YAAY,oBAAoB;AAGxD,SAAS,iBAAiB;;;ACH1B,SAAS,iBAAiB,wBAAwB;AAClD,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAarB,SAAS,gBAAgB,SAAoC;AAClE,QAAM,SAAS,qBAAqB;AACpC,QAAM,WAAW,YAAY,OAAO,SAAS,OAAO,eAAe;AACnE,QAAM,QAAQ,SAAS,OAAO,OAAO;AACrC,QAAM,QAAQ;AAEd,QAAM,EAAE,MAAM,MAAM,WAAW,YAAY,IAAI,gBAAgB;AAAA,IAC7D,SAAS,SAAS;AAAA,IAClB,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,QAAQ,CAAC,KAAK,IAAI;AAAA,IACxB,SAAS,MAAM;AAAA,IACf,OAAO,EAAE,SAAS,CAAC,CAAC,MAAM;AAAA,EAC5B,CAAC;AAED,QAAM,QAAQ,MAAM,UAAU;AAE9B,QAAM,YAAY,SAAS,OACvB,KAAK,IAAI,CAAC,GAAG,OAAO;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,OAAO,OAAO,CAAC,CAAC;AAAA,IACvB,SAAS,MAAM;AAAA,EACjB,EAAE,IACF,CAAC;AAEL,QAAM,EAAE,MAAM,UAAU,WAAW,gBAAgB,IAAI,iBAAiB;AAAA,IACtE;AAAA,IACA,OAAO,EAAE,SAAS,UAAU,SAAS,EAAE;AAAA,EACzC,CAAC;AAED,QAAM,gBAAgB,UAAU,KAAM,aAAa,UAAa,SAAS,WAAW;AAEpF,QAAM,EAAE,MAAM,QAAQ,WAAW,cAAc,IAAI,SAAS;AAAA,IAC1D,UAAU,CAAC,gBAAgB,OAAO,SAAS,SAAS,SAAS,SAAS,OAAO,aAAa;AAAA,IAC1F,SAAS,YAAoC;AAC3C,UAAI,CAAC,QAAQ,CAAC,QAAS,QAAO,CAAC;AAC/B,YAAM,UAAyB,CAAC;AAEhC,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAM,MAAM,KAAK,CAAC;AAClB,cAAM,UAAU,WAAW,CAAC;AAC5B,YAAI,eAA8B;AAClC,YAAI,eAA8B;AAClC,YAAI,WAAW,QAAQ,WAAW,WAAW;AAC3C,gBAAM,CAAC,QAAQ,MAAM,IAAI,QAAQ;AACjC,yBAAe,YAAY,MAAM;AACjC,yBAAe,YAAY,MAAM;AAAA,QACnC;AAEA,cAAM,cAAc,mBAAmB,IAAI,WAAW;AACtD,cAAM,eAAe,gBAAgB,eACjC,MAAM,kBAAkB,EAAE,cAAc,cAAc,aAAa,YAAY,QAAQ,CAAC,IACxF;AAEJ,cAAM,YAAY,OAAO,IAAI,SAAS;AACtC,gBAAQ,KAAK;AAAA,UACX,OAAO;AAAA,UACP;AAAA,UACA,WAAW,OAAO,IAAI,SAAS;AAAA,UAC/B,SAAS,cAAc;AAAA,UACvB,WAAW,cAAc,IAAI,OAAO;AAAA,UACpC,gBAAgB,OAAO,IAAI,cAAc;AAAA,UACzC;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAAA,IACA,SAAS,CAAC,CAAC,QAAQ;AAAA,IACnB,WAAW;AAAA,EACb,CAAC;AAED,QAAM,YAAY,eAAe,mBAAmB,iBAAkB,CAAC,CAAC,SAAS,SAAS,UAAa,CAAC;AAExG,QAAM,gBAAgB,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO;AAI5D,QAAM,iBAAiB,aAAa,OAAO,CAAC,MAAM,EAAE,cAAc,QAAQ;AAC1E,QAAM,qBAAqB,eAAe,SAAS,IAC/C,eAAe,eAAe,SAAS,CAAC,EAAE,cAC1C;AAEJ,SAAO;AAAA,IACL,QAAQ,UAAU,CAAC;AAAA,IACnB,aAAa;AAAA,IACb,cAAc,aAAa;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;;;AC5GA,SAAS,YAAAA,iBAAgB;AAIlB,SAAS,YAAY,SAAoC;AAC9D,QAAM,EAAE,MAAM,UAAU,IAAIC,UAA0B;AAAA,IACpD,UAAU,CAAC,aAAa,OAAO;AAAA,IAC/B,SAAS,MAAM,cAAc,OAAQ;AAAA,IACrC,SAAS,CAAC,CAAC;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AAED,SAAO;AAAA,IACL,KAAK,QAAQ;AAAA,IACb;AAAA,EACF;AACF;;;AChBA,SAAS,YAAAC,iBAAgB;AAelB,SAAS,aAAa,aAAwC,YAAuC;AAC1G,QAAM,SAAS,qBAAqB;AAEpC,QAAM,EAAE,KAAK,IAAIC,UAAS;AAAA;AAAA;AAAA,IAGxB,UAAU,CAAC,cAAc,aAAa,YAAY,UAAU,CAAC;AAAA,IAC7D,SAAS,YAA4E;AACnF,UAAI,CAAC,eAAe,CAAC,WAAY,QAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;AAEpE,YAAM,UAAU,MAAM,YAAY,UAAU;AAC5C,UAAI,CAAC,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;AAKjD,YAAM,aAAa,QAAQ,UACxB,IAAI,CAAC,MAAM,cAAc,CAAC,CAAC,EAC3B,OAAO,CAAC,MAAkC,MAAM,QAAQ,EAAE,aAAa,SAAS;AAGnF,YAAM,SAAwB,MAAM,QAAQ;AAAA,QAC1C,WAAW,IAAI,OAAO,UAAU;AAC9B,gBAAM,SAAS,MAAM,YAAY,OAAO,aAAa,OAAO,YAAY;AACxE,iBAAO;AAAA,YACL,UAAU,MAAM;AAAA,YAChB,OAAO,MAAM;AAAA,YACb,KAAK,MAAM;AAAA,YACX,YAAY,WAAW,KAAK;AAAA,YAC5B,MAAM,UAAU,KAAK;AAAA,YACrB,eAAe,mBAAmB,KAAK;AAAA,YACvC,QAAQ,OAAO,WAAW,aAAsB;AAAA,YAChD,QAAQ,OAAO;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH;AAMA,YAAM,YAAY,oBAAI,IAAyB;AAC/C,iBAAW,KAAK,QAAQ;AACtB,cAAM,MAAM,GAAG,EAAE,QAAQ,IAAI,EAAE,UAAU;AACzC,cAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,YAAI,CAAC,QAAS,EAAE,WAAW,cAAc,KAAK,WAAW,YAAa;AACpE,oBAAU,IAAI,KAAK,CAAC;AAAA,QACtB;AAAA,MACF;AAEA,aAAO,EAAE,SAAS,QAAQ,CAAC,GAAG,UAAU,OAAO,CAAC,EAAE;AAAA,IACpD;AAAA,IACA,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC;AAAA,IAC5B,WAAW;AAAA,EACb,CAAC;AAED,SAAO;AAAA,IACL,SAAS,MAAM,WAAW;AAAA,IAC1B,QAAQ,MAAM,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IAKzB,WAAW,CAAC,CAAC,eAAe,CAAC,CAAC,cAAc,SAAS;AAAA,EACvD;AACF;;;AHvEA,SAAS,UAAU,OAAwB;AACzC,SAAO,sBAAsB,KAAK,KAAK;AACzC;AAEA,SAAS,cAAc,MAAkC;AACvD,MAAI;AACF,WAAO,UAAU,IAAI;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,kBAAkB,cAAyD;AACzF,QAAM,QAAQ,SAAS,qBAAqB,EAAE,OAAO;AACrD,QAAM,SAAS,eAAe,UAAU,YAAY,IAAI;AACxD,QAAM,WAAW,gBAAgB,CAAC,SAAS,cAAc,YAAY,IAAI;AAGzE,QAAM,EAAE,MAAM,gBAAgB,IAAI,cAAc;AAAA,IAC9C,MAAM;AAAA,IACN,SAAS,MAAM;AAAA,IACf,OAAO,EAAE,SAAS,CAAC,CAAC,SAAS;AAAA,EAC/B,CAAC;AAED,QAAM,UAAU,SAAS,eAAgB,mBAAmB;AAG5D,QAAM,EAAE,MAAM,QAAQ,IAAI,WAAW;AAAA,IACnC;AAAA,IACA,SAAS,MAAM;AAAA,IACf,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ;AAAA,EAC9B,CAAC;AAED,QAAM,cAAc,YAAY,WAAW;AAE3C,QAAM,EAAE,MAAM,UAAU,IAAI,aAAa;AAAA,IACvC,MAAM,cAAc,cAAc,WAAW,IAAI;AAAA,IACjD,SAAS,MAAM;AAAA,IACf,OAAO,EAAE,SAAS,CAAC,CAAC,YAAY;AAAA,EAClC,CAAC;AAGD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb,IAAI,gBAAgB,OAAO;AAK3B,QAAM,eAAe,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE;AAAA,IACzC,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,cAAc,YAAY,EAAE,gBAAgB;AAAA,EACrE;AACA,QAAM;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA,WAAW;AAAA,EACb,IAAI,aAAa,oBAAoB,cAAc,gBAAgB,IAAI;AAGvE,QAAM,EAAE,KAAK,WAAW,WAAW,IAAI,YAAY,OAAO;AAE1D,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,WAAW,aAAa;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,iBAAiB,iBAAiB;AAAA,IAC7C,OAAO;AAAA,EACT;AACF;;;AIhFI,SACE,OAAAC,MADF;AAFJ,SAAS,aAAa;AACpB,SACE,qBAAC,SAAI,WAAU,kCAAiC,SAAQ,eAAc,OAAM,8BAC1E;AAAA,oBAAAA,KAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,MAAK,8BAA6B;AAAA,IACjE,gBAAAA,KAAC,UAAK,GAAE,oCAAmC,MAAK,QAAO,QAAO,WAAU,aAAY,KAAI,eAAc,SAAO;AAAA,IAC7G,gBAAAA,KAAC,UAAK,GAAE,oCAAmC,MAAK,QAAO,QAAO,WAAU,aAAY,KAAI,eAAc,SAAO;AAAA,IAC7G,gBAAAA,KAAC,UAAK,GAAE,oCAAmC,MAAK,QAAO,QAAO,WAAU,aAAY,KAAI,eAAc,SAAO;AAAA,IAC7G,gBAAAA,KAAC,UAAK,GAAE,iBAAgB,MAAK,QAAO,QAAO,WAAU,aAAY,KAAI,eAAc,SAAO;AAAA,KAC5F;AAEJ;AAQO,SAAS,WAAW,EAAE,KAAK,SAAS,QAAQ,SAAS,GAAoB;AAC9E,QAAM,QAAQ,OAAO;AACrB,QAAM,WAAW,kBAAkB,KAAK;AACxC,QAAM,SAAS,qBAAqB;AAEpC,QAAM,aAAa,SAAS,UACxB,GAAG,OAAO,OAAO,QAAQ,SAAS,OAAO,KACzC,MACE,GAAG,OAAO,OAAO,QAAQ,GAAG,KAC5B;AAEN,MAAI,SAAS,WAAW;AACtB,WACE,gBAAAA,KAAC,SAAI,WAAU,eAAc,qBAAmB,OAC9C,0BAAAA,KAAC,SAAI,WAAU,uBAAsB,iCAAmB,GAC1D;AAAA,EAEJ;AAEA,QAAM,iBAAiB,SAAS,WAAW;AAE3C,QAAM,iBAAiB,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;AAC9E,QAAM,iBAAiB,SAAS,OAAO,KAAK,CAAC,MAAM,EAAE,cAAc,YAAY,CAAC,EAAE,OAAO;AAEzF,SACE,qBAAC,SAAI,WAAU,eAAc,qBAAmB,OAC9C;AAAA,yBAAC,OAAE,WAAU,sBAAqB,MAAM,cAAc,QAAW,QAAO,UAAS,KAAI,uBAClF;AAAA,eAAS,YACR,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,KAAK,SAAS;AAAA,UACd,KAAK,SAAS,WAAW;AAAA;AAAA,MAC3B,IAEA,gBAAAA,KAAC,cAAW;AAAA,MAEd,qBAAC,SACE;AAAA,iBAAS,WACR,gBAAAA,KAAC,SAAI,WAAU,oBAAoB,mBAAS,SAAQ;AAAA,QAErD,kBACC,gBAAAA,KAAC,SAAI,WAAU,uBAAuB,0BAAe;AAAA,SAEzD;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,qBACb;AAAA,2BAAC,SAAI,WAAU,oBACb;AAAA,wBAAAA,KAAC,UAAK,WAAU,0BAA0B,mBAAS,cAAa;AAAA,QAChE,gBAAAA,KAAC,UAAK,WAAU,0BAAyB,0BAAY;AAAA,SACvD;AAAA,MACA,qBAAC,SAAI,WAAU,oBACb;AAAA,wBAAAA,KAAC,UAAK,WAAU,0BAA0B,0BAAe;AAAA,QACzD,gBAAAA,KAAC,UAAK,WAAU,0BAAyB,oBAAM;AAAA,SACjD;AAAA,MACA,qBAAC,SAAI,WAAU,oBACb;AAAA,wBAAAA,KAAC,UAAK,WAAU,0BACb,mBAAS,KAAK,aAAa,GAC9B;AAAA,QACA,gBAAAA,KAAC,UAAK,WAAU,0BAAyB,uBAAS;AAAA,SACpD;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,sBACZ;AAAA,wBACC,gBAAAA,KAAC,UAAK,WAAU,iDAAgD,0BAAY;AAAA,MAE7E,SAAS,KAAK,UACb,gBAAAA,KAAC,UAAK,WAAU,iDAAgD,iBAAG;AAAA,MAEpE,SAAS,OAAO,IAAI,CAAC,GAAG,MACvB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,wCAAwC,EAAE,WAAW,aAAa,aAAa,YAAY;AAAA,UAErG,YAAE;AAAA;AAAA,QAHE;AAAA,MAIP,CACD;AAAA,OACH;AAAA,IAEC,cACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAO;AAAA,QACP,KAAI;AAAA,QACL;AAAA;AAAA,IAED;AAAA,KAEJ;AAEJ;;;ACpHA,SAAS,kBAAkB;AAC3B,SAAS,aAAAC,kBAAiB;AAK1B,SAASC,eAAc,MAAkC;AACvD,MAAI;AAAE,WAAOC,WAAU,IAAI;AAAA,EAAE,QAAQ;AAAE,WAAO;AAAA,EAAU;AAC1D;AAOO,SAAS,WAAW,MAAiC,qBAAuG;AACjK,QAAM,QAAQ,SAAS,qBAAqB,EAAE,OAAO;AACrD,QAAM,UAAU,OAAOD,eAAc,IAAI,IAAI;AAC7C,QAAM,EAAE,MAAM,WAAW,QAAQ,IAAI,WAAW;AAAA,IAC9C,MAAM;AAAA,IACN,KAAK;AAAA,IACL,SAAS,MAAM;AAAA,IACf,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ;AAAA,EAC9B,CAAC;AACD,SAAO,EAAE,GAAG,WAAW,QAAQ,MAAM,mBAAmB,GAAG,WAAW,CAAC,CAAC,WAAW,WAAW,SAAS,MAAM;AAAE,SAAK,QAAQ;AAAA,EAAE,EAAE;AAClI;","names":["useQuery","useQuery","useQuery","useQuery","jsx","normalize","safeNormalize","normalize"]}
|
|
1
|
+
{"version":3,"sources":["../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"],"sourcesContent":["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"],"mappings":"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","names":["useQuery","useQuery","useQuery","useQuery","jsx","normalize","safeNormalize","normalize"]}
|