@thurinlabs/identity-kit 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -7,7 +7,7 @@ var _reactquery = require('@tanstack/react-query');
7
7
  // src/context.ts
8
8
 
9
9
  var defaultConfig = {
10
- scryBaseUrl: "https://scry.thurin.id"
10
+ scryBaseUrl: "https://thurin.id"
11
11
  };
12
12
  var IdentityKitContext = _react.createContext.call(void 0, defaultConfig);
13
13
  function useIdentityKitConfig() {
@@ -49,7 +49,7 @@ function IdentityKitProvider({
49
49
  children,
50
50
  rpcUrl,
51
51
  neynarApiKey,
52
- scryBaseUrl = "https://scry.thurin.id"
52
+ scryBaseUrl = "https://thurin.id"
53
53
  }) {
54
54
  const config = _react.useMemo.call(void 0,
55
55
  () => ({ rpcUrl, neynarApiKey, scryBaseUrl }),
@@ -393,8 +393,9 @@ var PROVIDERS = [
393
393
  parse: (m) => ({ instance: m[1], user: m[2] })
394
394
  }
395
395
  ];
396
+ var ACCEPTED_NAMESPACES = /* @__PURE__ */ new Set(["proof@thurin.id", "proof@ariadne.id"]);
396
397
  function identifyProof(notation) {
397
- if (notation.name !== "proof@thurin.id") return null;
398
+ if (!ACCEPTED_NAMESPACES.has(notation.name)) return null;
398
399
  for (const { provider, label, pattern, parse } of PROVIDERS) {
399
400
  const m = notation.value.match(pattern);
400
401
  if (m) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/benwoodall/Development/thurinlabs/identity-kit/dist/index.cjs","../src/provider.tsx","../src/context.ts","../src/hooks/useScryIdentity.ts","../src/hooks/useSignetClaims.ts","../src/core/contract.ts","../src/core/logs.ts","../src/core/pgp.ts","../src/hooks/useEFPGraph.ts","../src/core/efp.ts","../src/hooks/usePGPProofs.ts","../src/core/proofs.ts","../src/components/ScryCard/ScryCard.tsx"],"names":["key","mainnet","useQuery","jsx"],"mappings":"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","file":"/Users/benwoodall/Development/thurinlabs/identity-kit/dist/index.cjs","sourcesContent":[null,"import { type ReactNode, useMemo } from 'react'\nimport { WagmiProvider, createConfig, http, useConfig } from 'wagmi'\nimport { mainnet } from 'wagmi/chains'\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\nfunction createDefaultWagmiConfig(rpcUrl?: string) {\n return createConfig({\n chains: [mainnet],\n transports: {\n [mainnet.id]: http(rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n },\n })\n}\n\nfunction WagmiDetector({ children, rpcUrl }: { children: ReactNode; rpcUrl?: string }) {\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), [rpcUrl])\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 scryBaseUrl = 'https://scry.thurin.id',\n}: IdentityKitProviderProps) {\n const config = useMemo(\n () => ({ rpcUrl, neynarApiKey, scryBaseUrl }),\n [rpcUrl, neynarApiKey, scryBaseUrl],\n )\n\n return (\n <IdentityKitContext.Provider value={config}>\n <WagmiDetector rpcUrl={rpcUrl}>\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 scryBaseUrl: 'https://scry.thurin.id',\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 { mainnet } from 'wagmi/chains'\nimport { normalize } from 'viem/ens'\nimport { useSignetClaims } from './useSignetClaims'\nimport { useEFPGraph } from './useEFPGraph'\nimport { usePGPProofs } from './usePGPProofs'\nimport type { ScryIdentity } 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 useScryIdentity(ensOrAddress: string | undefined | null): ScryIdentity {\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: mainnet.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: mainnet.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: mainnet.id,\n query: { enabled: !!displayName },\n })\n\n // Signet claims\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\n } = useSignetClaims(address)\n\n // PGP proofs (from current fingerprint)\n const {\n keyInfo: pgpKeyInfo,\n proofs,\n isLoading: proofsLoading,\n } = usePGPProofs(currentFingerprint)\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 { mainnet } from 'wagmi/chains'\nimport { useQuery } from '@tanstack/react-query'\nimport { createPublicClient, http, parseAbiItem } from 'viem'\nimport { REGISTRY_ADDRESS, REGISTRY_ABI, CONTRACT_DEPLOY_BLOCK } from '../core/contract'\nimport { getLogsChunked } from '../core/logs'\nimport { verifyAttestation } from '../core/pgp'\nimport { useIdentityKitConfig } from '../context'\nimport type { SignetClaim } from '../core/types'\n\nexport function useSignetClaims(address: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data: count, isLoading: countLoading } = useReadContract({\n address: REGISTRY_ADDRESS,\n abi: REGISTRY_ABI,\n functionName: 'attestationCount',\n args: address ? [address as `0x${string}`] : undefined,\n chainId: mainnet.id,\n query: { enabled: !!address },\n })\n\n const attestationCount = count ? Number(count) : 0\n\n const contracts = address\n ? Array.from({ length: attestationCount }, (_, i) => ({\n address: REGISTRY_ADDRESS as `0x${string}`,\n abi: REGISTRY_ABI,\n functionName: 'getAttestation' as const,\n args: [address as `0x${string}`, BigInt(i)] as const,\n chainId: mainnet.id,\n }))\n : []\n\n const { data: attestations, isLoading: attestationsLoading } = useReadContracts({\n contracts,\n query: { enabled: contracts.length > 0 },\n })\n\n // Fetch event logs for PGP data (signature + public key not available from contract reads)\n const { data: eventData } = useQuery({\n queryKey: ['signet-logs', address],\n queryFn: async () => {\n if (!address) return []\n const client = createPublicClient({\n chain: mainnet,\n transport: http(config.rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n })\n const event = parseAbiItem(\n 'event Attested(address indexed ethAddress, string indexed fingerprintHash, string fingerprint, string pgpSignature, string pgpPublicKey, uint256 index, uint256 timestamp)',\n )\n return getLogsChunked(client, {\n address: REGISTRY_ADDRESS,\n event,\n args: { ethAddress: address as `0x${string}` },\n fromBlock: CONTRACT_DEPLOY_BLOCK,\n toBlock: 'latest',\n })\n },\n enabled: !!address && attestationCount > 0,\n staleTime: 300_000,\n })\n\n // Combine attestation data with event log data and verify\n const { data: claims, isLoading: verifyLoading } = useQuery({\n queryKey: ['signet-claims', address, attestationCount, !!eventData],\n queryFn: async (): Promise<SignetClaim[]> => {\n if (!attestations || !address) return []\n\n const results: SignetClaim[] = []\n\n for (let i = 0; i < attestations.length; i++) {\n const att = attestations[i]\n if (att.status !== 'success') continue\n\n const [fingerprint, createdAt, revoked] = att.result as [string, bigint, boolean]\n const log = (eventData || [])[i]\n\n const pgpSignature = log?.args?.pgpSignature ?? null\n const pgpPublicKey = log?.args?.pgpPublicKey ?? null\n const txHash = log?.transactionHash ?? null\n\n let verification = null\n if (pgpPublicKey && pgpSignature) {\n verification = await verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress: address,\n })\n }\n\n results.push({\n index: i,\n fingerprint,\n createdAt: Number(createdAt),\n revoked,\n pgpSignature,\n pgpPublicKey,\n txHash,\n verification,\n })\n }\n\n return results\n },\n enabled: !!attestations && attestations.length > 0,\n staleTime: 300_000,\n })\n\n const isLoading = countLoading || attestationsLoading || verifyLoading\n\n const activeClaims = (claims || []).filter((c) => !c.revoked)\n const currentFingerprint = activeClaims.length > 0\n ? activeClaims[activeClaims.length - 1].fingerprint\n : null\n\n return {\n claims: claims || [],\n totalClaims: attestationCount,\n activeClaims: activeClaims.length,\n currentFingerprint,\n isLoading,\n }\n}\n","export const REGISTRY_ADDRESS = '0xf7a45BC662A78a6fb417ED5f52b3766cbf13EbBb' as const\n\nexport const CONTRACT_DEPLOY_BLOCK = 24515891n\n\nexport const REGISTRY_ABI = [\n {\n name: 'Attested',\n type: 'event',\n inputs: [\n { name: 'ethAddress', type: 'address', indexed: true },\n { name: 'fingerprintHash', type: 'string', indexed: true },\n { name: 'fingerprint', type: 'string', indexed: false },\n { name: 'pgpSignature', type: 'string', indexed: false },\n { name: 'pgpPublicKey', type: 'string', indexed: false },\n { name: 'index', type: 'uint256', indexed: false },\n { name: 'timestamp', type: 'uint256', indexed: false },\n ],\n },\n {\n name: 'attestationCount',\n type: 'function',\n stateMutability: 'view',\n inputs: [{ name: 'addr', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n name: 'getAttestation',\n type: 'function',\n stateMutability: 'view',\n inputs: [\n { name: 'addr', type: 'address' },\n { name: 'index', type: 'uint256' },\n ],\n outputs: [\n { name: 'fingerprint', type: 'string' },\n { name: 'createdAt', type: 'uint256' },\n { name: 'revoked', type: 'bool' },\n ],\n },\n] as const\n","import { type PublicClient } from 'viem'\nimport { CONTRACT_DEPLOY_BLOCK } from './contract'\n\nconst LOG_CHUNK_SIZE = 49999n\n\nexport async function getLogsChunked(\n client: PublicClient,\n params: {\n address?: `0x${string}`\n event?: any\n args?: Record<string, any>\n fromBlock?: bigint\n toBlock?: bigint | 'latest'\n },\n) {\n const latest = await client.getBlockNumber()\n const fromBlock = params.fromBlock ?? CONTRACT_DEPLOY_BLOCK\n const toBlock = params.toBlock === 'latest' || !params.toBlock ? latest : params.toBlock\n\n const allLogs: any[] = []\n\n for (let start = fromBlock; start <= toBlock; start += LOG_CHUNK_SIZE) {\n const end = start + LOG_CHUNK_SIZE - 1n > toBlock ? toBlock : start + LOG_CHUNK_SIZE - 1n\n const logs = await client.getLogs({\n ...params,\n fromBlock: start,\n toBlock: end,\n })\n allLogs.push(...logs)\n }\n\n return allLogs\n}\n","import type { PGPKeyInfo, PGPVerification } from './types'\n\nexport async function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n const fingerprint = key.getFingerprint().toUpperCase()\n const userIDs = key.users.map((u: any) => u.userID?.userID).filter(Boolean)\n const algorithm = String(key.keyPacket.algorithm)\n const created = key.keyPacket.created?.toISOString() ?? null\n const expiration = await key.getExpirationTime()\n const expires =\n expiration && expiration !== Infinity\n ? new Date(expiration as number).toISOString()\n : null\n\n const notations: { name: string; value: string }[] = []\n const seen = new Set<string>()\n for (const user of key.users) {\n if (!(user as any).selfCertifications) continue\n for (const cert of (user as any).selfCertifications) {\n if (cert.rawNotations) {\n for (const n of cert.rawNotations) {\n const name =\n typeof n.name === 'string' ? n.name : new TextDecoder().decode(n.name)\n const value =\n n.value instanceof Uint8Array\n ? new TextDecoder().decode(n.value)\n : typeof n.value === 'string'\n ? n.value\n : null\n if (value) {\n const key = `${name}:${value}`\n if (!seen.has(key)) {\n seen.add(key)\n notations.push({ name, value })\n }\n }\n }\n }\n }\n }\n\n const subkeys = key.subkeys.map((sk: any) => ({\n algorithm: String(sk.keyPacket.algorithm),\n created: sk.keyPacket.created?.toISOString() ?? null,\n fingerprint: sk.getFingerprint().toUpperCase(),\n }))\n\n return { fingerprint, userIDs, algorithm, created, expires, notations, subkeys }\n } catch {\n return null\n }\n}\n\nexport async function verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress,\n}: {\n pgpPublicKey: string | null\n pgpSignature: string | null\n fingerprint: string\n ethAddress: string\n}): Promise<PGPVerification> {\n try {\n if (!pgpPublicKey || !pgpSignature) {\n return { verified: false, reason: 'Missing PGP data' }\n }\n\n const { readKey, readCleartextMessage, verify } = await import('openpgp')\n\n const publicKey = await readKey({ armoredKey: pgpPublicKey })\n const keyFingerprint = publicKey.getFingerprint().toUpperCase()\n if (keyFingerprint !== fingerprint.toUpperCase()) {\n return { verified: false, reason: 'Key fingerprint mismatch' }\n }\n\n const message = await readCleartextMessage({ cleartextMessage: pgpSignature })\n const { signatures } = await verify({ message, verificationKeys: publicKey })\n await signatures[0].verified\n\n const signedText = message.getText()\n if (!signedText.toLowerCase().includes(ethAddress.toLowerCase())) {\n return { verified: false, reason: 'Signed message does not contain ETH address' }\n }\n\n return { verified: true }\n } catch {\n return { verified: false, reason: 'Signature verification failed' }\n }\n}\n\nconst KEYSERVER_BASE = 'https://keys.openpgp.org/vks/v1'\n\nexport async function fetchKeyByFingerprint(fingerprint: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-fingerprint/${fingerprint}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\n }\n}\n\nexport async function fetchKeyByKeyId(keyId: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-keyid/${keyId}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\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 type { EFPGraph } from './types'\n\nconst EFP_API = 'https://api.ethfollow.xyz/api/v1'\n\nexport async function fetchEFPGraph(address: string): Promise<EFPGraph | null> {\n try {\n const listsResp = await fetch(`${EFP_API}/users/${address}/lists`)\n if (!listsResp.ok) return null\n const listsData = await listsResp.json()\n const listId = listsData.primary_list\n if (!listId) return null\n\n const [followingResp, statsResp, top8Resp] = await Promise.all([\n fetch(`${EFP_API}/lists/${listId}/following?limit=100`),\n fetch(`${EFP_API}/users/${address}/stats`),\n fetch(`${EFP_API}/lists/${listId}/following?limit=8&tags=top8`),\n ])\n\n const followingData = followingResp.ok ? await followingResp.json() : { following: [] }\n const statsData = statsResp.ok ? await statsResp.json() : {}\n const top8Data = top8Resp.ok ? await top8Resp.json() : { following: [] }\n\n return {\n followers: parseInt(statsData.followers_count) || 0,\n following: (followingData.following || []).length,\n top8: (top8Data.following || []).map((f: any) => f.data),\n hasEfp: true,\n }\n } catch {\n return null\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { fetchKeyByFingerprint, 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\nexport function usePGPProofs(fingerprint: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data, isLoading } = useQuery({\n queryKey: ['pgp-proofs', fingerprint],\n queryFn: async (): Promise<{ keyInfo: PGPKeyInfo | null; proofs: ProofResult[] }> => {\n if (!fingerprint) return { keyInfo: null, proofs: [] }\n\n const armoredKey = await fetchKeyByFingerprint(fingerprint)\n if (!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\n const identified = keyInfo.notations\n .map((n) => identifyProof(n))\n .filter((p): p is NonNullable<typeof p> => p !== null)\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 return { keyInfo, proofs }\n },\n enabled: !!fingerprint,\n staleTime: 300_000,\n })\n\n return {\n keyInfo: data?.keyInfo ?? null,\n proofs: data?.proofs ?? [],\n isLoading,\n }\n}\n","import type { Notation, Proof, PGPVerification } from './types'\n\nconst PROVIDERS: {\n provider: string\n label: string\n pattern: RegExp\n parse: (m: RegExpMatchArray) => Record<string, string>\n}[] = [\n {\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/gist\\.github\\.com\\/([^/]+)\\/([a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], gistId: m[2] }),\n },\n {\n provider: 'dns',\n label: 'DNS',\n pattern: /^dns:([^?]+)\\?type=TXT$/i,\n parse: (m) => ({ domain: m[1] }),\n },\n {\n provider: 'farcaster',\n label: 'Farcaster',\n pattern: /^https:\\/\\/farcaster\\.xyz\\/([^/]+)\\/(0x[a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], castHash: m[2] }),\n },\n {\n provider: 'codeberg',\n label: 'Codeberg',\n pattern: /^https:\\/\\/codeberg\\.org\\/([^/]+)\\/([^/]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'mastodon',\n label: 'Mastodon',\n pattern: /^https:\\/\\/([^/]+)\\/@([^/]+)$/i,\n parse: (m) => ({ instance: m[1], user: m[2] }),\n },\n]\n\nexport function identifyProof(notation: Notation): Proof | null {\n if (notation.name !== 'proof@thurin.id') return null\n\n for (const { provider, label, pattern, parse } of PROVIDERS) {\n const m = notation.value.match(pattern)\n if (m) {\n return { provider, label, url: notation.value, ...parse(m) }\n }\n }\n\n return { provider: 'unknown', label: 'Unknown', url: notation.value }\n}\n\nexport function displayUrl(proof: Proof): string {\n if (proof.provider === 'dns') return proof.domain!\n if (proof.provider === 'github') return proof.user!\n if (proof.provider === 'farcaster') return `@${proof.user}`\n if (proof.provider === 'codeberg') return proof.user!\n if (proof.provider === 'mastodon') return `@${proof.user}@${proof.instance}`\n return proof.url\n}\n\nexport function proofHref(proof: Proof): string | null {\n if (proof.provider === 'dns') return `https://${proof.domain}`\n if (proof.provider === 'github') return `https://github.com/${proof.user}`\n if (proof.provider === 'farcaster') return `https://farcaster.xyz/${proof.user}`\n if (proof.provider === 'codeberg') return `https://codeberg.org/${proof.user}`\n if (proof.provider === 'mastodon') return `https://${proof.instance}/@${proof.user}`\n if (proof.url.startsWith('http')) return proof.url\n return null\n}\n\nexport function proofSecondaryHref(proof: Proof): string | null {\n if (proof.provider === 'github') return proof.url\n if (proof.provider === 'farcaster') return proof.url\n if (proof.provider === 'codeberg') return proof.url\n if (proof.provider === 'mastodon') return proof.url\n return null\n}\n\n// ─── Verification ──────────────────────────────────────────────────────────\n\nconst FPR_TOKEN = 'OPENPGP4FPR:'\n\nfunction containsFingerprint(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(FPR_TOKEN + fingerprint.toUpperCase())\n}\n\nfunction containsFingerprintUrl(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(fingerprint.toUpperCase())\n}\n\nasync function verifyGitHub(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(`https://api.github.com/gists/${proof.gistId}`)\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n for (const file of Object.values(data.files || {}) as any[]) {\n if (file.content && containsFingerprint(file.content, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in gist' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyDNS(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(proof.domain!)}&type=TXT`,\n { headers: { Accept: 'application/dns-json' } },\n )\n if (!resp.ok) return { verified: false, reason: `DNS query returned ${resp.status}` }\n const data = await resp.json()\n\n for (const answer of data.Answer || []) {\n if (answer.data && containsFingerprint(answer.data, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in TXT records' }\n } catch (err: any) {\n return { verified: false, reason: `DNS fetch failed: ${err.message}` }\n }\n}\n\nconst NEYNAR_HUB = 'https://hub-api.neynar.com'\n\nasync function resolveFid(\n username: string,\n apiKey: string,\n): Promise<number | null> {\n const resp = await fetch(\n `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,\n { headers: { 'x-api-key': apiKey } },\n )\n if (!resp.ok) return null\n const data = await resp.json()\n return data.fid ?? null\n}\n\nasync function verifyFarcaster(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n if (!neynarApiKey) {\n return { verified: false, reason: 'Farcaster verification requires a Neynar API key' }\n }\n\n try {\n const fid = await resolveFid(proof.user!, neynarApiKey)\n if (!fid) return { verified: false, reason: `Could not resolve Farcaster user \"${proof.user}\"` }\n\n const headers = { 'x-api-key': neynarApiKey }\n let pageToken = ''\n for (let page = 0; page < 5; page++) {\n const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ''}`\n const resp = await fetch(url, { headers })\n if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` }\n const data = await resp.json()\n\n for (const msg of data.messages || []) {\n if (msg.hash && msg.hash.startsWith(proof.castHash!)) {\n const text = msg.data?.castAddBody?.text || ''\n if (containsFingerprint(text, fingerprint)) {\n return { verified: true }\n }\n return { verified: false, reason: 'Cast found but fingerprint token not in text' }\n }\n }\n\n if (!data.nextPageToken) break\n pageToken = data.nextPageToken\n }\n\n return { verified: false, reason: 'Cast not found' }\n } catch (err: any) {\n return { verified: false, reason: `Farcaster fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyCodeberg(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://codeberg.org/api/v1/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Codeberg API returned ${resp.status}` }\n const data = await resp.json()\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n\n return { verified: false, reason: 'Fingerprint token not found in repo description' }\n } catch (err: any) {\n return { verified: false, reason: `Codeberg fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyMastodon(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://${proof.instance}/api/v1/accounts/lookup?acct=${encodeURIComponent(proof.user!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Mastodon API returned ${resp.status}` }\n const data = await resp.json()\n\n const keyId = fingerprint.slice(-16)\n\n for (const field of data.fields || []) {\n const text = field.value.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n if (data.note) {\n const text = data.note.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n return { verified: false, reason: 'Fingerprint not found in profile fields or bio' }\n } catch (err: any) {\n return { verified: false, reason: `Mastodon fetch failed: ${err.message}` }\n }\n}\n\ntype Verifier = (proof: Proof, fingerprint: string, neynarApiKey?: string) => Promise<PGPVerification>\n\nconst verifiers: Record<string, Verifier> = {\n github: verifyGitHub,\n dns: verifyDNS,\n farcaster: verifyFarcaster,\n codeberg: verifyCodeberg,\n mastodon: verifyMastodon,\n}\n\nexport async function verifyProof(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n const fn = verifiers[proof.provider]\n if (!fn) return { verified: false, reason: 'Unknown provider' }\n return fn(proof, fingerprint, neynarApiKey)\n}\n","import { useScryIdentity } from '../../hooks/useScryIdentity'\nimport { useIdentityKitConfig } from '../../context'\nimport type { Theme } from '../../core/types'\nimport '../../themes/index.css'\nimport './ScryCard.css'\n\nfunction ThurinLogo() {\n return (\n <svg className=\"scry-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(--scry-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 ScryCardProps {\n ens?: string\n address?: string\n theme?: Theme\n}\n\nexport function ScryCard({ ens, address, theme = 'thurin' }: ScryCardProps) {\n const input = ens || address\n const identity = useScryIdentity(input)\n const config = useIdentityKitConfig()\n\n const scryUrl = identity.address\n ? `${config.scryBaseUrl}/eth/${identity.address}`\n : ens\n ? `${config.scryBaseUrl}/ens/${ens}`\n : null\n\n if (identity.isLoading) {\n return (\n <div className=\"scry-card\" data-scry-theme={theme}>\n <div className=\"scry-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=\"scry-card\" data-scry-theme={theme}>\n <a className=\"scry-card-header\" href={scryUrl || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n {identity.ensAvatar ? (\n <img\n className=\"scry-card-avatar\"\n src={identity.ensAvatar}\n alt={identity.ensName || ''}\n />\n ) : (\n <ThurinLogo />\n )}\n <div>\n {identity.ensName && (\n <div className=\"scry-card-name\">{identity.ensName}</div>\n )}\n {displayAddress && (\n <div className=\"scry-card-address\">{displayAddress}</div>\n )}\n </div>\n </a>\n\n <div className=\"scry-card-stats\">\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{identity.activeClaims}</span>\n <span className=\"scry-card-stat-label\">Seals</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{verifiedProofs}</span>\n <span className=\"scry-card-stat-label\">Proofs</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">\n {identity.efp?.followers ?? 0}\n </span>\n <span className=\"scry-card-stat-label\">Followers</span>\n </div>\n </div>\n\n <div className=\"scry-card-badges\">\n {hasVerifiedPgp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">PGP Verified</span>\n )}\n {identity.efp?.hasEfp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">EFP</span>\n )}\n {identity.proofs.map((p, i) => (\n <span\n key={i}\n className={`scry-card-badge scry-card-badge--${p.status === 'verified' ? 'verified' : 'unverified'}`}\n >\n {p.label}\n </span>\n ))}\n </div>\n\n {scryUrl && (\n <a\n className=\"scry-card-link\"\n href={scryUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on Scry\n </a>\n )}\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["/Users/benwoodall/Development/thurinlabs/identity-kit/dist/index.cjs","../src/provider.tsx","../src/context.ts","../src/hooks/useScryIdentity.ts","../src/hooks/useSignetClaims.ts","../src/core/contract.ts","../src/core/logs.ts","../src/core/pgp.ts","../src/hooks/useEFPGraph.ts","../src/core/efp.ts","../src/hooks/usePGPProofs.ts","../src/core/proofs.ts","../src/components/ScryCard/ScryCard.tsx"],"names":["key","mainnet","useQuery","jsx"],"mappings":"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","file":"/Users/benwoodall/Development/thurinlabs/identity-kit/dist/index.cjs","sourcesContent":[null,"import { type ReactNode, useMemo } from 'react'\nimport { WagmiProvider, createConfig, http, useConfig } from 'wagmi'\nimport { mainnet } from 'wagmi/chains'\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\nfunction createDefaultWagmiConfig(rpcUrl?: string) {\n return createConfig({\n chains: [mainnet],\n transports: {\n [mainnet.id]: http(rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n },\n })\n}\n\nfunction WagmiDetector({ children, rpcUrl }: { children: ReactNode; rpcUrl?: string }) {\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), [rpcUrl])\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 scryBaseUrl = 'https://thurin.id',\n}: IdentityKitProviderProps) {\n const config = useMemo(\n () => ({ rpcUrl, neynarApiKey, scryBaseUrl }),\n [rpcUrl, neynarApiKey, scryBaseUrl],\n )\n\n return (\n <IdentityKitContext.Provider value={config}>\n <WagmiDetector rpcUrl={rpcUrl}>\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 scryBaseUrl: 'https://thurin.id',\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 { mainnet } from 'wagmi/chains'\nimport { normalize } from 'viem/ens'\nimport { useSignetClaims } from './useSignetClaims'\nimport { useEFPGraph } from './useEFPGraph'\nimport { usePGPProofs } from './usePGPProofs'\nimport type { ScryIdentity } 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 useScryIdentity(ensOrAddress: string | undefined | null): ScryIdentity {\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: mainnet.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: mainnet.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: mainnet.id,\n query: { enabled: !!displayName },\n })\n\n // Signet claims\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\n } = useSignetClaims(address)\n\n // PGP proofs (from current fingerprint)\n const {\n keyInfo: pgpKeyInfo,\n proofs,\n isLoading: proofsLoading,\n } = usePGPProofs(currentFingerprint)\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 { mainnet } from 'wagmi/chains'\nimport { useQuery } from '@tanstack/react-query'\nimport { createPublicClient, http, parseAbiItem } from 'viem'\nimport { REGISTRY_ADDRESS, REGISTRY_ABI, CONTRACT_DEPLOY_BLOCK } from '../core/contract'\nimport { getLogsChunked } from '../core/logs'\nimport { verifyAttestation } from '../core/pgp'\nimport { useIdentityKitConfig } from '../context'\nimport type { SignetClaim } from '../core/types'\n\nexport function useSignetClaims(address: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data: count, isLoading: countLoading } = useReadContract({\n address: REGISTRY_ADDRESS,\n abi: REGISTRY_ABI,\n functionName: 'attestationCount',\n args: address ? [address as `0x${string}`] : undefined,\n chainId: mainnet.id,\n query: { enabled: !!address },\n })\n\n const attestationCount = count ? Number(count) : 0\n\n const contracts = address\n ? Array.from({ length: attestationCount }, (_, i) => ({\n address: REGISTRY_ADDRESS as `0x${string}`,\n abi: REGISTRY_ABI,\n functionName: 'getAttestation' as const,\n args: [address as `0x${string}`, BigInt(i)] as const,\n chainId: mainnet.id,\n }))\n : []\n\n const { data: attestations, isLoading: attestationsLoading } = useReadContracts({\n contracts,\n query: { enabled: contracts.length > 0 },\n })\n\n // Fetch event logs for PGP data (signature + public key not available from contract reads)\n const { data: eventData } = useQuery({\n queryKey: ['signet-logs', address],\n queryFn: async () => {\n if (!address) return []\n const client = createPublicClient({\n chain: mainnet,\n transport: http(config.rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n })\n const event = parseAbiItem(\n 'event Attested(address indexed ethAddress, string indexed fingerprintHash, string fingerprint, string pgpSignature, string pgpPublicKey, uint256 index, uint256 timestamp)',\n )\n return getLogsChunked(client, {\n address: REGISTRY_ADDRESS,\n event,\n args: { ethAddress: address as `0x${string}` },\n fromBlock: CONTRACT_DEPLOY_BLOCK,\n toBlock: 'latest',\n })\n },\n enabled: !!address && attestationCount > 0,\n staleTime: 300_000,\n })\n\n // Combine attestation data with event log data and verify\n const { data: claims, isLoading: verifyLoading } = useQuery({\n queryKey: ['signet-claims', address, attestationCount, !!eventData],\n queryFn: async (): Promise<SignetClaim[]> => {\n if (!attestations || !address) return []\n\n const results: SignetClaim[] = []\n\n for (let i = 0; i < attestations.length; i++) {\n const att = attestations[i]\n if (att.status !== 'success') continue\n\n const [fingerprint, createdAt, revoked] = att.result as [string, bigint, boolean]\n const log = (eventData || [])[i]\n\n const pgpSignature = log?.args?.pgpSignature ?? null\n const pgpPublicKey = log?.args?.pgpPublicKey ?? null\n const txHash = log?.transactionHash ?? null\n\n let verification = null\n if (pgpPublicKey && pgpSignature) {\n verification = await verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress: address,\n })\n }\n\n results.push({\n index: i,\n fingerprint,\n createdAt: Number(createdAt),\n revoked,\n pgpSignature,\n pgpPublicKey,\n txHash,\n verification,\n })\n }\n\n return results\n },\n enabled: !!attestations && attestations.length > 0,\n staleTime: 300_000,\n })\n\n const isLoading = countLoading || attestationsLoading || verifyLoading\n\n const activeClaims = (claims || []).filter((c) => !c.revoked)\n const currentFingerprint = activeClaims.length > 0\n ? activeClaims[activeClaims.length - 1].fingerprint\n : null\n\n return {\n claims: claims || [],\n totalClaims: attestationCount,\n activeClaims: activeClaims.length,\n currentFingerprint,\n isLoading,\n }\n}\n","export const REGISTRY_ADDRESS = '0xf7a45BC662A78a6fb417ED5f52b3766cbf13EbBb' as const\n\nexport const CONTRACT_DEPLOY_BLOCK = 24515891n\n\nexport const REGISTRY_ABI = [\n {\n name: 'Attested',\n type: 'event',\n inputs: [\n { name: 'ethAddress', type: 'address', indexed: true },\n { name: 'fingerprintHash', type: 'string', indexed: true },\n { name: 'fingerprint', type: 'string', indexed: false },\n { name: 'pgpSignature', type: 'string', indexed: false },\n { name: 'pgpPublicKey', type: 'string', indexed: false },\n { name: 'index', type: 'uint256', indexed: false },\n { name: 'timestamp', type: 'uint256', indexed: false },\n ],\n },\n {\n name: 'attestationCount',\n type: 'function',\n stateMutability: 'view',\n inputs: [{ name: 'addr', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n name: 'getAttestation',\n type: 'function',\n stateMutability: 'view',\n inputs: [\n { name: 'addr', type: 'address' },\n { name: 'index', type: 'uint256' },\n ],\n outputs: [\n { name: 'fingerprint', type: 'string' },\n { name: 'createdAt', type: 'uint256' },\n { name: 'revoked', type: 'bool' },\n ],\n },\n] as const\n","import { type PublicClient } from 'viem'\nimport { CONTRACT_DEPLOY_BLOCK } from './contract'\n\nconst LOG_CHUNK_SIZE = 49999n\n\nexport async function getLogsChunked(\n client: PublicClient,\n params: {\n address?: `0x${string}`\n event?: any\n args?: Record<string, any>\n fromBlock?: bigint\n toBlock?: bigint | 'latest'\n },\n) {\n const latest = await client.getBlockNumber()\n const fromBlock = params.fromBlock ?? CONTRACT_DEPLOY_BLOCK\n const toBlock = params.toBlock === 'latest' || !params.toBlock ? latest : params.toBlock\n\n const allLogs: any[] = []\n\n for (let start = fromBlock; start <= toBlock; start += LOG_CHUNK_SIZE) {\n const end = start + LOG_CHUNK_SIZE - 1n > toBlock ? toBlock : start + LOG_CHUNK_SIZE - 1n\n const logs = await client.getLogs({\n ...params,\n fromBlock: start,\n toBlock: end,\n })\n allLogs.push(...logs)\n }\n\n return allLogs\n}\n","import type { PGPKeyInfo, PGPVerification } from './types'\n\nexport async function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n const fingerprint = key.getFingerprint().toUpperCase()\n const userIDs = key.users.map((u: any) => u.userID?.userID).filter(Boolean)\n const algorithm = String(key.keyPacket.algorithm)\n const created = key.keyPacket.created?.toISOString() ?? null\n const expiration = await key.getExpirationTime()\n const expires =\n expiration && expiration !== Infinity\n ? new Date(expiration as number).toISOString()\n : null\n\n const notations: { name: string; value: string }[] = []\n const seen = new Set<string>()\n for (const user of key.users) {\n if (!(user as any).selfCertifications) continue\n for (const cert of (user as any).selfCertifications) {\n if (cert.rawNotations) {\n for (const n of cert.rawNotations) {\n const name =\n typeof n.name === 'string' ? n.name : new TextDecoder().decode(n.name)\n const value =\n n.value instanceof Uint8Array\n ? new TextDecoder().decode(n.value)\n : typeof n.value === 'string'\n ? n.value\n : null\n if (value) {\n const key = `${name}:${value}`\n if (!seen.has(key)) {\n seen.add(key)\n notations.push({ name, value })\n }\n }\n }\n }\n }\n }\n\n const subkeys = key.subkeys.map((sk: any) => ({\n algorithm: String(sk.keyPacket.algorithm),\n created: sk.keyPacket.created?.toISOString() ?? null,\n fingerprint: sk.getFingerprint().toUpperCase(),\n }))\n\n return { fingerprint, userIDs, algorithm, created, expires, notations, subkeys }\n } catch {\n return null\n }\n}\n\nexport async function verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress,\n}: {\n pgpPublicKey: string | null\n pgpSignature: string | null\n fingerprint: string\n ethAddress: string\n}): Promise<PGPVerification> {\n try {\n if (!pgpPublicKey || !pgpSignature) {\n return { verified: false, reason: 'Missing PGP data' }\n }\n\n const { readKey, readCleartextMessage, verify } = await import('openpgp')\n\n const publicKey = await readKey({ armoredKey: pgpPublicKey })\n const keyFingerprint = publicKey.getFingerprint().toUpperCase()\n if (keyFingerprint !== fingerprint.toUpperCase()) {\n return { verified: false, reason: 'Key fingerprint mismatch' }\n }\n\n const message = await readCleartextMessage({ cleartextMessage: pgpSignature })\n const { signatures } = await verify({ message, verificationKeys: publicKey })\n await signatures[0].verified\n\n const signedText = message.getText()\n if (!signedText.toLowerCase().includes(ethAddress.toLowerCase())) {\n return { verified: false, reason: 'Signed message does not contain ETH address' }\n }\n\n return { verified: true }\n } catch {\n return { verified: false, reason: 'Signature verification failed' }\n }\n}\n\nconst KEYSERVER_BASE = 'https://keys.openpgp.org/vks/v1'\n\nexport async function fetchKeyByFingerprint(fingerprint: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-fingerprint/${fingerprint}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\n }\n}\n\nexport async function fetchKeyByKeyId(keyId: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-keyid/${keyId}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\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 type { EFPGraph } from './types'\n\nconst EFP_API = 'https://api.ethfollow.xyz/api/v1'\n\nexport async function fetchEFPGraph(address: string): Promise<EFPGraph | null> {\n try {\n const listsResp = await fetch(`${EFP_API}/users/${address}/lists`)\n if (!listsResp.ok) return null\n const listsData = await listsResp.json()\n const listId = listsData.primary_list\n if (!listId) return null\n\n const [followingResp, statsResp, top8Resp] = await Promise.all([\n fetch(`${EFP_API}/lists/${listId}/following?limit=100`),\n fetch(`${EFP_API}/users/${address}/stats`),\n fetch(`${EFP_API}/lists/${listId}/following?limit=8&tags=top8`),\n ])\n\n const followingData = followingResp.ok ? await followingResp.json() : { following: [] }\n const statsData = statsResp.ok ? await statsResp.json() : {}\n const top8Data = top8Resp.ok ? await top8Resp.json() : { following: [] }\n\n return {\n followers: parseInt(statsData.followers_count) || 0,\n following: (followingData.following || []).length,\n top8: (top8Data.following || []).map((f: any) => f.data),\n hasEfp: true,\n }\n } catch {\n return null\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { fetchKeyByFingerprint, 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\nexport function usePGPProofs(fingerprint: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data, isLoading } = useQuery({\n queryKey: ['pgp-proofs', fingerprint],\n queryFn: async (): Promise<{ keyInfo: PGPKeyInfo | null; proofs: ProofResult[] }> => {\n if (!fingerprint) return { keyInfo: null, proofs: [] }\n\n const armoredKey = await fetchKeyByFingerprint(fingerprint)\n if (!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\n const identified = keyInfo.notations\n .map((n) => identifyProof(n))\n .filter((p): p is NonNullable<typeof p> => p !== null)\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 return { keyInfo, proofs }\n },\n enabled: !!fingerprint,\n staleTime: 300_000,\n })\n\n return {\n keyInfo: data?.keyInfo ?? null,\n proofs: data?.proofs ?? [],\n isLoading,\n }\n}\n","import type { Notation, Proof, PGPVerification } from './types'\n\nconst PROVIDERS: {\n provider: string\n label: string\n pattern: RegExp\n parse: (m: RegExpMatchArray) => Record<string, string>\n}[] = [\n {\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/gist\\.github\\.com\\/([^/]+)\\/([a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], gistId: m[2] }),\n },\n {\n provider: 'dns',\n label: 'DNS',\n pattern: /^dns:([^?]+)\\?type=TXT$/i,\n parse: (m) => ({ domain: m[1] }),\n },\n {\n provider: 'farcaster',\n label: 'Farcaster',\n pattern: /^https:\\/\\/farcaster\\.xyz\\/([^/]+)\\/(0x[a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], castHash: m[2] }),\n },\n {\n provider: 'codeberg',\n label: 'Codeberg',\n pattern: /^https:\\/\\/codeberg\\.org\\/([^/]+)\\/([^/]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'mastodon',\n label: 'Mastodon',\n pattern: /^https:\\/\\/([^/]+)\\/@([^/]+)$/i,\n parse: (m) => ({ instance: m[1], user: m[2] }),\n },\n]\n\nconst ACCEPTED_NAMESPACES = new Set(['proof@thurin.id', 'proof@ariadne.id'])\n\nexport function identifyProof(notation: Notation): Proof | null {\n if (!ACCEPTED_NAMESPACES.has(notation.name)) return null\n\n for (const { provider, label, pattern, parse } of PROVIDERS) {\n const m = notation.value.match(pattern)\n if (m) {\n return { provider, label, url: notation.value, ...parse(m) }\n }\n }\n\n return { provider: 'unknown', label: 'Unknown', url: notation.value }\n}\n\nexport function displayUrl(proof: Proof): string {\n if (proof.provider === 'dns') return proof.domain!\n if (proof.provider === 'github') return proof.user!\n if (proof.provider === 'farcaster') return `@${proof.user}`\n if (proof.provider === 'codeberg') return proof.user!\n if (proof.provider === 'mastodon') return `@${proof.user}@${proof.instance}`\n return proof.url\n}\n\nexport function proofHref(proof: Proof): string | null {\n if (proof.provider === 'dns') return `https://${proof.domain}`\n if (proof.provider === 'github') return `https://github.com/${proof.user}`\n if (proof.provider === 'farcaster') return `https://farcaster.xyz/${proof.user}`\n if (proof.provider === 'codeberg') return `https://codeberg.org/${proof.user}`\n if (proof.provider === 'mastodon') return `https://${proof.instance}/@${proof.user}`\n if (proof.url.startsWith('http')) return proof.url\n return null\n}\n\nexport function proofSecondaryHref(proof: Proof): string | null {\n if (proof.provider === 'github') return proof.url\n if (proof.provider === 'farcaster') return proof.url\n if (proof.provider === 'codeberg') return proof.url\n if (proof.provider === 'mastodon') return proof.url\n return null\n}\n\n// ─── Verification ──────────────────────────────────────────────────────────\n\nconst FPR_TOKEN = 'OPENPGP4FPR:'\n\nfunction containsFingerprint(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(FPR_TOKEN + fingerprint.toUpperCase())\n}\n\nfunction containsFingerprintUrl(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(fingerprint.toUpperCase())\n}\n\nasync function verifyGitHub(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(`https://api.github.com/gists/${proof.gistId}`)\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n for (const file of Object.values(data.files || {}) as any[]) {\n if (file.content && containsFingerprint(file.content, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in gist' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyDNS(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(proof.domain!)}&type=TXT`,\n { headers: { Accept: 'application/dns-json' } },\n )\n if (!resp.ok) return { verified: false, reason: `DNS query returned ${resp.status}` }\n const data = await resp.json()\n\n for (const answer of data.Answer || []) {\n if (answer.data && containsFingerprint(answer.data, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in TXT records' }\n } catch (err: any) {\n return { verified: false, reason: `DNS fetch failed: ${err.message}` }\n }\n}\n\nconst NEYNAR_HUB = 'https://hub-api.neynar.com'\n\nasync function resolveFid(\n username: string,\n apiKey: string,\n): Promise<number | null> {\n const resp = await fetch(\n `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,\n { headers: { 'x-api-key': apiKey } },\n )\n if (!resp.ok) return null\n const data = await resp.json()\n return data.fid ?? null\n}\n\nasync function verifyFarcaster(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n if (!neynarApiKey) {\n return { verified: false, reason: 'Farcaster verification requires a Neynar API key' }\n }\n\n try {\n const fid = await resolveFid(proof.user!, neynarApiKey)\n if (!fid) return { verified: false, reason: `Could not resolve Farcaster user \"${proof.user}\"` }\n\n const headers = { 'x-api-key': neynarApiKey }\n let pageToken = ''\n for (let page = 0; page < 5; page++) {\n const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ''}`\n const resp = await fetch(url, { headers })\n if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` }\n const data = await resp.json()\n\n for (const msg of data.messages || []) {\n if (msg.hash && msg.hash.startsWith(proof.castHash!)) {\n const text = msg.data?.castAddBody?.text || ''\n if (containsFingerprint(text, fingerprint)) {\n return { verified: true }\n }\n return { verified: false, reason: 'Cast found but fingerprint token not in text' }\n }\n }\n\n if (!data.nextPageToken) break\n pageToken = data.nextPageToken\n }\n\n return { verified: false, reason: 'Cast not found' }\n } catch (err: any) {\n return { verified: false, reason: `Farcaster fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyCodeberg(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://codeberg.org/api/v1/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Codeberg API returned ${resp.status}` }\n const data = await resp.json()\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n\n return { verified: false, reason: 'Fingerprint token not found in repo description' }\n } catch (err: any) {\n return { verified: false, reason: `Codeberg fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyMastodon(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://${proof.instance}/api/v1/accounts/lookup?acct=${encodeURIComponent(proof.user!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Mastodon API returned ${resp.status}` }\n const data = await resp.json()\n\n const keyId = fingerprint.slice(-16)\n\n for (const field of data.fields || []) {\n const text = field.value.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n if (data.note) {\n const text = data.note.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n return { verified: false, reason: 'Fingerprint not found in profile fields or bio' }\n } catch (err: any) {\n return { verified: false, reason: `Mastodon fetch failed: ${err.message}` }\n }\n}\n\ntype Verifier = (proof: Proof, fingerprint: string, neynarApiKey?: string) => Promise<PGPVerification>\n\nconst verifiers: Record<string, Verifier> = {\n github: verifyGitHub,\n dns: verifyDNS,\n farcaster: verifyFarcaster,\n codeberg: verifyCodeberg,\n mastodon: verifyMastodon,\n}\n\nexport async function verifyProof(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n const fn = verifiers[proof.provider]\n if (!fn) return { verified: false, reason: 'Unknown provider' }\n return fn(proof, fingerprint, neynarApiKey)\n}\n","import { useScryIdentity } from '../../hooks/useScryIdentity'\nimport { useIdentityKitConfig } from '../../context'\nimport type { Theme } from '../../core/types'\nimport '../../themes/index.css'\nimport './ScryCard.css'\n\nfunction ThurinLogo() {\n return (\n <svg className=\"scry-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(--scry-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 ScryCardProps {\n ens?: string\n address?: string\n theme?: Theme\n}\n\nexport function ScryCard({ ens, address, theme = 'thurin' }: ScryCardProps) {\n const input = ens || address\n const identity = useScryIdentity(input)\n const config = useIdentityKitConfig()\n\n const scryUrl = identity.address\n ? `${config.scryBaseUrl}/eth/${identity.address}`\n : ens\n ? `${config.scryBaseUrl}/ens/${ens}`\n : null\n\n if (identity.isLoading) {\n return (\n <div className=\"scry-card\" data-scry-theme={theme}>\n <div className=\"scry-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=\"scry-card\" data-scry-theme={theme}>\n <a className=\"scry-card-header\" href={scryUrl || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n {identity.ensAvatar ? (\n <img\n className=\"scry-card-avatar\"\n src={identity.ensAvatar}\n alt={identity.ensName || ''}\n />\n ) : (\n <ThurinLogo />\n )}\n <div>\n {identity.ensName && (\n <div className=\"scry-card-name\">{identity.ensName}</div>\n )}\n {displayAddress && (\n <div className=\"scry-card-address\">{displayAddress}</div>\n )}\n </div>\n </a>\n\n <div className=\"scry-card-stats\">\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{identity.activeClaims}</span>\n <span className=\"scry-card-stat-label\">Seals</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{verifiedProofs}</span>\n <span className=\"scry-card-stat-label\">Proofs</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">\n {identity.efp?.followers ?? 0}\n </span>\n <span className=\"scry-card-stat-label\">Followers</span>\n </div>\n </div>\n\n <div className=\"scry-card-badges\">\n {hasVerifiedPgp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">PGP Verified</span>\n )}\n {identity.efp?.hasEfp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">EFP</span>\n )}\n {identity.proofs.map((p, i) => (\n <span\n key={i}\n className={`scry-card-badge scry-card-badge--${p.status === 'verified' ? 'verified' : 'unverified'}`}\n >\n {p.label}\n </span>\n ))}\n </div>\n\n {scryUrl && (\n <a\n className=\"scry-card-link\"\n href={scryUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on Scry\n </a>\n )}\n </div>\n )\n}\n"]}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
7
7
  // src/context.ts
8
8
  import { createContext, useContext } from "react";
9
9
  var defaultConfig = {
10
- scryBaseUrl: "https://scry.thurin.id"
10
+ scryBaseUrl: "https://thurin.id"
11
11
  };
12
12
  var IdentityKitContext = createContext(defaultConfig);
13
13
  function useIdentityKitConfig() {
@@ -49,7 +49,7 @@ function IdentityKitProvider({
49
49
  children,
50
50
  rpcUrl,
51
51
  neynarApiKey,
52
- scryBaseUrl = "https://scry.thurin.id"
52
+ scryBaseUrl = "https://thurin.id"
53
53
  }) {
54
54
  const config = useMemo(
55
55
  () => ({ rpcUrl, neynarApiKey, scryBaseUrl }),
@@ -393,8 +393,9 @@ var PROVIDERS = [
393
393
  parse: (m) => ({ instance: m[1], user: m[2] })
394
394
  }
395
395
  ];
396
+ var ACCEPTED_NAMESPACES = /* @__PURE__ */ new Set(["proof@thurin.id", "proof@ariadne.id"]);
396
397
  function identifyProof(notation) {
397
- if (notation.name !== "proof@thurin.id") return null;
398
+ if (!ACCEPTED_NAMESPACES.has(notation.name)) return null;
398
399
  for (const { provider, label, pattern, parse } of PROVIDERS) {
399
400
  const m = notation.value.match(pattern);
400
401
  if (m) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/hooks/useScryIdentity.ts","../src/hooks/useSignetClaims.ts","../src/core/contract.ts","../src/core/logs.ts","../src/core/pgp.ts","../src/hooks/useEFPGraph.ts","../src/core/efp.ts","../src/hooks/usePGPProofs.ts","../src/core/proofs.ts","../src/components/ScryCard/ScryCard.tsx"],"sourcesContent":["import { type ReactNode, useMemo } from 'react'\nimport { WagmiProvider, createConfig, http, useConfig } from 'wagmi'\nimport { mainnet } from 'wagmi/chains'\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\nfunction createDefaultWagmiConfig(rpcUrl?: string) {\n return createConfig({\n chains: [mainnet],\n transports: {\n [mainnet.id]: http(rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n },\n })\n}\n\nfunction WagmiDetector({ children, rpcUrl }: { children: ReactNode; rpcUrl?: string }) {\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), [rpcUrl])\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 scryBaseUrl = 'https://scry.thurin.id',\n}: IdentityKitProviderProps) {\n const config = useMemo(\n () => ({ rpcUrl, neynarApiKey, scryBaseUrl }),\n [rpcUrl, neynarApiKey, scryBaseUrl],\n )\n\n return (\n <IdentityKitContext.Provider value={config}>\n <WagmiDetector rpcUrl={rpcUrl}>\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 scryBaseUrl: 'https://scry.thurin.id',\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 { mainnet } from 'wagmi/chains'\nimport { normalize } from 'viem/ens'\nimport { useSignetClaims } from './useSignetClaims'\nimport { useEFPGraph } from './useEFPGraph'\nimport { usePGPProofs } from './usePGPProofs'\nimport type { ScryIdentity } 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 useScryIdentity(ensOrAddress: string | undefined | null): ScryIdentity {\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: mainnet.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: mainnet.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: mainnet.id,\n query: { enabled: !!displayName },\n })\n\n // Signet claims\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\n } = useSignetClaims(address)\n\n // PGP proofs (from current fingerprint)\n const {\n keyInfo: pgpKeyInfo,\n proofs,\n isLoading: proofsLoading,\n } = usePGPProofs(currentFingerprint)\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 { mainnet } from 'wagmi/chains'\nimport { useQuery } from '@tanstack/react-query'\nimport { createPublicClient, http, parseAbiItem } from 'viem'\nimport { REGISTRY_ADDRESS, REGISTRY_ABI, CONTRACT_DEPLOY_BLOCK } from '../core/contract'\nimport { getLogsChunked } from '../core/logs'\nimport { verifyAttestation } from '../core/pgp'\nimport { useIdentityKitConfig } from '../context'\nimport type { SignetClaim } from '../core/types'\n\nexport function useSignetClaims(address: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data: count, isLoading: countLoading } = useReadContract({\n address: REGISTRY_ADDRESS,\n abi: REGISTRY_ABI,\n functionName: 'attestationCount',\n args: address ? [address as `0x${string}`] : undefined,\n chainId: mainnet.id,\n query: { enabled: !!address },\n })\n\n const attestationCount = count ? Number(count) : 0\n\n const contracts = address\n ? Array.from({ length: attestationCount }, (_, i) => ({\n address: REGISTRY_ADDRESS as `0x${string}`,\n abi: REGISTRY_ABI,\n functionName: 'getAttestation' as const,\n args: [address as `0x${string}`, BigInt(i)] as const,\n chainId: mainnet.id,\n }))\n : []\n\n const { data: attestations, isLoading: attestationsLoading } = useReadContracts({\n contracts,\n query: { enabled: contracts.length > 0 },\n })\n\n // Fetch event logs for PGP data (signature + public key not available from contract reads)\n const { data: eventData } = useQuery({\n queryKey: ['signet-logs', address],\n queryFn: async () => {\n if (!address) return []\n const client = createPublicClient({\n chain: mainnet,\n transport: http(config.rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n })\n const event = parseAbiItem(\n 'event Attested(address indexed ethAddress, string indexed fingerprintHash, string fingerprint, string pgpSignature, string pgpPublicKey, uint256 index, uint256 timestamp)',\n )\n return getLogsChunked(client, {\n address: REGISTRY_ADDRESS,\n event,\n args: { ethAddress: address as `0x${string}` },\n fromBlock: CONTRACT_DEPLOY_BLOCK,\n toBlock: 'latest',\n })\n },\n enabled: !!address && attestationCount > 0,\n staleTime: 300_000,\n })\n\n // Combine attestation data with event log data and verify\n const { data: claims, isLoading: verifyLoading } = useQuery({\n queryKey: ['signet-claims', address, attestationCount, !!eventData],\n queryFn: async (): Promise<SignetClaim[]> => {\n if (!attestations || !address) return []\n\n const results: SignetClaim[] = []\n\n for (let i = 0; i < attestations.length; i++) {\n const att = attestations[i]\n if (att.status !== 'success') continue\n\n const [fingerprint, createdAt, revoked] = att.result as [string, bigint, boolean]\n const log = (eventData || [])[i]\n\n const pgpSignature = log?.args?.pgpSignature ?? null\n const pgpPublicKey = log?.args?.pgpPublicKey ?? null\n const txHash = log?.transactionHash ?? null\n\n let verification = null\n if (pgpPublicKey && pgpSignature) {\n verification = await verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress: address,\n })\n }\n\n results.push({\n index: i,\n fingerprint,\n createdAt: Number(createdAt),\n revoked,\n pgpSignature,\n pgpPublicKey,\n txHash,\n verification,\n })\n }\n\n return results\n },\n enabled: !!attestations && attestations.length > 0,\n staleTime: 300_000,\n })\n\n const isLoading = countLoading || attestationsLoading || verifyLoading\n\n const activeClaims = (claims || []).filter((c) => !c.revoked)\n const currentFingerprint = activeClaims.length > 0\n ? activeClaims[activeClaims.length - 1].fingerprint\n : null\n\n return {\n claims: claims || [],\n totalClaims: attestationCount,\n activeClaims: activeClaims.length,\n currentFingerprint,\n isLoading,\n }\n}\n","export const REGISTRY_ADDRESS = '0xf7a45BC662A78a6fb417ED5f52b3766cbf13EbBb' as const\n\nexport const CONTRACT_DEPLOY_BLOCK = 24515891n\n\nexport const REGISTRY_ABI = [\n {\n name: 'Attested',\n type: 'event',\n inputs: [\n { name: 'ethAddress', type: 'address', indexed: true },\n { name: 'fingerprintHash', type: 'string', indexed: true },\n { name: 'fingerprint', type: 'string', indexed: false },\n { name: 'pgpSignature', type: 'string', indexed: false },\n { name: 'pgpPublicKey', type: 'string', indexed: false },\n { name: 'index', type: 'uint256', indexed: false },\n { name: 'timestamp', type: 'uint256', indexed: false },\n ],\n },\n {\n name: 'attestationCount',\n type: 'function',\n stateMutability: 'view',\n inputs: [{ name: 'addr', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n name: 'getAttestation',\n type: 'function',\n stateMutability: 'view',\n inputs: [\n { name: 'addr', type: 'address' },\n { name: 'index', type: 'uint256' },\n ],\n outputs: [\n { name: 'fingerprint', type: 'string' },\n { name: 'createdAt', type: 'uint256' },\n { name: 'revoked', type: 'bool' },\n ],\n },\n] as const\n","import { type PublicClient } from 'viem'\nimport { CONTRACT_DEPLOY_BLOCK } from './contract'\n\nconst LOG_CHUNK_SIZE = 49999n\n\nexport async function getLogsChunked(\n client: PublicClient,\n params: {\n address?: `0x${string}`\n event?: any\n args?: Record<string, any>\n fromBlock?: bigint\n toBlock?: bigint | 'latest'\n },\n) {\n const latest = await client.getBlockNumber()\n const fromBlock = params.fromBlock ?? CONTRACT_DEPLOY_BLOCK\n const toBlock = params.toBlock === 'latest' || !params.toBlock ? latest : params.toBlock\n\n const allLogs: any[] = []\n\n for (let start = fromBlock; start <= toBlock; start += LOG_CHUNK_SIZE) {\n const end = start + LOG_CHUNK_SIZE - 1n > toBlock ? toBlock : start + LOG_CHUNK_SIZE - 1n\n const logs = await client.getLogs({\n ...params,\n fromBlock: start,\n toBlock: end,\n })\n allLogs.push(...logs)\n }\n\n return allLogs\n}\n","import type { PGPKeyInfo, PGPVerification } from './types'\n\nexport async function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n const fingerprint = key.getFingerprint().toUpperCase()\n const userIDs = key.users.map((u: any) => u.userID?.userID).filter(Boolean)\n const algorithm = String(key.keyPacket.algorithm)\n const created = key.keyPacket.created?.toISOString() ?? null\n const expiration = await key.getExpirationTime()\n const expires =\n expiration && expiration !== Infinity\n ? new Date(expiration as number).toISOString()\n : null\n\n const notations: { name: string; value: string }[] = []\n const seen = new Set<string>()\n for (const user of key.users) {\n if (!(user as any).selfCertifications) continue\n for (const cert of (user as any).selfCertifications) {\n if (cert.rawNotations) {\n for (const n of cert.rawNotations) {\n const name =\n typeof n.name === 'string' ? n.name : new TextDecoder().decode(n.name)\n const value =\n n.value instanceof Uint8Array\n ? new TextDecoder().decode(n.value)\n : typeof n.value === 'string'\n ? n.value\n : null\n if (value) {\n const key = `${name}:${value}`\n if (!seen.has(key)) {\n seen.add(key)\n notations.push({ name, value })\n }\n }\n }\n }\n }\n }\n\n const subkeys = key.subkeys.map((sk: any) => ({\n algorithm: String(sk.keyPacket.algorithm),\n created: sk.keyPacket.created?.toISOString() ?? null,\n fingerprint: sk.getFingerprint().toUpperCase(),\n }))\n\n return { fingerprint, userIDs, algorithm, created, expires, notations, subkeys }\n } catch {\n return null\n }\n}\n\nexport async function verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress,\n}: {\n pgpPublicKey: string | null\n pgpSignature: string | null\n fingerprint: string\n ethAddress: string\n}): Promise<PGPVerification> {\n try {\n if (!pgpPublicKey || !pgpSignature) {\n return { verified: false, reason: 'Missing PGP data' }\n }\n\n const { readKey, readCleartextMessage, verify } = await import('openpgp')\n\n const publicKey = await readKey({ armoredKey: pgpPublicKey })\n const keyFingerprint = publicKey.getFingerprint().toUpperCase()\n if (keyFingerprint !== fingerprint.toUpperCase()) {\n return { verified: false, reason: 'Key fingerprint mismatch' }\n }\n\n const message = await readCleartextMessage({ cleartextMessage: pgpSignature })\n const { signatures } = await verify({ message, verificationKeys: publicKey })\n await signatures[0].verified\n\n const signedText = message.getText()\n if (!signedText.toLowerCase().includes(ethAddress.toLowerCase())) {\n return { verified: false, reason: 'Signed message does not contain ETH address' }\n }\n\n return { verified: true }\n } catch {\n return { verified: false, reason: 'Signature verification failed' }\n }\n}\n\nconst KEYSERVER_BASE = 'https://keys.openpgp.org/vks/v1'\n\nexport async function fetchKeyByFingerprint(fingerprint: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-fingerprint/${fingerprint}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\n }\n}\n\nexport async function fetchKeyByKeyId(keyId: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-keyid/${keyId}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\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 type { EFPGraph } from './types'\n\nconst EFP_API = 'https://api.ethfollow.xyz/api/v1'\n\nexport async function fetchEFPGraph(address: string): Promise<EFPGraph | null> {\n try {\n const listsResp = await fetch(`${EFP_API}/users/${address}/lists`)\n if (!listsResp.ok) return null\n const listsData = await listsResp.json()\n const listId = listsData.primary_list\n if (!listId) return null\n\n const [followingResp, statsResp, top8Resp] = await Promise.all([\n fetch(`${EFP_API}/lists/${listId}/following?limit=100`),\n fetch(`${EFP_API}/users/${address}/stats`),\n fetch(`${EFP_API}/lists/${listId}/following?limit=8&tags=top8`),\n ])\n\n const followingData = followingResp.ok ? await followingResp.json() : { following: [] }\n const statsData = statsResp.ok ? await statsResp.json() : {}\n const top8Data = top8Resp.ok ? await top8Resp.json() : { following: [] }\n\n return {\n followers: parseInt(statsData.followers_count) || 0,\n following: (followingData.following || []).length,\n top8: (top8Data.following || []).map((f: any) => f.data),\n hasEfp: true,\n }\n } catch {\n return null\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { fetchKeyByFingerprint, 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\nexport function usePGPProofs(fingerprint: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data, isLoading } = useQuery({\n queryKey: ['pgp-proofs', fingerprint],\n queryFn: async (): Promise<{ keyInfo: PGPKeyInfo | null; proofs: ProofResult[] }> => {\n if (!fingerprint) return { keyInfo: null, proofs: [] }\n\n const armoredKey = await fetchKeyByFingerprint(fingerprint)\n if (!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\n const identified = keyInfo.notations\n .map((n) => identifyProof(n))\n .filter((p): p is NonNullable<typeof p> => p !== null)\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 return { keyInfo, proofs }\n },\n enabled: !!fingerprint,\n staleTime: 300_000,\n })\n\n return {\n keyInfo: data?.keyInfo ?? null,\n proofs: data?.proofs ?? [],\n isLoading,\n }\n}\n","import type { Notation, Proof, PGPVerification } from './types'\n\nconst PROVIDERS: {\n provider: string\n label: string\n pattern: RegExp\n parse: (m: RegExpMatchArray) => Record<string, string>\n}[] = [\n {\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/gist\\.github\\.com\\/([^/]+)\\/([a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], gistId: m[2] }),\n },\n {\n provider: 'dns',\n label: 'DNS',\n pattern: /^dns:([^?]+)\\?type=TXT$/i,\n parse: (m) => ({ domain: m[1] }),\n },\n {\n provider: 'farcaster',\n label: 'Farcaster',\n pattern: /^https:\\/\\/farcaster\\.xyz\\/([^/]+)\\/(0x[a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], castHash: m[2] }),\n },\n {\n provider: 'codeberg',\n label: 'Codeberg',\n pattern: /^https:\\/\\/codeberg\\.org\\/([^/]+)\\/([^/]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'mastodon',\n label: 'Mastodon',\n pattern: /^https:\\/\\/([^/]+)\\/@([^/]+)$/i,\n parse: (m) => ({ instance: m[1], user: m[2] }),\n },\n]\n\nexport function identifyProof(notation: Notation): Proof | null {\n if (notation.name !== 'proof@thurin.id') return null\n\n for (const { provider, label, pattern, parse } of PROVIDERS) {\n const m = notation.value.match(pattern)\n if (m) {\n return { provider, label, url: notation.value, ...parse(m) }\n }\n }\n\n return { provider: 'unknown', label: 'Unknown', url: notation.value }\n}\n\nexport function displayUrl(proof: Proof): string {\n if (proof.provider === 'dns') return proof.domain!\n if (proof.provider === 'github') return proof.user!\n if (proof.provider === 'farcaster') return `@${proof.user}`\n if (proof.provider === 'codeberg') return proof.user!\n if (proof.provider === 'mastodon') return `@${proof.user}@${proof.instance}`\n return proof.url\n}\n\nexport function proofHref(proof: Proof): string | null {\n if (proof.provider === 'dns') return `https://${proof.domain}`\n if (proof.provider === 'github') return `https://github.com/${proof.user}`\n if (proof.provider === 'farcaster') return `https://farcaster.xyz/${proof.user}`\n if (proof.provider === 'codeberg') return `https://codeberg.org/${proof.user}`\n if (proof.provider === 'mastodon') return `https://${proof.instance}/@${proof.user}`\n if (proof.url.startsWith('http')) return proof.url\n return null\n}\n\nexport function proofSecondaryHref(proof: Proof): string | null {\n if (proof.provider === 'github') return proof.url\n if (proof.provider === 'farcaster') return proof.url\n if (proof.provider === 'codeberg') return proof.url\n if (proof.provider === 'mastodon') return proof.url\n return null\n}\n\n// ─── Verification ──────────────────────────────────────────────────────────\n\nconst FPR_TOKEN = 'OPENPGP4FPR:'\n\nfunction containsFingerprint(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(FPR_TOKEN + fingerprint.toUpperCase())\n}\n\nfunction containsFingerprintUrl(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(fingerprint.toUpperCase())\n}\n\nasync function verifyGitHub(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(`https://api.github.com/gists/${proof.gistId}`)\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n for (const file of Object.values(data.files || {}) as any[]) {\n if (file.content && containsFingerprint(file.content, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in gist' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyDNS(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(proof.domain!)}&type=TXT`,\n { headers: { Accept: 'application/dns-json' } },\n )\n if (!resp.ok) return { verified: false, reason: `DNS query returned ${resp.status}` }\n const data = await resp.json()\n\n for (const answer of data.Answer || []) {\n if (answer.data && containsFingerprint(answer.data, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in TXT records' }\n } catch (err: any) {\n return { verified: false, reason: `DNS fetch failed: ${err.message}` }\n }\n}\n\nconst NEYNAR_HUB = 'https://hub-api.neynar.com'\n\nasync function resolveFid(\n username: string,\n apiKey: string,\n): Promise<number | null> {\n const resp = await fetch(\n `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,\n { headers: { 'x-api-key': apiKey } },\n )\n if (!resp.ok) return null\n const data = await resp.json()\n return data.fid ?? null\n}\n\nasync function verifyFarcaster(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n if (!neynarApiKey) {\n return { verified: false, reason: 'Farcaster verification requires a Neynar API key' }\n }\n\n try {\n const fid = await resolveFid(proof.user!, neynarApiKey)\n if (!fid) return { verified: false, reason: `Could not resolve Farcaster user \"${proof.user}\"` }\n\n const headers = { 'x-api-key': neynarApiKey }\n let pageToken = ''\n for (let page = 0; page < 5; page++) {\n const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ''}`\n const resp = await fetch(url, { headers })\n if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` }\n const data = await resp.json()\n\n for (const msg of data.messages || []) {\n if (msg.hash && msg.hash.startsWith(proof.castHash!)) {\n const text = msg.data?.castAddBody?.text || ''\n if (containsFingerprint(text, fingerprint)) {\n return { verified: true }\n }\n return { verified: false, reason: 'Cast found but fingerprint token not in text' }\n }\n }\n\n if (!data.nextPageToken) break\n pageToken = data.nextPageToken\n }\n\n return { verified: false, reason: 'Cast not found' }\n } catch (err: any) {\n return { verified: false, reason: `Farcaster fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyCodeberg(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://codeberg.org/api/v1/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Codeberg API returned ${resp.status}` }\n const data = await resp.json()\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n\n return { verified: false, reason: 'Fingerprint token not found in repo description' }\n } catch (err: any) {\n return { verified: false, reason: `Codeberg fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyMastodon(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://${proof.instance}/api/v1/accounts/lookup?acct=${encodeURIComponent(proof.user!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Mastodon API returned ${resp.status}` }\n const data = await resp.json()\n\n const keyId = fingerprint.slice(-16)\n\n for (const field of data.fields || []) {\n const text = field.value.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n if (data.note) {\n const text = data.note.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n return { verified: false, reason: 'Fingerprint not found in profile fields or bio' }\n } catch (err: any) {\n return { verified: false, reason: `Mastodon fetch failed: ${err.message}` }\n }\n}\n\ntype Verifier = (proof: Proof, fingerprint: string, neynarApiKey?: string) => Promise<PGPVerification>\n\nconst verifiers: Record<string, Verifier> = {\n github: verifyGitHub,\n dns: verifyDNS,\n farcaster: verifyFarcaster,\n codeberg: verifyCodeberg,\n mastodon: verifyMastodon,\n}\n\nexport async function verifyProof(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n const fn = verifiers[proof.provider]\n if (!fn) return { verified: false, reason: 'Unknown provider' }\n return fn(proof, fingerprint, neynarApiKey)\n}\n","import { useScryIdentity } from '../../hooks/useScryIdentity'\nimport { useIdentityKitConfig } from '../../context'\nimport type { Theme } from '../../core/types'\nimport '../../themes/index.css'\nimport './ScryCard.css'\n\nfunction ThurinLogo() {\n return (\n <svg className=\"scry-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(--scry-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 ScryCardProps {\n ens?: string\n address?: string\n theme?: Theme\n}\n\nexport function ScryCard({ ens, address, theme = 'thurin' }: ScryCardProps) {\n const input = ens || address\n const identity = useScryIdentity(input)\n const config = useIdentityKitConfig()\n\n const scryUrl = identity.address\n ? `${config.scryBaseUrl}/eth/${identity.address}`\n : ens\n ? `${config.scryBaseUrl}/ens/${ens}`\n : null\n\n if (identity.isLoading) {\n return (\n <div className=\"scry-card\" data-scry-theme={theme}>\n <div className=\"scry-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=\"scry-card\" data-scry-theme={theme}>\n <a className=\"scry-card-header\" href={scryUrl || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n {identity.ensAvatar ? (\n <img\n className=\"scry-card-avatar\"\n src={identity.ensAvatar}\n alt={identity.ensName || ''}\n />\n ) : (\n <ThurinLogo />\n )}\n <div>\n {identity.ensName && (\n <div className=\"scry-card-name\">{identity.ensName}</div>\n )}\n {displayAddress && (\n <div className=\"scry-card-address\">{displayAddress}</div>\n )}\n </div>\n </a>\n\n <div className=\"scry-card-stats\">\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{identity.activeClaims}</span>\n <span className=\"scry-card-stat-label\">Seals</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{verifiedProofs}</span>\n <span className=\"scry-card-stat-label\">Proofs</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">\n {identity.efp?.followers ?? 0}\n </span>\n <span className=\"scry-card-stat-label\">Followers</span>\n </div>\n </div>\n\n <div className=\"scry-card-badges\">\n {hasVerifiedPgp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">PGP Verified</span>\n )}\n {identity.efp?.hasEfp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">EFP</span>\n )}\n {identity.proofs.map((p, i) => (\n <span\n key={i}\n className={`scry-card-badge scry-card-badge--${p.status === 'verified' ? 'verified' : 'unverified'}`}\n >\n {p.label}\n </span>\n ))}\n </div>\n\n {scryUrl && (\n <a\n className=\"scry-card-link\"\n href={scryUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on Scry\n </a>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["mainnet","mainnet","http","key","mainnet","http","useQuery","useQuery","useQuery","useQuery","mainnet","jsx"]}
1
+ {"version":3,"sources":["../src/provider.tsx","../src/context.ts","../src/hooks/useScryIdentity.ts","../src/hooks/useSignetClaims.ts","../src/core/contract.ts","../src/core/logs.ts","../src/core/pgp.ts","../src/hooks/useEFPGraph.ts","../src/core/efp.ts","../src/hooks/usePGPProofs.ts","../src/core/proofs.ts","../src/components/ScryCard/ScryCard.tsx"],"sourcesContent":["import { type ReactNode, useMemo } from 'react'\nimport { WagmiProvider, createConfig, http, useConfig } from 'wagmi'\nimport { mainnet } from 'wagmi/chains'\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\nfunction createDefaultWagmiConfig(rpcUrl?: string) {\n return createConfig({\n chains: [mainnet],\n transports: {\n [mainnet.id]: http(rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n },\n })\n}\n\nfunction WagmiDetector({ children, rpcUrl }: { children: ReactNode; rpcUrl?: string }) {\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), [rpcUrl])\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 scryBaseUrl = 'https://thurin.id',\n}: IdentityKitProviderProps) {\n const config = useMemo(\n () => ({ rpcUrl, neynarApiKey, scryBaseUrl }),\n [rpcUrl, neynarApiKey, scryBaseUrl],\n )\n\n return (\n <IdentityKitContext.Provider value={config}>\n <WagmiDetector rpcUrl={rpcUrl}>\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 scryBaseUrl: 'https://thurin.id',\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 { mainnet } from 'wagmi/chains'\nimport { normalize } from 'viem/ens'\nimport { useSignetClaims } from './useSignetClaims'\nimport { useEFPGraph } from './useEFPGraph'\nimport { usePGPProofs } from './usePGPProofs'\nimport type { ScryIdentity } 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 useScryIdentity(ensOrAddress: string | undefined | null): ScryIdentity {\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: mainnet.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: mainnet.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: mainnet.id,\n query: { enabled: !!displayName },\n })\n\n // Signet claims\n const {\n claims,\n totalClaims,\n activeClaims,\n currentFingerprint,\n isLoading: claimsLoading,\n } = useSignetClaims(address)\n\n // PGP proofs (from current fingerprint)\n const {\n keyInfo: pgpKeyInfo,\n proofs,\n isLoading: proofsLoading,\n } = usePGPProofs(currentFingerprint)\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 { mainnet } from 'wagmi/chains'\nimport { useQuery } from '@tanstack/react-query'\nimport { createPublicClient, http, parseAbiItem } from 'viem'\nimport { REGISTRY_ADDRESS, REGISTRY_ABI, CONTRACT_DEPLOY_BLOCK } from '../core/contract'\nimport { getLogsChunked } from '../core/logs'\nimport { verifyAttestation } from '../core/pgp'\nimport { useIdentityKitConfig } from '../context'\nimport type { SignetClaim } from '../core/types'\n\nexport function useSignetClaims(address: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data: count, isLoading: countLoading } = useReadContract({\n address: REGISTRY_ADDRESS,\n abi: REGISTRY_ABI,\n functionName: 'attestationCount',\n args: address ? [address as `0x${string}`] : undefined,\n chainId: mainnet.id,\n query: { enabled: !!address },\n })\n\n const attestationCount = count ? Number(count) : 0\n\n const contracts = address\n ? Array.from({ length: attestationCount }, (_, i) => ({\n address: REGISTRY_ADDRESS as `0x${string}`,\n abi: REGISTRY_ABI,\n functionName: 'getAttestation' as const,\n args: [address as `0x${string}`, BigInt(i)] as const,\n chainId: mainnet.id,\n }))\n : []\n\n const { data: attestations, isLoading: attestationsLoading } = useReadContracts({\n contracts,\n query: { enabled: contracts.length > 0 },\n })\n\n // Fetch event logs for PGP data (signature + public key not available from contract reads)\n const { data: eventData } = useQuery({\n queryKey: ['signet-logs', address],\n queryFn: async () => {\n if (!address) return []\n const client = createPublicClient({\n chain: mainnet,\n transport: http(config.rpcUrl || 'https://ethereum-rpc.publicnode.com'),\n })\n const event = parseAbiItem(\n 'event Attested(address indexed ethAddress, string indexed fingerprintHash, string fingerprint, string pgpSignature, string pgpPublicKey, uint256 index, uint256 timestamp)',\n )\n return getLogsChunked(client, {\n address: REGISTRY_ADDRESS,\n event,\n args: { ethAddress: address as `0x${string}` },\n fromBlock: CONTRACT_DEPLOY_BLOCK,\n toBlock: 'latest',\n })\n },\n enabled: !!address && attestationCount > 0,\n staleTime: 300_000,\n })\n\n // Combine attestation data with event log data and verify\n const { data: claims, isLoading: verifyLoading } = useQuery({\n queryKey: ['signet-claims', address, attestationCount, !!eventData],\n queryFn: async (): Promise<SignetClaim[]> => {\n if (!attestations || !address) return []\n\n const results: SignetClaim[] = []\n\n for (let i = 0; i < attestations.length; i++) {\n const att = attestations[i]\n if (att.status !== 'success') continue\n\n const [fingerprint, createdAt, revoked] = att.result as [string, bigint, boolean]\n const log = (eventData || [])[i]\n\n const pgpSignature = log?.args?.pgpSignature ?? null\n const pgpPublicKey = log?.args?.pgpPublicKey ?? null\n const txHash = log?.transactionHash ?? null\n\n let verification = null\n if (pgpPublicKey && pgpSignature) {\n verification = await verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress: address,\n })\n }\n\n results.push({\n index: i,\n fingerprint,\n createdAt: Number(createdAt),\n revoked,\n pgpSignature,\n pgpPublicKey,\n txHash,\n verification,\n })\n }\n\n return results\n },\n enabled: !!attestations && attestations.length > 0,\n staleTime: 300_000,\n })\n\n const isLoading = countLoading || attestationsLoading || verifyLoading\n\n const activeClaims = (claims || []).filter((c) => !c.revoked)\n const currentFingerprint = activeClaims.length > 0\n ? activeClaims[activeClaims.length - 1].fingerprint\n : null\n\n return {\n claims: claims || [],\n totalClaims: attestationCount,\n activeClaims: activeClaims.length,\n currentFingerprint,\n isLoading,\n }\n}\n","export const REGISTRY_ADDRESS = '0xf7a45BC662A78a6fb417ED5f52b3766cbf13EbBb' as const\n\nexport const CONTRACT_DEPLOY_BLOCK = 24515891n\n\nexport const REGISTRY_ABI = [\n {\n name: 'Attested',\n type: 'event',\n inputs: [\n { name: 'ethAddress', type: 'address', indexed: true },\n { name: 'fingerprintHash', type: 'string', indexed: true },\n { name: 'fingerprint', type: 'string', indexed: false },\n { name: 'pgpSignature', type: 'string', indexed: false },\n { name: 'pgpPublicKey', type: 'string', indexed: false },\n { name: 'index', type: 'uint256', indexed: false },\n { name: 'timestamp', type: 'uint256', indexed: false },\n ],\n },\n {\n name: 'attestationCount',\n type: 'function',\n stateMutability: 'view',\n inputs: [{ name: 'addr', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n name: 'getAttestation',\n type: 'function',\n stateMutability: 'view',\n inputs: [\n { name: 'addr', type: 'address' },\n { name: 'index', type: 'uint256' },\n ],\n outputs: [\n { name: 'fingerprint', type: 'string' },\n { name: 'createdAt', type: 'uint256' },\n { name: 'revoked', type: 'bool' },\n ],\n },\n] as const\n","import { type PublicClient } from 'viem'\nimport { CONTRACT_DEPLOY_BLOCK } from './contract'\n\nconst LOG_CHUNK_SIZE = 49999n\n\nexport async function getLogsChunked(\n client: PublicClient,\n params: {\n address?: `0x${string}`\n event?: any\n args?: Record<string, any>\n fromBlock?: bigint\n toBlock?: bigint | 'latest'\n },\n) {\n const latest = await client.getBlockNumber()\n const fromBlock = params.fromBlock ?? CONTRACT_DEPLOY_BLOCK\n const toBlock = params.toBlock === 'latest' || !params.toBlock ? latest : params.toBlock\n\n const allLogs: any[] = []\n\n for (let start = fromBlock; start <= toBlock; start += LOG_CHUNK_SIZE) {\n const end = start + LOG_CHUNK_SIZE - 1n > toBlock ? toBlock : start + LOG_CHUNK_SIZE - 1n\n const logs = await client.getLogs({\n ...params,\n fromBlock: start,\n toBlock: end,\n })\n allLogs.push(...logs)\n }\n\n return allLogs\n}\n","import type { PGPKeyInfo, PGPVerification } from './types'\n\nexport async function parsePgpKey(armoredKey: string): Promise<PGPKeyInfo | null> {\n try {\n const { readKey } = await import('openpgp')\n const key = await readKey({ armoredKey })\n const fingerprint = key.getFingerprint().toUpperCase()\n const userIDs = key.users.map((u: any) => u.userID?.userID).filter(Boolean)\n const algorithm = String(key.keyPacket.algorithm)\n const created = key.keyPacket.created?.toISOString() ?? null\n const expiration = await key.getExpirationTime()\n const expires =\n expiration && expiration !== Infinity\n ? new Date(expiration as number).toISOString()\n : null\n\n const notations: { name: string; value: string }[] = []\n const seen = new Set<string>()\n for (const user of key.users) {\n if (!(user as any).selfCertifications) continue\n for (const cert of (user as any).selfCertifications) {\n if (cert.rawNotations) {\n for (const n of cert.rawNotations) {\n const name =\n typeof n.name === 'string' ? n.name : new TextDecoder().decode(n.name)\n const value =\n n.value instanceof Uint8Array\n ? new TextDecoder().decode(n.value)\n : typeof n.value === 'string'\n ? n.value\n : null\n if (value) {\n const key = `${name}:${value}`\n if (!seen.has(key)) {\n seen.add(key)\n notations.push({ name, value })\n }\n }\n }\n }\n }\n }\n\n const subkeys = key.subkeys.map((sk: any) => ({\n algorithm: String(sk.keyPacket.algorithm),\n created: sk.keyPacket.created?.toISOString() ?? null,\n fingerprint: sk.getFingerprint().toUpperCase(),\n }))\n\n return { fingerprint, userIDs, algorithm, created, expires, notations, subkeys }\n } catch {\n return null\n }\n}\n\nexport async function verifyAttestation({\n pgpPublicKey,\n pgpSignature,\n fingerprint,\n ethAddress,\n}: {\n pgpPublicKey: string | null\n pgpSignature: string | null\n fingerprint: string\n ethAddress: string\n}): Promise<PGPVerification> {\n try {\n if (!pgpPublicKey || !pgpSignature) {\n return { verified: false, reason: 'Missing PGP data' }\n }\n\n const { readKey, readCleartextMessage, verify } = await import('openpgp')\n\n const publicKey = await readKey({ armoredKey: pgpPublicKey })\n const keyFingerprint = publicKey.getFingerprint().toUpperCase()\n if (keyFingerprint !== fingerprint.toUpperCase()) {\n return { verified: false, reason: 'Key fingerprint mismatch' }\n }\n\n const message = await readCleartextMessage({ cleartextMessage: pgpSignature })\n const { signatures } = await verify({ message, verificationKeys: publicKey })\n await signatures[0].verified\n\n const signedText = message.getText()\n if (!signedText.toLowerCase().includes(ethAddress.toLowerCase())) {\n return { verified: false, reason: 'Signed message does not contain ETH address' }\n }\n\n return { verified: true }\n } catch {\n return { verified: false, reason: 'Signature verification failed' }\n }\n}\n\nconst KEYSERVER_BASE = 'https://keys.openpgp.org/vks/v1'\n\nexport async function fetchKeyByFingerprint(fingerprint: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-fingerprint/${fingerprint}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\n }\n}\n\nexport async function fetchKeyByKeyId(keyId: string): Promise<string | null> {\n try {\n const resp = await fetch(`${KEYSERVER_BASE}/by-keyid/${keyId}`)\n if (!resp.ok) return null\n return await resp.text()\n } catch {\n return null\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 type { EFPGraph } from './types'\n\nconst EFP_API = 'https://api.ethfollow.xyz/api/v1'\n\nexport async function fetchEFPGraph(address: string): Promise<EFPGraph | null> {\n try {\n const listsResp = await fetch(`${EFP_API}/users/${address}/lists`)\n if (!listsResp.ok) return null\n const listsData = await listsResp.json()\n const listId = listsData.primary_list\n if (!listId) return null\n\n const [followingResp, statsResp, top8Resp] = await Promise.all([\n fetch(`${EFP_API}/lists/${listId}/following?limit=100`),\n fetch(`${EFP_API}/users/${address}/stats`),\n fetch(`${EFP_API}/lists/${listId}/following?limit=8&tags=top8`),\n ])\n\n const followingData = followingResp.ok ? await followingResp.json() : { following: [] }\n const statsData = statsResp.ok ? await statsResp.json() : {}\n const top8Data = top8Resp.ok ? await top8Resp.json() : { following: [] }\n\n return {\n followers: parseInt(statsData.followers_count) || 0,\n following: (followingData.following || []).length,\n top8: (top8Data.following || []).map((f: any) => f.data),\n hasEfp: true,\n }\n } catch {\n return null\n }\n}\n","import { useQuery } from '@tanstack/react-query'\nimport { fetchKeyByFingerprint, 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\nexport function usePGPProofs(fingerprint: string | undefined | null) {\n const config = useIdentityKitConfig()\n\n const { data, isLoading } = useQuery({\n queryKey: ['pgp-proofs', fingerprint],\n queryFn: async (): Promise<{ keyInfo: PGPKeyInfo | null; proofs: ProofResult[] }> => {\n if (!fingerprint) return { keyInfo: null, proofs: [] }\n\n const armoredKey = await fetchKeyByFingerprint(fingerprint)\n if (!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\n const identified = keyInfo.notations\n .map((n) => identifyProof(n))\n .filter((p): p is NonNullable<typeof p> => p !== null)\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 return { keyInfo, proofs }\n },\n enabled: !!fingerprint,\n staleTime: 300_000,\n })\n\n return {\n keyInfo: data?.keyInfo ?? null,\n proofs: data?.proofs ?? [],\n isLoading,\n }\n}\n","import type { Notation, Proof, PGPVerification } from './types'\n\nconst PROVIDERS: {\n provider: string\n label: string\n pattern: RegExp\n parse: (m: RegExpMatchArray) => Record<string, string>\n}[] = [\n {\n provider: 'github',\n label: 'GitHub',\n pattern: /^https:\\/\\/gist\\.github\\.com\\/([^/]+)\\/([a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], gistId: m[2] }),\n },\n {\n provider: 'dns',\n label: 'DNS',\n pattern: /^dns:([^?]+)\\?type=TXT$/i,\n parse: (m) => ({ domain: m[1] }),\n },\n {\n provider: 'farcaster',\n label: 'Farcaster',\n pattern: /^https:\\/\\/farcaster\\.xyz\\/([^/]+)\\/(0x[a-f0-9]+)$/i,\n parse: (m) => ({ user: m[1], castHash: m[2] }),\n },\n {\n provider: 'codeberg',\n label: 'Codeberg',\n pattern: /^https:\\/\\/codeberg\\.org\\/([^/]+)\\/([^/]+)$/i,\n parse: (m) => ({ user: m[1], repo: m[2] }),\n },\n {\n provider: 'mastodon',\n label: 'Mastodon',\n pattern: /^https:\\/\\/([^/]+)\\/@([^/]+)$/i,\n parse: (m) => ({ instance: m[1], user: m[2] }),\n },\n]\n\nconst ACCEPTED_NAMESPACES = new Set(['proof@thurin.id', 'proof@ariadne.id'])\n\nexport function identifyProof(notation: Notation): Proof | null {\n if (!ACCEPTED_NAMESPACES.has(notation.name)) return null\n\n for (const { provider, label, pattern, parse } of PROVIDERS) {\n const m = notation.value.match(pattern)\n if (m) {\n return { provider, label, url: notation.value, ...parse(m) }\n }\n }\n\n return { provider: 'unknown', label: 'Unknown', url: notation.value }\n}\n\nexport function displayUrl(proof: Proof): string {\n if (proof.provider === 'dns') return proof.domain!\n if (proof.provider === 'github') return proof.user!\n if (proof.provider === 'farcaster') return `@${proof.user}`\n if (proof.provider === 'codeberg') return proof.user!\n if (proof.provider === 'mastodon') return `@${proof.user}@${proof.instance}`\n return proof.url\n}\n\nexport function proofHref(proof: Proof): string | null {\n if (proof.provider === 'dns') return `https://${proof.domain}`\n if (proof.provider === 'github') return `https://github.com/${proof.user}`\n if (proof.provider === 'farcaster') return `https://farcaster.xyz/${proof.user}`\n if (proof.provider === 'codeberg') return `https://codeberg.org/${proof.user}`\n if (proof.provider === 'mastodon') return `https://${proof.instance}/@${proof.user}`\n if (proof.url.startsWith('http')) return proof.url\n return null\n}\n\nexport function proofSecondaryHref(proof: Proof): string | null {\n if (proof.provider === 'github') return proof.url\n if (proof.provider === 'farcaster') return proof.url\n if (proof.provider === 'codeberg') return proof.url\n if (proof.provider === 'mastodon') return proof.url\n return null\n}\n\n// ─── Verification ──────────────────────────────────────────────────────────\n\nconst FPR_TOKEN = 'OPENPGP4FPR:'\n\nfunction containsFingerprint(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(FPR_TOKEN + fingerprint.toUpperCase())\n}\n\nfunction containsFingerprintUrl(text: string, fingerprint: string): boolean {\n return text.toUpperCase().includes(fingerprint.toUpperCase())\n}\n\nasync function verifyGitHub(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(`https://api.github.com/gists/${proof.gistId}`)\n if (!resp.ok) return { verified: false, reason: `GitHub API returned ${resp.status}` }\n const data = await resp.json()\n\n for (const file of Object.values(data.files || {}) as any[]) {\n if (file.content && containsFingerprint(file.content, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in gist' }\n } catch (err: any) {\n return { verified: false, reason: `GitHub fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyDNS(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://cloudflare-dns.com/dns-query?name=${encodeURIComponent(proof.domain!)}&type=TXT`,\n { headers: { Accept: 'application/dns-json' } },\n )\n if (!resp.ok) return { verified: false, reason: `DNS query returned ${resp.status}` }\n const data = await resp.json()\n\n for (const answer of data.Answer || []) {\n if (answer.data && containsFingerprint(answer.data, fingerprint)) {\n return { verified: true }\n }\n }\n return { verified: false, reason: 'Fingerprint token not found in TXT records' }\n } catch (err: any) {\n return { verified: false, reason: `DNS fetch failed: ${err.message}` }\n }\n}\n\nconst NEYNAR_HUB = 'https://hub-api.neynar.com'\n\nasync function resolveFid(\n username: string,\n apiKey: string,\n): Promise<number | null> {\n const resp = await fetch(\n `${NEYNAR_HUB}/v1/userNameProofByName?name=${encodeURIComponent(username)}`,\n { headers: { 'x-api-key': apiKey } },\n )\n if (!resp.ok) return null\n const data = await resp.json()\n return data.fid ?? null\n}\n\nasync function verifyFarcaster(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n if (!neynarApiKey) {\n return { verified: false, reason: 'Farcaster verification requires a Neynar API key' }\n }\n\n try {\n const fid = await resolveFid(proof.user!, neynarApiKey)\n if (!fid) return { verified: false, reason: `Could not resolve Farcaster user \"${proof.user}\"` }\n\n const headers = { 'x-api-key': neynarApiKey }\n let pageToken = ''\n for (let page = 0; page < 5; page++) {\n const url = `${NEYNAR_HUB}/v1/castsByFid?fid=${fid}&pageSize=100&reverse=true${pageToken ? `&pageToken=${pageToken}` : ''}`\n const resp = await fetch(url, { headers })\n if (!resp.ok) return { verified: false, reason: `Farcaster Hub returned ${resp.status}` }\n const data = await resp.json()\n\n for (const msg of data.messages || []) {\n if (msg.hash && msg.hash.startsWith(proof.castHash!)) {\n const text = msg.data?.castAddBody?.text || ''\n if (containsFingerprint(text, fingerprint)) {\n return { verified: true }\n }\n return { verified: false, reason: 'Cast found but fingerprint token not in text' }\n }\n }\n\n if (!data.nextPageToken) break\n pageToken = data.nextPageToken\n }\n\n return { verified: false, reason: 'Cast not found' }\n } catch (err: any) {\n return { verified: false, reason: `Farcaster fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyCodeberg(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://codeberg.org/api/v1/repos/${encodeURIComponent(proof.user!)}/${encodeURIComponent(proof.repo!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Codeberg API returned ${resp.status}` }\n const data = await resp.json()\n\n if (data.description && containsFingerprint(data.description, fingerprint)) {\n return { verified: true }\n }\n\n return { verified: false, reason: 'Fingerprint token not found in repo description' }\n } catch (err: any) {\n return { verified: false, reason: `Codeberg fetch failed: ${err.message}` }\n }\n}\n\nasync function verifyMastodon(proof: Proof, fingerprint: string): Promise<PGPVerification> {\n try {\n const resp = await fetch(\n `https://${proof.instance}/api/v1/accounts/lookup?acct=${encodeURIComponent(proof.user!)}`,\n )\n if (!resp.ok) return { verified: false, reason: `Mastodon API returned ${resp.status}` }\n const data = await resp.json()\n\n const keyId = fingerprint.slice(-16)\n\n for (const field of data.fields || []) {\n const text = field.value.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n if (data.note) {\n const text = data.note.replace(/<[^>]*>/g, '')\n if (containsFingerprintUrl(text, fingerprint) || containsFingerprintUrl(text, keyId)) {\n return { verified: true }\n }\n }\n\n return { verified: false, reason: 'Fingerprint not found in profile fields or bio' }\n } catch (err: any) {\n return { verified: false, reason: `Mastodon fetch failed: ${err.message}` }\n }\n}\n\ntype Verifier = (proof: Proof, fingerprint: string, neynarApiKey?: string) => Promise<PGPVerification>\n\nconst verifiers: Record<string, Verifier> = {\n github: verifyGitHub,\n dns: verifyDNS,\n farcaster: verifyFarcaster,\n codeberg: verifyCodeberg,\n mastodon: verifyMastodon,\n}\n\nexport async function verifyProof(\n proof: Proof,\n fingerprint: string,\n neynarApiKey?: string,\n): Promise<PGPVerification> {\n const fn = verifiers[proof.provider]\n if (!fn) return { verified: false, reason: 'Unknown provider' }\n return fn(proof, fingerprint, neynarApiKey)\n}\n","import { useScryIdentity } from '../../hooks/useScryIdentity'\nimport { useIdentityKitConfig } from '../../context'\nimport type { Theme } from '../../core/types'\nimport '../../themes/index.css'\nimport './ScryCard.css'\n\nfunction ThurinLogo() {\n return (\n <svg className=\"scry-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(--scry-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 ScryCardProps {\n ens?: string\n address?: string\n theme?: Theme\n}\n\nexport function ScryCard({ ens, address, theme = 'thurin' }: ScryCardProps) {\n const input = ens || address\n const identity = useScryIdentity(input)\n const config = useIdentityKitConfig()\n\n const scryUrl = identity.address\n ? `${config.scryBaseUrl}/eth/${identity.address}`\n : ens\n ? `${config.scryBaseUrl}/ens/${ens}`\n : null\n\n if (identity.isLoading) {\n return (\n <div className=\"scry-card\" data-scry-theme={theme}>\n <div className=\"scry-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=\"scry-card\" data-scry-theme={theme}>\n <a className=\"scry-card-header\" href={scryUrl || undefined} target=\"_blank\" rel=\"noopener noreferrer\">\n {identity.ensAvatar ? (\n <img\n className=\"scry-card-avatar\"\n src={identity.ensAvatar}\n alt={identity.ensName || ''}\n />\n ) : (\n <ThurinLogo />\n )}\n <div>\n {identity.ensName && (\n <div className=\"scry-card-name\">{identity.ensName}</div>\n )}\n {displayAddress && (\n <div className=\"scry-card-address\">{displayAddress}</div>\n )}\n </div>\n </a>\n\n <div className=\"scry-card-stats\">\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{identity.activeClaims}</span>\n <span className=\"scry-card-stat-label\">Seals</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">{verifiedProofs}</span>\n <span className=\"scry-card-stat-label\">Proofs</span>\n </div>\n <div className=\"scry-card-stat\">\n <span className=\"scry-card-stat-value\">\n {identity.efp?.followers ?? 0}\n </span>\n <span className=\"scry-card-stat-label\">Followers</span>\n </div>\n </div>\n\n <div className=\"scry-card-badges\">\n {hasVerifiedPgp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">PGP Verified</span>\n )}\n {identity.efp?.hasEfp && (\n <span className=\"scry-card-badge scry-card-badge--verified\">EFP</span>\n )}\n {identity.proofs.map((p, i) => (\n <span\n key={i}\n className={`scry-card-badge scry-card-badge--${p.status === 'verified' ? 'verified' : 'unverified'}`}\n >\n {p.label}\n </span>\n ))}\n </div>\n\n {scryUrl && (\n <a\n className=\"scry-card-link\"\n href={scryUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n View on Scry\n </a>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["mainnet","mainnet","http","key","mainnet","http","useQuery","useQuery","useQuery","useQuery","mainnet","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thurinlabs/identity-kit",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "React SDK for embedding Thurin identity data",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",