@renown/sdk 6.2.2-dev.2 → 6.2.2-dev.20

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.
Files changed (48) hide show
  1. package/README.md +103 -1
  2. package/dist/crypto.d.ts +2 -2
  3. package/dist/crypto.js +1 -1
  4. package/dist/index-25fTa4yI.d.ts +127 -0
  5. package/dist/index-25fTa4yI.d.ts.map +1 -0
  6. package/dist/index.d.ts +9 -8
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +17 -8
  9. package/dist/index.js.map +1 -1
  10. package/dist/node.d.ts +54 -11
  11. package/dist/node.d.ts.map +1 -1
  12. package/dist/node.js +94 -12
  13. package/dist/node.js.map +1 -1
  14. package/dist/renown-builder-BqWoYtBR.js +841 -0
  15. package/dist/renown-builder-BqWoYtBR.js.map +1 -0
  16. package/dist/{signer-XkA-D7Qt.js → signer-CgYhXTV7.js} +2 -2
  17. package/dist/{signer-XkA-D7Qt.js.map → signer-CgYhXTV7.js.map} +1 -1
  18. package/dist/types-DG816Qa8.js +27 -0
  19. package/dist/types-DG816Qa8.js.map +1 -0
  20. package/dist/{signer-DYKGoYHB.d.ts → types-DsF91dDF.d.ts} +121 -115
  21. package/dist/types-DsF91dDF.d.ts.map +1 -0
  22. package/dist/types-Z6jyeonm.d.ts +54 -0
  23. package/dist/types-Z6jyeonm.d.ts.map +1 -0
  24. package/dist/{utils-D8C7f9Qs.d.ts → utils-OOrVXHof.d.ts} +39 -65
  25. package/dist/utils-OOrVXHof.d.ts.map +1 -0
  26. package/dist/wallet/index.d.ts +30 -0
  27. package/dist/wallet/index.d.ts.map +1 -0
  28. package/dist/wallet/index.js +74 -0
  29. package/dist/wallet/index.js.map +1 -0
  30. package/dist/wallet/mock/index.d.ts +18 -0
  31. package/dist/wallet/mock/index.d.ts.map +1 -0
  32. package/dist/wallet/mock/index.js +38 -0
  33. package/dist/wallet/mock/index.js.map +1 -0
  34. package/dist/wallet/privy/index.d.ts +63 -0
  35. package/dist/wallet/privy/index.d.ts.map +1 -0
  36. package/dist/wallet/privy/index.js +230 -0
  37. package/dist/wallet/privy/index.js.map +1 -0
  38. package/dist/wallet/rainbow/index.d.ts +14 -0
  39. package/dist/wallet/rainbow/index.d.ts.map +1 -0
  40. package/dist/wallet/rainbow/index.js +218 -0
  41. package/dist/wallet/rainbow/index.js.map +1 -0
  42. package/package.json +57 -3
  43. package/dist/browser-key-storage-DSkDBAhU.d.ts +0 -14
  44. package/dist/browser-key-storage-DSkDBAhU.d.ts.map +0 -1
  45. package/dist/renown-builder-DP0iFzK1.js +0 -433
  46. package/dist/renown-builder-DP0iFzK1.js.map +0 -1
  47. package/dist/signer-DYKGoYHB.d.ts.map +0 -1
  48. package/dist/utils-D8C7f9Qs.d.ts.map +0 -1
@@ -0,0 +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,7 +1,7 @@
1
- import { fromString, toString } from "uint8arrays";
2
1
  import { createVerifiableCredentialJwt, verifyCredential } from "did-jwt-vc";
3
2
  import { Resolver } from "did-resolver";
4
3
  import { getResolver } from "key-did-resolver";
4
+ import { fromString, toString } from "uint8arrays";
5
5
  import { encodeDIDFromPub, getPublicKey } from "@didtools/key-webcrypto";
6
6
  //#region src/utils.ts
