@renown/sdk 6.2.2-dev.22 → 6.2.2-dev.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -26
- package/dist/crypto.d.ts +2 -2
- package/dist/{index-25fTa4yI.d.ts → index-CLJb-Nle.d.ts} +2 -2
- package/dist/{index-25fTa4yI.d.ts.map → index-CLJb-Nle.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/meta-BIIw0yao.d.ts +16 -0
- package/dist/meta-BIIw0yao.d.ts.map +1 -0
- package/dist/meta-ClnkfLQZ.js +27 -0
- package/dist/meta-ClnkfLQZ.js.map +1 -0
- package/dist/meta-DEiGzvRl.d.ts +14 -0
- package/dist/meta-DEiGzvRl.d.ts.map +1 -0
- package/dist/meta-DoUiCChW.d.ts +19 -0
- package/dist/meta-DoUiCChW.d.ts.map +1 -0
- package/dist/meta-v66wx9x-.js +31 -0
- package/dist/meta-v66wx9x-.js.map +1 -0
- package/dist/node.d.ts +3 -46
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +17 -8
- package/dist/node.js.map +1 -1
- package/dist/{renown-builder-BqWoYtBR.js → renown-builder-1WTEoRc6.js} +24 -1
- package/dist/{renown-builder-BqWoYtBR.js.map → renown-builder-1WTEoRc6.js.map} +1 -1
- package/dist/types-DiIZNA8t.js +20 -0
- package/dist/types-DiIZNA8t.js.map +1 -0
- package/dist/{types-Z6jyeonm.d.ts → types-DteAE_lL.d.ts} +23 -18
- package/dist/types-DteAE_lL.d.ts.map +1 -0
- package/dist/{types-DsF91dDF.d.ts → types-efrA0fu2.d.ts} +6 -4
- package/dist/{types-DsF91dDF.d.ts.map → types-efrA0fu2.d.ts.map} +1 -1
- package/dist/{utils-OOrVXHof.d.ts → utils-BuICPHTW.d.ts} +51 -3
- package/dist/utils-BuICPHTW.d.ts.map +1 -0
- package/dist/wallet/index.d.ts +4 -26
- package/dist/wallet/index.d.ts.map +1 -1
- package/dist/wallet/index.js +20 -64
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/mock/factory.d.ts +9 -0
- package/dist/wallet/mock/factory.d.ts.map +1 -0
- package/dist/wallet/mock/factory.js +35 -0
- package/dist/wallet/mock/factory.js.map +1 -0
- package/dist/wallet/mock/index.d.ts +5 -14
- package/dist/wallet/mock/index.d.ts.map +1 -1
- package/dist/wallet/mock/index.js +9 -31
- package/dist/wallet/mock/index.js.map +1 -1
- package/dist/wallet/privy/factory.d.ts +58 -0
- package/dist/wallet/privy/factory.d.ts.map +1 -0
- package/dist/wallet/privy/factory.js +218 -0
- package/dist/wallet/privy/factory.js.map +1 -0
- package/dist/wallet/privy/index.d.ts +5 -59
- package/dist/wallet/privy/index.d.ts.map +1 -1
- package/dist/wallet/privy/index.js +9 -223
- package/dist/wallet/privy/index.js.map +1 -1
- package/dist/wallet/rainbow/factory.d.ts +7 -0
- package/dist/wallet/rainbow/factory.d.ts.map +1 -0
- package/dist/wallet/rainbow/factory.js +216 -0
- package/dist/wallet/rainbow/factory.js.map +1 -0
- package/dist/wallet/rainbow/index.d.ts +6 -11
- package/dist/wallet/rainbow/index.d.ts.map +1 -1
- package/dist/wallet/rainbow/index.js +13 -210
- package/dist/wallet/rainbow/index.js.map +1 -1
- package/package.json +21 -2
- package/dist/types-DG816Qa8.js +0 -27
- package/dist/types-DG816Qa8.js.map +0 -1
- package/dist/types-Z6jyeonm.d.ts.map +0 -1
- package/dist/utils-OOrVXHof.d.ts.map +0 -1
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","names":["#filePath","#envKeyName","#logger","#parseKeyPair","#loadFromFile","#saveToFile","#emitter","#revalidate"],"sources":["../src/crypto/node-key-storage.ts","../src/event/event.node.ts","../src/storage/storage.node.ts","../src/init.node.ts","../src/login.node.ts","../src/session.ts"],"sourcesContent":["import {\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { ILogger } from \"../utils.js\";\nimport type { JsonWebKeyPairStorage, JwkKeyPair } from \"./types.js\";\n\nexport const RENOWN_PRIVATE_KEY_ENV = \"PH_RENOWN_PRIVATE_KEY\";\nexport const DEFAULT_KEYPAIR_PATH = \".ph/.keypair.json\";\n\n/**\n * Key storage that supports:\n * 1. PH_RENOWN_PRIVATE_KEY environment variable (JSON-encoded JwkKeyPair)\n * 2. Custom file path passed via options\n * 3. Falls back to file storage at .ph/.keypair.json in current working directory\n */\nexport class NodeKeyStorage implements JsonWebKeyPairStorage {\n #filePath: string;\n #envKeyName: string;\n #logger?: ILogger;\n\n static readonly DEFAULT_KEYPAIR_PATH = DEFAULT_KEYPAIR_PATH;\n static readonly RENOWN_PRIVATE_KEY_ENV = RENOWN_PRIVATE_KEY_ENV;\n\n constructor(\n filePath?: string,\n options: { envKeyName?: string; logger?: ILogger } = {},\n ) {\n this.#filePath = filePath || join(process.cwd(), DEFAULT_KEYPAIR_PATH);\n this.#envKeyName = options.envKeyName || RENOWN_PRIVATE_KEY_ENV;\n this.#logger = options.logger;\n\n // Ensure directory exists\n const dir = dirname(this.#filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n loadKeyPair(): Promise<JwkKeyPair | undefined> {\n // First check environment variable\n const envKey = process.env[this.#envKeyName];\n if (envKey) {\n try {\n const keyPairJson = JSON.parse(envKey) as unknown;\n const keyPair: JwkKeyPair = this.#parseKeyPair(keyPairJson);\n\n // Validate it has the required structure\n this.#logger?.debug(\"Loaded keypair from environment variable\");\n return Promise.resolve(keyPair);\n } catch (e) {\n throw new Error(\n `Failed to parse ${this.#envKeyName}: ${e instanceof Error ? e.message : String(e)}`,\n {\n cause: e,\n },\n );\n }\n }\n\n // Fall back to file storage\n return Promise.resolve(this.#loadFromFile());\n }\n\n async saveKeyPair(keyPair: JwkKeyPair): Promise<void> {\n // Don't save if using env var\n if (process.env[this.#envKeyName]) {\n return;\n }\n\n // Save to file\n this.#saveToFile(keyPair);\n return Promise.resolve();\n }\n\n removeKeyPair(): Promise<void> {\n if (process.env[this.#envKeyName]) {\n delete process.env[this.#envKeyName];\n }\n if (existsSync(this.#filePath)) {\n unlinkSync(this.#filePath);\n }\n return Promise.resolve();\n }\n\n #loadFromFile(): JwkKeyPair | undefined {\n try {\n if (!existsSync(this.#filePath)) {\n return undefined;\n }\n const data = readFileSync(this.#filePath, \"utf-8\");\n const parsed = JSON.parse(data) as unknown;\n const keyPair: JwkKeyPair = this.#parseKeyPair(parsed);\n this.#logger?.debug(`Loaded keypair from ${this.#filePath}`);\n return keyPair;\n } catch (e) {\n throw new Error(\n `Failed to parse ${this.#filePath}: ${e instanceof Error ? e.message : String(e)}`,\n {\n cause: e,\n },\n );\n }\n }\n\n #saveToFile(keyPair: JwkKeyPair): void {\n const data = { keyPair };\n writeFileSync(this.#filePath, JSON.stringify(data, null, 2), \"utf-8\");\n this.#logger?.debug(`Saved keypair to ${this.#filePath}`);\n }\n\n #parseKeyPair(json: unknown): JwkKeyPair {\n if (typeof json !== \"object\") {\n throw new Error(\"Invalid keyPair format:\" + JSON.stringify(json));\n }\n\n const object = json as JwkKeyPair | { keyPair: JwkKeyPair };\n let keyPair: JwkKeyPair;\n if (\"keyPair\" in object) {\n keyPair = object.keyPair;\n } else {\n keyPair = object;\n }\n\n if (\"publicKey\" in keyPair && \"privateKey\" in keyPair) {\n return keyPair;\n } else {\n throw new Error(\"Invalid keyPair format:\" + JSON.stringify(json));\n }\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { IEventEmitter } from \"./types.js\";\n\nexport class NodeEventEmitter<\n Events extends Record<string, unknown>,\n> implements IEventEmitter<Events> {\n #emitter = new EventEmitter();\n\n constructor() {\n this.#emitter.setMaxListeners(0);\n }\n\n on<K extends keyof Events>(\n event: K,\n listener: (data: Events[K]) => void,\n ): () => void {\n this.#emitter.on(event as string, listener);\n return () => {\n this.#emitter.removeListener(event.toString(), listener);\n };\n }\n\n emit<K extends keyof Events>(event: K, data: Events[K]): void {\n this.#emitter.emit(event.toString(), data);\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { BaseStorage } from \"./common.js\";\n\nexport class NodeStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n> extends BaseStorage<T> {\n private readonly filePath: string;\n\n constructor(filePath: string) {\n super();\n this.filePath = filePath;\n\n const parentFolder = dirname(this.filePath);\n mkdirSync(parentFolder, { recursive: true });\n\n if (!existsSync(this.filePath)) {\n writeFileSync(this.filePath, JSON.stringify({}));\n }\n }\n\n private readData(): T {\n const data = readFileSync(this.filePath, \"utf-8\");\n return JSON.parse(data) as T;\n }\n\n private writeData(data: T): void {\n writeFileSync(this.filePath, JSON.stringify(data, null, 2));\n }\n\n get<Key extends keyof T>(key: Key): T[Key] | undefined {\n const data = this.readData();\n return data[key];\n }\n\n set<Key extends keyof T>(key: Key, value?: T[Key]): void {\n const data = this.readData();\n if (value === undefined) {\n delete data[key];\n } else {\n data[key] = value;\n }\n this.writeData(data);\n }\n\n delete(key: keyof T): void {\n const data = this.readData();\n delete data[key];\n this.writeData(data);\n }\n}\n","import type { Renown } from \"./common.js\";\nimport { NodeKeyStorage } from \"./crypto/node-key-storage.js\";\nimport { NodeEventEmitter } from \"./event/event.node.js\";\nimport { BaseRenownBuilder } from \"./renown-builder.js\";\nimport { NodeStorage } from \"./storage/storage.node.js\";\nimport type { RenownEvents, RenownStorageMap } from \"./types.js\";\n\nexport class NodeRenownEventEmitter extends NodeEventEmitter<RenownEvents> {}\nexport class NodeRenownStorage extends NodeStorage<RenownStorageMap> {}\n\nexport const DEFAULT_RENOWN_STORAGE_PATH = \"./.ph/.renown.json\";\n\nexport interface NodeRenownBuilderOptions {\n /** File path for user storage. Defaults to \".ph/.renown.json\" in cwd */\n storagePath?: string;\n /** File path for keypair storage. Defaults to \".ph/.keypair.json\" in cwd */\n keyPath?: string;\n /** Renown server URL. Defaults to https://www.renown.id */\n baseUrl?: string;\n /** Switchboard GraphQL endpoint for the direct-to-reactor flow. */\n switchboardUrl?: string;\n /** Re-check a stored credential on build (default \"always\"). */\n revalidate?: \"always\" | \"never\";\n}\n\n/** Node.js Renown builder: file-based user + key storage. */\nexport class RenownBuilder extends BaseRenownBuilder {\n #revalidate: \"always\" | \"never\";\n\n constructor(appName: string, options: NodeRenownBuilderOptions = {}) {\n super(appName);\n\n const {\n storagePath = DEFAULT_RENOWN_STORAGE_PATH,\n keyPath,\n baseUrl,\n switchboardUrl,\n revalidate = \"always\",\n } = options;\n\n this.#revalidate = revalidate;\n this.withKeyPairStorage(new NodeKeyStorage(keyPath));\n this.withStorage(new NodeRenownStorage(storagePath));\n this.withEventEmitter(new NodeRenownEventEmitter());\n if (baseUrl) {\n this.withBaseUrl(baseUrl);\n }\n if (switchboardUrl) {\n this.withSwitchboardUrl(switchboardUrl);\n }\n }\n\n // Node scripts/CLI act on auth state once and exit, so revalidation must\n // finish before build() resolves — block on it (unlike the browser builder).\n async build(): Promise<Renown> {\n const renown = await super.build();\n if (this.#revalidate === \"always\" && renown.user) {\n await renown.revalidate();\n }\n return renown;\n }\n}\n","import type { CreateBearerTokenOptions, IRenown, User } from \"./types.js\";\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst POLL_INTERVAL_MS = 500; // 0.5s: session store is in-memory, cheap to poll\nconst SECONDS_IN_DAY = 24 * 60 * 60;\n\nexport interface BrowserLoginOptions {\n /** Renown server URL */\n renownUrl: string;\n /** Timeout in milliseconds. Defaults to 5 minutes. */\n timeoutMs?: number;\n /** Called with the login URL and session ID before the browser is opened */\n onLoginUrl?: (url: string, sessionId: string) => void;\n /** Called on each poll tick while waiting for authentication */\n onPollTick?: () => void;\n /** Called when the browser failed to open automatically */\n onBrowserOpenFailed?: (url: string) => void;\n /** AbortSignal to cancel the login flow */\n signal?: AbortSignal;\n}\n\nexport interface BrowserLoginResult {\n user: User;\n cliDid: string;\n}\n\nexport interface AuthStatusResult {\n authenticated: boolean;\n address?: string;\n userDid?: string;\n chainId?: number;\n cliDid: string;\n authenticatedAt?: Date;\n baseUrl: string;\n}\n\ninterface PendingSessionResponse {\n sessionId: string;\n status: \"pending\";\n}\n\ninterface ReadySessionResponse {\n sessionId: string;\n status: \"ready\";\n address: string;\n chainId: number;\n did: string;\n credentialId: string;\n userDocumentId: string;\n}\n\ntype SessionResponse = PendingSessionResponse | ReadySessionResponse;\n\nfunction abortReason(signal: AbortSignal): Error {\n if (signal.reason instanceof Error) return signal.reason;\n if (signal.reason) return new Error(String(signal.reason));\n return new DOMException(\"Aborted\", \"AbortError\");\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortReason(signal));\n return;\n }\n const onAbort = () => {\n clearTimeout(timer);\n reject(abortReason(signal!));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Open a URL in the default browser (cross-platform).\n */\nexport async function openBrowser(url: string): Promise<void> {\n const { execFile } = await import(\"node:child_process\");\n const { promisify } = await import(\"node:util\");\n const execFileAsync = promisify(execFile);\n const platform = process.platform;\n\n if (platform === \"darwin\") {\n await execFileAsync(\"open\", [url]);\n } else if (platform === \"win32\") {\n await execFileAsync(\"cmd\", [\"/c\", \"start\", \"\", url]);\n } else {\n await execFileAsync(\"xdg-open\", [url]);\n }\n}\n\nasync function pollSession(\n renownUrl: string,\n sessionId: string,\n timeoutMs: number,\n onPollTick?: () => void,\n signal?: AbortSignal,\n): Promise<ReadySessionResponse | null> {\n const startTime = Date.now();\n const sessionUrl = new URL(\n `/api/console/session/${sessionId}`,\n renownUrl,\n ).toString();\n\n while (Date.now() - startTime < timeoutMs) {\n signal?.throwIfAborted();\n try {\n const response = await fetch(sessionUrl, { signal });\n if (response.ok) {\n const data = (await response.json()) as SessionResponse;\n if (data.status === \"ready\") {\n return data;\n }\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\")\n throw error;\n // Network error, will retry\n }\n onPollTick?.();\n await sleep(POLL_INTERVAL_MS, signal);\n }\n\n return null;\n}\n\n/**\n * Perform a browser-based login flow with Renown.\n * Opens the user's browser to authenticate, then polls for completion.\n * Throws if already authenticated or if the flow times out.\n * If the browser fails to open, the flow continues polling — callers\n * can use onBrowserOpenFailed to show the URL as a fallback.\n */\nexport async function browserLogin(\n renown: IRenown,\n options: BrowserLoginOptions,\n): Promise<BrowserLoginResult> {\n if (renown.user?.credential) {\n throw new Error(\n `Already authenticated as ${renown.user.address}. Logout first.`,\n );\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const sessionId = crypto.randomUUID();\n\n const loginUrl = new URL(\"/console\", options.renownUrl);\n loginUrl.searchParams.set(\"session\", sessionId);\n loginUrl.searchParams.set(\"connect\", renown.did);\n loginUrl.searchParams.set(\"app\", renown.did);\n\n const url = loginUrl.toString();\n options.onLoginUrl?.(url, sessionId);\n\n try {\n await openBrowser(url);\n } catch {\n options.onBrowserOpenFailed?.(url);\n }\n\n const result = await pollSession(\n options.renownUrl,\n sessionId,\n timeoutMs,\n options.onPollTick,\n options.signal,\n );\n\n if (!result) {\n throw new Error(\"Authentication timed out.\");\n }\n\n const user = await renown.login(result.did);\n return { user, cliDid: renown.did };\n}\n\n/**\n * Get the current authentication status from a Renown instance.\n */\nexport function getAuthStatus(renown: IRenown): AuthStatusResult {\n const user = renown.user;\n const credential = user?.credential;\n\n return {\n authenticated: !!credential,\n address: user?.address,\n userDid: user?.did,\n chainId: user?.chainId,\n cliDid: renown.did,\n authenticatedAt: credential ? new Date(credential.issuanceDate) : undefined,\n baseUrl: renown.baseUrl,\n };\n}\n\nexport interface AccessTokenResult {\n token: string;\n did: string;\n address: string;\n expiresIn: number;\n}\n\n/**\n * Generate a bearer token for API authentication.\n * Requires the user to be authenticated (via browserLogin or equivalent).\n * Throws if not authenticated.\n */\nexport async function generateAccessToken(\n renown: IRenown,\n options?: CreateBearerTokenOptions,\n): Promise<AccessTokenResult> {\n const user = renown.user;\n if (!user?.credential) {\n throw new Error(\n \"Not authenticated. Login first to generate access tokens.\",\n );\n }\n\n const token = await renown.getBearerToken(options ?? {});\n\n return {\n token,\n did: renown.did,\n address: user.address,\n expiresIn: options?.expiresIn ?? 0,\n };\n}\n\n/**\n * Parse a human-readable expiry string to seconds.\n * Supports formats: \"7d\" (days), \"24h\" (hours), \"3600\" (seconds), \"3600s\" (seconds).\n * Only accepts positive integers — decimals like \"1.5h\" are rejected.\n */\nexport function parseExpiry(expiry: string): number {\n const trimmed = expiry.trim().toLowerCase();\n const match = trimmed.match(/^(\\d+)(d|h|s)?$/);\n\n if (!match) {\n throw new Error(\n `Invalid expiry format: ${expiry}. Expected a positive integer with optional suffix: \"7d\", \"24h\", \"3600s\", or \"3600\".`,\n );\n }\n\n const value = Number(match[1]);\n const unit = match[2];\n\n if (value <= 0) {\n throw new Error(\n `Invalid expiry format: ${expiry}. Value must be a positive integer.`,\n );\n }\n\n switch (unit) {\n case \"d\":\n return value * SECONDS_IN_DAY;\n case \"h\":\n return value * 60 * 60;\n default:\n return value;\n }\n}\n\n/**\n * Format an expiry duration in seconds to a human-readable string.\n */\nexport function formatExpiry(expiresIn: number): string {\n const days = Math.floor(expiresIn / SECONDS_IN_DAY);\n const hours = Math.floor((expiresIn % SECONDS_IN_DAY) / 3600);\n\n if (days > 0) {\n const dayStr = `${days} day${days !== 1 ? \"s\" : \"\"}`;\n if (hours > 0) {\n return `${dayStr} and ${hours} hour${hours !== 1 ? \"s\" : \"\"}`;\n }\n return dayStr;\n }\n\n if (hours > 0) {\n return `${hours} hour${hours !== 1 ? \"s\" : \"\"}`;\n }\n\n return `${expiresIn} second${expiresIn !== 1 ? \"s\" : \"\"}`;\n}\n","import { verifyAuthCredential } from \"./credential.js\";\nimport type { User } from \"./types.js\";\nimport { verifyAuthBearerToken } from \"./utils.js\";\n\n/** Server-side view of an authenticated Renown session. */\nexport interface RenownSession {\n /** Authenticated user identity derived from the session token. */\n user: User;\n /** App/client DID the token was issued by. */\n appDid: string;\n /** Token expiry (epoch seconds), when present. */\n expiresAt?: number;\n}\n\n/** Display hint carried alongside the token (unverified; not for auth). */\nexport interface RenownSessionProfile {\n name?: string | null;\n avatar?: string | null;\n}\n\n/** The `renown_session` cookie payload: the bearer token + a display hint. */\nexport interface RenownSessionCookie {\n token: string;\n profile?: RenownSessionProfile | null;\n}\n\nexport interface VerifyRenownSessionOptions {\n /** Expected `aud` claim on the token. */\n audience?: string;\n /** Switchboard GraphQL endpoint used when re-verifying the credential. */\n switchboardUrl?: string;\n /** Renown service base URL used when re-verifying the credential. */\n renownUrl?: string;\n /** Also re-verify the credential against Switchboard (default false = token-only, no network). */\n verifyCredential?: boolean;\n}\n\n/** Claims read from a session token without verifying its signature. */\nexport interface RenownSessionClaims {\n address?: string;\n chainId?: number;\n networkId?: string;\n /** Expiry in epoch seconds. */\n expiresAt?: number;\n}\n\n/** Serialize a session cookie value (token + optional display hint). */\nexport function serializeRenownSessionCookie(\n value: RenownSessionCookie,\n): string {\n return JSON.stringify(value);\n}\n\n// Parse the JSON cookie envelope { token, profile }; undefined if malformed.\nfunction parseSessionCookie(value: string): RenownSessionCookie | undefined {\n try {\n const parsed = JSON.parse(value) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n typeof (parsed as RenownSessionCookie).token === \"string\"\n ) {\n return parsed as RenownSessionCookie;\n }\n } catch {\n // Malformed cookie.\n }\n return undefined;\n}\n\n// Decode a session cookie's claims WITHOUT verifying the signature — cheap\n// optimistic checks only (e.g. proxy redirect); never trust for access control.\nexport function readSessionClaims(\n value: string,\n): RenownSessionClaims | undefined {\n const parsed = parseSessionCookie(value);\n if (!parsed) return undefined;\n const parts = parsed.token.split(\".\");\n if (parts.length < 2) return undefined;\n try {\n const json = Buffer.from(parts[1], \"base64url\").toString(\"utf8\");\n const payload = JSON.parse(json) as {\n exp?: number;\n vc?: {\n credentialSubject?: {\n address?: string;\n chainId?: number;\n networkId?: string;\n };\n };\n };\n const subject = payload.vc?.credentialSubject;\n return {\n address: subject?.address,\n chainId: subject?.chainId,\n networkId: subject?.networkId,\n expiresAt: payload.exp,\n };\n } catch {\n return undefined;\n }\n}\n\n// Verify a session cookie (envelope or bare token) → user, or undefined. Pass\n// verifyCredential:true to also check vs Switchboard; envelope hint is merged.\nexport async function verifyRenownSession(\n value: string,\n options: VerifyRenownSessionOptions = {},\n): Promise<RenownSession | undefined> {\n const { verifyCredential = false } = options;\n const parsed = parseSessionCookie(value);\n if (!parsed) return undefined;\n const { token, profile } = parsed;\n\n let session: RenownSession | undefined;\n if (verifyCredential) {\n const verified = await verifyAuthCredential(token, {\n audience: options.audience,\n renownUrl: options.renownUrl,\n switchboardUrl: options.switchboardUrl,\n });\n if (verified) {\n session = {\n user: {\n address: verified.address as `0x${string}`,\n chainId: verified.chainId,\n networkId: verified.networkId,\n did: verified.did,\n credential: verified.credential,\n },\n appDid: verified.appDid,\n };\n }\n } else {\n const verified = await verifyAuthBearerToken(token, {\n audience: options.audience,\n });\n if (verified) {\n const subject = verified.verifiableCredential.credentialSubject;\n const did = `did:pkh:${subject.networkId}:${subject.chainId}:${subject.address.toLowerCase()}`;\n session = {\n user: {\n address: subject.address as `0x${string}`,\n chainId: subject.chainId,\n networkId: subject.networkId,\n did,\n credential: undefined,\n },\n appDid: verified.issuer,\n expiresAt: verified.payload.exp,\n };\n }\n }\n\n if (!session) return undefined;\n\n // Merge the (unverified) display hint from the envelope — display only.\n if (profile?.name) {\n session.user = {\n ...session.user,\n ens: { name: profile.name, avatarUrl: profile.avatar ?? undefined },\n };\n }\n return session;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"node.js","names":["#filePath","#envKeyName","#logger","#parseKeyPair","#loadFromFile","#saveToFile","#emitter","#revalidate"],"sources":["../src/crypto/node-key-storage.ts","../src/event/event.node.ts","../src/storage/storage.node.ts","../src/init.node.ts","../src/login.node.ts","../src/session.ts"],"sourcesContent":["import {\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { ILogger } from \"../utils.js\";\nimport type { JsonWebKeyPairStorage, JwkKeyPair } from \"./types.js\";\n\nexport const RENOWN_PRIVATE_KEY_ENV = \"PH_RENOWN_PRIVATE_KEY\";\nexport const DEFAULT_KEYPAIR_PATH = \".ph/.keypair.json\";\n\n/**\n * Key storage that supports:\n * 1. PH_RENOWN_PRIVATE_KEY environment variable (JSON-encoded JwkKeyPair)\n * 2. Custom file path passed via options\n * 3. Falls back to file storage at .ph/.keypair.json in current working directory\n */\nexport class NodeKeyStorage implements JsonWebKeyPairStorage {\n #filePath: string;\n #envKeyName: string;\n #logger?: ILogger;\n\n static readonly DEFAULT_KEYPAIR_PATH = DEFAULT_KEYPAIR_PATH;\n static readonly RENOWN_PRIVATE_KEY_ENV = RENOWN_PRIVATE_KEY_ENV;\n\n constructor(\n filePath?: string,\n options: { envKeyName?: string; logger?: ILogger } = {},\n ) {\n this.#filePath = filePath || join(process.cwd(), DEFAULT_KEYPAIR_PATH);\n this.#envKeyName = options.envKeyName || RENOWN_PRIVATE_KEY_ENV;\n this.#logger = options.logger;\n\n // Ensure directory exists\n const dir = dirname(this.#filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n loadKeyPair(): Promise<JwkKeyPair | undefined> {\n // First check environment variable\n const envKey = process.env[this.#envKeyName];\n if (envKey) {\n try {\n const keyPairJson = JSON.parse(envKey) as unknown;\n const keyPair: JwkKeyPair = this.#parseKeyPair(keyPairJson);\n\n // Validate it has the required structure\n this.#logger?.debug(\"Loaded keypair from environment variable\");\n return Promise.resolve(keyPair);\n } catch (e) {\n throw new Error(\n `Failed to parse ${this.#envKeyName}: ${e instanceof Error ? e.message : String(e)}`,\n {\n cause: e,\n },\n );\n }\n }\n\n // Fall back to file storage\n return Promise.resolve(this.#loadFromFile());\n }\n\n async saveKeyPair(keyPair: JwkKeyPair): Promise<void> {\n // Don't save if using env var\n if (process.env[this.#envKeyName]) {\n return;\n }\n\n // Save to file\n this.#saveToFile(keyPair);\n return Promise.resolve();\n }\n\n removeKeyPair(): Promise<void> {\n if (process.env[this.#envKeyName]) {\n delete process.env[this.#envKeyName];\n }\n if (existsSync(this.#filePath)) {\n unlinkSync(this.#filePath);\n }\n return Promise.resolve();\n }\n\n #loadFromFile(): JwkKeyPair | undefined {\n try {\n if (!existsSync(this.#filePath)) {\n return undefined;\n }\n const data = readFileSync(this.#filePath, \"utf-8\");\n const parsed = JSON.parse(data) as unknown;\n const keyPair: JwkKeyPair = this.#parseKeyPair(parsed);\n this.#logger?.debug(`Loaded keypair from ${this.#filePath}`);\n return keyPair;\n } catch (e) {\n throw new Error(\n `Failed to parse ${this.#filePath}: ${e instanceof Error ? e.message : String(e)}`,\n {\n cause: e,\n },\n );\n }\n }\n\n #saveToFile(keyPair: JwkKeyPair): void {\n const data = { keyPair };\n writeFileSync(this.#filePath, JSON.stringify(data, null, 2), \"utf-8\");\n this.#logger?.debug(`Saved keypair to ${this.#filePath}`);\n }\n\n #parseKeyPair(json: unknown): JwkKeyPair {\n if (typeof json !== \"object\") {\n throw new Error(\"Invalid keyPair format:\" + JSON.stringify(json));\n }\n\n const object = json as JwkKeyPair | { keyPair: JwkKeyPair };\n let keyPair: JwkKeyPair;\n if (\"keyPair\" in object) {\n keyPair = object.keyPair;\n } else {\n keyPair = object;\n }\n\n if (\"publicKey\" in keyPair && \"privateKey\" in keyPair) {\n return keyPair;\n } else {\n throw new Error(\"Invalid keyPair format:\" + JSON.stringify(json));\n }\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { IEventEmitter } from \"./types.js\";\n\nexport class NodeEventEmitter<\n Events extends Record<string, unknown>,\n> implements IEventEmitter<Events> {\n #emitter = new EventEmitter();\n\n constructor() {\n this.#emitter.setMaxListeners(0);\n }\n\n on<K extends keyof Events>(\n event: K,\n listener: (data: Events[K]) => void,\n ): () => void {\n this.#emitter.on(event as string, listener);\n return () => {\n this.#emitter.removeListener(event.toString(), listener);\n };\n }\n\n emit<K extends keyof Events>(event: K, data: Events[K]): void {\n this.#emitter.emit(event.toString(), data);\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { BaseStorage } from \"./common.js\";\n\nexport class NodeStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n> extends BaseStorage<T> {\n private readonly filePath: string;\n\n constructor(filePath: string) {\n super();\n this.filePath = filePath;\n\n const parentFolder = dirname(this.filePath);\n mkdirSync(parentFolder, { recursive: true });\n\n if (!existsSync(this.filePath)) {\n writeFileSync(this.filePath, JSON.stringify({}));\n }\n }\n\n private readData(): T {\n const data = readFileSync(this.filePath, \"utf-8\");\n return JSON.parse(data) as T;\n }\n\n private writeData(data: T): void {\n writeFileSync(this.filePath, JSON.stringify(data, null, 2));\n }\n\n get<Key extends keyof T>(key: Key): T[Key] | undefined {\n const data = this.readData();\n return data[key];\n }\n\n set<Key extends keyof T>(key: Key, value?: T[Key]): void {\n const data = this.readData();\n if (value === undefined) {\n delete data[key];\n } else {\n data[key] = value;\n }\n this.writeData(data);\n }\n\n delete(key: keyof T): void {\n const data = this.readData();\n delete data[key];\n this.writeData(data);\n }\n}\n","import type { Renown } from \"./common.js\";\nimport { NodeKeyStorage } from \"./crypto/node-key-storage.js\";\nimport { NodeEventEmitter } from \"./event/event.node.js\";\nimport { BaseRenownBuilder } from \"./renown-builder.js\";\nimport { NodeStorage } from \"./storage/storage.node.js\";\nimport type { RenownEvents, RenownStorageMap } from \"./types.js\";\n\nexport class NodeRenownEventEmitter extends NodeEventEmitter<RenownEvents> {}\nexport class NodeRenownStorage extends NodeStorage<RenownStorageMap> {}\n\nexport const DEFAULT_RENOWN_STORAGE_PATH = \"./.ph/.renown.json\";\n\nexport interface NodeRenownBuilderOptions {\n /** File path for user storage. Defaults to \".ph/.renown.json\" in cwd */\n storagePath?: string;\n /** File path for keypair storage. Defaults to \".ph/.keypair.json\" in cwd */\n keyPath?: string;\n /** Renown server URL. Defaults to https://www.renown.id */\n baseUrl?: string;\n /** Switchboard GraphQL endpoint for the direct-to-reactor flow. */\n switchboardUrl?: string;\n /** Re-check a stored credential on build (default \"always\"). */\n revalidate?: \"always\" | \"never\";\n}\n\n/** Node.js Renown builder: file-based user + key storage. */\nexport class RenownBuilder extends BaseRenownBuilder {\n #revalidate: \"always\" | \"never\";\n\n constructor(appName: string, options: NodeRenownBuilderOptions = {}) {\n super(appName);\n\n const {\n storagePath = DEFAULT_RENOWN_STORAGE_PATH,\n keyPath,\n baseUrl,\n switchboardUrl,\n revalidate = \"always\",\n } = options;\n\n this.#revalidate = revalidate;\n this.withKeyPairStorage(new NodeKeyStorage(keyPath));\n this.withStorage(new NodeRenownStorage(storagePath));\n this.withEventEmitter(new NodeRenownEventEmitter());\n if (baseUrl) {\n this.withBaseUrl(baseUrl);\n }\n if (switchboardUrl) {\n this.withSwitchboardUrl(switchboardUrl);\n }\n }\n\n // Node scripts/CLI act on auth state once and exit, so revalidation must\n // finish before build() resolves — block on it (unlike the browser builder).\n async build(): Promise<Renown> {\n const renown = await super.build();\n if (this.#revalidate === \"always\" && renown.user) {\n await renown.revalidate();\n }\n return renown;\n }\n}\n","import type { CreateBearerTokenOptions, IRenown, User } from \"./types.js\";\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst POLL_INTERVAL_MS = 500; // 0.5s: session store is in-memory, cheap to poll\nconst SECONDS_IN_DAY = 24 * 60 * 60;\n\nexport interface BrowserLoginOptions {\n /** Renown server URL */\n renownUrl: string;\n /** Timeout in milliseconds. Defaults to 5 minutes. */\n timeoutMs?: number;\n /** Called with the login URL and session ID before the browser is opened */\n onLoginUrl?: (url: string, sessionId: string) => void;\n /** Called on each poll tick while waiting for authentication */\n onPollTick?: () => void;\n /** Called when the browser failed to open automatically */\n onBrowserOpenFailed?: (url: string) => void;\n /** AbortSignal to cancel the login flow */\n signal?: AbortSignal;\n}\n\nexport interface BrowserLoginResult {\n user: User;\n cliDid: string;\n}\n\nexport interface AuthStatusResult {\n authenticated: boolean;\n address?: string;\n userDid?: string;\n chainId?: number;\n cliDid: string;\n authenticatedAt?: Date;\n baseUrl: string;\n}\n\ninterface PendingSessionResponse {\n sessionId: string;\n status: \"pending\";\n}\n\ninterface ReadySessionResponse {\n sessionId: string;\n status: \"ready\";\n address: string;\n chainId: number;\n did: string;\n credentialId: string;\n userDocumentId: string;\n}\n\ntype SessionResponse = PendingSessionResponse | ReadySessionResponse;\n\nfunction abortReason(signal: AbortSignal): Error {\n if (signal.reason instanceof Error) return signal.reason;\n if (signal.reason) return new Error(String(signal.reason));\n return new DOMException(\"Aborted\", \"AbortError\");\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortReason(signal));\n return;\n }\n const onAbort = () => {\n clearTimeout(timer);\n reject(abortReason(signal!));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\n/**\n * Open a URL in the default browser (cross-platform).\n */\nexport async function openBrowser(url: string): Promise<void> {\n const { execFile } = await import(\"node:child_process\");\n const { promisify } = await import(\"node:util\");\n const execFileAsync = promisify(execFile);\n const platform = process.platform;\n\n if (platform === \"darwin\") {\n await execFileAsync(\"open\", [url]);\n } else if (platform === \"win32\") {\n await execFileAsync(\"cmd\", [\"/c\", \"start\", \"\", url]);\n } else {\n await execFileAsync(\"xdg-open\", [url]);\n }\n}\n\nasync function pollSession(\n renownUrl: string,\n sessionId: string,\n timeoutMs: number,\n onPollTick?: () => void,\n signal?: AbortSignal,\n): Promise<ReadySessionResponse | null> {\n const startTime = Date.now();\n const sessionUrl = new URL(\n `/api/console/session/${sessionId}`,\n renownUrl,\n ).toString();\n\n while (Date.now() - startTime < timeoutMs) {\n signal?.throwIfAborted();\n try {\n const response = await fetch(sessionUrl, { signal });\n if (response.ok) {\n const data = (await response.json()) as SessionResponse;\n if (data.status === \"ready\") {\n return data;\n }\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\")\n throw error;\n // Network error, will retry\n }\n onPollTick?.();\n await sleep(POLL_INTERVAL_MS, signal);\n }\n\n return null;\n}\n\n/**\n * Perform a browser-based login flow with Renown.\n * Opens the user's browser to authenticate, then polls for completion.\n * Throws if already authenticated or if the flow times out.\n * If the browser fails to open, the flow continues polling — callers\n * can use onBrowserOpenFailed to show the URL as a fallback.\n */\nexport async function browserLogin(\n renown: IRenown,\n options: BrowserLoginOptions,\n): Promise<BrowserLoginResult> {\n if (renown.user?.credential) {\n throw new Error(\n `Already authenticated as ${renown.user.address}. Logout first.`,\n );\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const sessionId = crypto.randomUUID();\n\n const loginUrl = new URL(\"/console\", options.renownUrl);\n loginUrl.searchParams.set(\"session\", sessionId);\n loginUrl.searchParams.set(\"connect\", renown.did);\n loginUrl.searchParams.set(\"app\", renown.did);\n\n const url = loginUrl.toString();\n options.onLoginUrl?.(url, sessionId);\n\n try {\n await openBrowser(url);\n } catch {\n options.onBrowserOpenFailed?.(url);\n }\n\n const result = await pollSession(\n options.renownUrl,\n sessionId,\n timeoutMs,\n options.onPollTick,\n options.signal,\n );\n\n if (!result) {\n throw new Error(\"Authentication timed out.\");\n }\n\n const user = await renown.login(result.did);\n return { user, cliDid: renown.did };\n}\n\n/**\n * Get the current authentication status from a Renown instance.\n */\nexport function getAuthStatus(renown: IRenown): AuthStatusResult {\n const user = renown.user;\n const credential = user?.credential;\n\n return {\n authenticated: !!credential,\n address: user?.address,\n userDid: user?.did,\n chainId: user?.chainId,\n cliDid: renown.did,\n authenticatedAt: credential ? new Date(credential.issuanceDate) : undefined,\n baseUrl: renown.baseUrl,\n };\n}\n\nexport interface AccessTokenResult {\n token: string;\n did: string;\n address: string;\n expiresIn: number;\n}\n\n/**\n * Generate a bearer token for API authentication.\n * Requires the user to be authenticated (via browserLogin or equivalent).\n * Throws if not authenticated.\n */\nexport async function generateAccessToken(\n renown: IRenown,\n options?: CreateBearerTokenOptions,\n): Promise<AccessTokenResult> {\n const user = renown.user;\n if (!user?.credential) {\n throw new Error(\n \"Not authenticated. Login first to generate access tokens.\",\n );\n }\n\n const token = await renown.getBearerToken(options ?? {});\n\n return {\n token,\n did: renown.did,\n address: user.address,\n expiresIn: options?.expiresIn ?? 0,\n };\n}\n\n/**\n * Parse a human-readable expiry string to seconds.\n * Supports formats: \"7d\" (days), \"24h\" (hours), \"3600\" (seconds), \"3600s\" (seconds).\n * Only accepts positive integers — decimals like \"1.5h\" are rejected.\n */\nexport function parseExpiry(expiry: string): number {\n const trimmed = expiry.trim().toLowerCase();\n const match = trimmed.match(/^(\\d+)(d|h|s)?$/);\n\n if (!match) {\n throw new Error(\n `Invalid expiry format: ${expiry}. Expected a positive integer with optional suffix: \"7d\", \"24h\", \"3600s\", or \"3600\".`,\n );\n }\n\n const value = Number(match[1]);\n const unit = match[2];\n\n if (value <= 0) {\n throw new Error(\n `Invalid expiry format: ${expiry}. Value must be a positive integer.`,\n );\n }\n\n switch (unit) {\n case \"d\":\n return value * SECONDS_IN_DAY;\n case \"h\":\n return value * 60 * 60;\n default:\n return value;\n }\n}\n\n/**\n * Format an expiry duration in seconds to a human-readable string.\n */\nexport function formatExpiry(expiresIn: number): string {\n const days = Math.floor(expiresIn / SECONDS_IN_DAY);\n const hours = Math.floor((expiresIn % SECONDS_IN_DAY) / 3600);\n\n if (days > 0) {\n const dayStr = `${days} day${days !== 1 ? \"s\" : \"\"}`;\n if (hours > 0) {\n return `${dayStr} and ${hours} hour${hours !== 1 ? \"s\" : \"\"}`;\n }\n return dayStr;\n }\n\n if (hours > 0) {\n return `${hours} hour${hours !== 1 ? \"s\" : \"\"}`;\n }\n\n return `${expiresIn} second${expiresIn !== 1 ? \"s\" : \"\"}`;\n}\n","import { verifyAuthCredential } from \"./credential.js\";\nimport type { User } from \"./types.js\";\nimport { verifyAuthBearerToken } from \"./utils.js\";\n\n/** Server-side view of an authenticated Renown session. */\nexport interface RenownSession {\n /** Authenticated user identity derived from the session token. */\n user: User;\n /** App/client DID the token was issued by. */\n appDid: string;\n /** Token expiry (epoch seconds), when present. */\n expiresAt?: number;\n}\n\n/** Display hint carried alongside the token (unverified; not for auth). */\nexport interface RenownSessionProfile {\n name?: string | null;\n avatar?: string | null;\n /** Renown profile document id, so SSR can resolve profile links. */\n documentId?: string | null;\n username?: string | null;\n userImage?: string | null;\n}\n\n/** The `renown_session` cookie payload: the bearer token + a display hint. */\nexport interface RenownSessionCookie {\n token: string;\n profile?: RenownSessionProfile | null;\n}\n\nexport interface VerifyRenownSessionOptions {\n /** Expected `aud` claim on the token. */\n audience?: string;\n /** Switchboard GraphQL endpoint used when re-verifying the credential. */\n switchboardUrl?: string;\n /** Renown service base URL used when re-verifying the credential. */\n renownUrl?: string;\n /** Also re-verify the credential against Switchboard (default false = token-only, no network). */\n verifyCredential?: boolean;\n}\n\n/** Claims read from a session token without verifying its signature. */\nexport interface RenownSessionClaims {\n address?: string;\n chainId?: number;\n networkId?: string;\n /** Expiry in epoch seconds. */\n expiresAt?: number;\n}\n\n/** Serialize a session cookie value (token + optional display hint). */\nexport function serializeRenownSessionCookie(\n value: RenownSessionCookie,\n): string {\n return JSON.stringify(value);\n}\n\n// Parse the JSON cookie envelope { token, profile }; undefined if malformed.\nfunction parseSessionCookie(value: string): RenownSessionCookie | undefined {\n try {\n const parsed = JSON.parse(value) as unknown;\n if (\n parsed &&\n typeof parsed === \"object\" &&\n typeof (parsed as RenownSessionCookie).token === \"string\"\n ) {\n return parsed as RenownSessionCookie;\n }\n } catch {\n // Malformed cookie.\n }\n return undefined;\n}\n\n// Decode a session cookie's claims WITHOUT verifying the signature — cheap\n// optimistic checks only (e.g. proxy redirect); never trust for access control.\nexport function readSessionClaims(\n value: string,\n): RenownSessionClaims | undefined {\n const parsed = parseSessionCookie(value);\n if (!parsed) return undefined;\n const parts = parsed.token.split(\".\");\n if (parts.length < 2) return undefined;\n try {\n const json = Buffer.from(parts[1], \"base64url\").toString(\"utf8\");\n const payload = JSON.parse(json) as {\n exp?: number;\n vc?: {\n credentialSubject?: {\n address?: string;\n chainId?: number;\n networkId?: string;\n };\n };\n };\n const subject = payload.vc?.credentialSubject;\n return {\n address: subject?.address,\n chainId: subject?.chainId,\n networkId: subject?.networkId,\n expiresAt: payload.exp,\n };\n } catch {\n return undefined;\n }\n}\n\n// Verify a session cookie (envelope or bare token) → user, or undefined. Pass\n// verifyCredential:true to also check vs Switchboard; envelope hint is merged.\nexport async function verifyRenownSession(\n value: string,\n options: VerifyRenownSessionOptions = {},\n): Promise<RenownSession | undefined> {\n const { verifyCredential = false } = options;\n const parsed = parseSessionCookie(value);\n if (!parsed) return undefined;\n const { token, profile } = parsed;\n\n let session: RenownSession | undefined;\n if (verifyCredential) {\n const verified = await verifyAuthCredential(token, {\n audience: options.audience,\n renownUrl: options.renownUrl,\n switchboardUrl: options.switchboardUrl,\n });\n if (verified) {\n session = {\n user: {\n address: verified.address as `0x${string}`,\n chainId: verified.chainId,\n networkId: verified.networkId,\n did: verified.did,\n credential: verified.credential,\n },\n appDid: verified.appDid,\n };\n }\n } else {\n const verified = await verifyAuthBearerToken(token, {\n audience: options.audience,\n });\n if (verified) {\n const subject = verified.verifiableCredential.credentialSubject;\n const did = `did:pkh:${subject.networkId}:${subject.chainId}:${subject.address.toLowerCase()}`;\n session = {\n user: {\n address: subject.address as `0x${string}`,\n chainId: subject.chainId,\n networkId: subject.networkId,\n did,\n credential: undefined,\n },\n appDid: verified.issuer,\n expiresAt: verified.payload.exp,\n };\n }\n }\n\n if (!session) return undefined;\n\n // Merge the (unverified) display hint from the envelope — display only. The\n // richer fields make this seed shape-identical to the client's restored user.\n if (profile) {\n const name = profile.name ?? profile.username ?? undefined;\n const avatarUrl = profile.avatar ?? profile.userImage ?? undefined;\n const user = { ...session.user };\n if (name || avatarUrl) {\n user.ens = { name, avatarUrl };\n }\n // Only `documentId` makes a seeded profile useful (profile links); display\n // already flows through `ens`, so there is nothing to seed without it.\n if (profile.documentId) {\n user.profile = {\n documentId: profile.documentId,\n username: profile.username ?? null,\n userImage: profile.userImage ?? null,\n ethAddress: session.user.address,\n };\n }\n session.user = user;\n }\n return session;\n}\n"],"mappings":"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"}
|
|
@@ -666,11 +666,34 @@ var Renown = class {
|
|
|
666
666
|
await this.logout();
|
|
667
667
|
return false;
|
|
668
668
|
}
|
|
669
|
+
await this.refreshProfile();
|
|
669
670
|
return true;
|
|
670
671
|
} catch {
|
|
671
672
|
return true;
|
|
672
673
|
}
|
|
673
674
|
}
|
|
675
|
+
async refreshProfile() {
|
|
676
|
+
const user = this.user;
|
|
677
|
+
if (!user || !this.#profileFetcher) return false;
|
|
678
|
+
try {
|
|
679
|
+
const profile = await this.#profileFetcher(user, this.#baseUrl);
|
|
680
|
+
if (!profile) return false;
|
|
681
|
+
const current = this.user;
|
|
682
|
+
if (!current || current.address !== user.address || current.chainId !== user.chainId) return false;
|
|
683
|
+
if (current.profile !== void 0 && current.profile.documentId === profile.documentId && current.profile.username === profile.username && current.profile.userImage === profile.userImage) return false;
|
|
684
|
+
this.#updateUser({
|
|
685
|
+
...current,
|
|
686
|
+
profile,
|
|
687
|
+
ens: {
|
|
688
|
+
name: profile.username ?? void 0,
|
|
689
|
+
avatarUrl: profile.userImage ?? void 0
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
return true;
|
|
693
|
+
} catch {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
674
697
|
on(event, listener) {
|
|
675
698
|
return this.#eventEmitter.on(event, listener);
|
|
676
699
|
}
|
|
@@ -838,4 +861,4 @@ var BaseRenownBuilder = class BaseRenownBuilder {
|
|
|
838
861
|
//#endregion
|
|
839
862
|
export { VERIFIABLE_CREDENTIAL_EIP712_TYPE as S, DEFAULT_RENOWN_NETWORK_ID as _, BaseStorage as a, ISSUER_TYPE as b, recoverCredentialSigner as c, SwitchboardClient as d, resolveSwitchboardEndpoint as f, DEFAULT_RENOWN_CHAIN_ID as g, CREDENTIAL_TYPES as h, RenownMemoryStorage as i, verifyAuthCredential as l, CREDENTIAL_SUBJECT_TYPE as m, fetchRenownProfile as n, buildAndSignCredential as o, CREDENTIAL_SCHEMA_EIP712_TYPE as p, Renown as r, fetchDelegationCredential as s, BaseRenownBuilder as t, verifyCredentialSignature as u, DEFAULT_RENOWN_URL as v, RENOWN_SESSION_COOKIE as x, DOMAIN_TYPE as y };
|
|
840
863
|
|
|
841
|
-
//# sourceMappingURL=renown-builder-
|
|
864
|
+
//# sourceMappingURL=renown-builder-1WTEoRc6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renown-builder-BqWoYtBR.js","names":["#endpoint","#request","#store","#eventEmitter","#baseUrl","#crypto","#appName","#profileFetcher","#switchboard","#signer","#status","#updateStatus","#getCredential","#updateUser","#completeLogin","#listeners","#appName","#storage","#eventEmitter","#crypto","#keyPairStorage","#baseUrl","#switchboardUrl","#profileFetcher"],"sources":["../src/constants.ts","../src/discovery.ts","../src/switchboard.ts","../src/credential.ts","../src/storage/common.ts","../src/common.ts","../src/event/memory.ts","../src/profile.ts","../src/renown-builder.ts"],"sourcesContent":["export const DEFAULT_RENOWN_URL = \"https://www.renown.id\";\nexport const DEFAULT_RENOWN_NETWORK_ID = \"eip155\";\nexport const DEFAULT_RENOWN_CHAIN_ID = \"1\";\n\n/** Default cookie name for a server-readable Renown session (bearer token). */\nexport const RENOWN_SESSION_COOKIE = \"renown_session\";\n\nexport const DOMAIN_TYPE = [\n { name: \"version\", type: \"string\" },\n { name: \"chainId\", type: \"uint256\" },\n] as const;\n\nexport const VERIFIABLE_CREDENTIAL_EIP712_TYPE = [\n { name: \"@context\", type: \"string[]\" },\n { name: \"type\", type: \"string[]\" },\n { name: \"id\", type: \"string\" },\n { name: \"issuer\", type: \"Issuer\" },\n { name: \"credentialSubject\", type: \"CredentialSubject\" },\n { name: \"credentialSchema\", type: \"CredentialSchema\" },\n { name: \"issuanceDate\", type: \"string\" },\n { name: \"expirationDate\", type: \"string\" },\n] as const;\n\nexport const CREDENTIAL_SCHEMA_EIP712_TYPE = [\n { name: \"id\", type: \"string\" },\n { name: \"type\", type: \"string\" },\n] as const;\n\nexport const CREDENTIAL_SUBJECT_TYPE = [\n { name: \"app\", type: \"string\" },\n { name: \"id\", type: \"string\" },\n] as const;\n\nexport const ISSUER_TYPE = [\n { name: \"id\", type: \"string\" },\n { name: \"ethereumAddress\", type: \"string\" },\n] as const;\n\nexport const CREDENTIAL_TYPES = {\n EIP712Domain: DOMAIN_TYPE,\n VerifiableCredential: VERIFIABLE_CREDENTIAL_EIP712_TYPE,\n CredentialSchema: CREDENTIAL_SCHEMA_EIP712_TYPE,\n CredentialSubject: CREDENTIAL_SUBJECT_TYPE,\n Issuer: ISSUER_TYPE,\n} as const;\n","export interface ResolveSwitchboardEndpointOptions {\n // Explicit Switchboard GraphQL endpoint. When set, used directly.\n switchboardUrl?: string;\n // Renown base URL to ask for a switchboard endpoint when none is explicit.\n baseUrl?: string;\n // Max time (ms) to wait for the discovery probe before falling back to REST.\n timeoutMs?: number;\n}\n\n// Legacy Renown instances accept the connection but never respond to the\n// discovery request; without a bound, `fetch` hangs and blocks startup.\nconst DEFAULT_DISCOVERY_TIMEOUT_MS = 3000;\n\n// Shape returned by the Renown app's `/api/switchboard` discovery endpoint.\ninterface DiscoveryResponse {\n endpoint?: string;\n}\n\n// Resolve the Switchboard GraphQL endpoint: explicit `switchboardUrl` wins,\n// else discover via `{baseUrl}/api/switchboard`; undefined means use REST.\nexport async function resolveSwitchboardEndpoint(\n options: ResolveSwitchboardEndpointOptions,\n): Promise<string | undefined> {\n const { switchboardUrl, baseUrl, timeoutMs } = options;\n\n if (switchboardUrl) {\n return switchboardUrl;\n }\n\n if (!baseUrl) {\n return undefined;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n timeoutMs ?? DEFAULT_DISCOVERY_TIMEOUT_MS,\n );\n\n try {\n const url = new URL(\"/api/switchboard\", baseUrl);\n const response = await fetch(url, {\n method: \"GET\",\n signal: controller.signal,\n });\n if (!response.ok) {\n return undefined;\n }\n const body = (await response.json()) as DiscoveryResponse;\n return body.endpoint || undefined;\n } catch {\n // Old Renown instances never answer (or lack the endpoint); the abort\n // timeout rejects here so we fall back to the REST flow instead of hanging.\n return undefined;\n } finally {\n clearTimeout(timeout);\n }\n}\n","import {\n createAction,\n type Action,\n} from \"@powerhousedao/shared/document-model\";\nimport { CREDENTIAL_TYPES } from \"./constants.js\";\nimport type {\n PowerhouseVerifiableCredential,\n ProfileFetcher,\n RenownProfile,\n} from \"./types.js\";\n\n// Per-user drive convention shared with the Renown app: `renown-<address>`.\n// The read-model ignores driveId, but we pass it for parity.\nfunction userDriveId(address: string): string {\n return `renown-${address.toLowerCase()}`;\n}\n\n// Flat row returned by the `renownCredentials` read-model query.\ninterface ReadRenownCredential {\n documentId: string;\n credentialId: string;\n context: string[];\n type: string[];\n issuerId: string;\n issuerEthereumAddress: string;\n issuanceDate: string;\n expirationDate: string | null;\n credentialSubjectId: string | null;\n credentialSubjectApp: string;\n credentialStatusId: string | null;\n credentialStatusType: string | null;\n credentialSchemaId: string;\n credentialSchemaType: string;\n proofVerificationMethod: string;\n proofEthereumAddress: string;\n proofCreated: string;\n proofPurpose: string;\n proofType: string;\n proofValue: string;\n proofEip712Domain: string;\n proofEip712PrimaryType: string;\n revoked: boolean;\n}\n\n// Flat row returned by the `renownUsers` read-model query.\ninterface ReadRenownUser {\n documentId: string;\n username: string | null;\n ethAddress: string | null;\n userImage: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nconst CREDENTIALS_QUERY = /* GraphQL */ `\n query RenownCredentials($input: RenownCredentialsInput!) {\n renownCredentials(input: $input) {\n documentId\n credentialId\n context\n type\n issuerId\n issuerEthereumAddress\n issuanceDate\n expirationDate\n credentialSubjectId\n credentialSubjectApp\n credentialStatusId\n credentialStatusType\n credentialSchemaId\n credentialSchemaType\n proofVerificationMethod\n proofEthereumAddress\n proofCreated\n proofPurpose\n proofType\n proofValue\n proofEip712Domain\n proofEip712PrimaryType\n revoked\n }\n }\n`;\n\nconst USERS_QUERY = /* GraphQL */ `\n query RenownUsers($input: RenownUsersInput!) {\n renownUsers(input: $input) {\n documentId\n username\n ethAddress\n userImage\n createdAt\n updatedAt\n }\n }\n`;\n\nconst CREATE_EMPTY_DOCUMENT_MUTATION = /* GraphQL */ `\n mutation CreateEmptyDocument(\n $documentType: String!\n $parentIdentifier: String\n ) {\n createEmptyDocument(\n documentType: $documentType\n parentIdentifier: $parentIdentifier\n ) {\n id\n }\n }\n`;\n\nconst MUTATE_DOCUMENT_MUTATION = /* GraphQL */ `\n mutation MutateDocument(\n $documentIdentifier: String!\n $actions: [JSONObject!]!\n ) {\n mutateDocument(documentIdentifier: $documentIdentifier, actions: $actions) {\n id\n }\n }\n`;\n\nconst RENOWN_CREDENTIAL_DOC_TYPE = \"powerhouse/renown-credential\";\nconst RENOWN_USER_DOC_TYPE = \"powerhouse/renown-user\";\n\n// Rebuild the nested EIP-712 verifiable credential from a flat read-model row.\nfunction reshapeCredential(\n row: ReadRenownCredential,\n): PowerhouseVerifiableCredential {\n // `proofEip712Domain` is stored as a JSON string ({ version, chainId }).\n const domain = JSON.parse(row.proofEip712Domain) as {\n version: string;\n chainId: number;\n };\n\n return {\n \"@context\": row.context,\n type: row.type,\n id: row.credentialId,\n issuer: {\n id: row.issuerId,\n ethereumAddress: row.issuerEthereumAddress as `0x${string}`,\n },\n credentialSubject: {\n id: row.credentialSubjectId ?? \"\",\n app: row.credentialSubjectApp,\n },\n credentialSchema: {\n id: row.credentialSchemaId,\n type: row.credentialSchemaType,\n },\n ...(row.credentialStatusId\n ? {\n credentialStatus: {\n id: row.credentialStatusId,\n type: row.credentialStatusType ?? \"\",\n },\n }\n : {}),\n issuanceDate: row.issuanceDate,\n expirationDate: row.expirationDate ?? \"\",\n proof: {\n type: row.proofType,\n created: row.proofCreated,\n verificationMethod: row.proofVerificationMethod,\n proofPurpose: row.proofPurpose,\n proofValue: row.proofValue,\n ethereumAddress: row.proofEthereumAddress as `0x${string}`,\n eip712: {\n domain,\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n}\n\n// The chain id in a `did:pkh:<net>:<chainId>:<address>` issuer id.\nfunction issuerChainId(issuerId: string): string | undefined {\n return issuerId.split(\":\")[3];\n}\n\n// Reads a Switchboard reactor's `renown-read-model` subgraph directly over\n// GraphQL, replacing the Renown Next.js REST proxy. Read-only; plain `fetch`.\nexport class SwitchboardClient {\n #endpoint: string;\n\n constructor(endpoint: string) {\n this.#endpoint = endpoint;\n }\n\n get endpoint() {\n return this.#endpoint;\n }\n\n async #request<T>(\n query: string,\n variables: Record<string, unknown>,\n ): Promise<T> {\n const response = await fetch(this.#endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ query, variables }),\n });\n if (!response.ok) {\n throw new Error(`Switchboard request failed: ${response.status}`);\n }\n const body = (await response.json()) as {\n data?: T;\n errors?: { message: string }[];\n };\n if (body.errors?.length) {\n throw new Error(body.errors.map((e) => e.message).join(\"; \"));\n }\n if (!body.data) {\n throw new Error(\"Switchboard returned no data\");\n }\n return body.data;\n }\n\n // Fetch the active delegation credential for (address, chainId) that delegates\n // to `appDid`: filter by chainId, drop expired, return most recent.\n async getCredential(params: {\n address: string;\n chainId: number;\n appDid: string;\n }): Promise<PowerhouseVerifiableCredential | undefined> {\n const { address, chainId, appDid } = params;\n const { renownCredentials } = await this.#request<{\n renownCredentials: ReadRenownCredential[];\n }>(CREDENTIALS_QUERY, {\n input: {\n driveId: userDriveId(address),\n ethAddress: address.toLowerCase(),\n did: appDid,\n includeRevoked: false,\n },\n });\n\n const now = Date.now();\n const candidates = renownCredentials\n .filter((row) => issuerChainId(row.issuerId) === String(chainId))\n .filter((row) => {\n if (!row.expirationDate) return true;\n const expiresAt = Date.parse(row.expirationDate);\n return !Number.isNaN(expiresAt) && expiresAt > now;\n })\n .sort((a, b) => Date.parse(b.issuanceDate) - Date.parse(a.issuanceDate));\n\n const mostRecent = candidates.at(0);\n return mostRecent ? reshapeCredential(mostRecent) : undefined;\n }\n\n // Look up a Renown profile by ethereum address via the `renownUsers` query.\n async getProfileByAddress(\n address: string,\n ): Promise<RenownProfile | undefined> {\n const { renownUsers } = await this.#request<{\n renownUsers: ReadRenownUser[];\n }>(USERS_QUERY, {\n input: {\n driveId: userDriveId(address),\n ethAddresses: [address.toLowerCase()],\n },\n });\n\n const user = renownUsers.at(0);\n if (!user) return undefined;\n return {\n documentId: user.documentId,\n username: user.username,\n ethAddress: user.ethAddress,\n userImage: user.userImage,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt,\n };\n }\n\n // Create an empty document of the given type; returns its document id.\n async createEmptyDocument(\n documentType: string,\n parentIdentifier?: string,\n ): Promise<string> {\n const { createEmptyDocument } = await this.#request<{\n createEmptyDocument: { id: string };\n }>(CREATE_EMPTY_DOCUMENT_MUTATION, { documentType, parentIdentifier });\n return createEmptyDocument.id;\n }\n\n // Apply reactor action envelopes to a document; returns its document id.\n async mutateDocument(\n documentIdentifier: string,\n actions: Action[],\n ): Promise<string> {\n const { mutateDocument } = await this.#request<{\n mutateDocument: { id: string };\n }>(MUTATE_DOCUMENT_MUTATION, { documentIdentifier, actions });\n return mutateDocument.id;\n }\n\n // Issue a signed credential: create a renown-credential doc and INIT it.\n async issueCredential(\n credential: PowerhouseVerifiableCredential,\n ): Promise<string> {\n const documentId = await this.createEmptyDocument(\n RENOWN_CREDENTIAL_DOC_TYPE,\n );\n const input: Record<string, unknown> = {\n id: credential.id,\n context: credential[\"@context\"],\n type: credential.type,\n issuer: {\n id: credential.issuer.id,\n ethereumAddress: credential.issuer.ethereumAddress,\n },\n credentialSubject: {\n id: credential.credentialSubject.id,\n app: credential.credentialSubject.app,\n },\n credentialSchema: {\n id: credential.credentialSchema.id,\n type: credential.credentialSchema.type,\n },\n issuanceDate: credential.issuanceDate,\n expirationDate: credential.expirationDate || undefined,\n proof: {\n type: credential.proof.type,\n created: credential.proof.created,\n verificationMethod: credential.proof.verificationMethod,\n proofPurpose: credential.proof.proofPurpose,\n proofValue: credential.proof.proofValue,\n ethereumAddress: credential.proof.ethereumAddress,\n eip712: {\n domain: {\n version: credential.proof.eip712.domain.version,\n chainId: credential.proof.eip712.domain.chainId,\n },\n primaryType: credential.proof.eip712.primaryType,\n },\n },\n };\n await this.mutateDocument(documentId, [createAction(\"INIT\", input)]);\n return documentId;\n }\n\n // Find the RenownUser for an address or create one; returns its document id.\n async findOrCreateUser(\n address: string,\n profile: { username?: string; userImage?: string } = {},\n ): Promise<string> {\n const updates: Action[] = [];\n if (profile.username !== undefined) {\n updates.push(\n createAction(\"SET_USERNAME\", { username: profile.username }),\n );\n }\n if (profile.userImage !== undefined) {\n updates.push(\n createAction(\"SET_USER_IMAGE\", { userImage: profile.userImage }),\n );\n }\n\n const existing = await this.getProfileByAddress(address);\n if (existing) {\n if (updates.length)\n await this.mutateDocument(existing.documentId, updates);\n return existing.documentId;\n }\n\n const documentId = await this.createEmptyDocument(RENOWN_USER_DOC_TYPE);\n await this.mutateDocument(documentId, [\n createAction(\"SET_ETH_ADDRESS\", { ethAddress: address }),\n ...updates,\n ]);\n return documentId;\n }\n\n // Revoke a credential by its document id.\n async revokeCredential(documentId: string, reason?: string): Promise<void> {\n await this.mutateDocument(documentId, [\n createAction(\"REVOKE\", {\n revokedAt: new Date().toISOString(),\n reason: reason ?? null,\n }),\n ]);\n }\n\n // A ProfileFetcher backed by this client; used as the default when the\n // direct-switchboard flow is active. The `baseUrl` argument is ignored.\n profileFetcher: ProfileFetcher = (user) =>\n this.getProfileByAddress(user.address).catch(() => undefined);\n}\n","import { recoverTypedDataAddress } from \"viem\";\nimport {\n CREDENTIAL_TYPES,\n DEFAULT_RENOWN_NETWORK_ID,\n DEFAULT_RENOWN_URL,\n} from \"./constants.js\";\nimport { resolveSwitchboardEndpoint } from \"./discovery.js\";\nimport { SwitchboardClient } from \"./switchboard.js\";\nimport type { IProof, PowerhouseVerifiableCredential } from \"./types.js\";\nimport { verifyAuthBearerToken } from \"./utils.js\";\n\n/* Local structural aliases (EIP-712 standard shapes) so renown's public .d.ts\n * never names viem — a viem type in the surface drags viem's whole closure in. */\ntype Hex = `0x${string}`;\ntype TypedDataDomain = {\n name?: string;\n version?: string;\n chainId?: number;\n verifyingContract?: Hex;\n salt?: Hex;\n};\ntype TypedDataParameter = { name: string; type: string };\n\n/** EIP-712 domain as signed by the credential issuer. */\nexport type CredentialDomain = {\n version: string;\n chainId: number;\n};\n\n/** The credential body that is EIP-712 signed (everything except `proof`). */\nexport type CredentialMessage = {\n \"@context\": string[];\n type: string[];\n id: string;\n issuer: { id: string; ethereumAddress: Hex };\n credentialSubject: { id: string; app: string };\n credentialSchema: { id: string; type: string };\n issuanceDate: string;\n expirationDate: string;\n};\n\n/** Typed-data signer; matches the loose shape used by wallet adapters. */\nexport type SignCredentialTypedData = (args: {\n domain: TypedDataDomain;\n types: Record<string, readonly TypedDataParameter[]>;\n primaryType: string;\n message: Record<string, unknown>;\n}) => Promise<Hex>;\n\nexport interface BuildCredentialParams {\n signTypedData: SignCredentialTypedData;\n address: Hex;\n chainId: number;\n app: string;\n /** Credential subject id: the app/client DID the credential delegates to. */\n appId: string;\n expiresInDays?: number;\n}\n\n/** Assemble a Renown delegation VC and sign it with the provided signer. */\nexport async function buildAndSignCredential(\n params: BuildCredentialParams,\n): Promise<PowerhouseVerifiableCredential> {\n const {\n signTypedData,\n address,\n chainId,\n app,\n appId,\n expiresInDays = 7,\n } = params;\n\n const issuerId = `did:pkh:${DEFAULT_RENOWN_NETWORK_ID}:${chainId}:${address.toLowerCase()}`;\n const credentialId = `urn:uuid:${globalThis.crypto.randomUUID()}`;\n const now = new Date();\n const expirationDate = new Date(\n now.getTime() + expiresInDays * 24 * 60 * 60 * 1000,\n );\n\n const message: CredentialMessage = {\n \"@context\": [\"https://www.w3.org/2018/credentials/v1\"],\n type: [\"VerifiableCredential\", \"RenownCredential\"],\n id: credentialId,\n issuer: { id: issuerId, ethereumAddress: address },\n credentialSubject: { id: appId, app },\n credentialSchema: {\n id: \"https://renown.id/schemas/renown-credential/v1\",\n type: \"JsonSchemaValidator2018\",\n },\n issuanceDate: now.toISOString(),\n expirationDate: expirationDate.toISOString(),\n };\n\n const domain: CredentialDomain = { version: \"1\", chainId };\n\n // viem and most wallet adapters reserve EIP712Domain and derive it from\n // `domain` — passing it explicitly makes them throw.\n const { EIP712Domain, ...signTypes } = CREDENTIAL_TYPES;\n void EIP712Domain;\n const signature = await signTypedData({\n domain,\n types: signTypes,\n primaryType: \"VerifiableCredential\",\n message,\n });\n\n return {\n ...message,\n proof: {\n type: \"EthereumEip712Signature2021\",\n created: message.issuanceDate,\n verificationMethod: issuerId,\n proofPurpose: \"assertionMethod\",\n proofValue: signature,\n ethereumAddress: address,\n eip712: {\n domain,\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n}\n\n/** Recover the address that signed a credential's EIP-712 proof. */\nexport async function recoverCredentialSigner(\n credential: PowerhouseVerifiableCredential,\n): Promise<Hex> {\n const { proof, ...message } = credential;\n // Drop EIP712Domain so viem derives it from `domain`; viem ignores\n // message keys not present in the types, so the proof is excluded too.\n const { EIP712Domain, ...types } = CREDENTIAL_TYPES;\n void EIP712Domain;\n return recoverTypedDataAddress({\n domain: proof.eip712.domain,\n types,\n primaryType: \"VerifiableCredential\",\n message,\n signature: proof.proofValue as Hex,\n } as Parameters<typeof recoverTypedDataAddress>[0]);\n}\n\n/** True when the proof was signed by the credential's declared issuer address. */\nexport async function verifyCredentialSignature(\n credential: PowerhouseVerifiableCredential,\n): Promise<boolean> {\n try {\n const recovered = await recoverCredentialSigner(credential);\n return (\n recovered.toLowerCase() ===\n credential.issuer.ethereumAddress.toLowerCase()\n );\n } catch {\n // Malformed proof (bad hex, missing fields) is an invalid signature.\n return false;\n }\n}\n\n// The deployed Renown API may omit proof.eip712.domain; it's canonical\n// (version \"1\", the credential's chainId), so reconstruct it before verifying.\nfunction withEip712Domain(\n credential: PowerhouseVerifiableCredential,\n chainId: number,\n): PowerhouseVerifiableCredential {\n const eip712 = credential.proof.eip712 as\n | Partial<IProof[\"eip712\"]>\n | undefined;\n if (eip712?.domain) return credential;\n return {\n ...credential,\n proof: {\n ...credential.proof,\n eip712: {\n domain: { version: \"1\", chainId },\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n}\n\nexport interface FetchDelegationCredentialOptions {\n /** Ethereum address that must have issued the credential. */\n address: string;\n /** Chain id the credential must be scoped to. */\n chainId: number;\n /** App/client DID the credential must delegate to (credentialSubject.id). */\n appDid: string;\n /** Renown service base URL. Defaults to DEFAULT_RENOWN_URL. */\n baseUrl?: string;\n /** Switchboard GraphQL endpoint; when reachable, read the reactor directly. */\n switchboardUrl?: string;\n /** Probe {baseUrl}/api/switchboard for an endpoint (default true). */\n discover?: boolean;\n /** Re-verify the EIP-712 proof signature (default true). */\n verifySignature?: boolean;\n}\n\n// Fetch + binding/expiry-validate the credential over the Renown REST API.\nasync function fetchDelegationCredentialRest(params: {\n address: string;\n chainId: number;\n appDid: string;\n baseUrl: string;\n}): Promise<PowerhouseVerifiableCredential | undefined> {\n const { address, chainId, appDid, baseUrl } = params;\n const url = new URL(\n `/api/auth/credential?address=${encodeURIComponent(address)}&chainId=${encodeURIComponent(chainId)}&connectId=${encodeURIComponent(appDid)}&appId=${encodeURIComponent(appDid)}`,\n baseUrl,\n );\n const response = await fetch(url, { method: \"GET\" });\n if (!response.ok) return undefined;\n const { credential } = (await response.json()) as {\n credential?: PowerhouseVerifiableCredential;\n };\n if (!credential) return undefined;\n\n // Binding: delegates to this app DID, issued by this address on this chain\n // (issuer.id = did:pkh:<networkId>:<chainId>:<address>).\n const [, , , issuerChainId, issuerAddress] = credential.issuer.id.split(\":\");\n if (\n credential.credentialSubject.id !== appDid ||\n issuerChainId !== String(chainId) ||\n issuerAddress.toLowerCase() !== address.toLowerCase() ||\n credential.issuer.ethereumAddress.toLowerCase() !== address.toLowerCase()\n ) {\n return undefined;\n }\n\n // Reject an expired credential (revocation drops it from the endpoint\n // instead); a malformed date (NaN) counts as invalid, not non-expiring.\n if (credential.expirationDate) {\n const expiresAt = Date.parse(credential.expirationDate);\n if (Number.isNaN(expiresAt) || expiresAt <= Date.now()) {\n return undefined;\n }\n }\n\n return credential;\n}\n\n// Optionally re-verify the EIP-712 proof; returns the credential or undefined.\nasync function finalizeCredential(\n credential: PowerhouseVerifiableCredential,\n chainId: number,\n verifySignature: boolean,\n): Promise<PowerhouseVerifiableCredential | undefined> {\n if (!verifySignature) return credential;\n const withDomain = withEip712Domain(credential, chainId);\n if (\n withDomain.proof.eip712.domain.chainId !== chainId ||\n !(await verifyCredentialSignature(withDomain))\n ) {\n return undefined;\n }\n return withDomain;\n}\n\n// Fetch the Renown delegation credential for (address, chainId) and validate it\n// delegates to `appDid`; returns it, or undefined if absent/invalid. No throw.\nexport async function fetchDelegationCredential(\n options: FetchDelegationCredentialOptions,\n): Promise<PowerhouseVerifiableCredential | undefined> {\n const {\n address,\n chainId,\n appDid,\n switchboardUrl,\n discover = true,\n verifySignature = true,\n } = options;\n const explicitBaseUrl = options.baseUrl;\n const baseUrl = explicitBaseUrl ?? DEFAULT_RENOWN_URL;\n try {\n // An explicit switchboardUrl is used directly; otherwise discover from the\n // base URL unless disabled (callers that already resolved the endpoint).\n const endpoint = switchboardUrl\n ? switchboardUrl\n : discover && explicitBaseUrl\n ? await resolveSwitchboardEndpoint({ baseUrl })\n : undefined;\n\n const credential = endpoint\n ? await new SwitchboardClient(endpoint).getCredential({\n address,\n chainId,\n appDid,\n })\n : await fetchDelegationCredentialRest({\n address,\n chainId,\n appDid,\n baseUrl,\n });\n\n if (!credential) return undefined;\n return await finalizeCredential(credential, chainId, verifySignature);\n } catch {\n return undefined;\n }\n}\n\nexport interface VerifiedAuthCredential {\n address: string;\n chainId: number;\n networkId: string;\n /** Owner identity: the pkh DID (did:pkh:<net>:<chainId>:<address>). */\n did: string;\n /** App/client DID the bearer token was issued by. */\n appDid: string;\n credential: PowerhouseVerifiableCredential;\n}\n\nexport interface VerifyAuthCredentialOptions {\n /** Expected `aud` claim on the bearer token. */\n audience?: string;\n /** Renown service base URL. */\n renownUrl?: string;\n /** Switchboard GraphQL endpoint; when reachable, read the reactor directly. */\n switchboardUrl?: string;\n /** Re-verify the credential's EIP-712 proof (default true). */\n verifySignature?: boolean;\n}\n\n// Verify a renown bearer token end to end: check the JWT, then fetch+verify the\n// matching credential. Resolves the owner identity, or undefined. No throw.\nexport async function verifyAuthCredential(\n jwt: string,\n options: VerifyAuthCredentialOptions = {},\n): Promise<VerifiedAuthCredential | undefined> {\n const verified = await verifyAuthBearerToken(jwt, {\n audience: options.audience,\n });\n if (!verified) return undefined;\n\n const { address, chainId, networkId } =\n verified.verifiableCredential.credentialSubject;\n const appDid = verified.issuer;\n const credential = await fetchDelegationCredential({\n address,\n chainId,\n appDid,\n baseUrl: options.renownUrl,\n switchboardUrl: options.switchboardUrl,\n verifySignature: options.verifySignature,\n });\n if (!credential) return undefined;\n\n return {\n address,\n chainId,\n networkId,\n did: credential.issuer.id,\n appDid,\n credential,\n };\n}\n","export interface IStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n Key extends keyof T = keyof T,\n> {\n get(key: Key): T[Key] | undefined;\n set(key: Key, value?: T[Key]): void;\n delete(key: Key): void;\n}\n\nexport abstract class BaseStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n Key extends keyof T = keyof T,\n> implements IStorage<T> {\n abstract get(key: Key): T[Key] | undefined;\n abstract set(key: Key, value?: T[Key]): void;\n abstract delete(key: Key): void;\n}\n\nexport class MemoryStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n Key extends keyof T = keyof T,\n> extends BaseStorage<T> {\n private readonly data = new Map<Key, T[Key]>();\n\n get(key: Key) {\n return this.data.get(key);\n }\n\n set(key: Key, value?: T[Key]): void {\n if (value === undefined) {\n this.data.delete(key);\n } else {\n this.data.set(key, value);\n }\n }\n\n delete(key: Key): void {\n this.data.delete(key);\n }\n}\n","import {\n CREDENTIAL_TYPES,\n DEFAULT_RENOWN_NETWORK_ID,\n DEFAULT_RENOWN_URL,\n} from \"./constants.js\";\nimport {\n buildAndSignCredential,\n verifyCredentialSignature,\n} from \"./credential.js\";\nimport { RenownCryptoSigner, type IRenownCrypto } from \"./crypto/index.js\";\nimport { MemoryStorage } from \"./storage/common.js\";\nimport type { SwitchboardClient } from \"./switchboard.js\";\nimport type {\n CreateBearerTokenOptions,\n IProof,\n IRenown,\n ISigner,\n LoginStatus,\n PKHDid,\n PowerhouseVerifiableCredential,\n ProfileFetcher,\n RenownEventEmitter,\n RenownEvents,\n RenownStorage,\n RenownStorageMap,\n SignInParams,\n User,\n} from \"./types.js\";\nimport { parsePkhDid, verifyAuthBearerToken } from \"./utils.js\";\nexport * from \"./constants.js\";\n\nexport class RenownMemoryStorage extends MemoryStorage<RenownStorageMap> {}\n\nexport class Renown implements IRenown {\n #baseUrl: string;\n #store: RenownStorage;\n #eventEmitter: RenownEventEmitter;\n #appName: string;\n #crypto: IRenownCrypto;\n #signer: ISigner;\n #profileFetcher?: ProfileFetcher;\n #switchboard?: SwitchboardClient;\n #status: LoginStatus = \"initial\";\n\n constructor(\n store: RenownStorage,\n eventEmitter: RenownEventEmitter,\n crypto: IRenownCrypto,\n appName: string,\n baseUrl = DEFAULT_RENOWN_URL,\n profileFetcher?: ProfileFetcher,\n switchboard?: SwitchboardClient,\n ) {\n this.#store = store;\n this.#eventEmitter = eventEmitter;\n this.#baseUrl = baseUrl;\n this.#crypto = crypto;\n this.#appName = appName;\n this.#profileFetcher = profileFetcher;\n this.#switchboard = switchboard;\n const restoredUser = this.user;\n this.#signer = new RenownCryptoSigner(crypto, this.#appName, restoredUser);\n\n // A restored, previously-verified user is an authorized session; otherwise\n // status stays \"initial\" after a reload while the user is present.\n if (restoredUser) {\n this.#status = \"authorized\";\n }\n\n this.on(\"user\", (user) => {\n this.#signer.user = user;\n });\n }\n\n get baseUrl() {\n return this.#baseUrl;\n }\n\n get user() {\n return this.#store.get(\"user\");\n }\n\n get status() {\n return this.#status;\n }\n\n get signer() {\n return this.#signer;\n }\n\n get crypto() {\n return this.#crypto;\n }\n\n get did() {\n return this.#crypto.did;\n }\n\n get profileFetcher() {\n return this.#profileFetcher;\n }\n\n #updateStatus(status: LoginStatus) {\n this.#status = status;\n this.#eventEmitter.emit(\"status\", status);\n }\n\n #updateUser(user: User | undefined) {\n if (user) {\n this.#store.set(\"user\", user);\n } else {\n this.#store.delete(\"user\");\n }\n this.#eventEmitter.emit(\"user\", user);\n }\n\n async login(userDid: string): Promise<User> {\n this.#updateStatus(\"checking\");\n try {\n const result = parsePkhDid(userDid);\n const credential = await this.#getCredential(\n result.address,\n result.chainId,\n this.#crypto.did,\n );\n\n if (!credential) {\n this.#updateUser(undefined);\n throw new Error(\"Credential not found\");\n }\n\n return await this.#completeLogin(userDid, result, credential);\n } catch (error) {\n this.#updateUser(undefined);\n this.#updateStatus(\"not-authorized\");\n throw error;\n }\n }\n\n // Sign in without the Renown redirect: build + sign a delegation credential\n // with the caller's wallet signer, write it to the switchboard, then log in.\n async signIn(params: SignInParams): Promise<User> {\n if (!this.#switchboard) {\n throw new Error(\n \"signIn requires a switchboard endpoint. Set switchboardUrl or a discoverable baseUrl.\",\n );\n }\n const {\n address,\n chainId,\n signTypedData,\n username,\n userImage,\n expiresInDays,\n } = params;\n\n this.#updateStatus(\"checking\");\n try {\n const credential = await buildAndSignCredential({\n signTypedData,\n address,\n chainId,\n app: this.#appName,\n appId: this.did,\n expiresInDays,\n });\n\n await this.#switchboard.issueCredential(credential);\n await this.#switchboard.findOrCreateUser(address, {\n username,\n userImage,\n });\n\n const userDid = `did:pkh:${DEFAULT_RENOWN_NETWORK_ID}:${chainId}:${address.toLowerCase()}`;\n // Authenticate from the freshly signed credential — no read-back, which\n // avoids racing the read-model processor that indexes the write.\n return await this.#completeLogin(\n userDid,\n parsePkhDid(userDid),\n credential,\n );\n } catch (error) {\n this.#updateUser(undefined);\n this.#updateStatus(\"not-authorized\");\n throw error;\n }\n }\n\n // Verify a credential binds to userDid + this app key, set the user, and\n // start the background profile fetch. Throws if the credential is invalid.\n async #completeLogin(\n userDid: string,\n result: PKHDid,\n credential: PowerhouseVerifiableCredential,\n ): Promise<User> {\n if (\n !(\n credential.issuer.id === userDid &&\n credential.credentialSubject.id === this.did\n )\n ) {\n throw new Error(\"Invalid credential\");\n }\n\n // The API may return proof.eip712 without domain/types; the domain is\n // canonical (version \"1\", the chainId), so reconstruct it before verifying.\n const eip712 = credential.proof.eip712 as\n | Partial<IProof[\"eip712\"]>\n | undefined;\n const verifiableCredential: PowerhouseVerifiableCredential = eip712?.domain\n ? credential\n : {\n ...credential,\n proof: {\n ...credential.proof,\n eip712: {\n domain: { version: \"1\", chainId: result.chainId },\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n\n // Verify the EIP-712 proof was signed by the DID's address on its chain.\n if (\n credential.issuer.ethereumAddress.toLowerCase() !==\n result.address.toLowerCase() ||\n verifiableCredential.proof.eip712.domain.chainId !== result.chainId ||\n !(await verifyCredentialSignature(verifiableCredential))\n ) {\n throw new Error(\"Invalid credential signature\");\n }\n\n const user: User = {\n ...result,\n address: credential.issuer.ethereumAddress,\n did: userDid,\n credential: verifiableCredential,\n };\n\n this.#updateUser(user);\n this.#updateStatus(\"authorized\");\n\n // Fetch profile data in the background if a fetcher is configured\n if (this.#profileFetcher) {\n this.#profileFetcher(user, this.#baseUrl)\n .then((profile) => {\n if (\n profile &&\n this.user?.address === user.address &&\n this.user.chainId === user.chainId\n ) {\n this.#updateUser({\n ...this.user,\n profile,\n ens: {\n name: profile.username ?? undefined,\n avatarUrl: profile.userImage ?? undefined,\n },\n });\n }\n })\n .catch(console.error);\n }\n\n return user;\n }\n\n logout() {\n this.#updateUser(undefined);\n this.#updateStatus(\"initial\");\n return Promise.resolve();\n }\n\n // Re-check the current user's credential at the source; logs out if it was\n // revoked or expired. Network errors keep the session (fail open).\n async revalidate(): Promise<boolean> {\n const user = this.user;\n if (!user) return false;\n try {\n const credential = await this.#getCredential(\n user.address,\n user.chainId,\n this.#crypto.did,\n );\n if (!credential) {\n await this.logout();\n return false;\n }\n return true;\n } catch {\n return true;\n }\n }\n\n on<K extends keyof RenownEvents>(\n event: K,\n listener: (data: RenownEvents[K]) => void,\n ): () => void {\n return this.#eventEmitter.on(event, listener);\n }\n\n async #getCredential(\n address: string,\n chainId: number,\n appDid: string,\n ): Promise<PowerhouseVerifiableCredential | undefined> {\n // Direct-switchboard flow: read the credential from the reactor subgraph.\n if (this.#switchboard) {\n return this.#switchboard.getCredential({ address, chainId, appDid });\n }\n if (!this.#baseUrl) {\n throw new Error(\"RENOWN_URL is not set\");\n }\n const url = new URL(\n `/api/auth/credential?address=${encodeURIComponent(address)}&chainId=${encodeURIComponent(chainId)}&connectId=${encodeURIComponent(appDid)}&appId=${encodeURIComponent(appDid)}`,\n this.#baseUrl,\n );\n const response = await fetch(url, {\n method: \"GET\",\n });\n if (response.ok) {\n const result = (await response.json()) as {\n credential: PowerhouseVerifiableCredential;\n };\n return result.credential;\n } else {\n throw new Error(`Failed to get credential: ${response.status}`);\n }\n }\n\n async verifyBearerToken(token: string) {\n return verifyAuthBearerToken(token);\n }\n\n async getBearerToken(options: CreateBearerTokenOptions) {\n if (!this.user) {\n throw new Error(\"User not found\");\n }\n return this.#crypto.getBearerToken(this.user.address, options);\n }\n}\n","import type { RenownEvents } from \"../types.js\";\nimport type { IEventEmitter } from \"./types.js\";\n\nexport class MemoryEventEmitter implements IEventEmitter<RenownEvents> {\n #listeners = new Map<keyof RenownEvents, Set<(data: unknown) => void>>();\n\n on<K extends keyof RenownEvents>(\n event: K,\n listener: (data: RenownEvents[K]) => void,\n ): () => void {\n if (!this.#listeners.has(event)) {\n this.#listeners.set(event, new Set());\n }\n this.#listeners.get(event)!.add(listener as (data: unknown) => void);\n return () => {\n this.#listeners.get(event)?.delete(listener as (data: unknown) => void);\n };\n }\n\n emit<K extends keyof RenownEvents>(event: K, data: RenownEvents[K]): void {\n this.#listeners.get(event)?.forEach((listener) => listener(data));\n }\n}\n","import type { ProfileFetcher, RenownProfile } from \"./types.js\";\n\nexport const fetchRenownProfile: ProfileFetcher = async (user, baseUrl) => {\n try {\n const response = await fetch(`${baseUrl.replace(/\\/+$/, \"\")}/api/profile`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n ethAddress: user.address,\n }),\n });\n\n if (!response.ok) {\n return undefined;\n }\n\n const result = (await response.json()) as {\n profile?: RenownProfile;\n };\n\n return result.profile ?? undefined;\n } catch {\n return undefined;\n }\n};\n","import { Renown, RenownMemoryStorage } from \"./common.js\";\nimport { DEFAULT_RENOWN_URL } from \"./constants.js\";\nimport { RenownCryptoBuilder } from \"./crypto/renown-crypto-builder.js\";\nimport type { IRenownCrypto, JsonWebKeyPairStorage } from \"./crypto/types.js\";\nimport { resolveSwitchboardEndpoint } from \"./discovery.js\";\nimport { MemoryEventEmitter } from \"./event/memory.js\";\nimport { fetchRenownProfile } from \"./profile.js\";\nimport { SwitchboardClient } from \"./switchboard.js\";\nimport type {\n ProfileFetcher,\n RenownEventEmitter,\n RenownStorage,\n} from \"./types.js\";\n\nexport interface RenownBuilderOptions {\n appName: string;\n storage?: RenownStorage;\n eventEmitter?: RenownEventEmitter;\n crypto?: IRenownCrypto;\n keyPairStorage?: JsonWebKeyPairStorage;\n baseUrl?: string;\n switchboardUrl?: string;\n profileFetcher?: ProfileFetcher;\n}\n\n/**\n * Base builder for creating Renown instances.\n * Use platform-specific builders (RenownBuilder from init.browser.js or init.node.js)\n * for pre-configured defaults.\n */\nexport class BaseRenownBuilder {\n #appName: string;\n #storage?: RenownStorage;\n #eventEmitter?: RenownEventEmitter;\n #crypto?: IRenownCrypto;\n #keyPairStorage?: JsonWebKeyPairStorage;\n #baseUrl?: string;\n #switchboardUrl?: string;\n #profileFetcher?: ProfileFetcher;\n\n /**\n * @param appName - Application name used for signing context\n */\n constructor(appName: string) {\n this.#appName = appName;\n }\n\n /**\n * Set custom storage for user data persistence.\n * Defaults to in-memory storage if not set.\n */\n withStorage(storage: RenownStorage): this {\n this.#storage = storage;\n return this;\n }\n\n /**\n * Set custom event emitter for user state changes.\n * Defaults to in-memory event emitter if not set.\n */\n withEventEmitter(eventEmitter: RenownEventEmitter): this {\n this.#eventEmitter = eventEmitter;\n return this;\n }\n\n /**\n * Set a pre-built crypto instance.\n * Either crypto or keyPairStorage must be provided.\n */\n withCrypto(crypto: IRenownCrypto): this {\n this.#crypto = crypto;\n return this;\n }\n\n /**\n * Set key pair storage for cryptographic keys.\n * A crypto instance will be built from this storage.\n * Either crypto or keyPairStorage must be provided.\n */\n withKeyPairStorage(keyPairStorage: JsonWebKeyPairStorage): this {\n this.#keyPairStorage = keyPairStorage;\n return this;\n }\n\n /**\n * Set the Renown server URL for credential verification.\n * Defaults to https://www.renown.id\n */\n withBaseUrl(baseUrl: string): this {\n this.#baseUrl = baseUrl;\n return this;\n }\n\n // Set the Switchboard GraphQL endpoint to read from the reactor directly.\n // When unset, the SDK discovers it from the base URL, else uses the REST flow.\n withSwitchboardUrl(switchboardUrl: string): this {\n this.#switchboardUrl = switchboardUrl;\n return this;\n }\n\n /**\n * Set a profile fetcher strategy for enriching user data after login.\n * The fetcher receives the authenticated user and the base URL,\n * and returns a RenownProfile. Called in the background after each login.\n * Defaults to fetchRenownProfile which calls the Renown API.\n */\n withProfileFetcher(profileFetcher: ProfileFetcher): this {\n this.#profileFetcher = profileFetcher;\n return this;\n }\n\n /**\n * Build and initialize the Renown instance.\n * If a user is stored, attempts to re-authenticate them.\n * @throws Error if neither crypto nor keyPairStorage is provided\n */\n async build(): Promise<Renown> {\n if (!this.#crypto && !this.#keyPairStorage) {\n throw new Error(\n \"Either crypto or keyPairStorage is required. Use withCrypto() or withKeyPairStorage() to set one.\",\n );\n }\n\n const crypto =\n this.#crypto ??\n (await new RenownCryptoBuilder()\n .withKeyPairStorage(this.#keyPairStorage!)\n .build());\n\n const storage = this.#storage ?? new RenownMemoryStorage();\n const eventEmitter = this.#eventEmitter ?? new MemoryEventEmitter();\n const baseUrl = this.#baseUrl ?? DEFAULT_RENOWN_URL;\n\n // Pick the transport once: direct-switchboard when an endpoint resolves,\n // else the REST flow. A custom profile fetcher always takes precedence.\n const switchboardEndpoint = await resolveSwitchboardEndpoint({\n switchboardUrl: this.#switchboardUrl,\n baseUrl,\n });\n const switchboard = switchboardEndpoint\n ? new SwitchboardClient(switchboardEndpoint)\n : undefined;\n const profileFetcher =\n this.#profileFetcher ??\n (switchboard ? switchboard.profileFetcher : fetchRenownProfile);\n\n const renown = new Renown(\n storage,\n eventEmitter,\n crypto,\n this.#appName,\n baseUrl,\n profileFetcher,\n switchboard,\n );\n\n // A stored user is loaded as-is for an instant, offline-safe start; callers\n // revalidate against the source separately via renown.revalidate().\n return renown;\n }\n\n /**\n * Create a BaseRenownBuilder from options object for a more concise API\n */\n static from(options: RenownBuilderOptions): BaseRenownBuilder {\n const builder = new BaseRenownBuilder(options.appName);\n\n if (options.storage) {\n builder.withStorage(options.storage);\n }\n if (options.eventEmitter) {\n builder.withEventEmitter(options.eventEmitter);\n }\n if (options.crypto) {\n builder.withCrypto(options.crypto);\n }\n if (options.keyPairStorage) {\n builder.withKeyPairStorage(options.keyPairStorage);\n }\n if (options.baseUrl) {\n builder.withBaseUrl(options.baseUrl);\n }\n if (options.switchboardUrl) {\n builder.withSwitchboardUrl(options.switchboardUrl);\n }\n if (options.profileFetcher) {\n builder.withProfileFetcher(options.profileFetcher);\n }\n\n return builder;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"renown-builder-1WTEoRc6.js","names":["#endpoint","#request","#store","#eventEmitter","#baseUrl","#crypto","#appName","#profileFetcher","#switchboard","#signer","#status","#updateStatus","#getCredential","#updateUser","#completeLogin","#listeners","#appName","#storage","#eventEmitter","#crypto","#keyPairStorage","#baseUrl","#switchboardUrl","#profileFetcher"],"sources":["../src/constants.ts","../src/discovery.ts","../src/switchboard.ts","../src/credential.ts","../src/storage/common.ts","../src/common.ts","../src/event/memory.ts","../src/profile.ts","../src/renown-builder.ts"],"sourcesContent":["export const DEFAULT_RENOWN_URL = \"https://www.renown.id\";\nexport const DEFAULT_RENOWN_NETWORK_ID = \"eip155\";\nexport const DEFAULT_RENOWN_CHAIN_ID = \"1\";\n\n/** Default cookie name for a server-readable Renown session (bearer token). */\nexport const RENOWN_SESSION_COOKIE = \"renown_session\";\n\nexport const DOMAIN_TYPE = [\n { name: \"version\", type: \"string\" },\n { name: \"chainId\", type: \"uint256\" },\n] as const;\n\nexport const VERIFIABLE_CREDENTIAL_EIP712_TYPE = [\n { name: \"@context\", type: \"string[]\" },\n { name: \"type\", type: \"string[]\" },\n { name: \"id\", type: \"string\" },\n { name: \"issuer\", type: \"Issuer\" },\n { name: \"credentialSubject\", type: \"CredentialSubject\" },\n { name: \"credentialSchema\", type: \"CredentialSchema\" },\n { name: \"issuanceDate\", type: \"string\" },\n { name: \"expirationDate\", type: \"string\" },\n] as const;\n\nexport const CREDENTIAL_SCHEMA_EIP712_TYPE = [\n { name: \"id\", type: \"string\" },\n { name: \"type\", type: \"string\" },\n] as const;\n\nexport const CREDENTIAL_SUBJECT_TYPE = [\n { name: \"app\", type: \"string\" },\n { name: \"id\", type: \"string\" },\n] as const;\n\nexport const ISSUER_TYPE = [\n { name: \"id\", type: \"string\" },\n { name: \"ethereumAddress\", type: \"string\" },\n] as const;\n\nexport const CREDENTIAL_TYPES = {\n EIP712Domain: DOMAIN_TYPE,\n VerifiableCredential: VERIFIABLE_CREDENTIAL_EIP712_TYPE,\n CredentialSchema: CREDENTIAL_SCHEMA_EIP712_TYPE,\n CredentialSubject: CREDENTIAL_SUBJECT_TYPE,\n Issuer: ISSUER_TYPE,\n} as const;\n","export interface ResolveSwitchboardEndpointOptions {\n // Explicit Switchboard GraphQL endpoint. When set, used directly.\n switchboardUrl?: string;\n // Renown base URL to ask for a switchboard endpoint when none is explicit.\n baseUrl?: string;\n // Max time (ms) to wait for the discovery probe before falling back to REST.\n timeoutMs?: number;\n}\n\n// Legacy Renown instances accept the connection but never respond to the\n// discovery request; without a bound, `fetch` hangs and blocks startup.\nconst DEFAULT_DISCOVERY_TIMEOUT_MS = 3000;\n\n// Shape returned by the Renown app's `/api/switchboard` discovery endpoint.\ninterface DiscoveryResponse {\n endpoint?: string;\n}\n\n// Resolve the Switchboard GraphQL endpoint: explicit `switchboardUrl` wins,\n// else discover via `{baseUrl}/api/switchboard`; undefined means use REST.\nexport async function resolveSwitchboardEndpoint(\n options: ResolveSwitchboardEndpointOptions,\n): Promise<string | undefined> {\n const { switchboardUrl, baseUrl, timeoutMs } = options;\n\n if (switchboardUrl) {\n return switchboardUrl;\n }\n\n if (!baseUrl) {\n return undefined;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(\n () => controller.abort(),\n timeoutMs ?? DEFAULT_DISCOVERY_TIMEOUT_MS,\n );\n\n try {\n const url = new URL(\"/api/switchboard\", baseUrl);\n const response = await fetch(url, {\n method: \"GET\",\n signal: controller.signal,\n });\n if (!response.ok) {\n return undefined;\n }\n const body = (await response.json()) as DiscoveryResponse;\n return body.endpoint || undefined;\n } catch {\n // Old Renown instances never answer (or lack the endpoint); the abort\n // timeout rejects here so we fall back to the REST flow instead of hanging.\n return undefined;\n } finally {\n clearTimeout(timeout);\n }\n}\n","import {\n createAction,\n type Action,\n} from \"@powerhousedao/shared/document-model\";\nimport { CREDENTIAL_TYPES } from \"./constants.js\";\nimport type {\n PowerhouseVerifiableCredential,\n ProfileFetcher,\n RenownProfile,\n} from \"./types.js\";\n\n// Per-user drive convention shared with the Renown app: `renown-<address>`.\n// The read-model ignores driveId, but we pass it for parity.\nfunction userDriveId(address: string): string {\n return `renown-${address.toLowerCase()}`;\n}\n\n// Flat row returned by the `renownCredentials` read-model query.\ninterface ReadRenownCredential {\n documentId: string;\n credentialId: string;\n context: string[];\n type: string[];\n issuerId: string;\n issuerEthereumAddress: string;\n issuanceDate: string;\n expirationDate: string | null;\n credentialSubjectId: string | null;\n credentialSubjectApp: string;\n credentialStatusId: string | null;\n credentialStatusType: string | null;\n credentialSchemaId: string;\n credentialSchemaType: string;\n proofVerificationMethod: string;\n proofEthereumAddress: string;\n proofCreated: string;\n proofPurpose: string;\n proofType: string;\n proofValue: string;\n proofEip712Domain: string;\n proofEip712PrimaryType: string;\n revoked: boolean;\n}\n\n// Flat row returned by the `renownUsers` read-model query.\ninterface ReadRenownUser {\n documentId: string;\n username: string | null;\n ethAddress: string | null;\n userImage: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nconst CREDENTIALS_QUERY = /* GraphQL */ `\n query RenownCredentials($input: RenownCredentialsInput!) {\n renownCredentials(input: $input) {\n documentId\n credentialId\n context\n type\n issuerId\n issuerEthereumAddress\n issuanceDate\n expirationDate\n credentialSubjectId\n credentialSubjectApp\n credentialStatusId\n credentialStatusType\n credentialSchemaId\n credentialSchemaType\n proofVerificationMethod\n proofEthereumAddress\n proofCreated\n proofPurpose\n proofType\n proofValue\n proofEip712Domain\n proofEip712PrimaryType\n revoked\n }\n }\n`;\n\nconst USERS_QUERY = /* GraphQL */ `\n query RenownUsers($input: RenownUsersInput!) {\n renownUsers(input: $input) {\n documentId\n username\n ethAddress\n userImage\n createdAt\n updatedAt\n }\n }\n`;\n\nconst CREATE_EMPTY_DOCUMENT_MUTATION = /* GraphQL */ `\n mutation CreateEmptyDocument(\n $documentType: String!\n $parentIdentifier: String\n ) {\n createEmptyDocument(\n documentType: $documentType\n parentIdentifier: $parentIdentifier\n ) {\n id\n }\n }\n`;\n\nconst MUTATE_DOCUMENT_MUTATION = /* GraphQL */ `\n mutation MutateDocument(\n $documentIdentifier: String!\n $actions: [JSONObject!]!\n ) {\n mutateDocument(documentIdentifier: $documentIdentifier, actions: $actions) {\n id\n }\n }\n`;\n\nconst RENOWN_CREDENTIAL_DOC_TYPE = \"powerhouse/renown-credential\";\nconst RENOWN_USER_DOC_TYPE = \"powerhouse/renown-user\";\n\n// Rebuild the nested EIP-712 verifiable credential from a flat read-model row.\nfunction reshapeCredential(\n row: ReadRenownCredential,\n): PowerhouseVerifiableCredential {\n // `proofEip712Domain` is stored as a JSON string ({ version, chainId }).\n const domain = JSON.parse(row.proofEip712Domain) as {\n version: string;\n chainId: number;\n };\n\n return {\n \"@context\": row.context,\n type: row.type,\n id: row.credentialId,\n issuer: {\n id: row.issuerId,\n ethereumAddress: row.issuerEthereumAddress as `0x${string}`,\n },\n credentialSubject: {\n id: row.credentialSubjectId ?? \"\",\n app: row.credentialSubjectApp,\n },\n credentialSchema: {\n id: row.credentialSchemaId,\n type: row.credentialSchemaType,\n },\n ...(row.credentialStatusId\n ? {\n credentialStatus: {\n id: row.credentialStatusId,\n type: row.credentialStatusType ?? \"\",\n },\n }\n : {}),\n issuanceDate: row.issuanceDate,\n expirationDate: row.expirationDate ?? \"\",\n proof: {\n type: row.proofType,\n created: row.proofCreated,\n verificationMethod: row.proofVerificationMethod,\n proofPurpose: row.proofPurpose,\n proofValue: row.proofValue,\n ethereumAddress: row.proofEthereumAddress as `0x${string}`,\n eip712: {\n domain,\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n}\n\n// The chain id in a `did:pkh:<net>:<chainId>:<address>` issuer id.\nfunction issuerChainId(issuerId: string): string | undefined {\n return issuerId.split(\":\")[3];\n}\n\n// Reads a Switchboard reactor's `renown-read-model` subgraph directly over\n// GraphQL, replacing the Renown Next.js REST proxy. Read-only; plain `fetch`.\nexport class SwitchboardClient {\n #endpoint: string;\n\n constructor(endpoint: string) {\n this.#endpoint = endpoint;\n }\n\n get endpoint() {\n return this.#endpoint;\n }\n\n async #request<T>(\n query: string,\n variables: Record<string, unknown>,\n ): Promise<T> {\n const response = await fetch(this.#endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ query, variables }),\n });\n if (!response.ok) {\n throw new Error(`Switchboard request failed: ${response.status}`);\n }\n const body = (await response.json()) as {\n data?: T;\n errors?: { message: string }[];\n };\n if (body.errors?.length) {\n throw new Error(body.errors.map((e) => e.message).join(\"; \"));\n }\n if (!body.data) {\n throw new Error(\"Switchboard returned no data\");\n }\n return body.data;\n }\n\n // Fetch the active delegation credential for (address, chainId) that delegates\n // to `appDid`: filter by chainId, drop expired, return most recent.\n async getCredential(params: {\n address: string;\n chainId: number;\n appDid: string;\n }): Promise<PowerhouseVerifiableCredential | undefined> {\n const { address, chainId, appDid } = params;\n const { renownCredentials } = await this.#request<{\n renownCredentials: ReadRenownCredential[];\n }>(CREDENTIALS_QUERY, {\n input: {\n driveId: userDriveId(address),\n ethAddress: address.toLowerCase(),\n did: appDid,\n includeRevoked: false,\n },\n });\n\n const now = Date.now();\n const candidates = renownCredentials\n .filter((row) => issuerChainId(row.issuerId) === String(chainId))\n .filter((row) => {\n if (!row.expirationDate) return true;\n const expiresAt = Date.parse(row.expirationDate);\n return !Number.isNaN(expiresAt) && expiresAt > now;\n })\n .sort((a, b) => Date.parse(b.issuanceDate) - Date.parse(a.issuanceDate));\n\n const mostRecent = candidates.at(0);\n return mostRecent ? reshapeCredential(mostRecent) : undefined;\n }\n\n // Look up a Renown profile by ethereum address via the `renownUsers` query.\n async getProfileByAddress(\n address: string,\n ): Promise<RenownProfile | undefined> {\n const { renownUsers } = await this.#request<{\n renownUsers: ReadRenownUser[];\n }>(USERS_QUERY, {\n input: {\n driveId: userDriveId(address),\n ethAddresses: [address.toLowerCase()],\n },\n });\n\n const user = renownUsers.at(0);\n if (!user) return undefined;\n return {\n documentId: user.documentId,\n username: user.username,\n ethAddress: user.ethAddress,\n userImage: user.userImage,\n createdAt: user.createdAt,\n updatedAt: user.updatedAt,\n };\n }\n\n // Create an empty document of the given type; returns its document id.\n async createEmptyDocument(\n documentType: string,\n parentIdentifier?: string,\n ): Promise<string> {\n const { createEmptyDocument } = await this.#request<{\n createEmptyDocument: { id: string };\n }>(CREATE_EMPTY_DOCUMENT_MUTATION, { documentType, parentIdentifier });\n return createEmptyDocument.id;\n }\n\n // Apply reactor action envelopes to a document; returns its document id.\n async mutateDocument(\n documentIdentifier: string,\n actions: Action[],\n ): Promise<string> {\n const { mutateDocument } = await this.#request<{\n mutateDocument: { id: string };\n }>(MUTATE_DOCUMENT_MUTATION, { documentIdentifier, actions });\n return mutateDocument.id;\n }\n\n // Issue a signed credential: create a renown-credential doc and INIT it.\n async issueCredential(\n credential: PowerhouseVerifiableCredential,\n ): Promise<string> {\n const documentId = await this.createEmptyDocument(\n RENOWN_CREDENTIAL_DOC_TYPE,\n );\n const input: Record<string, unknown> = {\n id: credential.id,\n context: credential[\"@context\"],\n type: credential.type,\n issuer: {\n id: credential.issuer.id,\n ethereumAddress: credential.issuer.ethereumAddress,\n },\n credentialSubject: {\n id: credential.credentialSubject.id,\n app: credential.credentialSubject.app,\n },\n credentialSchema: {\n id: credential.credentialSchema.id,\n type: credential.credentialSchema.type,\n },\n issuanceDate: credential.issuanceDate,\n expirationDate: credential.expirationDate || undefined,\n proof: {\n type: credential.proof.type,\n created: credential.proof.created,\n verificationMethod: credential.proof.verificationMethod,\n proofPurpose: credential.proof.proofPurpose,\n proofValue: credential.proof.proofValue,\n ethereumAddress: credential.proof.ethereumAddress,\n eip712: {\n domain: {\n version: credential.proof.eip712.domain.version,\n chainId: credential.proof.eip712.domain.chainId,\n },\n primaryType: credential.proof.eip712.primaryType,\n },\n },\n };\n await this.mutateDocument(documentId, [createAction(\"INIT\", input)]);\n return documentId;\n }\n\n // Find the RenownUser for an address or create one; returns its document id.\n async findOrCreateUser(\n address: string,\n profile: { username?: string; userImage?: string } = {},\n ): Promise<string> {\n const updates: Action[] = [];\n if (profile.username !== undefined) {\n updates.push(\n createAction(\"SET_USERNAME\", { username: profile.username }),\n );\n }\n if (profile.userImage !== undefined) {\n updates.push(\n createAction(\"SET_USER_IMAGE\", { userImage: profile.userImage }),\n );\n }\n\n const existing = await this.getProfileByAddress(address);\n if (existing) {\n if (updates.length)\n await this.mutateDocument(existing.documentId, updates);\n return existing.documentId;\n }\n\n const documentId = await this.createEmptyDocument(RENOWN_USER_DOC_TYPE);\n await this.mutateDocument(documentId, [\n createAction(\"SET_ETH_ADDRESS\", { ethAddress: address }),\n ...updates,\n ]);\n return documentId;\n }\n\n // Revoke a credential by its document id.\n async revokeCredential(documentId: string, reason?: string): Promise<void> {\n await this.mutateDocument(documentId, [\n createAction(\"REVOKE\", {\n revokedAt: new Date().toISOString(),\n reason: reason ?? null,\n }),\n ]);\n }\n\n // A ProfileFetcher backed by this client; used as the default when the\n // direct-switchboard flow is active. The `baseUrl` argument is ignored.\n profileFetcher: ProfileFetcher = (user) =>\n this.getProfileByAddress(user.address).catch(() => undefined);\n}\n","import { recoverTypedDataAddress } from \"viem\";\nimport {\n CREDENTIAL_TYPES,\n DEFAULT_RENOWN_NETWORK_ID,\n DEFAULT_RENOWN_URL,\n} from \"./constants.js\";\nimport { resolveSwitchboardEndpoint } from \"./discovery.js\";\nimport { SwitchboardClient } from \"./switchboard.js\";\nimport type { IProof, PowerhouseVerifiableCredential } from \"./types.js\";\nimport { verifyAuthBearerToken } from \"./utils.js\";\n\n/* Local structural aliases (EIP-712 standard shapes) so renown's public .d.ts\n * never names viem — a viem type in the surface drags viem's whole closure in. */\ntype Hex = `0x${string}`;\ntype TypedDataDomain = {\n name?: string;\n version?: string;\n chainId?: number;\n verifyingContract?: Hex;\n salt?: Hex;\n};\ntype TypedDataParameter = { name: string; type: string };\n\n/** EIP-712 domain as signed by the credential issuer. */\nexport type CredentialDomain = {\n version: string;\n chainId: number;\n};\n\n/** The credential body that is EIP-712 signed (everything except `proof`). */\nexport type CredentialMessage = {\n \"@context\": string[];\n type: string[];\n id: string;\n issuer: { id: string; ethereumAddress: Hex };\n credentialSubject: { id: string; app: string };\n credentialSchema: { id: string; type: string };\n issuanceDate: string;\n expirationDate: string;\n};\n\n/** Typed-data signer; matches the loose shape used by wallet adapters. */\nexport type SignCredentialTypedData = (args: {\n domain: TypedDataDomain;\n types: Record<string, readonly TypedDataParameter[]>;\n primaryType: string;\n message: Record<string, unknown>;\n}) => Promise<Hex>;\n\nexport interface BuildCredentialParams {\n signTypedData: SignCredentialTypedData;\n address: Hex;\n chainId: number;\n app: string;\n /** Credential subject id: the app/client DID the credential delegates to. */\n appId: string;\n expiresInDays?: number;\n}\n\n/** Assemble a Renown delegation VC and sign it with the provided signer. */\nexport async function buildAndSignCredential(\n params: BuildCredentialParams,\n): Promise<PowerhouseVerifiableCredential> {\n const {\n signTypedData,\n address,\n chainId,\n app,\n appId,\n expiresInDays = 7,\n } = params;\n\n const issuerId = `did:pkh:${DEFAULT_RENOWN_NETWORK_ID}:${chainId}:${address.toLowerCase()}`;\n const credentialId = `urn:uuid:${globalThis.crypto.randomUUID()}`;\n const now = new Date();\n const expirationDate = new Date(\n now.getTime() + expiresInDays * 24 * 60 * 60 * 1000,\n );\n\n const message: CredentialMessage = {\n \"@context\": [\"https://www.w3.org/2018/credentials/v1\"],\n type: [\"VerifiableCredential\", \"RenownCredential\"],\n id: credentialId,\n issuer: { id: issuerId, ethereumAddress: address },\n credentialSubject: { id: appId, app },\n credentialSchema: {\n id: \"https://renown.id/schemas/renown-credential/v1\",\n type: \"JsonSchemaValidator2018\",\n },\n issuanceDate: now.toISOString(),\n expirationDate: expirationDate.toISOString(),\n };\n\n const domain: CredentialDomain = { version: \"1\", chainId };\n\n // viem and most wallet adapters reserve EIP712Domain and derive it from\n // `domain` — passing it explicitly makes them throw.\n const { EIP712Domain, ...signTypes } = CREDENTIAL_TYPES;\n void EIP712Domain;\n const signature = await signTypedData({\n domain,\n types: signTypes,\n primaryType: \"VerifiableCredential\",\n message,\n });\n\n return {\n ...message,\n proof: {\n type: \"EthereumEip712Signature2021\",\n created: message.issuanceDate,\n verificationMethod: issuerId,\n proofPurpose: \"assertionMethod\",\n proofValue: signature,\n ethereumAddress: address,\n eip712: {\n domain,\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n}\n\n/** Recover the address that signed a credential's EIP-712 proof. */\nexport async function recoverCredentialSigner(\n credential: PowerhouseVerifiableCredential,\n): Promise<Hex> {\n const { proof, ...message } = credential;\n // Drop EIP712Domain so viem derives it from `domain`; viem ignores\n // message keys not present in the types, so the proof is excluded too.\n const { EIP712Domain, ...types } = CREDENTIAL_TYPES;\n void EIP712Domain;\n return recoverTypedDataAddress({\n domain: proof.eip712.domain,\n types,\n primaryType: \"VerifiableCredential\",\n message,\n signature: proof.proofValue as Hex,\n } as Parameters<typeof recoverTypedDataAddress>[0]);\n}\n\n/** True when the proof was signed by the credential's declared issuer address. */\nexport async function verifyCredentialSignature(\n credential: PowerhouseVerifiableCredential,\n): Promise<boolean> {\n try {\n const recovered = await recoverCredentialSigner(credential);\n return (\n recovered.toLowerCase() ===\n credential.issuer.ethereumAddress.toLowerCase()\n );\n } catch {\n // Malformed proof (bad hex, missing fields) is an invalid signature.\n return false;\n }\n}\n\n// The deployed Renown API may omit proof.eip712.domain; it's canonical\n// (version \"1\", the credential's chainId), so reconstruct it before verifying.\nfunction withEip712Domain(\n credential: PowerhouseVerifiableCredential,\n chainId: number,\n): PowerhouseVerifiableCredential {\n const eip712 = credential.proof.eip712 as\n | Partial<IProof[\"eip712\"]>\n | undefined;\n if (eip712?.domain) return credential;\n return {\n ...credential,\n proof: {\n ...credential.proof,\n eip712: {\n domain: { version: \"1\", chainId },\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n}\n\nexport interface FetchDelegationCredentialOptions {\n /** Ethereum address that must have issued the credential. */\n address: string;\n /** Chain id the credential must be scoped to. */\n chainId: number;\n /** App/client DID the credential must delegate to (credentialSubject.id). */\n appDid: string;\n /** Renown service base URL. Defaults to DEFAULT_RENOWN_URL. */\n baseUrl?: string;\n /** Switchboard GraphQL endpoint; when reachable, read the reactor directly. */\n switchboardUrl?: string;\n /** Probe {baseUrl}/api/switchboard for an endpoint (default true). */\n discover?: boolean;\n /** Re-verify the EIP-712 proof signature (default true). */\n verifySignature?: boolean;\n}\n\n// Fetch + binding/expiry-validate the credential over the Renown REST API.\nasync function fetchDelegationCredentialRest(params: {\n address: string;\n chainId: number;\n appDid: string;\n baseUrl: string;\n}): Promise<PowerhouseVerifiableCredential | undefined> {\n const { address, chainId, appDid, baseUrl } = params;\n const url = new URL(\n `/api/auth/credential?address=${encodeURIComponent(address)}&chainId=${encodeURIComponent(chainId)}&connectId=${encodeURIComponent(appDid)}&appId=${encodeURIComponent(appDid)}`,\n baseUrl,\n );\n const response = await fetch(url, { method: \"GET\" });\n if (!response.ok) return undefined;\n const { credential } = (await response.json()) as {\n credential?: PowerhouseVerifiableCredential;\n };\n if (!credential) return undefined;\n\n // Binding: delegates to this app DID, issued by this address on this chain\n // (issuer.id = did:pkh:<networkId>:<chainId>:<address>).\n const [, , , issuerChainId, issuerAddress] = credential.issuer.id.split(\":\");\n if (\n credential.credentialSubject.id !== appDid ||\n issuerChainId !== String(chainId) ||\n issuerAddress.toLowerCase() !== address.toLowerCase() ||\n credential.issuer.ethereumAddress.toLowerCase() !== address.toLowerCase()\n ) {\n return undefined;\n }\n\n // Reject an expired credential (revocation drops it from the endpoint\n // instead); a malformed date (NaN) counts as invalid, not non-expiring.\n if (credential.expirationDate) {\n const expiresAt = Date.parse(credential.expirationDate);\n if (Number.isNaN(expiresAt) || expiresAt <= Date.now()) {\n return undefined;\n }\n }\n\n return credential;\n}\n\n// Optionally re-verify the EIP-712 proof; returns the credential or undefined.\nasync function finalizeCredential(\n credential: PowerhouseVerifiableCredential,\n chainId: number,\n verifySignature: boolean,\n): Promise<PowerhouseVerifiableCredential | undefined> {\n if (!verifySignature) return credential;\n const withDomain = withEip712Domain(credential, chainId);\n if (\n withDomain.proof.eip712.domain.chainId !== chainId ||\n !(await verifyCredentialSignature(withDomain))\n ) {\n return undefined;\n }\n return withDomain;\n}\n\n// Fetch the Renown delegation credential for (address, chainId) and validate it\n// delegates to `appDid`; returns it, or undefined if absent/invalid. No throw.\nexport async function fetchDelegationCredential(\n options: FetchDelegationCredentialOptions,\n): Promise<PowerhouseVerifiableCredential | undefined> {\n const {\n address,\n chainId,\n appDid,\n switchboardUrl,\n discover = true,\n verifySignature = true,\n } = options;\n const explicitBaseUrl = options.baseUrl;\n const baseUrl = explicitBaseUrl ?? DEFAULT_RENOWN_URL;\n try {\n // An explicit switchboardUrl is used directly; otherwise discover from the\n // base URL unless disabled (callers that already resolved the endpoint).\n const endpoint = switchboardUrl\n ? switchboardUrl\n : discover && explicitBaseUrl\n ? await resolveSwitchboardEndpoint({ baseUrl })\n : undefined;\n\n const credential = endpoint\n ? await new SwitchboardClient(endpoint).getCredential({\n address,\n chainId,\n appDid,\n })\n : await fetchDelegationCredentialRest({\n address,\n chainId,\n appDid,\n baseUrl,\n });\n\n if (!credential) return undefined;\n return await finalizeCredential(credential, chainId, verifySignature);\n } catch {\n return undefined;\n }\n}\n\nexport interface VerifiedAuthCredential {\n address: string;\n chainId: number;\n networkId: string;\n /** Owner identity: the pkh DID (did:pkh:<net>:<chainId>:<address>). */\n did: string;\n /** App/client DID the bearer token was issued by. */\n appDid: string;\n credential: PowerhouseVerifiableCredential;\n}\n\nexport interface VerifyAuthCredentialOptions {\n /** Expected `aud` claim on the bearer token. */\n audience?: string;\n /** Renown service base URL. */\n renownUrl?: string;\n /** Switchboard GraphQL endpoint; when reachable, read the reactor directly. */\n switchboardUrl?: string;\n /** Re-verify the credential's EIP-712 proof (default true). */\n verifySignature?: boolean;\n}\n\n// Verify a renown bearer token end to end: check the JWT, then fetch+verify the\n// matching credential. Resolves the owner identity, or undefined. No throw.\nexport async function verifyAuthCredential(\n jwt: string,\n options: VerifyAuthCredentialOptions = {},\n): Promise<VerifiedAuthCredential | undefined> {\n const verified = await verifyAuthBearerToken(jwt, {\n audience: options.audience,\n });\n if (!verified) return undefined;\n\n const { address, chainId, networkId } =\n verified.verifiableCredential.credentialSubject;\n const appDid = verified.issuer;\n const credential = await fetchDelegationCredential({\n address,\n chainId,\n appDid,\n baseUrl: options.renownUrl,\n switchboardUrl: options.switchboardUrl,\n verifySignature: options.verifySignature,\n });\n if (!credential) return undefined;\n\n return {\n address,\n chainId,\n networkId,\n did: credential.issuer.id,\n appDid,\n credential,\n };\n}\n","export interface IStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n Key extends keyof T = keyof T,\n> {\n get(key: Key): T[Key] | undefined;\n set(key: Key, value?: T[Key]): void;\n delete(key: Key): void;\n}\n\nexport abstract class BaseStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n Key extends keyof T = keyof T,\n> implements IStorage<T> {\n abstract get(key: Key): T[Key] | undefined;\n abstract set(key: Key, value?: T[Key]): void;\n abstract delete(key: Key): void;\n}\n\nexport class MemoryStorage<\n T extends Record<string, unknown> = Record<string, unknown>,\n Key extends keyof T = keyof T,\n> extends BaseStorage<T> {\n private readonly data = new Map<Key, T[Key]>();\n\n get(key: Key) {\n return this.data.get(key);\n }\n\n set(key: Key, value?: T[Key]): void {\n if (value === undefined) {\n this.data.delete(key);\n } else {\n this.data.set(key, value);\n }\n }\n\n delete(key: Key): void {\n this.data.delete(key);\n }\n}\n","import {\n CREDENTIAL_TYPES,\n DEFAULT_RENOWN_NETWORK_ID,\n DEFAULT_RENOWN_URL,\n} from \"./constants.js\";\nimport {\n buildAndSignCredential,\n verifyCredentialSignature,\n} from \"./credential.js\";\nimport { RenownCryptoSigner, type IRenownCrypto } from \"./crypto/index.js\";\nimport { MemoryStorage } from \"./storage/common.js\";\nimport type { SwitchboardClient } from \"./switchboard.js\";\nimport type {\n CreateBearerTokenOptions,\n IProof,\n IRenown,\n ISigner,\n LoginStatus,\n PKHDid,\n PowerhouseVerifiableCredential,\n ProfileFetcher,\n RenownEventEmitter,\n RenownEvents,\n RenownStorage,\n RenownStorageMap,\n SignInParams,\n User,\n} from \"./types.js\";\nimport { parsePkhDid, verifyAuthBearerToken } from \"./utils.js\";\nexport * from \"./constants.js\";\n\nexport class RenownMemoryStorage extends MemoryStorage<RenownStorageMap> {}\n\nexport class Renown implements IRenown {\n #baseUrl: string;\n #store: RenownStorage;\n #eventEmitter: RenownEventEmitter;\n #appName: string;\n #crypto: IRenownCrypto;\n #signer: ISigner;\n #profileFetcher?: ProfileFetcher;\n #switchboard?: SwitchboardClient;\n #status: LoginStatus = \"initial\";\n\n constructor(\n store: RenownStorage,\n eventEmitter: RenownEventEmitter,\n crypto: IRenownCrypto,\n appName: string,\n baseUrl = DEFAULT_RENOWN_URL,\n profileFetcher?: ProfileFetcher,\n switchboard?: SwitchboardClient,\n ) {\n this.#store = store;\n this.#eventEmitter = eventEmitter;\n this.#baseUrl = baseUrl;\n this.#crypto = crypto;\n this.#appName = appName;\n this.#profileFetcher = profileFetcher;\n this.#switchboard = switchboard;\n const restoredUser = this.user;\n this.#signer = new RenownCryptoSigner(crypto, this.#appName, restoredUser);\n\n // A restored, previously-verified user is an authorized session; otherwise\n // status stays \"initial\" after a reload while the user is present.\n if (restoredUser) {\n this.#status = \"authorized\";\n }\n\n this.on(\"user\", (user) => {\n this.#signer.user = user;\n });\n }\n\n get baseUrl() {\n return this.#baseUrl;\n }\n\n get user() {\n return this.#store.get(\"user\");\n }\n\n get status() {\n return this.#status;\n }\n\n get signer() {\n return this.#signer;\n }\n\n get crypto() {\n return this.#crypto;\n }\n\n get did() {\n return this.#crypto.did;\n }\n\n get profileFetcher() {\n return this.#profileFetcher;\n }\n\n #updateStatus(status: LoginStatus) {\n this.#status = status;\n this.#eventEmitter.emit(\"status\", status);\n }\n\n #updateUser(user: User | undefined) {\n if (user) {\n this.#store.set(\"user\", user);\n } else {\n this.#store.delete(\"user\");\n }\n this.#eventEmitter.emit(\"user\", user);\n }\n\n async login(userDid: string): Promise<User> {\n this.#updateStatus(\"checking\");\n try {\n const result = parsePkhDid(userDid);\n const credential = await this.#getCredential(\n result.address,\n result.chainId,\n this.#crypto.did,\n );\n\n if (!credential) {\n this.#updateUser(undefined);\n throw new Error(\"Credential not found\");\n }\n\n return await this.#completeLogin(userDid, result, credential);\n } catch (error) {\n this.#updateUser(undefined);\n this.#updateStatus(\"not-authorized\");\n throw error;\n }\n }\n\n // Sign in without the Renown redirect: build + sign a delegation credential\n // with the caller's wallet signer, write it to the switchboard, then log in.\n async signIn(params: SignInParams): Promise<User> {\n if (!this.#switchboard) {\n throw new Error(\n \"signIn requires a switchboard endpoint. Set switchboardUrl or a discoverable baseUrl.\",\n );\n }\n const {\n address,\n chainId,\n signTypedData,\n username,\n userImage,\n expiresInDays,\n } = params;\n\n this.#updateStatus(\"checking\");\n try {\n const credential = await buildAndSignCredential({\n signTypedData,\n address,\n chainId,\n app: this.#appName,\n appId: this.did,\n expiresInDays,\n });\n\n await this.#switchboard.issueCredential(credential);\n await this.#switchboard.findOrCreateUser(address, {\n username,\n userImage,\n });\n\n const userDid = `did:pkh:${DEFAULT_RENOWN_NETWORK_ID}:${chainId}:${address.toLowerCase()}`;\n // Authenticate from the freshly signed credential — no read-back, which\n // avoids racing the read-model processor that indexes the write.\n return await this.#completeLogin(\n userDid,\n parsePkhDid(userDid),\n credential,\n );\n } catch (error) {\n this.#updateUser(undefined);\n this.#updateStatus(\"not-authorized\");\n throw error;\n }\n }\n\n // Verify a credential binds to userDid + this app key, set the user, and\n // start the background profile fetch. Throws if the credential is invalid.\n async #completeLogin(\n userDid: string,\n result: PKHDid,\n credential: PowerhouseVerifiableCredential,\n ): Promise<User> {\n if (\n !(\n credential.issuer.id === userDid &&\n credential.credentialSubject.id === this.did\n )\n ) {\n throw new Error(\"Invalid credential\");\n }\n\n // The API may return proof.eip712 without domain/types; the domain is\n // canonical (version \"1\", the chainId), so reconstruct it before verifying.\n const eip712 = credential.proof.eip712 as\n | Partial<IProof[\"eip712\"]>\n | undefined;\n const verifiableCredential: PowerhouseVerifiableCredential = eip712?.domain\n ? credential\n : {\n ...credential,\n proof: {\n ...credential.proof,\n eip712: {\n domain: { version: \"1\", chainId: result.chainId },\n types: CREDENTIAL_TYPES,\n primaryType: \"VerifiableCredential\",\n },\n },\n };\n\n // Verify the EIP-712 proof was signed by the DID's address on its chain.\n if (\n credential.issuer.ethereumAddress.toLowerCase() !==\n result.address.toLowerCase() ||\n verifiableCredential.proof.eip712.domain.chainId !== result.chainId ||\n !(await verifyCredentialSignature(verifiableCredential))\n ) {\n throw new Error(\"Invalid credential signature\");\n }\n\n const user: User = {\n ...result,\n address: credential.issuer.ethereumAddress,\n did: userDid,\n credential: verifiableCredential,\n };\n\n this.#updateUser(user);\n this.#updateStatus(\"authorized\");\n\n // Fetch profile data in the background if a fetcher is configured\n if (this.#profileFetcher) {\n this.#profileFetcher(user, this.#baseUrl)\n .then((profile) => {\n if (\n profile &&\n this.user?.address === user.address &&\n this.user.chainId === user.chainId\n ) {\n this.#updateUser({\n ...this.user,\n profile,\n ens: {\n name: profile.username ?? undefined,\n avatarUrl: profile.userImage ?? undefined,\n },\n });\n }\n })\n .catch(console.error);\n }\n\n return user;\n }\n\n logout() {\n this.#updateUser(undefined);\n this.#updateStatus(\"initial\");\n return Promise.resolve();\n }\n\n // Re-check the current user's credential at the source; logs out if it was\n // revoked or expired. Network errors keep the session (fail open).\n async revalidate(): Promise<boolean> {\n const user = this.user;\n if (!user) return false;\n try {\n const credential = await this.#getCredential(\n user.address,\n user.chainId,\n this.#crypto.did,\n );\n if (!credential) {\n await this.logout();\n return false;\n }\n await this.refreshProfile();\n return true;\n } catch {\n return true;\n }\n }\n\n // Re-read profile attributes at the source so a renamed user or changed avatar\n // shows up on the next load. Carries no logout risk, unlike revalidate().\n async refreshProfile(): Promise<boolean> {\n const user = this.user;\n if (!user || !this.#profileFetcher) return false;\n try {\n const profile = await this.#profileFetcher(user, this.#baseUrl);\n if (!profile) return false;\n // Asserted because narrowing from the pre-await read would otherwise hide\n // that a logout during the fetch can clear this.\n const current = this.user as User | undefined;\n if (\n !current ||\n current.address !== user.address ||\n current.chainId !== user.chainId\n ) {\n return false;\n }\n // Narrow `profile` first: the fetched payload is unvalidated JSON, so a\n // missing documentId must not make the undefined case compare equal.\n const unchanged =\n current.profile !== undefined &&\n current.profile.documentId === profile.documentId &&\n current.profile.username === profile.username &&\n current.profile.userImage === profile.userImage;\n if (unchanged) return false;\n this.#updateUser({\n ...current,\n profile,\n ens: {\n name: profile.username ?? undefined,\n avatarUrl: profile.userImage ?? undefined,\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n on<K extends keyof RenownEvents>(\n event: K,\n listener: (data: RenownEvents[K]) => void,\n ): () => void {\n return this.#eventEmitter.on(event, listener);\n }\n\n async #getCredential(\n address: string,\n chainId: number,\n appDid: string,\n ): Promise<PowerhouseVerifiableCredential | undefined> {\n // Direct-switchboard flow: read the credential from the reactor subgraph.\n if (this.#switchboard) {\n return this.#switchboard.getCredential({ address, chainId, appDid });\n }\n if (!this.#baseUrl) {\n throw new Error(\"RENOWN_URL is not set\");\n }\n const url = new URL(\n `/api/auth/credential?address=${encodeURIComponent(address)}&chainId=${encodeURIComponent(chainId)}&connectId=${encodeURIComponent(appDid)}&appId=${encodeURIComponent(appDid)}`,\n this.#baseUrl,\n );\n const response = await fetch(url, {\n method: \"GET\",\n });\n if (response.ok) {\n const result = (await response.json()) as {\n credential: PowerhouseVerifiableCredential;\n };\n return result.credential;\n } else {\n throw new Error(`Failed to get credential: ${response.status}`);\n }\n }\n\n async verifyBearerToken(token: string) {\n return verifyAuthBearerToken(token);\n }\n\n async getBearerToken(options: CreateBearerTokenOptions) {\n if (!this.user) {\n throw new Error(\"User not found\");\n }\n return this.#crypto.getBearerToken(this.user.address, options);\n }\n}\n","import type { RenownEvents } from \"../types.js\";\nimport type { IEventEmitter } from \"./types.js\";\n\nexport class MemoryEventEmitter implements IEventEmitter<RenownEvents> {\n #listeners = new Map<keyof RenownEvents, Set<(data: unknown) => void>>();\n\n on<K extends keyof RenownEvents>(\n event: K,\n listener: (data: RenownEvents[K]) => void,\n ): () => void {\n if (!this.#listeners.has(event)) {\n this.#listeners.set(event, new Set());\n }\n this.#listeners.get(event)!.add(listener as (data: unknown) => void);\n return () => {\n this.#listeners.get(event)?.delete(listener as (data: unknown) => void);\n };\n }\n\n emit<K extends keyof RenownEvents>(event: K, data: RenownEvents[K]): void {\n this.#listeners.get(event)?.forEach((listener) => listener(data));\n }\n}\n","import type { ProfileFetcher, RenownProfile } from \"./types.js\";\n\nexport const fetchRenownProfile: ProfileFetcher = async (user, baseUrl) => {\n try {\n const response = await fetch(`${baseUrl.replace(/\\/+$/, \"\")}/api/profile`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n ethAddress: user.address,\n }),\n });\n\n if (!response.ok) {\n return undefined;\n }\n\n const result = (await response.json()) as {\n profile?: RenownProfile;\n };\n\n return result.profile ?? undefined;\n } catch {\n return undefined;\n }\n};\n","import { Renown, RenownMemoryStorage } from \"./common.js\";\nimport { DEFAULT_RENOWN_URL } from \"./constants.js\";\nimport { RenownCryptoBuilder } from \"./crypto/renown-crypto-builder.js\";\nimport type { IRenownCrypto, JsonWebKeyPairStorage } from \"./crypto/types.js\";\nimport { resolveSwitchboardEndpoint } from \"./discovery.js\";\nimport { MemoryEventEmitter } from \"./event/memory.js\";\nimport { fetchRenownProfile } from \"./profile.js\";\nimport { SwitchboardClient } from \"./switchboard.js\";\nimport type {\n ProfileFetcher,\n RenownEventEmitter,\n RenownStorage,\n} from \"./types.js\";\n\nexport interface RenownBuilderOptions {\n appName: string;\n storage?: RenownStorage;\n eventEmitter?: RenownEventEmitter;\n crypto?: IRenownCrypto;\n keyPairStorage?: JsonWebKeyPairStorage;\n baseUrl?: string;\n switchboardUrl?: string;\n profileFetcher?: ProfileFetcher;\n}\n\n/**\n * Base builder for creating Renown instances.\n * Use platform-specific builders (RenownBuilder from init.browser.js or init.node.js)\n * for pre-configured defaults.\n */\nexport class BaseRenownBuilder {\n #appName: string;\n #storage?: RenownStorage;\n #eventEmitter?: RenownEventEmitter;\n #crypto?: IRenownCrypto;\n #keyPairStorage?: JsonWebKeyPairStorage;\n #baseUrl?: string;\n #switchboardUrl?: string;\n #profileFetcher?: ProfileFetcher;\n\n /**\n * @param appName - Application name used for signing context\n */\n constructor(appName: string) {\n this.#appName = appName;\n }\n\n /**\n * Set custom storage for user data persistence.\n * Defaults to in-memory storage if not set.\n */\n withStorage(storage: RenownStorage): this {\n this.#storage = storage;\n return this;\n }\n\n /**\n * Set custom event emitter for user state changes.\n * Defaults to in-memory event emitter if not set.\n */\n withEventEmitter(eventEmitter: RenownEventEmitter): this {\n this.#eventEmitter = eventEmitter;\n return this;\n }\n\n /**\n * Set a pre-built crypto instance.\n * Either crypto or keyPairStorage must be provided.\n */\n withCrypto(crypto: IRenownCrypto): this {\n this.#crypto = crypto;\n return this;\n }\n\n /**\n * Set key pair storage for cryptographic keys.\n * A crypto instance will be built from this storage.\n * Either crypto or keyPairStorage must be provided.\n */\n withKeyPairStorage(keyPairStorage: JsonWebKeyPairStorage): this {\n this.#keyPairStorage = keyPairStorage;\n return this;\n }\n\n /**\n * Set the Renown server URL for credential verification.\n * Defaults to https://www.renown.id\n */\n withBaseUrl(baseUrl: string): this {\n this.#baseUrl = baseUrl;\n return this;\n }\n\n // Set the Switchboard GraphQL endpoint to read from the reactor directly.\n // When unset, the SDK discovers it from the base URL, else uses the REST flow.\n withSwitchboardUrl(switchboardUrl: string): this {\n this.#switchboardUrl = switchboardUrl;\n return this;\n }\n\n /**\n * Set a profile fetcher strategy for enriching user data after login.\n * The fetcher receives the authenticated user and the base URL,\n * and returns a RenownProfile. Called in the background after each login.\n * Defaults to fetchRenownProfile which calls the Renown API.\n */\n withProfileFetcher(profileFetcher: ProfileFetcher): this {\n this.#profileFetcher = profileFetcher;\n return this;\n }\n\n /**\n * Build and initialize the Renown instance.\n * If a user is stored, attempts to re-authenticate them.\n * @throws Error if neither crypto nor keyPairStorage is provided\n */\n async build(): Promise<Renown> {\n if (!this.#crypto && !this.#keyPairStorage) {\n throw new Error(\n \"Either crypto or keyPairStorage is required. Use withCrypto() or withKeyPairStorage() to set one.\",\n );\n }\n\n const crypto =\n this.#crypto ??\n (await new RenownCryptoBuilder()\n .withKeyPairStorage(this.#keyPairStorage!)\n .build());\n\n const storage = this.#storage ?? new RenownMemoryStorage();\n const eventEmitter = this.#eventEmitter ?? new MemoryEventEmitter();\n const baseUrl = this.#baseUrl ?? DEFAULT_RENOWN_URL;\n\n // Pick the transport once: direct-switchboard when an endpoint resolves,\n // else the REST flow. A custom profile fetcher always takes precedence.\n const switchboardEndpoint = await resolveSwitchboardEndpoint({\n switchboardUrl: this.#switchboardUrl,\n baseUrl,\n });\n const switchboard = switchboardEndpoint\n ? new SwitchboardClient(switchboardEndpoint)\n : undefined;\n const profileFetcher =\n this.#profileFetcher ??\n (switchboard ? switchboard.profileFetcher : fetchRenownProfile);\n\n const renown = new Renown(\n storage,\n eventEmitter,\n crypto,\n this.#appName,\n baseUrl,\n profileFetcher,\n switchboard,\n );\n\n // A stored user is loaded as-is for an instant, offline-safe start; callers\n // revalidate against the source separately via renown.revalidate().\n return renown;\n }\n\n /**\n * Create a BaseRenownBuilder from options object for a more concise API\n */\n static from(options: RenownBuilderOptions): BaseRenownBuilder {\n const builder = new BaseRenownBuilder(options.appName);\n\n if (options.storage) {\n builder.withStorage(options.storage);\n }\n if (options.eventEmitter) {\n builder.withEventEmitter(options.eventEmitter);\n }\n if (options.crypto) {\n builder.withCrypto(options.crypto);\n }\n if (options.keyPairStorage) {\n builder.withKeyPairStorage(options.keyPairStorage);\n }\n if (options.baseUrl) {\n builder.withBaseUrl(options.baseUrl);\n }\n if (options.switchboardUrl) {\n builder.withSwitchboardUrl(options.switchboardUrl);\n }\n if (options.profileFetcher) {\n builder.withProfileFetcher(options.profileFetcher);\n }\n\n return builder;\n }\n}\n"],"mappings":";;;;AAAA,MAAa,qBAAqB;AAClC,MAAa,4BAA4B;AACzC,MAAa,0BAA0B;;AAGvC,MAAa,wBAAwB;AAErC,MAAa,cAAc,CACzB;CAAE,MAAM;CAAW,MAAM;CAAU,EACnC;CAAE,MAAM;CAAW,MAAM;CAAW,CACrC;AAED,MAAa,oCAAoC;CAC/C;EAAE,MAAM;EAAY,MAAM;EAAY;CACtC;EAAE,MAAM;EAAQ,MAAM;EAAY;CAClC;EAAE,MAAM;EAAM,MAAM;EAAU;CAC9B;EAAE,MAAM;EAAU,MAAM;EAAU;CAClC;EAAE,MAAM;EAAqB,MAAM;EAAqB;CACxD;EAAE,MAAM;EAAoB,MAAM;EAAoB;CACtD;EAAE,MAAM;EAAgB,MAAM;EAAU;CACxC;EAAE,MAAM;EAAkB,MAAM;EAAU;CAC3C;AAED,MAAa,gCAAgC,CAC3C;CAAE,MAAM;CAAM,MAAM;CAAU,EAC9B;CAAE,MAAM;CAAQ,MAAM;CAAU,CACjC;AAED,MAAa,0BAA0B,CACrC;CAAE,MAAM;CAAO,MAAM;CAAU,EAC/B;CAAE,MAAM;CAAM,MAAM;CAAU,CAC/B;AAED,MAAa,cAAc,CACzB;CAAE,MAAM;CAAM,MAAM;CAAU,EAC9B;CAAE,MAAM;CAAmB,MAAM;CAAU,CAC5C;AAED,MAAa,mBAAmB;CAC9B,cAAc;CACd,sBAAsB;CACtB,kBAAkB;CAClB,mBAAmB;CACnB,QAAQ;CACT;;;ACjCD,MAAM,+BAA+B;AASrC,eAAsB,2BACpB,SAC6B;CAC7B,MAAM,EAAE,gBAAgB,SAAS,cAAc;AAE/C,KAAI,eACF,QAAO;AAGT,KAAI,CAAC,QACH;CAGF,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,UAAU,iBACR,WAAW,OAAO,EACxB,aAAa,6BACd;AAED,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,oBAAoB,QAAQ;EAChD,MAAM,WAAW,MAAM,MAAM,KAAK;GAChC,QAAQ;GACR,QAAQ,WAAW;GACpB,CAAC;AACF,MAAI,CAAC,SAAS,GACZ;AAGF,UADc,MAAM,SAAS,MAAM,EACvB,YAAY,KAAA;SAClB;AAGN;WACQ;AACR,eAAa,QAAQ;;;;;AC1CzB,SAAS,YAAY,SAAyB;AAC5C,QAAO,UAAU,QAAQ,aAAa;;AAwCxC,MAAM,oBAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BxC,MAAM,cAA4B;;;;;;;;;;;;AAalC,MAAM,iCAA+C;;;;;;;;;;;;;AAcrD,MAAM,2BAAyC;;;;;;;;;;AAW/C,MAAM,6BAA6B;AACnC,MAAM,uBAAuB;AAG7B,SAAS,kBACP,KACgC;CAEhC,MAAM,SAAS,KAAK,MAAM,IAAI,kBAAkB;AAKhD,QAAO;EACL,YAAY,IAAI;EAChB,MAAM,IAAI;EACV,IAAI,IAAI;EACR,QAAQ;GACN,IAAI,IAAI;GACR,iBAAiB,IAAI;GACtB;EACD,mBAAmB;GACjB,IAAI,IAAI,uBAAuB;GAC/B,KAAK,IAAI;GACV;EACD,kBAAkB;GAChB,IAAI,IAAI;GACR,MAAM,IAAI;GACX;EACD,GAAI,IAAI,qBACJ,EACE,kBAAkB;GAChB,IAAI,IAAI;GACR,MAAM,IAAI,wBAAwB;GACnC,EACF,GACD,EAAE;EACN,cAAc,IAAI;EAClB,gBAAgB,IAAI,kBAAkB;EACtC,OAAO;GACL,MAAM,IAAI;GACV,SAAS,IAAI;GACb,oBAAoB,IAAI;GACxB,cAAc,IAAI;GAClB,YAAY,IAAI;GAChB,iBAAiB,IAAI;GACrB,QAAQ;IACN;IACA,OAAO;IACP,aAAa;IACd;GACF;EACF;;AAIH,SAAS,cAAc,UAAsC;AAC3D,QAAO,SAAS,MAAM,IAAI,CAAC;;AAK7B,IAAa,oBAAb,MAA+B;CAC7B;CAEA,YAAY,UAAkB;AAC5B,QAAA,WAAiB;;CAGnB,IAAI,WAAW;AACb,SAAO,MAAA;;CAGT,OAAA,QACE,OACA,WACY;EACZ,MAAM,WAAW,MAAM,MAAM,MAAA,UAAgB;GAC3C,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,MAAM,KAAK,UAAU;IAAE;IAAO;IAAW,CAAC;GAC3C,CAAC;AACF,MAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,+BAA+B,SAAS,SAAS;EAEnE,MAAM,OAAQ,MAAM,SAAS,MAAM;AAInC,MAAI,KAAK,QAAQ,OACf,OAAM,IAAI,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,KAAK,KAAK,CAAC;AAE/D,MAAI,CAAC,KAAK,KACR,OAAM,IAAI,MAAM,+BAA+B;AAEjD,SAAO,KAAK;;CAKd,MAAM,cAAc,QAIoC;EACtD,MAAM,EAAE,SAAS,SAAS,WAAW;EACrC,MAAM,EAAE,sBAAsB,MAAM,MAAA,QAEjC,mBAAmB,EACpB,OAAO;GACL,SAAS,YAAY,QAAQ;GAC7B,YAAY,QAAQ,aAAa;GACjC,KAAK;GACL,gBAAgB;GACjB,EACF,CAAC;EAEF,MAAM,MAAM,KAAK,KAAK;EAUtB,MAAM,aATa,kBAChB,QAAQ,QAAQ,cAAc,IAAI,SAAS,KAAK,OAAO,QAAQ,CAAC,CAChE,QAAQ,QAAQ;AACf,OAAI,CAAC,IAAI,eAAgB,QAAO;GAChC,MAAM,YAAY,KAAK,MAAM,IAAI,eAAe;AAChD,UAAO,CAAC,OAAO,MAAM,UAAU,IAAI,YAAY;IAC/C,CACD,MAAM,GAAG,MAAM,KAAK,MAAM,EAAE,aAAa,GAAG,KAAK,MAAM,EAAE,aAAa,CAAC,CAE5C,GAAG,EAAE;AACnC,SAAO,aAAa,kBAAkB,WAAW,GAAG,KAAA;;CAItD,MAAM,oBACJ,SACoC;EACpC,MAAM,EAAE,gBAAgB,MAAM,MAAA,QAE3B,aAAa,EACd,OAAO;GACL,SAAS,YAAY,QAAQ;GAC7B,cAAc,CAAC,QAAQ,aAAa,CAAC;GACtC,EACF,CAAC;EAEF,MAAM,OAAO,YAAY,GAAG,EAAE;AAC9B,MAAI,CAAC,KAAM,QAAO,KAAA;AAClB,SAAO;GACL,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,YAAY,KAAK;GACjB,WAAW,KAAK;GAChB,WAAW,KAAK;GAChB,WAAW,KAAK;GACjB;;CAIH,MAAM,oBACJ,cACA,kBACiB;EACjB,MAAM,EAAE,wBAAwB,MAAM,MAAA,QAEnC,gCAAgC;GAAE;GAAc;GAAkB,CAAC;AACtE,SAAO,oBAAoB;;CAI7B,MAAM,eACJ,oBACA,SACiB;EACjB,MAAM,EAAE,mBAAmB,MAAM,MAAA,QAE9B,0BAA0B;GAAE;GAAoB;GAAS,CAAC;AAC7D,SAAO,eAAe;;CAIxB,MAAM,gBACJ,YACiB;EACjB,MAAM,aAAa,MAAM,KAAK,oBAC5B,2BACD;EACD,MAAM,QAAiC;GACrC,IAAI,WAAW;GACf,SAAS,WAAW;GACpB,MAAM,WAAW;GACjB,QAAQ;IACN,IAAI,WAAW,OAAO;IACtB,iBAAiB,WAAW,OAAO;IACpC;GACD,mBAAmB;IACjB,IAAI,WAAW,kBAAkB;IACjC,KAAK,WAAW,kBAAkB;IACnC;GACD,kBAAkB;IAChB,IAAI,WAAW,iBAAiB;IAChC,MAAM,WAAW,iBAAiB;IACnC;GACD,cAAc,WAAW;GACzB,gBAAgB,WAAW,kBAAkB,KAAA;GAC7C,OAAO;IACL,MAAM,WAAW,MAAM;IACvB,SAAS,WAAW,MAAM;IAC1B,oBAAoB,WAAW,MAAM;IACrC,cAAc,WAAW,MAAM;IAC/B,YAAY,WAAW,MAAM;IAC7B,iBAAiB,WAAW,MAAM;IAClC,QAAQ;KACN,QAAQ;MACN,SAAS,WAAW,MAAM,OAAO,OAAO;MACxC,SAAS,WAAW,MAAM,OAAO,OAAO;MACzC;KACD,aAAa,WAAW,MAAM,OAAO;KACtC;IACF;GACF;AACD,QAAM,KAAK,eAAe,YAAY,CAAC,aAAa,QAAQ,MAAM,CAAC,CAAC;AACpE,SAAO;;CAIT,MAAM,iBACJ,SACA,UAAqD,EAAE,EACtC;EACjB,MAAM,UAAoB,EAAE;AAC5B,MAAI,QAAQ,aAAa,KAAA,EACvB,SAAQ,KACN,aAAa,gBAAgB,EAAE,UAAU,QAAQ,UAAU,CAAC,CAC7D;AAEH,MAAI,QAAQ,cAAc,KAAA,EACxB,SAAQ,KACN,aAAa,kBAAkB,EAAE,WAAW,QAAQ,WAAW,CAAC,CACjE;EAGH,MAAM,WAAW,MAAM,KAAK,oBAAoB,QAAQ;AACxD,MAAI,UAAU;AACZ,OAAI,QAAQ,OACV,OAAM,KAAK,eAAe,SAAS,YAAY,QAAQ;AACzD,UAAO,SAAS;;EAGlB,MAAM,aAAa,MAAM,KAAK,oBAAoB,qBAAqB;AACvE,QAAM,KAAK,eAAe,YAAY,CACpC,aAAa,mBAAmB,EAAE,YAAY,SAAS,CAAC,EACxD,GAAG,QACJ,CAAC;AACF,SAAO;;CAIT,MAAM,iBAAiB,YAAoB,QAAgC;AACzE,QAAM,KAAK,eAAe,YAAY,CACpC,aAAa,UAAU;GACrB,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,QAAQ,UAAU;GACnB,CAAC,CACH,CAAC;;CAKJ,kBAAkC,SAChC,KAAK,oBAAoB,KAAK,QAAQ,CAAC,YAAY,KAAA,EAAU;;;;;AC1UjE,eAAsB,uBACpB,QACyC;CACzC,MAAM,EACJ,eACA,SACA,SACA,KACA,OACA,gBAAgB,MACd;CAEJ,MAAM,WAAW,WAAW,0BAA0B,GAAG,QAAQ,GAAG,QAAQ,aAAa;CACzF,MAAM,eAAe,YAAY,WAAW,OAAO,YAAY;CAC/D,MAAM,sBAAM,IAAI,MAAM;CACtB,MAAM,iBAAiB,IAAI,KACzB,IAAI,SAAS,GAAG,gBAAgB,KAAK,KAAK,KAAK,IAChD;CAED,MAAM,UAA6B;EACjC,YAAY,CAAC,yCAAyC;EACtD,MAAM,CAAC,wBAAwB,mBAAmB;EAClD,IAAI;EACJ,QAAQ;GAAE,IAAI;GAAU,iBAAiB;GAAS;EAClD,mBAAmB;GAAE,IAAI;GAAO;GAAK;EACrC,kBAAkB;GAChB,IAAI;GACJ,MAAM;GACP;EACD,cAAc,IAAI,aAAa;EAC/B,gBAAgB,eAAe,aAAa;EAC7C;CAED,MAAM,SAA2B;EAAE,SAAS;EAAK;EAAS;CAI1D,MAAM,EAAE,cAAc,GAAG,cAAc;CAEvC,MAAM,YAAY,MAAM,cAAc;EACpC;EACA,OAAO;EACP,aAAa;EACb;EACD,CAAC;AAEF,QAAO;EACL,GAAG;EACH,OAAO;GACL,MAAM;GACN,SAAS,QAAQ;GACjB,oBAAoB;GACpB,cAAc;GACd,YAAY;GACZ,iBAAiB;GACjB,QAAQ;IACN;IACA,OAAO;IACP,aAAa;IACd;GACF;EACF;;;AAIH,eAAsB,wBACpB,YACc;CACd,MAAM,EAAE,OAAO,GAAG,YAAY;CAG9B,MAAM,EAAE,cAAc,GAAG,UAAU;AAEnC,QAAO,wBAAwB;EAC7B,QAAQ,MAAM,OAAO;EACrB;EACA,aAAa;EACb;EACA,WAAW,MAAM;EAClB,CAAkD;;;AAIrD,eAAsB,0BACpB,YACkB;AAClB,KAAI;AAEF,UADkB,MAAM,wBAAwB,WAAW,EAE/C,aAAa,KACvB,WAAW,OAAO,gBAAgB,aAAa;SAE3C;AAEN,SAAO;;;AAMX,SAAS,iBACP,YACA,SACgC;AAIhC,KAHe,WAAW,MAAM,QAGpB,OAAQ,QAAO;AAC3B,QAAO;EACL,GAAG;EACH,OAAO;GACL,GAAG,WAAW;GACd,QAAQ;IACN,QAAQ;KAAE,SAAS;KAAK;KAAS;IACjC,OAAO;IACP,aAAa;IACd;GACF;EACF;;AAqBH,eAAe,8BAA8B,QAKW;CACtD,MAAM,EAAE,SAAS,SAAS,QAAQ,YAAY;CAC9C,MAAM,MAAM,IAAI,IACd,gCAAgC,mBAAmB,QAAQ,CAAC,WAAW,mBAAmB,QAAQ,CAAC,aAAa,mBAAmB,OAAO,CAAC,SAAS,mBAAmB,OAAO,IAC9K,QACD;CACD,MAAM,WAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC;AACpD,KAAI,CAAC,SAAS,GAAI,QAAO,KAAA;CACzB,MAAM,EAAE,eAAgB,MAAM,SAAS,MAAM;AAG7C,KAAI,CAAC,WAAY,QAAO,KAAA;CAIxB,MAAM,OAAO,eAAe,iBAAiB,WAAW,OAAO,GAAG,MAAM,IAAI;AAC5E,KACE,WAAW,kBAAkB,OAAO,UACpC,kBAAkB,OAAO,QAAQ,IACjC,cAAc,aAAa,KAAK,QAAQ,aAAa,IACrD,WAAW,OAAO,gBAAgB,aAAa,KAAK,QAAQ,aAAa,CAEzE;AAKF,KAAI,WAAW,gBAAgB;EAC7B,MAAM,YAAY,KAAK,MAAM,WAAW,eAAe;AACvD,MAAI,OAAO,MAAM,UAAU,IAAI,aAAa,KAAK,KAAK,CACpD;;AAIJ,QAAO;;AAIT,eAAe,mBACb,YACA,SACA,iBACqD;AACrD,KAAI,CAAC,gBAAiB,QAAO;CAC7B,MAAM,aAAa,iBAAiB,YAAY,QAAQ;AACxD,KACE,WAAW,MAAM,OAAO,OAAO,YAAY,WAC3C,CAAE,MAAM,0BAA0B,WAAW,CAE7C;AAEF,QAAO;;AAKT,eAAsB,0BACpB,SACqD;CACrD,MAAM,EACJ,SACA,SACA,QACA,gBACA,WAAW,MACX,kBAAkB,SAChB;CACJ,MAAM,kBAAkB,QAAQ;CAChC,MAAM,UAAU,mBAAA;AAChB,KAAI;EAGF,MAAM,WAAW,iBACb,iBACA,YAAY,kBACV,MAAM,2BAA2B,EAAE,SAAS,CAAC,GAC7C,KAAA;EAEN,MAAM,aAAa,WACf,MAAM,IAAI,kBAAkB,SAAS,CAAC,cAAc;GAClD;GACA;GACA;GACD,CAAC,GACF,MAAM,8BAA8B;GAClC;GACA;GACA;GACA;GACD,CAAC;AAEN,MAAI,CAAC,WAAY,QAAO,KAAA;AACxB,SAAO,MAAM,mBAAmB,YAAY,SAAS,gBAAgB;SAC/D;AACN;;;AA4BJ,eAAsB,qBACpB,KACA,UAAuC,EAAE,EACI;CAC7C,MAAM,WAAW,MAAM,sBAAsB,KAAK,EAChD,UAAU,QAAQ,UACnB,CAAC;AACF,KAAI,CAAC,SAAU,QAAO,KAAA;CAEtB,MAAM,EAAE,SAAS,SAAS,cACxB,SAAS,qBAAqB;CAChC,MAAM,SAAS,SAAS;CACxB,MAAM,aAAa,MAAM,0BAA0B;EACjD;EACA;EACA;EACA,SAAS,QAAQ;EACjB,gBAAgB,QAAQ;EACxB,iBAAiB,QAAQ;EAC1B,CAAC;AACF,KAAI,CAAC,WAAY,QAAO,KAAA;AAExB,QAAO;EACL;EACA;EACA;EACA,KAAK,WAAW,OAAO;EACvB;EACA;EACD;;;;AC1VH,IAAsB,cAAtB,MAGyB;AAMzB,IAAa,gBAAb,cAGU,YAAe;CACvB,uBAAwB,IAAI,KAAkB;CAE9C,IAAI,KAAU;AACZ,SAAO,KAAK,KAAK,IAAI,IAAI;;CAG3B,IAAI,KAAU,OAAsB;AAClC,MAAI,UAAU,KAAA,EACZ,MAAK,KAAK,OAAO,IAAI;MAErB,MAAK,KAAK,IAAI,KAAK,MAAM;;CAI7B,OAAO,KAAgB;AACrB,OAAK,KAAK,OAAO,IAAI;;;;;ACNzB,IAAa,sBAAb,cAAyC,cAAgC;AAEzE,IAAa,SAAb,MAAuC;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,UAAuB;CAEvB,YACE,OACA,cACA,QACA,SACA,UAAU,oBACV,gBACA,aACA;AACA,QAAA,QAAc;AACd,QAAA,eAAqB;AACrB,QAAA,UAAgB;AAChB,QAAA,SAAe;AACf,QAAA,UAAgB;AAChB,QAAA,iBAAuB;AACvB,QAAA,cAAoB;EACpB,MAAM,eAAe,KAAK;AAC1B,QAAA,SAAe,IAAI,mBAAmB,QAAQ,MAAA,SAAe,aAAa;AAI1E,MAAI,aACF,OAAA,SAAe;AAGjB,OAAK,GAAG,SAAS,SAAS;AACxB,SAAA,OAAa,OAAO;IACpB;;CAGJ,IAAI,UAAU;AACZ,SAAO,MAAA;;CAGT,IAAI,OAAO;AACT,SAAO,MAAA,MAAY,IAAI,OAAO;;CAGhC,IAAI,SAAS;AACX,SAAO,MAAA;;CAGT,IAAI,SAAS;AACX,SAAO,MAAA;;CAGT,IAAI,SAAS;AACX,SAAO,MAAA;;CAGT,IAAI,MAAM;AACR,SAAO,MAAA,OAAa;;CAGtB,IAAI,iBAAiB;AACnB,SAAO,MAAA;;CAGT,cAAc,QAAqB;AACjC,QAAA,SAAe;AACf,QAAA,aAAmB,KAAK,UAAU,OAAO;;CAG3C,YAAY,MAAwB;AAClC,MAAI,KACF,OAAA,MAAY,IAAI,QAAQ,KAAK;MAE7B,OAAA,MAAY,OAAO,OAAO;AAE5B,QAAA,aAAmB,KAAK,QAAQ,KAAK;;CAGvC,MAAM,MAAM,SAAgC;AAC1C,QAAA,aAAmB,WAAW;AAC9B,MAAI;GACF,MAAM,SAAS,YAAY,QAAQ;GACnC,MAAM,aAAa,MAAM,MAAA,cACvB,OAAO,SACP,OAAO,SACP,MAAA,OAAa,IACd;AAED,OAAI,CAAC,YAAY;AACf,UAAA,WAAiB,KAAA,EAAU;AAC3B,UAAM,IAAI,MAAM,uBAAuB;;AAGzC,UAAO,MAAM,MAAA,cAAoB,SAAS,QAAQ,WAAW;WACtD,OAAO;AACd,SAAA,WAAiB,KAAA,EAAU;AAC3B,SAAA,aAAmB,iBAAiB;AACpC,SAAM;;;CAMV,MAAM,OAAO,QAAqC;AAChD,MAAI,CAAC,MAAA,YACH,OAAM,IAAI,MACR,wFACD;EAEH,MAAM,EACJ,SACA,SACA,eACA,UACA,WACA,kBACE;AAEJ,QAAA,aAAmB,WAAW;AAC9B,MAAI;GACF,MAAM,aAAa,MAAM,uBAAuB;IAC9C;IACA;IACA;IACA,KAAK,MAAA;IACL,OAAO,KAAK;IACZ;IACD,CAAC;AAEF,SAAM,MAAA,YAAkB,gBAAgB,WAAW;AACnD,SAAM,MAAA,YAAkB,iBAAiB,SAAS;IAChD;IACA;IACD,CAAC;GAEF,MAAM,UAAU,WAAW,0BAA0B,GAAG,QAAQ,GAAG,QAAQ,aAAa;AAGxF,UAAO,MAAM,MAAA,cACX,SACA,YAAY,QAAQ,EACpB,WACD;WACM,OAAO;AACd,SAAA,WAAiB,KAAA,EAAU;AAC3B,SAAA,aAAmB,iBAAiB;AACpC,SAAM;;;CAMV,OAAA,cACE,SACA,QACA,YACe;AACf,MACE,EACE,WAAW,OAAO,OAAO,WACzB,WAAW,kBAAkB,OAAO,KAAK,KAG3C,OAAM,IAAI,MAAM,qBAAqB;EAQvC,MAAM,uBAHS,WAAW,MAAM,QAGqC,SACjE,aACA;GACE,GAAG;GACH,OAAO;IACL,GAAG,WAAW;IACd,QAAQ;KACN,QAAQ;MAAE,SAAS;MAAK,SAAS,OAAO;MAAS;KACjD,OAAO;KACP,aAAa;KACd;IACF;GACF;AAGL,MACE,WAAW,OAAO,gBAAgB,aAAa,KAC7C,OAAO,QAAQ,aAAa,IAC9B,qBAAqB,MAAM,OAAO,OAAO,YAAY,OAAO,WAC5D,CAAE,MAAM,0BAA0B,qBAAqB,CAEvD,OAAM,IAAI,MAAM,+BAA+B;EAGjD,MAAM,OAAa;GACjB,GAAG;GACH,SAAS,WAAW,OAAO;GAC3B,KAAK;GACL,YAAY;GACb;AAED,QAAA,WAAiB,KAAK;AACtB,QAAA,aAAmB,aAAa;AAGhC,MAAI,MAAA,eACF,OAAA,eAAqB,MAAM,MAAA,QAAc,CACtC,MAAM,YAAY;AACjB,OACE,WACA,KAAK,MAAM,YAAY,KAAK,WAC5B,KAAK,KAAK,YAAY,KAAK,QAE3B,OAAA,WAAiB;IACf,GAAG,KAAK;IACR;IACA,KAAK;KACH,MAAM,QAAQ,YAAY,KAAA;KAC1B,WAAW,QAAQ,aAAa,KAAA;KACjC;IACF,CAAC;IAEJ,CACD,MAAM,QAAQ,MAAM;AAGzB,SAAO;;CAGT,SAAS;AACP,QAAA,WAAiB,KAAA,EAAU;AAC3B,QAAA,aAAmB,UAAU;AAC7B,SAAO,QAAQ,SAAS;;CAK1B,MAAM,aAA+B;EACnC,MAAM,OAAO,KAAK;AAClB,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AAMF,OAAI,CALe,MAAM,MAAA,cACvB,KAAK,SACL,KAAK,SACL,MAAA,OAAa,IACd,EACgB;AACf,UAAM,KAAK,QAAQ;AACnB,WAAO;;AAET,SAAM,KAAK,gBAAgB;AAC3B,UAAO;UACD;AACN,UAAO;;;CAMX,MAAM,iBAAmC;EACvC,MAAM,OAAO,KAAK;AAClB,MAAI,CAAC,QAAQ,CAAC,MAAA,eAAsB,QAAO;AAC3C,MAAI;GACF,MAAM,UAAU,MAAM,MAAA,eAAqB,MAAM,MAAA,QAAc;AAC/D,OAAI,CAAC,QAAS,QAAO;GAGrB,MAAM,UAAU,KAAK;AACrB,OACE,CAAC,WACD,QAAQ,YAAY,KAAK,WACzB,QAAQ,YAAY,KAAK,QAEzB,QAAO;AAST,OAJE,QAAQ,YAAY,KAAA,KACpB,QAAQ,QAAQ,eAAe,QAAQ,cACvC,QAAQ,QAAQ,aAAa,QAAQ,YACrC,QAAQ,QAAQ,cAAc,QAAQ,UACzB,QAAO;AACtB,SAAA,WAAiB;IACf,GAAG;IACH;IACA,KAAK;KACH,MAAM,QAAQ,YAAY,KAAA;KAC1B,WAAW,QAAQ,aAAa,KAAA;KACjC;IACF,CAAC;AACF,UAAO;UACD;AACN,UAAO;;;CAIX,GACE,OACA,UACY;AACZ,SAAO,MAAA,aAAmB,GAAG,OAAO,SAAS;;CAG/C,OAAA,cACE,SACA,SACA,QACqD;AAErD,MAAI,MAAA,YACF,QAAO,MAAA,YAAkB,cAAc;GAAE;GAAS;GAAS;GAAQ,CAAC;AAEtE,MAAI,CAAC,MAAA,QACH,OAAM,IAAI,MAAM,wBAAwB;EAE1C,MAAM,MAAM,IAAI,IACd,gCAAgC,mBAAmB,QAAQ,CAAC,WAAW,mBAAmB,QAAQ,CAAC,aAAa,mBAAmB,OAAO,CAAC,SAAS,mBAAmB,OAAO,IAC9K,MAAA,QACD;EACD,MAAM,WAAW,MAAM,MAAM,KAAK,EAChC,QAAQ,OACT,CAAC;AACF,MAAI,SAAS,GAIX,SAHgB,MAAM,SAAS,MAAM,EAGvB;MAEd,OAAM,IAAI,MAAM,6BAA6B,SAAS,SAAS;;CAInE,MAAM,kBAAkB,OAAe;AACrC,SAAO,sBAAsB,MAAM;;CAGrC,MAAM,eAAe,SAAmC;AACtD,MAAI,CAAC,KAAK,KACR,OAAM,IAAI,MAAM,iBAAiB;AAEnC,SAAO,MAAA,OAAa,eAAe,KAAK,KAAK,SAAS,QAAQ;;;;;ACzXlE,IAAa,qBAAb,MAAuE;CACrE,6BAAa,IAAI,KAAuD;CAExE,GACE,OACA,UACY;AACZ,MAAI,CAAC,MAAA,UAAgB,IAAI,MAAM,CAC7B,OAAA,UAAgB,IAAI,uBAAO,IAAI,KAAK,CAAC;AAEvC,QAAA,UAAgB,IAAI,MAAM,CAAE,IAAI,SAAoC;AACpE,eAAa;AACX,SAAA,UAAgB,IAAI,MAAM,EAAE,OAAO,SAAoC;;;CAI3E,KAAmC,OAAU,MAA6B;AACxE,QAAA,UAAgB,IAAI,MAAM,EAAE,SAAS,aAAa,SAAS,KAAK,CAAC;;;;;AClBrE,MAAa,qBAAqC,OAAO,MAAM,YAAY;AACzE,KAAI;EACF,MAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,QAAQ,QAAQ,GAAG,CAAC,eAAe;GACzE,QAAQ;GACR,SAAS,EACP,gBAAgB,oBACjB;GACD,MAAM,KAAK,UAAU,EACnB,YAAY,KAAK,SAClB,CAAC;GACH,CAAC;AAEF,MAAI,CAAC,SAAS,GACZ;AAOF,UAJgB,MAAM,SAAS,MAAM,EAIvB,WAAW,KAAA;SACnB;AACN;;;;;;;;;;ACMJ,IAAa,oBAAb,MAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;CAKA,YAAY,SAAiB;AAC3B,QAAA,UAAgB;;;;;;CAOlB,YAAY,SAA8B;AACxC,QAAA,UAAgB;AAChB,SAAO;;;;;;CAOT,iBAAiB,cAAwC;AACvD,QAAA,eAAqB;AACrB,SAAO;;;;;;CAOT,WAAW,QAA6B;AACtC,QAAA,SAAe;AACf,SAAO;;;;;;;CAQT,mBAAmB,gBAA6C;AAC9D,QAAA,iBAAuB;AACvB,SAAO;;;;;;CAOT,YAAY,SAAuB;AACjC,QAAA,UAAgB;AAChB,SAAO;;CAKT,mBAAmB,gBAA8B;AAC/C,QAAA,iBAAuB;AACvB,SAAO;;;;;;;;CAST,mBAAmB,gBAAsC;AACvD,QAAA,iBAAuB;AACvB,SAAO;;;;;;;CAQT,MAAM,QAAyB;AAC7B,MAAI,CAAC,MAAA,UAAgB,CAAC,MAAA,eACpB,OAAM,IAAI,MACR,oGACD;EAGH,MAAM,SACJ,MAAA,UACC,MAAM,IAAI,qBAAqB,CAC7B,mBAAmB,MAAA,eAAsB,CACzC,OAAO;EAEZ,MAAM,UAAU,MAAA,WAAiB,IAAI,qBAAqB;EAC1D,MAAM,eAAe,MAAA,gBAAsB,IAAI,oBAAoB;EACnE,MAAM,UAAU,MAAA,WAAKqB;EAIrB,MAAM,sBAAsB,MAAM,2BAA2B;GAC3D,gBAAgB,MAAA;GAChB;GACD,CAAC;EACF,MAAM,cAAc,sBAChB,IAAI,kBAAkB,oBAAoB,GAC1C,KAAA;EACJ,MAAM,iBACJ,MAAA,mBACC,cAAc,YAAY,iBAAiB;AAc9C,SAZe,IAAI,OACjB,SACA,cACA,QACA,MAAA,SACA,SACA,gBACA,YACD;;;;;CAUH,OAAO,KAAK,SAAkD;EAC5D,MAAM,UAAU,IAAI,kBAAkB,QAAQ,QAAQ;AAEtD,MAAI,QAAQ,QACV,SAAQ,YAAY,QAAQ,QAAQ;AAEtC,MAAI,QAAQ,aACV,SAAQ,iBAAiB,QAAQ,aAAa;AAEhD,MAAI,QAAQ,OACV,SAAQ,WAAW,QAAQ,OAAO;AAEpC,MAAI,QAAQ,eACV,SAAQ,mBAAmB,QAAQ,eAAe;AAEpD,MAAI,QAAQ,QACV,SAAQ,YAAY,QAAQ,QAAQ;AAEtC,MAAI,QAAQ,eACV,SAAQ,mBAAmB,QAAQ,eAAe;AAEpD,MAAI,QAAQ,eACV,SAAQ,mBAAmB,QAAQ,eAAe;AAGpD,SAAO"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/wallet/types.ts
|
|
2
|
+
const LoginMethod = {
|
|
3
|
+
WALLET: "wallet",
|
|
4
|
+
GOOGLE: "google",
|
|
5
|
+
EMAIL: "email",
|
|
6
|
+
APPLE: "apple"
|
|
7
|
+
};
|
|
8
|
+
function normalizeWalletTheme(theme) {
|
|
9
|
+
if (theme === void 0) return { mode: "light" };
|
|
10
|
+
if (typeof theme === "string") return { mode: theme };
|
|
11
|
+
return {
|
|
12
|
+
mode: theme.mode,
|
|
13
|
+
accentColor: theme.accentColor,
|
|
14
|
+
accentColorForeground: theme.accentColorForeground
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { normalizeWalletTheme as n, LoginMethod as t };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=types-DiIZNA8t.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-DiIZNA8t.js","names":[],"sources":["../src/wallet/types.ts"],"sourcesContent":["import type { ComponentType, ReactNode } from \"react\";\nimport type { SignCredentialTypedData } from \"../credential.js\";\n\n// Const object rather than an enum so config can be authored with plain string\n// literals (`methods: [\"google\"]`) while `LoginMethod.GOOGLE` still works.\nexport const LoginMethod = {\n WALLET: \"wallet\",\n GOOGLE: \"google\",\n EMAIL: \"email\",\n APPLE: \"apple\",\n} as const;\n\nexport type LoginMethod = (typeof LoginMethod)[keyof typeof LoginMethod];\n\n// Colors the host passes into an adapter Provider so its wallet UI matches.\n// The adapter stays agnostic to how the host derives them (CSS tokens, etc.).\nexport interface WalletThemeColors {\n accentColor?: string;\n accentColorForeground?: string;\n}\n\n// The theme the host passes at runtime: a bare mode, or a mode plus colors.\nexport type WalletTheme =\n | \"light\"\n | \"dark\"\n | ({ mode: \"light\" | \"dark\" } & WalletThemeColors);\n\n// Normalize a WalletTheme (or undefined) to a mode + colors the adapters use.\nexport function normalizeWalletTheme(theme: WalletTheme | undefined): {\n mode: \"light\" | \"dark\";\n accentColor?: string;\n accentColorForeground?: string;\n} {\n if (theme === undefined) return { mode: \"light\" };\n if (typeof theme === \"string\") return { mode: theme };\n return {\n mode: theme.mode,\n accentColor: theme.accentColor,\n accentColorForeground: theme.accentColorForeground,\n };\n}\n\n// The signer surface signIn needs, produced by an adapter after the user connects.\nexport interface WalletSession {\n address: `0x${string}`;\n chainId: number;\n signTypedData: SignCredentialTypedData;\n // Capability, not policy: the session can sign without a user prompt (e.g. a\n // Privy embedded wallet). Whether/when to sign silently is the host's call.\n canSignSilently?: boolean;\n}\n\n// Imperative controls returned by an adapter's React hook (used inside its Provider).\nexport interface WalletController {\n connect(method?: LoginMethod): Promise<WalletSession>;\n disconnect(): Promise<void>;\n getSession(): WalletSession | undefined;\n // Optional push stream of session changes (fires immediately with the current\n // one), so a host can complete sign-in on an OAuth return with no live connect().\n subscribe?(\n listener: (session: WalletSession | undefined) => void,\n ): () => void;\n}\n\n// Identity + capabilities, declared once per adapter in a dependency-free module\n// so a host can list methods and detect a redirect return with no wallet library.\nexport interface WalletAdapterMeta {\n id: string;\n // URL params the adapter leaves when a full-page OAuth login returns; empty for\n // adapters with no redirect flow.\n redirectReturnParams: string[];\n // Must be known before load(): the login UI renders buttons before any wallet\n // library is fetched.\n supportedMethods: LoginMethod[];\n}\n\n// Behaviour only — what an adapter factory returns. Identity lives in the meta.\nexport interface WalletAdapterImpl {\n // React provider that must wrap the app subtree for this adapter to work; the\n // host passes its current theme so the adapter's UI can match.\n Provider: ComponentType<{ children: ReactNode; theme?: WalletTheme }>;\n // Hook returning imperative controls; MUST be called inside <Provider>.\n useController: () => WalletController;\n}\n\n// What the host consumes: resolveAdapters pairs an impl with its meta.\nexport interface WalletAdapter extends WalletAdapterImpl {\n meta: WalletAdapterMeta;\n}\n\n// An adapter's light entry: eager meta plus a lazy loader that pulls the factory\n// and its wallet library only once login is activated.\nexport interface WalletAdapterDescriptor {\n meta: WalletAdapterMeta;\n load: () => Promise<WalletAdapterImpl>;\n}\n\nexport type WalletAdapterFactory<Config = unknown> = (\n config: Config,\n) => WalletAdapterImpl;\n\nexport type WalletAdapterProvider<Config = unknown> = (\n config: Config,\n) => WalletAdapterDescriptor;\n"],"mappings":";AAKA,MAAa,cAAc;CACzB,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACR;AAkBD,SAAgB,qBAAqB,OAInC;AACA,KAAI,UAAU,KAAA,EAAW,QAAO,EAAE,MAAM,SAAS;AACjD,KAAI,OAAO,UAAU,SAAU,QAAO,EAAE,MAAM,OAAO;AACrD,QAAO;EACL,MAAM,MAAM;EACZ,aAAa,MAAM;EACnB,uBAAuB,MAAM;EAC9B"}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { it as SignCredentialTypedData } from "./types-
|
|
1
|
+
import { it as SignCredentialTypedData } from "./types-efrA0fu2.js";
|
|
2
2
|
import { ComponentType, ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/wallet/types.d.ts
|
|
5
|
-
declare
|
|
6
|
-
WALLET
|
|
7
|
-
GOOGLE
|
|
8
|
-
EMAIL
|
|
9
|
-
APPLE
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
declare const DEFAULT_MOCK_METHODS: LoginMethod[];
|
|
5
|
+
declare const LoginMethod: {
|
|
6
|
+
readonly WALLET: "wallet";
|
|
7
|
+
readonly GOOGLE: "google";
|
|
8
|
+
readonly EMAIL: "email";
|
|
9
|
+
readonly APPLE: "apple";
|
|
10
|
+
};
|
|
11
|
+
type LoginMethod = (typeof LoginMethod)[keyof typeof LoginMethod];
|
|
13
12
|
interface WalletThemeColors {
|
|
14
13
|
accentColor?: string;
|
|
15
14
|
accentColorForeground?: string;
|
|
@@ -33,22 +32,28 @@ interface WalletController {
|
|
|
33
32
|
disconnect(): Promise<void>;
|
|
34
33
|
getSession(): WalletSession | undefined;
|
|
35
34
|
subscribe?(listener: (session: WalletSession | undefined) => void): () => void;
|
|
36
|
-
supportedMethods: LoginMethod[];
|
|
37
35
|
}
|
|
38
|
-
interface
|
|
39
|
-
id:
|
|
36
|
+
interface WalletAdapterMeta {
|
|
37
|
+
id: string;
|
|
38
|
+
redirectReturnParams: string[];
|
|
40
39
|
supportedMethods: LoginMethod[];
|
|
40
|
+
}
|
|
41
|
+
interface WalletAdapterImpl {
|
|
41
42
|
Provider: ComponentType<{
|
|
42
43
|
children: ReactNode;
|
|
43
44
|
theme?: WalletTheme;
|
|
44
45
|
}>;
|
|
45
46
|
useController: () => WalletController;
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
interface WalletAdapter extends WalletAdapterImpl {
|
|
49
|
+
meta: WalletAdapterMeta;
|
|
50
|
+
}
|
|
51
|
+
interface WalletAdapterDescriptor {
|
|
52
|
+
meta: WalletAdapterMeta;
|
|
53
|
+
load: () => Promise<WalletAdapterImpl>;
|
|
51
54
|
}
|
|
55
|
+
type WalletAdapterFactory<Config = unknown> = (config: Config) => WalletAdapterImpl;
|
|
56
|
+
type WalletAdapterProvider<Config = unknown> = (config: Config) => WalletAdapterDescriptor;
|
|
52
57
|
//#endregion
|
|
53
|
-
export {
|
|
54
|
-
//# sourceMappingURL=types-
|
|
58
|
+
export { WalletAdapterImpl as a, WalletController as c, WalletThemeColors as d, normalizeWalletTheme as f, WalletAdapterFactory as i, WalletSession as l, WalletAdapter as n, WalletAdapterMeta as o, WalletAdapterDescriptor as r, WalletAdapterProvider as s, LoginMethod as t, WalletTheme as u };
|
|
59
|
+
//# sourceMappingURL=types-DteAE_lL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-DteAE_lL.d.ts","names":[],"sources":["../src/wallet/types.ts"],"mappings":";;;;cAKa,WAAA;EAAA;;;;;KAOD,WAAA,WAAsB,WAAA,eAA0B,WAAA;AAAA,UAI3C,iBAAA;EACf,WAAA;EACA,qBAAA;AAAA;AAAA,KAIU,WAAA;EAGL,IAAA;AAAA,IAA2B,iBAAA;AAAA,iBAGlB,oBAAA,CAAqB,KAAA,EAAO,WAAA;EAC1C,IAAA;EACA,WAAA;EACA,qBAAA;AAAA;AAAA,UAYe,aAAA;EACf,OAAA;EACA,OAAA;EACA,aAAA,EAAe,uBAAA;EAGf,eAAA;AAAA;AAAA,UAIe,gBAAA;EACf,OAAA,CAAQ,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,aAAA;EACvC,UAAA,IAAc,OAAA;EACd,UAAA,IAAc,aAAA;EAGd,SAAA,EACE,QAAA,GAAW,OAAA,EAAS,aAAA;AAAA;AAAA,UAMP,iBAAA;EACf,EAAA;EAGA,oBAAA;EAGA,gBAAA,EAAkB,WAAA;AAAA;AAAA,UAIH,iBAAA;EAGf,QAAA,EAAU,aAAA;IAAgB,QAAA,EAAU,SAAA;IAAW,KAAA,GAAQ,WAAA;EAAA;EAEvD,aAAA,QAAqB,gBAAA;AAAA;AAAA,UAIN,aAAA,SAAsB,iBAAA;EACrC,IAAA,EAAM,iBAAA;AAAA;AAAA,UAKS,uBAAA;EACf,IAAA,EAAM,iBAAA;EACN,IAAA,QAAY,OAAA,CAAQ,iBAAA;AAAA;AAAA,KAGV,oBAAA,sBACV,MAAA,EAAQ,MAAA,KACL,iBAAA;AAAA,KAEO,qBAAA,sBACV,MAAA,EAAQ,MAAA,KACL,uBAAA"}
|