7
7
  /**
@@ -457,4 +457,4 @@ function signatureHasResultingHash(signature) {
457
457
  //#endregion
458
458
  export { signatureHasResultingHash as a, ConnectCrypto as c, createAuthBearerToken as d, getResolver$1 as f, parseSignatureHashField as i, RenownCrypto as l, verifyAuthBearerToken as m, createSignatureVerifier as n, MemoryKeyStorage as o, parsePkhDid as p, extractResultingHashFromSignature as r, RenownCryptoBuilder as s, RenownCryptoSigner as t, assertIsAuthCredential as u };
459
459
 
460
- //# sourceMappingURL=signer-XkA-D7Qt.js.map
460
+ //# sourceMappingURL=signer-CgYhXTV7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signer-XkA-D7Qt.js","names":["getResolver","keyDidResolver","#keyPairStorage","#subtleCrypto","#keyPair","#stringToBytes","#initializeKeyPair"],"sources":["../src/utils.ts","../src/crypto/utils.ts","../src/crypto/renown-crypto.ts","../src/crypto/renown-crypto-builder.ts","../src/crypto/memory-key-storage.ts","../src/crypto/signer.ts"],"sourcesContent":["import type { JwtCredentialPayload } from \"did-jwt-vc\";\nimport { createVerifiableCredentialJwt, verifyCredential } from \"did-jwt-vc\";\nimport { Resolver } from \"did-resolver\";\nimport { getResolver as keyDidResolver } from \"key-did-resolver\";\nimport type {\n AuthVerifiedCredential,\n CreateBearerTokenOptions,\n IAuthCredentialSubject,\n Issuer,\n PKHDid,\n VerifiedCredential,\n} from \"./types.js\";\n\nexport type ILogger = {\n level: \"verbose\" | \"debug\" | \"info\" | \"warn\" | \"error\";\n\n verbose: (message: string, ...replacements: any[]) => void;\n debug: (message: string, ...replacements: any[]) => void;\n info: (message: string, ...replacements: any[]) => void;\n warn: (message: string, ...replacements: any[]) => void;\n error: (message: string, ...replacements: any[]) => void;\n};\n\n/**\n * Parse a DID:pkh string to extract network, chain ID, and address information\n * @param did - The DID string in format \"did:pkh:networkId:chainId:address\"\n * @returns Parsed DID information\n * @throws Error if the DID format is invalid\n */\nexport function parsePkhDid(did: string): PKHDid {\n const parts = did.split(\":\");\n if (!did.startsWith(\"did:pkh:\") || parts.length !== 5) {\n throw new Error(\"Invalid pkh did\");\n }\n const [, , networkId, chainIdStr, address] = parts;\n\n if (!address.startsWith(\"0x\")) {\n throw new Error(`Invalid address: ${address}`);\n }\n\n const chainId = Number(chainIdStr);\n if (isNaN(chainId)) {\n throw new Error(`Invalid chain id: ${chainIdStr}`);\n }\n\n return {\n chainId,\n networkId,\n address: address as PKHDid[\"address\"],\n };\n}\n\nexport interface VerifyAuthBearerTokenOptions {\n /** Expected `aud` claim. Required when verifying tokens that include an\n * audience claim — did-jwt rejects them otherwise with\n * `invalid_config: JWT audience is required but your app address has not\n * been configured`. Tokens minted without `aud` are unaffected. */\n audience?: string;\n}\n\nexport async function verifyAuthBearerToken(\n jwt: string,\n options?: VerifyAuthBearerTokenOptions,\n): Promise<false | AuthVerifiedCredential> {\n try {\n const now = parseInt(String(Date.now() / 1000));\n const verified: VerifiedCredential = await verifyCredential(\n jwt,\n getResolver(),\n {\n ...(options?.audience !== undefined && { audience: options.audience }),\n policies: {\n now: parseInt(String(Date.now() / 1000)),\n expirationDate: true,\n issuanceDate: true,\n },\n },\n );\n\n if (verified.payload.exp && verified.payload.exp < now) {\n return false;\n }\n assertIsAuthCredential(verified);\n return verified;\n } catch (e) {\n console.error(e);\n return false;\n }\n}\n\nexport function assertIsAuthCredential(\n credential: VerifiedCredential,\n): asserts credential is AuthVerifiedCredential {\n const subjectKeys = Object.keys(\n credential.verifiableCredential.credentialSubject,\n );\n if (\n ![\"address\", \"chainId\", \"networkId\"].every((key) =>\n subjectKeys.includes(key),\n )\n ) {\n throw new Error(\n \"Invalid Auth Credential Subject:\" +\n JSON.stringify(\n credential.verifiableCredential.credentialSubject,\n null,\n 2,\n ),\n );\n }\n}\n\nexport async function createAuthBearerToken(\n chainId: number,\n networkId: string,\n address: string,\n issuer: Issuer,\n options?: CreateBearerTokenOptions,\n) {\n const vcPayload: JwtCredentialPayload = {\n sub: issuer.did,\n vc: {\n \"@context\": [\"https://www.w3.org/2018/credentials/v1\"],\n type: [\"VerifiableCredential\"],\n credentialSubject: {\n chainId,\n networkId,\n address,\n } satisfies IAuthCredentialSubject,\n },\n aud: options?.aud,\n };\n\n const jwt = await createVerifiableCredentialJwt(vcPayload, issuer, {\n expiresIn: options?.expiresIn,\n });\n return jwt;\n}\n\nexport const getResolver = () => {\n const keyResolver = keyDidResolver();\n if (!keyResolver) {\n throw new Error(\"Failed to get key resolver\");\n }\n\n return new Resolver(keyResolver);\n};\n","import { encodeDIDFromPub, getPublicKey } from \"@didtools/key-webcrypto\";\nimport type { DID, JwkKeyPair } from \"./types.js\";\n\nexport const ECDSA_ALGORITHM: EcKeyAlgorithm = {\n name: \"ECDSA\",\n namedCurve: \"P-256\",\n};\n\nexport const ECDSA_SIGN_ALGORITHM = {\n name: \"ECDSA\",\n namedCurve: \"P-256\",\n hash: \"SHA-256\",\n};\n\nexport async function parseDid(keyPair: CryptoKeyPair): Promise<DID> {\n return encodeDIDFromPub(await getPublicKey(keyPair)) as DID;\n}\n\nexport async function exportKeyPair(\n keyPair: CryptoKeyPair,\n subtleCrypto: SubtleCrypto,\n): Promise<JwkKeyPair> {\n return {\n publicKey: await subtleCrypto.exportKey(\"jwk\", keyPair.publicKey),\n privateKey: await subtleCrypto.exportKey(\"jwk\", keyPair.privateKey),\n };\n}\n\nexport async function importKeyPair(\n jwkKeyPair: JwkKeyPair,\n subtleCrypto: SubtleCrypto,\n algorithm: EcKeyAlgorithm = ECDSA_ALGORITHM,\n): Promise<CryptoKeyPair> {\n return {\n publicKey: await subtleCrypto.importKey(\n \"jwk\",\n jwkKeyPair.publicKey,\n algorithm,\n true,\n [\"verify\"],\n ),\n privateKey: await subtleCrypto.importKey(\n \"jwk\",\n jwkKeyPair.privateKey,\n algorithm,\n true,\n [\"sign\"],\n ),\n };\n}\n\nexport async function generateKeyPair(\n subtleCrypto: SubtleCrypto,\n algorithm: EcKeyAlgorithm = ECDSA_ALGORITHM,\n): Promise<CryptoKeyPair> {\n return subtleCrypto.generateKey(algorithm, true, [\"sign\", \"verify\"]);\n}\n","import { fromString, toString } from \"uint8arrays\";\nimport type { CreateBearerTokenOptions, Issuer } from \"../types.js\";\nimport { createAuthBearerToken } from \"../utils.js\";\nimport type { DID, IRenownCrypto, JsonWebKeyPairStorage } from \"./types.js\";\nimport { ECDSA_ALGORITHM, ECDSA_SIGN_ALGORITHM } from \"./utils.js\";\n\nconst RENOWN_NETWORK_ID = \"eip155\";\nconst RENOWN_CHAIN_ID = 1;\n\nexport class RenownCrypto implements IRenownCrypto {\n #subtleCrypto: SubtleCrypto;\n #keyPair: CryptoKeyPair;\n #keyPairStorage: JsonWebKeyPairStorage;\n\n readonly did: DID;\n\n static algorithm = ECDSA_ALGORITHM;\n static signAlgorithm = ECDSA_SIGN_ALGORITHM;\n\n constructor(\n keyPairStorage: JsonWebKeyPairStorage,\n crypto: SubtleCrypto,\n keyPair: CryptoKeyPair,\n did: DID,\n ) {\n this.#keyPairStorage = keyPairStorage;\n this.#subtleCrypto = crypto;\n this.#keyPair = keyPair;\n this.did = did;\n }\n\n get publicKey() {\n return this.#keyPair.publicKey;\n }\n\n async getBearerToken(\n address: string | undefined,\n options?: CreateBearerTokenOptions,\n ): Promise<string> {\n return await createAuthBearerToken(\n Number(RENOWN_CHAIN_ID),\n RENOWN_NETWORK_ID,\n address || this.did,\n this.issuer,\n options,\n );\n }\n\n async removeDid(): Promise<void> {\n await this.#keyPairStorage.removeKeyPair();\n }\n\n #stringToBytes(s: string): Uint8Array {\n return fromString(s, \"utf-8\");\n }\n\n async sign(data: Uint8Array | string): Promise<Uint8Array> {\n const dataBytes: Uint8Array =\n typeof data === \"string\" ? this.#stringToBytes(data) : data;\n\n const arrayBuffer = await this.#subtleCrypto.sign(\n RenownCrypto.signAlgorithm,\n this.#keyPair.privateKey,\n dataBytes.buffer as ArrayBuffer,\n );\n\n return new Uint8Array(arrayBuffer);\n }\n\n async verify(data: Uint8Array, signature: Uint8Array): Promise<boolean> {\n return this.#subtleCrypto.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n this.#keyPair.publicKey,\n signature.buffer as ArrayBuffer,\n data.buffer as ArrayBuffer,\n );\n }\n\n get issuer(): Issuer {\n return {\n did: this.did,\n signer: async (data: string | Uint8Array) => {\n const signature = await this.sign(\n typeof data === \"string\" ? new TextEncoder().encode(data) : data,\n );\n return toString(signature, \"base64url\");\n },\n alg: \"ES256\",\n };\n }\n}\n\n/**\n * @deprecated Use RenownCrypto instead\n */\nexport class ConnectCrypto extends RenownCrypto {}\n","import { RenownCrypto } from \"./renown-crypto.js\";\nimport type { JsonWebKeyPairStorage } from \"./types.js\";\nimport {\n exportKeyPair,\n generateKeyPair,\n importKeyPair,\n parseDid,\n} from \"./utils.js\";\n\nexport class RenownCryptoBuilder {\n private keyPairStorage?: JsonWebKeyPairStorage;\n private subtleCrypto?: SubtleCrypto;\n\n withKeyPairStorage(storage: JsonWebKeyPairStorage): this {\n this.keyPairStorage = storage;\n return this;\n }\n\n withSubtleCrypto(crypto: SubtleCrypto): this {\n this.subtleCrypto = crypto;\n return this;\n }\n\n async build(): Promise<RenownCrypto> {\n if (!this.keyPairStorage) {\n throw new Error(\n \"KeyPairStorage is required. Use withKeyPairStorage() to set it.\",\n );\n }\n\n const subtleCrypto = this.subtleCrypto ?? globalThis.crypto.subtle;\n const keyPair = await this.#initializeKeyPair(\n subtleCrypto,\n this.keyPairStorage,\n );\n const did = await parseDid(keyPair);\n\n return new RenownCrypto(this.keyPairStorage, subtleCrypto, keyPair, did);\n }\n\n async #initializeKeyPair(\n subtleCrypto: SubtleCrypto,\n keyPairStorage: JsonWebKeyPairStorage,\n ): Promise<CryptoKeyPair> {\n const loadedKeyPair = await keyPairStorage.loadKeyPair();\n if (loadedKeyPair) {\n return importKeyPair(loadedKeyPair, subtleCrypto);\n }\n\n const keyPair = await generateKeyPair(subtleCrypto);\n const exported = await exportKeyPair(keyPair, subtleCrypto);\n await keyPairStorage.saveKeyPair(exported);\n return keyPair;\n }\n}\n","import type { JsonWebKeyPairStorage, JwkKeyPair } from \"./types.js\";\n\nexport class MemoryKeyStorage implements JsonWebKeyPairStorage {\n private keyPair: JwkKeyPair | undefined;\n\n constructor(keyPair?: JwkKeyPair) {\n this.keyPair = keyPair;\n }\n\n loadKeyPair() {\n return Promise.resolve(this.keyPair);\n }\n\n saveKeyPair(keyPair: JwkKeyPair) {\n this.keyPair = keyPair;\n return Promise.resolve();\n }\n\n removeKeyPair() {\n this.keyPair = undefined;\n return Promise.resolve();\n }\n}\n","import type {\n Action,\n AppActionSigner,\n ISigner,\n Operation,\n Signature,\n SignatureVerificationHandler,\n UserActionSigner,\n} from \"@powerhousedao/shared/document-model\";\nimport type { IRenownCrypto } from \"./index.js\";\n\nexport class InvalidSignatureError extends Error {\n constructor() {\n super(\"Invalid signature\");\n }\n}\n\nexport class RenownCryptoSigner implements ISigner {\n readonly app: AppActionSigner;\n\n constructor(\n private readonly crypto: IRenownCrypto,\n private readonly appName: string,\n public user?: UserActionSigner,\n ) {\n this.app = {\n key: this.crypto.did,\n name: this.appName,\n };\n }\n\n get publicKey() {\n return this.crypto.publicKey;\n }\n\n async sign(data: Uint8Array): Promise<Uint8Array> {\n return this.crypto.sign(data);\n }\n\n async verify(data: Uint8Array, signature: Uint8Array): Promise<void> {\n const isValid = await this.crypto.verify(data, signature);\n if (!isValid) {\n throw new InvalidSignatureError();\n }\n }\n\n async signAction(\n action: Action,\n abortSignal?: AbortSignal,\n ): Promise<Signature> {\n const hashField = action.context?.prevOpHash ?? \"\";\n return this._signAction(action, hashField, abortSignal);\n }\n\n /**\n * Signs an action including a predicted resulting state hash.\n *\n * The resulting hash is packed into the signature tuple's 4th element (index 3)\n * using the format: `${prevStateHash}:${resultingStateHash}`\n *\n * This allows offline verification of documents without reducer logic:\n * - Verifier can check that the signature is valid for the claimed resulting state\n * - Verifier can compare claimed resulting state to actual operation.hash\n *\n * @param action - The action to sign\n * @param resultingStateHash - The predicted hash of document state AFTER this action runs\n * @param abortSignal - Optional abort signal\n * @returns A Signature tuple with the resulting hash encoded in element [3]\n */\n async signActionWithResultingState(\n action: Action,\n resultingStateHash: string,\n abortSignal?: AbortSignal,\n ): Promise<Signature> {\n const prevStateHash = action.context?.prevOpHash ?? \"\";\n const hashField = `${prevStateHash}:${resultingStateHash}`;\n return this._signAction(action, hashField, abortSignal);\n }\n\n /**\n * Internal signing implementation shared by signAction and signActionWithResultingState.\n */\n private async _signAction(\n action: Action,\n hashField: string,\n abortSignal?: AbortSignal,\n ): Promise<Signature> {\n if (abortSignal?.aborted) {\n throw new Error(\"Signing aborted\");\n }\n\n const timestamp = (new Date().getTime() / 1000).toFixed(0);\n const hash = await this.hashAction(action);\n\n if (abortSignal?.aborted) {\n throw new Error(\"Signing aborted\");\n }\n\n const params: [string, string, string, string] = [\n timestamp,\n this.crypto.did,\n hash,\n hashField,\n ];\n const message = this.buildSignatureMessage(params);\n const signatureBytes = await this.crypto.sign(message);\n const signatureHex = `0x${this.arrayBufferToHex(signatureBytes)}`;\n\n if (abortSignal?.aborted) {\n throw new Error(\"Signing aborted\");\n }\n\n return [...params, signatureHex];\n }\n\n private async hashAction(action: Action): Promise<string> {\n const payload = [\n action.scope,\n action.type,\n JSON.stringify(action.input),\n ].join(\"\");\n const encoder = new TextEncoder();\n const data = encoder.encode(payload);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n return this.arrayBufferToBase64(hashBuffer);\n }\n\n private buildSignatureMessage(\n params: [string, string, string, string],\n ): Uint8Array {\n const message = params.join(\"\");\n const prefix = \"\\x19Signed Operation:\\n\" + message.length.toString();\n const encoder = new TextEncoder();\n return encoder.encode(prefix + message);\n }\n\n private arrayBufferToHex(buffer: Uint8Array | ArrayBuffer): string {\n const bytes =\n buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n}\n\n/**\n * Creates a signature verification handler that verifies signatures using the Web Crypto API.\n * The verification uses ECDSA with P-256 curve and SHA-256 hash, matching the RenownCrypto signing algorithm.\n */\nexport function createSignatureVerifier(\n requireSignature = false,\n): SignatureVerificationHandler {\n return async (operation: Operation, publicKey: string): Promise<boolean> => {\n const signer = operation.action.context?.signer;\n if (!signer || !publicKey) {\n return !requireSignature;\n }\n\n const signatures = signer.signatures;\n if (signatures.length === 0) {\n return false;\n }\n\n const signature = signatures[signatures.length - 1];\n const [timestamp, signerKey, hash, prevStateHash, signatureHex] = signature;\n\n if (signerKey !== publicKey) {\n return false;\n }\n\n const params: [string, string, string, string] = [\n timestamp,\n signerKey,\n hash,\n prevStateHash,\n ];\n const message = buildSignatureMessage(params);\n const signatureBytes = hexToUint8Array(signatureHex);\n\n const cryptoKey = await importPublicKey(publicKey);\n\n const isValid = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n cryptoKey,\n signatureBytes.buffer as ArrayBuffer,\n message.buffer as ArrayBuffer,\n );\n\n return isValid;\n };\n}\n\nfunction buildSignatureMessage(\n params: [string, string, string, string],\n): Uint8Array {\n const message = params.join(\"\");\n const prefix = \"\\x19Signed Operation:\\n\" + message.length.toString();\n const encoder = new TextEncoder();\n return encoder.encode(prefix + message);\n}\n\nfunction hexToUint8Array(hex: string): Uint8Array {\n const cleanHex = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const bytes = new Uint8Array(cleanHex.length / 2);\n for (let i = 0; i < cleanHex.length; i += 2) {\n bytes[i / 2] = parseInt(cleanHex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n\nasync function importPublicKey(did: string): Promise<CryptoKey> {\n const keyData = extractKeyFromDid(did);\n return crypto.subtle.importKey(\n \"raw\",\n keyData.buffer as ArrayBuffer,\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"verify\"],\n );\n}\n\nfunction extractKeyFromDid(did: string): Uint8Array {\n const parts = did.split(\":\");\n if (parts.length < 3 || parts[0] !== \"did\" || parts[1] !== \"key\") {\n throw new Error(`Invalid DID format: ${did}`);\n }\n\n const multibaseKey = parts[2];\n if (!multibaseKey.startsWith(\"z\")) {\n throw new Error(`Unsupported multibase encoding: ${multibaseKey[0]}`);\n }\n\n const decoded = base58Decode(multibaseKey.slice(1));\n\n if (decoded[0] !== 0x80 || decoded[1] !== 0x24) {\n throw new Error(\"Not a P-256 public key multicodec\");\n }\n\n const compressedKey = decoded.slice(2);\n return decompressP256PublicKey(compressedKey);\n}\n\nfunction base58Decode(input: string): Uint8Array {\n const ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n const ALPHABET_MAP = new Map<string, number>();\n for (let i = 0; i < ALPHABET.length; i++) {\n ALPHABET_MAP.set(ALPHABET[i], i);\n }\n\n if (input.length === 0) {\n return new Uint8Array(0);\n }\n\n const bytes: number[] = [0];\n for (const char of input) {\n const value = ALPHABET_MAP.get(char);\n if (value === undefined) {\n throw new Error(`Invalid base58 character: ${char}`);\n }\n\n let carry = value;\n for (let j = 0; j < bytes.length; j++) {\n carry += bytes[j] * 58;\n bytes[j] = carry & 0xff;\n carry >>= 8;\n }\n\n while (carry > 0) {\n bytes.push(carry & 0xff);\n carry >>= 8;\n }\n }\n\n for (const char of input) {\n if (char !== \"1\") break;\n bytes.push(0);\n }\n\n return new Uint8Array(bytes.reverse());\n}\n\nfunction decompressP256PublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== 33) {\n throw new Error(`Invalid compressed key length: ${compressed.length}`);\n }\n\n const prefix = compressed[0];\n if (prefix !== 0x02 && prefix !== 0x03) {\n throw new Error(`Invalid compression prefix: ${prefix}`);\n }\n\n const p = BigInt(\n \"0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff\",\n );\n const a = BigInt(\n \"0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc\",\n );\n const b = BigInt(\n \"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b\",\n );\n\n let x = BigInt(0);\n for (let i = 1; i < compressed.length; i++) {\n x = (x << BigInt(8)) | BigInt(compressed[i]);\n }\n\n const ySquared = (modPow(x, BigInt(3), p) + a * x + b) % p;\n let y = modPow(ySquared, (p + BigInt(1)) / BigInt(4), p);\n\n const isYEven = y % BigInt(2) === BigInt(0);\n const shouldBeEven = prefix === 0x02;\n if (isYEven !== shouldBeEven) {\n y = p - y;\n }\n\n const uncompressed = new Uint8Array(65);\n uncompressed[0] = 0x04;\n\n const xBytes = bigIntToBytes(x, 32);\n const yBytes = bigIntToBytes(y, 32);\n\n uncompressed.set(xBytes, 1);\n uncompressed.set(yBytes, 33);\n\n return uncompressed;\n}\n\nfunction modPow(base: bigint, exp: bigint, mod: bigint): bigint {\n let result = BigInt(1);\n base = base % mod;\n while (exp > BigInt(0)) {\n if (exp % BigInt(2) === BigInt(1)) {\n result = (result * base) % mod;\n }\n exp = exp >> BigInt(1);\n base = (base * base) % mod;\n }\n return result;\n}\n\nfunction bigIntToBytes(n: bigint, length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n for (let i = length - 1; i >= 0; i--) {\n bytes[i] = Number(n & BigInt(0xff));\n n = n >> BigInt(8);\n }\n return bytes;\n}\n\n/**\n * Parses the hash field (element [3]) from a signature tuple.\n *\n * Supports two formats:\n * - Old format: just `prevStateHash` (no colon)\n * - New format: `prevStateHash:resultingStateHash` (colon-separated)\n *\n * @param hashField - The 4th element of a Signature tuple\n * @returns Object with prevStateHash and optional resultingStateHash\n */\nexport function parseSignatureHashField(hashField: string): {\n prevStateHash: string;\n resultingStateHash: string | undefined;\n} {\n const colonIndex = hashField.indexOf(\":\");\n\n if (colonIndex === -1) {\n return {\n prevStateHash: hashField,\n resultingStateHash: undefined,\n };\n }\n\n return {\n prevStateHash: hashField.substring(0, colonIndex),\n resultingStateHash: hashField.substring(colonIndex + 1),\n };\n}\n\n/**\n * Extracts the resulting state hash from a signature, if present.\n *\n * @param signature - A Signature tuple\n * @returns The resulting state hash, or undefined if not present\n */\nexport function extractResultingHashFromSignature(\n signature: Signature,\n): string | undefined {\n const hashField = signature[3];\n const { resultingStateHash } = parseSignatureHashField(hashField);\n return resultingStateHash;\n}\n\n/**\n * Checks if a signature includes a resulting state hash.\n *\n * @param signature - A Signature tuple\n * @returns true if the signature includes a resulting state hash\n */\nexport function signatureHasResultingHash(signature: Signature): boolean {\n return extractResultingHashFromSignature(signature) !== undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"signer-CgYhXTV7.js","names":["getResolver","keyDidResolver","#keyPairStorage","#subtleCrypto","#keyPair","#stringToBytes","#initializeKeyPair"],"sources":["../src/utils.ts","../src/crypto/utils.ts","../src/crypto/renown-crypto.ts","../src/crypto/renown-crypto-builder.ts","../src/crypto/memory-key-storage.ts","../src/crypto/signer.ts"],"sourcesContent":["import type { JwtCredentialPayload } from \"did-jwt-vc\";\nimport { createVerifiableCredentialJwt, verifyCredential } from \"did-jwt-vc\";\nimport { Resolver } from \"did-resolver\";\nimport { getResolver as keyDidResolver } from \"key-did-resolver\";\nimport type {\n AuthVerifiedCredential,\n CreateBearerTokenOptions,\n IAuthCredentialSubject,\n Issuer,\n PKHDid,\n VerifiedCredential,\n} from \"./types.js\";\n\nexport type ILogger = {\n level: \"verbose\" | \"debug\" | \"info\" | \"warn\" | \"error\";\n\n verbose: (message: string, ...replacements: any[]) => void;\n debug: (message: string, ...replacements: any[]) => void;\n info: (message: string, ...replacements: any[]) => void;\n warn: (message: string, ...replacements: any[]) => void;\n error: (message: string, ...replacements: any[]) => void;\n};\n\n/**\n * Parse a DID:pkh string to extract network, chain ID, and address information\n * @param did - The DID string in format \"did:pkh:networkId:chainId:address\"\n * @returns Parsed DID information\n * @throws Error if the DID format is invalid\n */\nexport function parsePkhDid(did: string): PKHDid {\n const parts = did.split(\":\");\n if (!did.startsWith(\"did:pkh:\") || parts.length !== 5) {\n throw new Error(\"Invalid pkh did\");\n }\n const [, , networkId, chainIdStr, address] = parts;\n\n if (!address.startsWith(\"0x\")) {\n throw new Error(`Invalid address: ${address}`);\n }\n\n const chainId = Number(chainIdStr);\n if (isNaN(chainId)) {\n throw new Error(`Invalid chain id: ${chainIdStr}`);\n }\n\n return {\n chainId,\n networkId,\n address: address as PKHDid[\"address\"],\n };\n}\n\nexport interface VerifyAuthBearerTokenOptions {\n /** Expected `aud` claim. Required when verifying tokens that include an\n * audience claim — did-jwt rejects them otherwise with\n * `invalid_config: JWT audience is required but your app address has not\n * been configured`. Tokens minted without `aud` are unaffected. */\n audience?: string;\n}\n\nexport async function verifyAuthBearerToken(\n jwt: string,\n options?: VerifyAuthBearerTokenOptions,\n): Promise<false | AuthVerifiedCredential> {\n try {\n const now = parseInt(String(Date.now() / 1000));\n const verified: VerifiedCredential = await verifyCredential(\n jwt,\n getResolver(),\n {\n ...(options?.audience !== undefined && { audience: options.audience }),\n policies: {\n now: parseInt(String(Date.now() / 1000)),\n expirationDate: true,\n issuanceDate: true,\n },\n },\n );\n\n if (verified.payload.exp && verified.payload.exp < now) {\n return false;\n }\n assertIsAuthCredential(verified);\n return verified;\n } catch (e) {\n console.error(e);\n return false;\n }\n}\n\nexport function assertIsAuthCredential(\n credential: VerifiedCredential,\n): asserts credential is AuthVerifiedCredential {\n const subjectKeys = Object.keys(\n credential.verifiableCredential.credentialSubject,\n );\n if (\n ![\"address\", \"chainId\", \"networkId\"].every((key) =>\n subjectKeys.includes(key),\n )\n ) {\n throw new Error(\n \"Invalid Auth Credential Subject:\" +\n JSON.stringify(\n credential.verifiableCredential.credentialSubject,\n null,\n 2,\n ),\n );\n }\n}\n\nexport async function createAuthBearerToken(\n chainId: number,\n networkId: string,\n address: string,\n issuer: Issuer,\n options?: CreateBearerTokenOptions,\n) {\n const vcPayload: JwtCredentialPayload = {\n sub: issuer.did,\n vc: {\n \"@context\": [\"https://www.w3.org/2018/credentials/v1\"],\n type: [\"VerifiableCredential\"],\n credentialSubject: {\n chainId,\n networkId,\n address,\n } satisfies IAuthCredentialSubject,\n },\n aud: options?.aud,\n };\n\n const jwt = await createVerifiableCredentialJwt(vcPayload, issuer, {\n expiresIn: options?.expiresIn,\n });\n return jwt;\n}\n\nexport const getResolver = () => {\n const keyResolver = keyDidResolver();\n if (!keyResolver) {\n throw new Error(\"Failed to get key resolver\");\n }\n\n return new Resolver(keyResolver);\n};\n","import { encodeDIDFromPub, getPublicKey } from \"@didtools/key-webcrypto\";\nimport type { DID, JwkKeyPair } from \"./types.js\";\n\nexport const ECDSA_ALGORITHM: EcKeyAlgorithm = {\n name: \"ECDSA\",\n namedCurve: \"P-256\",\n};\n\nexport const ECDSA_SIGN_ALGORITHM = {\n name: \"ECDSA\",\n namedCurve: \"P-256\",\n hash: \"SHA-256\",\n};\n\nexport async function parseDid(keyPair: CryptoKeyPair): Promise<DID> {\n return encodeDIDFromPub(await getPublicKey(keyPair)) as DID;\n}\n\nexport async function exportKeyPair(\n keyPair: CryptoKeyPair,\n subtleCrypto: SubtleCrypto,\n): Promise<JwkKeyPair> {\n return {\n publicKey: await subtleCrypto.exportKey(\"jwk\", keyPair.publicKey),\n privateKey: await subtleCrypto.exportKey(\"jwk\", keyPair.privateKey),\n };\n}\n\nexport async function importKeyPair(\n jwkKeyPair: JwkKeyPair,\n subtleCrypto: SubtleCrypto,\n algorithm: EcKeyAlgorithm = ECDSA_ALGORITHM,\n): Promise<CryptoKeyPair> {\n return {\n publicKey: await subtleCrypto.importKey(\n \"jwk\",\n jwkKeyPair.publicKey,\n algorithm,\n true,\n [\"verify\"],\n ),\n privateKey: await subtleCrypto.importKey(\n \"jwk\",\n jwkKeyPair.privateKey,\n algorithm,\n true,\n [\"sign\"],\n ),\n };\n}\n\nexport async function generateKeyPair(\n subtleCrypto: SubtleCrypto,\n algorithm: EcKeyAlgorithm = ECDSA_ALGORITHM,\n): Promise<CryptoKeyPair> {\n return subtleCrypto.generateKey(algorithm, true, [\"sign\", \"verify\"]);\n}\n","import { fromString, toString } from \"uint8arrays\";\nimport type { CreateBearerTokenOptions, Issuer } from \"../types.js\";\nimport { createAuthBearerToken } from \"../utils.js\";\nimport type { DID, IRenownCrypto, JsonWebKeyPairStorage } from \"./types.js\";\nimport { ECDSA_ALGORITHM, ECDSA_SIGN_ALGORITHM } from \"./utils.js\";\n\nconst RENOWN_NETWORK_ID = \"eip155\";\nconst RENOWN_CHAIN_ID = 1;\n\nexport class RenownCrypto implements IRenownCrypto {\n #subtleCrypto: SubtleCrypto;\n #keyPair: CryptoKeyPair;\n #keyPairStorage: JsonWebKeyPairStorage;\n\n readonly did: DID;\n\n static algorithm = ECDSA_ALGORITHM;\n static signAlgorithm = ECDSA_SIGN_ALGORITHM;\n\n constructor(\n keyPairStorage: JsonWebKeyPairStorage,\n crypto: SubtleCrypto,\n keyPair: CryptoKeyPair,\n did: DID,\n ) {\n this.#keyPairStorage = keyPairStorage;\n this.#subtleCrypto = crypto;\n this.#keyPair = keyPair;\n this.did = did;\n }\n\n get publicKey() {\n return this.#keyPair.publicKey;\n }\n\n async getBearerToken(\n address: string | undefined,\n options?: CreateBearerTokenOptions,\n ): Promise<string> {\n return await createAuthBearerToken(\n Number(RENOWN_CHAIN_ID),\n RENOWN_NETWORK_ID,\n address || this.did,\n this.issuer,\n options,\n );\n }\n\n async removeDid(): Promise<void> {\n await this.#keyPairStorage.removeKeyPair();\n }\n\n #stringToBytes(s: string): Uint8Array {\n return fromString(s, \"utf-8\");\n }\n\n async sign(data: Uint8Array | string): Promise<Uint8Array> {\n const dataBytes: Uint8Array =\n typeof data === \"string\" ? this.#stringToBytes(data) : data;\n\n const arrayBuffer = await this.#subtleCrypto.sign(\n RenownCrypto.signAlgorithm,\n this.#keyPair.privateKey,\n dataBytes.buffer as ArrayBuffer,\n );\n\n return new Uint8Array(arrayBuffer);\n }\n\n async verify(data: Uint8Array, signature: Uint8Array): Promise<boolean> {\n return this.#subtleCrypto.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n this.#keyPair.publicKey,\n signature.buffer as ArrayBuffer,\n data.buffer as ArrayBuffer,\n );\n }\n\n get issuer(): Issuer {\n return {\n did: this.did,\n signer: async (data: string | Uint8Array) => {\n const signature = await this.sign(\n typeof data === \"string\" ? new TextEncoder().encode(data) : data,\n );\n return toString(signature, \"base64url\");\n },\n alg: \"ES256\",\n };\n }\n}\n\n/**\n * @deprecated Use RenownCrypto instead\n */\nexport class ConnectCrypto extends RenownCrypto {}\n","import { RenownCrypto } from \"./renown-crypto.js\";\nimport type { JsonWebKeyPairStorage } from \"./types.js\";\nimport {\n exportKeyPair,\n generateKeyPair,\n importKeyPair,\n parseDid,\n} from \"./utils.js\";\n\nexport class RenownCryptoBuilder {\n private keyPairStorage?: JsonWebKeyPairStorage;\n private subtleCrypto?: SubtleCrypto;\n\n withKeyPairStorage(storage: JsonWebKeyPairStorage): this {\n this.keyPairStorage = storage;\n return this;\n }\n\n withSubtleCrypto(crypto: SubtleCrypto): this {\n this.subtleCrypto = crypto;\n return this;\n }\n\n async build(): Promise<RenownCrypto> {\n if (!this.keyPairStorage) {\n throw new Error(\n \"KeyPairStorage is required. Use withKeyPairStorage() to set it.\",\n );\n }\n\n const subtleCrypto = this.subtleCrypto ?? globalThis.crypto.subtle;\n const keyPair = await this.#initializeKeyPair(\n subtleCrypto,\n this.keyPairStorage,\n );\n const did = await parseDid(keyPair);\n\n return new RenownCrypto(this.keyPairStorage, subtleCrypto, keyPair, did);\n }\n\n async #initializeKeyPair(\n subtleCrypto: SubtleCrypto,\n keyPairStorage: JsonWebKeyPairStorage,\n ): Promise<CryptoKeyPair> {\n const loadedKeyPair = await keyPairStorage.loadKeyPair();\n if (loadedKeyPair) {\n return importKeyPair(loadedKeyPair, subtleCrypto);\n }\n\n const keyPair = await generateKeyPair(subtleCrypto);\n const exported = await exportKeyPair(keyPair, subtleCrypto);\n await keyPairStorage.saveKeyPair(exported);\n return keyPair;\n }\n}\n","import type { JsonWebKeyPairStorage, JwkKeyPair } from \"./types.js\";\n\nexport class MemoryKeyStorage implements JsonWebKeyPairStorage {\n private keyPair: JwkKeyPair | undefined;\n\n constructor(keyPair?: JwkKeyPair) {\n this.keyPair = keyPair;\n }\n\n loadKeyPair() {\n return Promise.resolve(this.keyPair);\n }\n\n saveKeyPair(keyPair: JwkKeyPair) {\n this.keyPair = keyPair;\n return Promise.resolve();\n }\n\n removeKeyPair() {\n this.keyPair = undefined;\n return Promise.resolve();\n }\n}\n","import type {\n Action,\n AppActionSigner,\n ISigner,\n Operation,\n Signature,\n SignatureVerificationHandler,\n UserActionSigner,\n} from \"@powerhousedao/shared/document-model\";\nimport type { IRenownCrypto } from \"./index.js\";\n\nexport class InvalidSignatureError extends Error {\n constructor() {\n super(\"Invalid signature\");\n }\n}\n\nexport class RenownCryptoSigner implements ISigner {\n readonly app: AppActionSigner;\n\n constructor(\n private readonly crypto: IRenownCrypto,\n private readonly appName: string,\n public user?: UserActionSigner,\n ) {\n this.app = {\n key: this.crypto.did,\n name: this.appName,\n };\n }\n\n get publicKey() {\n return this.crypto.publicKey;\n }\n\n async sign(data: Uint8Array): Promise<Uint8Array> {\n return this.crypto.sign(data);\n }\n\n async verify(data: Uint8Array, signature: Uint8Array): Promise<void> {\n const isValid = await this.crypto.verify(data, signature);\n if (!isValid) {\n throw new InvalidSignatureError();\n }\n }\n\n async signAction(\n action: Action,\n abortSignal?: AbortSignal,\n ): Promise<Signature> {\n const hashField = action.context?.prevOpHash ?? \"\";\n return this._signAction(action, hashField, abortSignal);\n }\n\n /**\n * Signs an action including a predicted resulting state hash.\n *\n * The resulting hash is packed into the signature tuple's 4th element (index 3)\n * using the format: `${prevStateHash}:${resultingStateHash}`\n *\n * This allows offline verification of documents without reducer logic:\n * - Verifier can check that the signature is valid for the claimed resulting state\n * - Verifier can compare claimed resulting state to actual operation.hash\n *\n * @param action - The action to sign\n * @param resultingStateHash - The predicted hash of document state AFTER this action runs\n * @param abortSignal - Optional abort signal\n * @returns A Signature tuple with the resulting hash encoded in element [3]\n */\n async signActionWithResultingState(\n action: Action,\n resultingStateHash: string,\n abortSignal?: AbortSignal,\n ): Promise<Signature> {\n const prevStateHash = action.context?.prevOpHash ?? \"\";\n const hashField = `${prevStateHash}:${resultingStateHash}`;\n return this._signAction(action, hashField, abortSignal);\n }\n\n /**\n * Internal signing implementation shared by signAction and signActionWithResultingState.\n */\n private async _signAction(\n action: Action,\n hashField: string,\n abortSignal?: AbortSignal,\n ): Promise<Signature> {\n if (abortSignal?.aborted) {\n throw new Error(\"Signing aborted\");\n }\n\n const timestamp = (new Date().getTime() / 1000).toFixed(0);\n const hash = await this.hashAction(action);\n\n if (abortSignal?.aborted) {\n throw new Error(\"Signing aborted\");\n }\n\n const params: [string, string, string, string] = [\n timestamp,\n this.crypto.did,\n hash,\n hashField,\n ];\n const message = this.buildSignatureMessage(params);\n const signatureBytes = await this.crypto.sign(message);\n const signatureHex = `0x${this.arrayBufferToHex(signatureBytes)}`;\n\n if (abortSignal?.aborted) {\n throw new Error(\"Signing aborted\");\n }\n\n return [...params, signatureHex];\n }\n\n private async hashAction(action: Action): Promise<string> {\n const payload = [\n action.scope,\n action.type,\n JSON.stringify(action.input),\n ].join(\"\");\n const encoder = new TextEncoder();\n const data = encoder.encode(payload);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n return this.arrayBufferToBase64(hashBuffer);\n }\n\n private buildSignatureMessage(\n params: [string, string, string, string],\n ): Uint8Array {\n const message = params.join(\"\");\n const prefix = \"\\x19Signed Operation:\\n\" + message.length.toString();\n const encoder = new TextEncoder();\n return encoder.encode(prefix + message);\n }\n\n private arrayBufferToHex(buffer: Uint8Array | ArrayBuffer): string {\n const bytes =\n buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n}\n\n/**\n * Creates a signature verification handler that verifies signatures using the Web Crypto API.\n * The verification uses ECDSA with P-256 curve and SHA-256 hash, matching the RenownCrypto signing algorithm.\n */\nexport function createSignatureVerifier(\n requireSignature = false,\n): SignatureVerificationHandler {\n return async (operation: Operation, publicKey: string): Promise<boolean> => {\n const signer = operation.action.context?.signer;\n if (!signer || !publicKey) {\n return !requireSignature;\n }\n\n const signatures = signer.signatures;\n if (signatures.length === 0) {\n return false;\n }\n\n const signature = signatures[signatures.length - 1];\n const [timestamp, signerKey, hash, prevStateHash, signatureHex] = signature;\n\n if (signerKey !== publicKey) {\n return false;\n }\n\n const params: [string, string, string, string] = [\n timestamp,\n signerKey,\n hash,\n prevStateHash,\n ];\n const message = buildSignatureMessage(params);\n const signatureBytes = hexToUint8Array(signatureHex);\n\n const cryptoKey = await importPublicKey(publicKey);\n\n const isValid = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n cryptoKey,\n signatureBytes.buffer as ArrayBuffer,\n message.buffer as ArrayBuffer,\n );\n\n return isValid;\n };\n}\n\nfunction buildSignatureMessage(\n params: [string, string, string, string],\n): Uint8Array {\n const message = params.join(\"\");\n const prefix = \"\\x19Signed Operation:\\n\" + message.length.toString();\n const encoder = new TextEncoder();\n return encoder.encode(prefix + message);\n}\n\nfunction hexToUint8Array(hex: string): Uint8Array {\n const cleanHex = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const bytes = new Uint8Array(cleanHex.length / 2);\n for (let i = 0; i < cleanHex.length; i += 2) {\n bytes[i / 2] = parseInt(cleanHex.substring(i, i + 2), 16);\n }\n return bytes;\n}\n\nasync function importPublicKey(did: string): Promise<CryptoKey> {\n const keyData = extractKeyFromDid(did);\n return crypto.subtle.importKey(\n \"raw\",\n keyData.buffer as ArrayBuffer,\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"verify\"],\n );\n}\n\nfunction extractKeyFromDid(did: string): Uint8Array {\n const parts = did.split(\":\");\n if (parts.length < 3 || parts[0] !== \"did\" || parts[1] !== \"key\") {\n throw new Error(`Invalid DID format: ${did}`);\n }\n\n const multibaseKey = parts[2];\n if (!multibaseKey.startsWith(\"z\")) {\n throw new Error(`Unsupported multibase encoding: ${multibaseKey[0]}`);\n }\n\n const decoded = base58Decode(multibaseKey.slice(1));\n\n if (decoded[0] !== 0x80 || decoded[1] !== 0x24) {\n throw new Error(\"Not a P-256 public key multicodec\");\n }\n\n const compressedKey = decoded.slice(2);\n return decompressP256PublicKey(compressedKey);\n}\n\nfunction base58Decode(input: string): Uint8Array {\n const ALPHABET = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\n const ALPHABET_MAP = new Map<string, number>();\n for (let i = 0; i < ALPHABET.length; i++) {\n ALPHABET_MAP.set(ALPHABET[i], i);\n }\n\n if (input.length === 0) {\n return new Uint8Array(0);\n }\n\n const bytes: number[] = [0];\n for (const char of input) {\n const value = ALPHABET_MAP.get(char);\n if (value === undefined) {\n throw new Error(`Invalid base58 character: ${char}`);\n }\n\n let carry = value;\n for (let j = 0; j < bytes.length; j++) {\n carry += bytes[j] * 58;\n bytes[j] = carry & 0xff;\n carry >>= 8;\n }\n\n while (carry > 0) {\n bytes.push(carry & 0xff);\n carry >>= 8;\n }\n }\n\n for (const char of input) {\n if (char !== \"1\") break;\n bytes.push(0);\n }\n\n return new Uint8Array(bytes.reverse());\n}\n\nfunction decompressP256PublicKey(compressed: Uint8Array): Uint8Array {\n if (compressed.length !== 33) {\n throw new Error(`Invalid compressed key length: ${compressed.length}`);\n }\n\n const prefix = compressed[0];\n if (prefix !== 0x02 && prefix !== 0x03) {\n throw new Error(`Invalid compression prefix: ${prefix}`);\n }\n\n const p = BigInt(\n \"0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff\",\n );\n const a = BigInt(\n \"0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc\",\n );\n const b = BigInt(\n \"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b\",\n );\n\n let x = BigInt(0);\n for (let i = 1; i < compressed.length; i++) {\n x = (x << BigInt(8)) | BigInt(compressed[i]);\n }\n\n const ySquared = (modPow(x, BigInt(3), p) + a * x + b) % p;\n let y = modPow(ySquared, (p + BigInt(1)) / BigInt(4), p);\n\n const isYEven = y % BigInt(2) === BigInt(0);\n const shouldBeEven = prefix === 0x02;\n if (isYEven !== shouldBeEven) {\n y = p - y;\n }\n\n const uncompressed = new Uint8Array(65);\n uncompressed[0] = 0x04;\n\n const xBytes = bigIntToBytes(x, 32);\n const yBytes = bigIntToBytes(y, 32);\n\n uncompressed.set(xBytes, 1);\n uncompressed.set(yBytes, 33);\n\n return uncompressed;\n}\n\nfunction modPow(base: bigint, exp: bigint, mod: bigint): bigint {\n let result = BigInt(1);\n base = base % mod;\n while (exp > BigInt(0)) {\n if (exp % BigInt(2) === BigInt(1)) {\n result = (result * base) % mod;\n }\n exp = exp >> BigInt(1);\n base = (base * base) % mod;\n }\n return result;\n}\n\nfunction bigIntToBytes(n: bigint, length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n for (let i = length - 1; i >= 0; i--) {\n bytes[i] = Number(n & BigInt(0xff));\n n = n >> BigInt(8);\n }\n return bytes;\n}\n\n/**\n * Parses the hash field (element [3]) from a signature tuple.\n *\n * Supports two formats:\n * - Old format: just `prevStateHash` (no colon)\n * - New format: `prevStateHash:resultingStateHash` (colon-separated)\n *\n * @param hashField - The 4th element of a Signature tuple\n * @returns Object with prevStateHash and optional resultingStateHash\n */\nexport function parseSignatureHashField(hashField: string): {\n prevStateHash: string;\n resultingStateHash: string | undefined;\n} {\n const colonIndex = hashField.indexOf(\":\");\n\n if (colonIndex === -1) {\n return {\n prevStateHash: hashField,\n resultingStateHash: undefined,\n };\n }\n\n return {\n prevStateHash: hashField.substring(0, colonIndex),\n resultingStateHash: hashField.substring(colonIndex + 1),\n };\n}\n\n/**\n * Extracts the resulting state hash from a signature, if present.\n *\n * @param signature - A Signature tuple\n * @returns The resulting state hash, or undefined if not present\n */\nexport function extractResultingHashFromSignature(\n signature: Signature,\n): string | undefined {\n const hashField = signature[3];\n const { resultingStateHash } = parseSignatureHashField(hashField);\n return resultingStateHash;\n}\n\n/**\n * Checks if a signature includes a resulting state hash.\n *\n * @param signature - A Signature tuple\n * @returns true if the signature includes a resulting state hash\n */\nexport function signatureHasResultingHash(signature: Signature): boolean {\n return extractResultingHashFromSignature(signature) !== undefined;\n}\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ //#region src/wallet/types.ts
2
+ let LoginMethod = /* @__PURE__ */ function(LoginMethod) {
3
+ LoginMethod["WALLET"] = "wallet";
4
+ LoginMethod["GOOGLE"] = "google";
5
+ LoginMethod["EMAIL"] = "email";
6
+ LoginMethod["APPLE"] = "apple";
7
+ return LoginMethod;
8
+ }({});
9
+ const DEFAULT_PRIVY_METHODS = [LoginMethod.GOOGLE, LoginMethod.EMAIL];
10
+ const DEFAULT_MOCK_METHODS = [
11
+ LoginMethod.WALLET,
12
+ LoginMethod.GOOGLE,
13
+ LoginMethod.EMAIL
14
+ ];
15
+ function normalizeWalletTheme(theme) {
16
+ if (theme === void 0) return { mode: "light" };
17
+ if (typeof theme === "string") return { mode: theme };
18
+ return {
19
+ mode: theme.mode,
20
+ accentColor: theme.accentColor,
21
+ accentColorForeground: theme.accentColorForeground
22
+ };
23
+ }
24
+ //#endregion
25
+ export { normalizeWalletTheme as i, DEFAULT_PRIVY_METHODS as n, LoginMethod as r, DEFAULT_MOCK_METHODS as t };
26
+
27
+ //# sourceMappingURL=types-DG816Qa8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DG816Qa8.js","names":[],"sources":["../src/wallet/types.ts"],"sourcesContent":["import type { ComponentType, ReactNode } from \"react\";\nimport type { SignCredentialTypedData } from \"../credential.js\";\n\nexport enum LoginMethod {\n WALLET = \"wallet\",\n GOOGLE = \"google\",\n EMAIL = \"email\",\n APPLE = \"apple\",\n}\n\n// Default login methods per adapter when config omits `methods`; single source\n// of truth shared by the adapters and useRenownLoginMethods so they can't drift.\nexport const DEFAULT_PRIVY_METHODS: LoginMethod[] = [\n LoginMethod.GOOGLE,\n LoginMethod.EMAIL,\n];\nexport const DEFAULT_MOCK_METHODS: LoginMethod[] = [\n LoginMethod.WALLET,\n LoginMethod.GOOGLE,\n LoginMethod.EMAIL,\n];\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 supportedMethods: LoginMethod[];\n}\n\n// What each adapter subexport default-exports (a factory over its own config slice).\nexport interface WalletAdapter {\n id: \"rainbow\" | \"privy\" | \"mock\";\n supportedMethods: LoginMethod[];\n // React provider that must wrap the app subtree for this adapter to work.\n // The 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\nexport type WalletAdapterFactory<Config = unknown> = (\n config: Config,\n) => WalletAdapter;\n\n// Minimal descriptor an adapter exposes for eager import (no wallet library), so\n// a host can detect a redirect return without loading the adapter's heavy factory.\nexport interface WalletAdapterMeta {\n id: WalletAdapter[\"id\"];\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}\n"],"mappings":";AAGA,IAAY,cAAL,yBAAA,aAAA;AACL,aAAA,YAAA;AACA,aAAA,YAAA;AACA,aAAA,WAAA;AACA,aAAA,WAAA;;KACD;AAID,MAAa,wBAAuC,CAClD,YAAY,QACZ,YAAY,MACb;AACD,MAAa,uBAAsC;CACjD,YAAY;CACZ,YAAY;CACZ,YAAY;CACb;AAgBD,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,9 +1,11 @@
1
- import { Action, AppActionSigner, ISigner, ISigner as ISigner$1, Signature, SignatureVerificationHandler, User, UserActionSigner } from "@powerhousedao/shared/document-model";
1
+ import { ISigner as ISigner$1, User } from "@powerhousedao/shared/document-model";
2
2
 
3
3
  //#region src/constants.d.ts
4
4
  declare const DEFAULT_RENOWN_URL = "https://www.renown.id";
5
5
  declare const DEFAULT_RENOWN_NETWORK_ID = "eip155";
6
6
  declare const DEFAULT_RENOWN_CHAIN_ID = "1";
7
+ /** Default cookie name for a server-readable Renown session (bearer token). */
8
+ declare const RENOWN_SESSION_COOKIE = "renown_session";
7
9
  declare const DOMAIN_TYPE: readonly [{
8
10
  readonly name: "version";
9
11
  readonly type: "string";
@@ -113,6 +115,105 @@ declare const CREDENTIAL_TYPES: {
113
115
  }];
114
116
  };
115
117
  //#endregion
118
+ //#region src/credential.d.ts
119
+ type Hex = `0x${string}`;
120
+ type TypedDataDomain = {
121
+ name?: string;
122
+ version?: string;
123
+ chainId?: number;
124
+ verifyingContract?: Hex;
125
+ salt?: Hex;
126
+ };
127
+ type TypedDataParameter = {
128
+ name: string;
129
+ type: string;
130
+ };
131
+ /** EIP-712 domain as signed by the credential issuer. */
132
+ type CredentialDomain = {
133
+ version: string;
134
+ chainId: number;
135
+ };
136
+ /** The credential body that is EIP-712 signed (everything except `proof`). */
137
+ type CredentialMessage = {
138
+ "@context": string[];
139
+ type: string[];
140
+ id: string;
141
+ issuer: {
142
+ id: string;
143
+ ethereumAddress: Hex;
144
+ };
145
+ credentialSubject: {
146
+ id: string;
147
+ app: string;
148
+ };
149
+ credentialSchema: {
150
+ id: string;
151
+ type: string;
152
+ };
153
+ issuanceDate: string;
154
+ expirationDate: string;
155
+ };
156
+ /** Typed-data signer; matches the loose shape used by wallet adapters. */
157
+ type SignCredentialTypedData = (args: {
158
+ domain: TypedDataDomain;
159
+ types: Record<string, readonly TypedDataParameter[]>;
160
+ primaryType: string;
161
+ message: Record<string, unknown>;
162
+ }) => Promise<Hex>;
163
+ interface BuildCredentialParams {
164
+ signTypedData: SignCredentialTypedData;
165
+ address: Hex;
166
+ chainId: number;
167
+ app: string;
168
+ /** Credential subject id: the app/client DID the credential delegates to. */
169
+ appId: string;
170
+ expiresInDays?: number;
171
+ }
172
+ /** Assemble a Renown delegation VC and sign it with the provided signer. */
173
+ declare function buildAndSignCredential(params: BuildCredentialParams): Promise<PowerhouseVerifiableCredential>;
174
+ /** Recover the address that signed a credential's EIP-712 proof. */
175
+ declare function recoverCredentialSigner(credential: PowerhouseVerifiableCredential): Promise<Hex>;
176
+ /** True when the proof was signed by the credential's declared issuer address. */
177
+ declare function verifyCredentialSignature(credential: PowerhouseVerifiableCredential): Promise<boolean>;
178
+ interface FetchDelegationCredentialOptions {
179
+ /** Ethereum address that must have issued the credential. */
180
+ address: string;
181
+ /** Chain id the credential must be scoped to. */
182
+ chainId: number;
183
+ /** App/client DID the credential must delegate to (credentialSubject.id). */
184
+ appDid: string;
185
+ /** Renown service base URL. Defaults to DEFAULT_RENOWN_URL. */
186
+ baseUrl?: string;
187
+ /** Switchboard GraphQL endpoint; when reachable, read the reactor directly. */
188
+ switchboardUrl?: string;
189
+ /** Probe {baseUrl}/api/switchboard for an endpoint (default true). */
190
+ discover?: boolean;
191
+ /** Re-verify the EIP-712 proof signature (default true). */
192
+ verifySignature?: boolean;
193
+ }
194
+ declare function fetchDelegationCredential(options: FetchDelegationCredentialOptions): Promise<PowerhouseVerifiableCredential | undefined>;
195
+ interface VerifiedAuthCredential {
196
+ address: string;
197
+ chainId: number;
198
+ networkId: string;
199
+ /** Owner identity: the pkh DID (did:pkh:<net>:<chainId>:<address>). */
200
+ did: string;
201
+ /** App/client DID the bearer token was issued by. */
202
+ appDid: string;
203
+ credential: PowerhouseVerifiableCredential;
204
+ }
205
+ interface VerifyAuthCredentialOptions {
206
+ /** Expected `aud` claim on the bearer token. */
207
+ audience?: string;
208
+ /** Renown service base URL. */
209
+ renownUrl?: string;
210
+ /** Switchboard GraphQL endpoint; when reachable, read the reactor directly. */
211
+ switchboardUrl?: string;
212
+ /** Re-verify the credential's EIP-712 proof (default true). */
213
+ verifySignature?: boolean;
214
+ }
215
+ declare function verifyAuthCredential(jwt: string, options?: VerifyAuthCredentialOptions): Promise<VerifiedAuthCredential | undefined>;
216
+ //#endregion
116
217
  //#region src/event/types.d.ts
117
218
  interface IEventEmitter<Events extends Record<string, unknown>> {
118
219
  /**
@@ -319,6 +420,20 @@ type User$1 = InternalUser;
319
420
  * Must not throw — return undefined on failure.
320
421
  */
321
422
  type ProfileFetcher = (user: User$1, baseUrl: string) => Promise<RenownProfile | undefined>;
423
+ interface SignInParams {
424
+ /** Ethereum address of the signing wallet. */
425
+ address: `0x${string}`;
426
+ /** Chain id the credential is scoped to. */
427
+ chainId: number;
428
+ /** Wallet/Privy EIP-712 typed-data signer that authorizes the app key. */
429
+ signTypedData: SignCredentialTypedData;
430
+ /** Optional profile username to set on the RenownUser. */
431
+ username?: string;
432
+ /** Optional profile image URL to set on the RenownUser. */
433
+ userImage?: string;
434
+ /** Delegation credential lifetime in days (default 7). */
435
+ expiresInDays?: number;
436
+ }
322
437
  type Unsubscribe = () => void;
323
438
  type LoginStatus = "initial" | "checking" | "authorized" | "not-authorized";
324
439
  type RenownStorageMap = {
@@ -335,7 +450,10 @@ interface IRenown extends Pick<RenownEventEmitter, "on"> {
335
450
  readonly user: User$1 | undefined;
336
451
  readonly status: LoginStatus;
337
452
  login: (userDid: string) => Promise<User$1>;
453
+ signIn: (params: SignInParams) => Promise<User$1>;
338
454
  logout: () => Promise<void>;
455
+ /** Re-check the current credential at the source; logs out if revoked/expired. */
456
+ revalidate: () => Promise<boolean>;
339
457
  readonly crypto: IRenownCrypto;
340
458
  readonly signer: ISigner$1;
341
459
  readonly did: string;
@@ -435,117 +553,5 @@ interface IRenownCrypto {
435
553
  */
436
554
  interface IConnectCrypto extends IRenownCrypto {}
437
555
  //#endregion
438
- //#region src/crypto/renown-crypto.d.ts
439
- declare class RenownCrypto implements IRenownCrypto {
440
- #private;
441
- readonly did: DID;
442
- static algorithm: EcKeyAlgorithm;
443
- static signAlgorithm: {
444
- name: string;
445
- namedCurve: string;
446
- hash: string;
447
- };
448
- constructor(keyPairStorage: JsonWebKeyPairStorage, crypto: SubtleCrypto, keyPair: CryptoKeyPair, did: DID);
449
- get publicKey(): CryptoKey;
450
- getBearerToken(address: string | undefined, options?: CreateBearerTokenOptions): Promise<string>;
451
- removeDid(): Promise<void>;
452
- sign(data: Uint8Array | string): Promise<Uint8Array>;
453
- verify(data: Uint8Array, signature: Uint8Array): Promise<boolean>;
454
- get issuer(): Issuer;
455
- }
456
- /**
457
- * @deprecated Use RenownCrypto instead
458
- */
459
- declare class ConnectCrypto extends RenownCrypto {}
460
- //#endregion
461
- //#region src/crypto/renown-crypto-builder.d.ts
462
- declare class RenownCryptoBuilder {
463
- #private;
464
- private keyPairStorage?;
465
- private subtleCrypto?;
466
- withKeyPairStorage(storage: JsonWebKeyPairStorage): this;
467
- withSubtleCrypto(crypto: SubtleCrypto): this;
468
- build(): Promise<RenownCrypto>;
469
- }
470
- //#endregion
471
- //#region src/crypto/memory-key-storage.d.ts
472
- declare class MemoryKeyStorage implements JsonWebKeyPairStorage {
473
- private keyPair;
474
- constructor(keyPair?: JwkKeyPair);
475
- loadKeyPair(): Promise<JwkKeyPair | undefined>;
476
- saveKeyPair(keyPair: JwkKeyPair): Promise<void>;
477
- removeKeyPair(): Promise<void>;
478
- }
479
- //#endregion
480
- //#region src/crypto/signer.d.ts
481
- declare class RenownCryptoSigner implements ISigner {
482
- private readonly crypto;
483
- private readonly appName;
484
- user?: UserActionSigner | undefined;
485
- readonly app: AppActionSigner;
486
- constructor(crypto: IRenownCrypto, appName: string, user?: UserActionSigner | undefined);
487
- get publicKey(): CryptoKey;
488
- sign(data: Uint8Array): Promise<Uint8Array>;
489
- verify(data: Uint8Array, signature: Uint8Array): Promise<void>;
490
- signAction(action: Action, abortSignal?: AbortSignal): Promise<Signature>;
491
- /**
492
- * Signs an action including a predicted resulting state hash.
493
- *
494
- * The resulting hash is packed into the signature tuple's 4th element (index 3)
495
- * using the format: `${prevStateHash}:${resultingStateHash}`
496
- *
497
- * This allows offline verification of documents without reducer logic:
498
- * - Verifier can check that the signature is valid for the claimed resulting state
499
- * - Verifier can compare claimed resulting state to actual operation.hash
500
- *
501
- * @param action - The action to sign
502
- * @param resultingStateHash - The predicted hash of document state AFTER this action runs
503
- * @param abortSignal - Optional abort signal
504
- * @returns A Signature tuple with the resulting hash encoded in element [3]
505
- */
506
- signActionWithResultingState(action: Action, resultingStateHash: string, abortSignal?: AbortSignal): Promise<Signature>;
507
- /**
508
- * Internal signing implementation shared by signAction and signActionWithResultingState.
509
- */
510
- private _signAction;
511
- private hashAction;
512
- private buildSignatureMessage;
513
- private arrayBufferToHex;
514
- private arrayBufferToBase64;
515
- }
516
- /**
517
- * Creates a signature verification handler that verifies signatures using the Web Crypto API.
518
- * The verification uses ECDSA with P-256 curve and SHA-256 hash, matching the RenownCrypto signing algorithm.
519
- */
520
- declare function createSignatureVerifier(requireSignature?: boolean): SignatureVerificationHandler;
521
- /**
522
- * Parses the hash field (element [3]) from a signature tuple.
523
- *
524
- * Supports two formats:
525
- * - Old format: just `prevStateHash` (no colon)
526
- * - New format: `prevStateHash:resultingStateHash` (colon-separated)
527
- *
528
- * @param hashField - The 4th element of a Signature tuple
529
- * @returns Object with prevStateHash and optional resultingStateHash
530
- */
531
- declare function parseSignatureHashField(hashField: string): {
532
- prevStateHash: string;
533
- resultingStateHash: string | undefined;
534
- };
535
- /**
536
- * Extracts the resulting state hash from a signature, if present.
537
- *
538
- * @param signature - A Signature tuple
539
- * @returns The resulting state hash, or undefined if not present
540
- */
541
- declare function extractResultingHashFromSignature(signature: Signature): string | undefined;
542
- /**
543
- * Checks if a signature includes a resulting state hash.
544
- *
545
- * @param signature - A Signature tuple
546
- * @returns true if the signature includes a resulting state hash
547
- */
548
- declare function signatureHasResultingHash(signature: Signature): boolean;
549
- //#endregion
550
- export { User$1 as $, ISigner$1 as A, PKHDid as B, DIDResolutionResult as C, IPowerhouseIssuerType as D, IPowerhouseCredentialSubject as E, JWTVerified as F, RenownEvents as G, ProfileFetcher as H, JWTVerifyPolicies as I, RenownStorageMap as J, RenownProfile as K, JsonWebKey$1 as L, InternalUser as M, Issuer as N, IProof as O, JWTPayload as P, Unsubscribe as Q, KeyCapabilitySection as R, DIDResolutionMetadata as S, IAuthCredentialSubject as T, Proof as U, PowerhouseVerifiableCredential as V, RenownEventEmitter as W, ServiceEndpoint as X, Service as Y, Signer as Z, ConditionWeightedThreshold as _, signatureHasResultingHash as a, BaseStorage as at, DIDDocument as b, ConnectCrypto as c, CREDENTIAL_SCHEMA_EIP712_TYPE as ct, IConnectCrypto as d, DEFAULT_RENOWN_CHAIN_ID as dt, Verifiable as et, IRenownCrypto as f, DEFAULT_RENOWN_NETWORK_ID as ft, AuthVerifiedCredential as g, VERIFIABLE_CREDENTIAL_EIP712_TYPE as gt, AuthVerifiableCredential as h, ISSUER_TYPE as ht, parseSignatureHashField as i, W3CCredential as it, IVerifiableCredential as j, IRenown as k, RenownCrypto as l, CREDENTIAL_SUBJECT_TYPE as lt, JwkKeyPair as m, DOMAIN_TYPE as mt, createSignatureVerifier as n, VerifiedCredential as nt, MemoryKeyStorage as o, MemoryStorage as ot, JsonWebKeyPairStorage as p, DEFAULT_RENOWN_URL as pt, RenownStorage as q, extractResultingHashFromSignature as r, VerifiedJWT as rt, RenownCryptoBuilder as s, IEventEmitter as st, RenownCryptoSigner as t, VerificationMethod as tt, DID as u, CREDENTIAL_TYPES as ut, CreateBearerTokenOptions as v, EcdsaSignature as w, DIDDocumentMetadata as x, CredentialStatus as y, LoginStatus as z };
551
- //# sourceMappingURL=signer-DYKGoYHB.d.ts.map
556
+ export { IEventEmitter as $, LoginStatus as A, Service as B, InternalUser as C, JWTVerifyPolicies as D, JWTVerified as E, RenownEventEmitter as F, User$1 as G, SignInParams as H, RenownEvents as I, VerifiedCredential as J, Verifiable as K, RenownProfile as L, PowerhouseVerifiableCredential as M, ProfileFetcher as N, JsonWebKey$1 as O, Proof as P, MemoryStorage as Q, RenownStorage as R, IVerifiableCredential as S, JWTPayload as T, Signer as U, ServiceEndpoint as V, Unsubscribe as W, W3CCredential as X, VerifiedJWT as Y, BaseStorage as Z, IPowerhouseCredentialSubject as _, DEFAULT_RENOWN_URL as _t, JwkKeyPair as a, VerifiedAuthCredential as at, IRenown as b, RENOWN_SESSION_COOKIE as bt, ConditionWeightedThreshold as c, fetchDelegationCredential as ct, DIDDocument as d, verifyCredentialSignature as dt, BuildCredentialParams as et, DIDDocumentMetadata as f, CREDENTIAL_SCHEMA_EIP712_TYPE as ft, IAuthCredentialSubject as g, DEFAULT_RENOWN_NETWORK_ID as gt, EcdsaSignature as h, DEFAULT_RENOWN_CHAIN_ID as ht, JsonWebKeyPairStorage as i, SignCredentialTypedData as it, PKHDid as j, KeyCapabilitySection as k, CreateBearerTokenOptions as l, recoverCredentialSigner as lt, DIDResolutionResult as m, CREDENTIAL_TYPES as mt, IConnectCrypto as n, CredentialMessage as nt, AuthVerifiableCredential as o, VerifyAuthCredentialOptions as ot, DIDResolutionMetadata as p, CREDENTIAL_SUBJECT_TYPE as pt, VerificationMethod as q, IRenownCrypto as r, FetchDelegationCredentialOptions as rt, AuthVerifiedCredential as s, buildAndSignCredential as st, DID as t, CredentialDomain as tt, CredentialStatus as u, verifyAuthCredential as ut, IPowerhouseIssuerType as v, DOMAIN_TYPE as vt, Issuer as w, ISigner$1 as x, VERIFIABLE_CREDENTIAL_EIP712_TYPE as xt, IProof as y, ISSUER_TYPE as yt, RenownStorageMap as z };
557
+ //# sourceMappingURL=types-DsF91dDF.d.ts.map