{"version":3,"sources":["../../src/account/personal-server-registration.ts"],"sourcesContent":["/**\n * Optional first-party Account integration for Personal Server registration.\n *\n * The protocol helper lives in `protocol/personal-server-registration`.\n * This module is only for callers that want to use an Account deployment's\n * constrained silent-sign endpoint.\n *\n * @category Account\n */\n\nimport { isAddress, type Address, type Hex } from \"viem\";\nimport {\n  buildPersonalServerRegistrationTypedData,\n  type BuildPersonalServerRegistrationTypedDataInput,\n  type PersonalServerRegistrationSignature,\n  type PersonalServerRegistrationSigner,\n  type PersonalServerRegistrationTypedData,\n  personalServerRegistrationDomain,\n} from \"../protocol/personal-server-registration\";\nimport { SERVER_REGISTRATION_TYPES } from \"../protocol/eip712\";\n\nexport const ACCOUNT_PERSONAL_SERVER_REGISTRATION_INTENT =\n  \"personal_server.server_registration.v1\" as const;\n\nexport type AccountPersonalServerRegistrationIntent =\n  typeof ACCOUNT_PERSONAL_SERVER_REGISTRATION_INTENT;\n\nexport type AccountPersonalServerRegistrationStatus =\n  | \"signed\"\n  | \"confirmation_required\"\n  | \"fallback_required\";\n\nexport interface AccountPersonalServerRegistrationRequest extends Omit<\n  BuildPersonalServerRegistrationTypedDataInput,\n  \"ownerAddress\"\n> {}\n\nexport interface AccountPersonalServerRegistrationConfig {\n  /**\n   * Origin for the Account deployment to call, e.g. an app-dev Account origin.\n   * No production origin is assumed by the SDK.\n   */\n  accountOrigin: string;\n  /**\n   * Path for Account's constrained PS registration silent-sign endpoint.\n   */\n  endpointPath?: string;\n  /**\n   * Optional fetch implementation for tests and non-default runtimes.\n   */\n  fetchImpl?: typeof fetch;\n  /**\n   * Optional signer used when Account says user confirmation is required and\n   * returns typed data for the caller to sign interactively.\n   */\n  fallbackSigner?: PersonalServerRegistrationSigner;\n}\n\nexport type AccountPersonalServerRegistrationSignature =\n  PersonalServerRegistrationSignature & {\n    intent: AccountPersonalServerRegistrationIntent;\n  };\n\nexport interface AccountSignedPersonalServerRegistration {\n  status: \"signed\";\n  result: AccountPersonalServerRegistrationSignature;\n}\n\nexport interface AccountConfirmationRequiredPersonalServerRegistration {\n  status: \"confirmation_required\";\n  typedData: PersonalServerRegistrationTypedData;\n  signerAddress?: Address;\n}\n\nexport interface AccountFallbackSignedPersonalServerRegistration {\n  status: \"fallback_signed\";\n  accountStatus: \"confirmation_required\";\n  result: AccountPersonalServerRegistrationSignature;\n}\n\nexport type AccountPersonalServerRegistrationResult =\n  | AccountSignedPersonalServerRegistration\n  | AccountConfirmationRequiredPersonalServerRegistration\n  | AccountFallbackSignedPersonalServerRegistration;\n\nexport class AccountPersonalServerRegistrationError extends Error {\n  status: number;\n  code?: string;\n  details?: unknown;\n\n  constructor(input: {\n    status: number;\n    message: string;\n    code?: string;\n    details?: unknown;\n  }) {\n    super(input.message);\n    this.name = \"AccountPersonalServerRegistrationError\";\n    this.status = input.status;\n    this.code = input.code;\n    this.details = input.details;\n  }\n}\n\ninterface AccountSilentSignResponse {\n  status: AccountPersonalServerRegistrationStatus;\n  signature?: Hex;\n  signerAddress?: Address;\n  signer?: { address?: Address };\n  typedData?: PersonalServerRegistrationTypedData;\n  typed_data?: PersonalServerRegistrationTypedData;\n  error?: unknown;\n}\n\n// Account-owned route policy. Protocol signing primitives deliberately do not\n// define Account intent names or API paths.\nconst DEFAULT_ACCOUNT_PS_REGISTRATION_PATH =\n  \"/api/v1/intents/personal-server-registration/sign\";\n\nfunction trimTrailingSlash(value: string): string {\n  return value.replace(/\\/+$/, \"\");\n}\n\nfunction assertAddress(value: Address, name: string): void {\n  if (!isAddress(value)) {\n    throw new Error(`${name} must be a valid EVM address`);\n  }\n}\n\nasync function parseAccountResponse(\n  response: Response,\n): Promise<AccountSilentSignResponse> {\n  const body = (await response.json().catch(() => undefined)) as unknown;\n\n  if (!response.ok) {\n    throw new AccountPersonalServerRegistrationError({\n      status: response.status,\n      code: accountErrorCode(body),\n      message: accountErrorMessage(response.status, body),\n      details: body,\n    });\n  }\n\n  return body as AccountSilentSignResponse;\n}\n\nfunction accountErrorMessage(status: number, body: unknown): string {\n  const nestedMessage = nestedAccountErrorField(body, \"message\");\n  if (nestedMessage) {\n    return nestedMessage;\n  }\n\n  if (isRecord(body) && typeof body.message === \"string\") {\n    return body.message;\n  }\n\n  const code = accountErrorCode(body);\n  if (code) {\n    return `Account PS registration signing failed: ${code}`;\n  }\n\n  return `Account PS registration signing failed: ${status}`;\n}\n\nfunction accountErrorCode(body: unknown): string | undefined {\n  const nestedCode = nestedAccountErrorField(body, \"code\");\n  if (nestedCode) {\n    return nestedCode;\n  }\n\n  if (isRecord(body)) {\n    if (typeof body.code === \"string\") {\n      return body.code;\n    }\n    if (typeof body.error === \"string\") {\n      return body.error;\n    }\n  }\n\n  return undefined;\n}\n\nfunction nestedAccountErrorField(\n  body: unknown,\n  field: \"code\" | \"message\",\n): string | undefined {\n  if (!isRecord(body) || !isRecord(body.error)) {\n    return undefined;\n  }\n\n  const value = body.error[field];\n  return typeof value === \"string\" ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null;\n}\n\nfunction normalizeAccountResponse(\n  response: AccountSilentSignResponse,\n): AccountSilentSignResponse {\n  return {\n    ...response,\n    status:\n      response.status === \"fallback_required\"\n        ? \"confirmation_required\"\n        : response.status,\n    signerAddress: response.signerAddress ?? response.signer?.address,\n    typedData: response.typedData ?? response.typed_data,\n  };\n}\n\nfunction buildSignedResult(\n  response: Required<\n    Pick<AccountSilentSignResponse, \"signature\" | \"signerAddress\">\n  > &\n    Pick<AccountSilentSignResponse, \"typedData\">,\n  request: AccountPersonalServerRegistrationRequest,\n): AccountPersonalServerRegistrationSignature {\n  assertAddress(response.signerAddress, \"signerAddress\");\n  if (response.typedData) {\n    assertTypedDataMatchesRequest(\n      response.typedData,\n      request,\n      response.signerAddress,\n    );\n  }\n\n  return {\n    signature: response.signature,\n    signerAddress: response.signerAddress,\n    typedData:\n      response.typedData ??\n      buildPersonalServerRegistrationTypedData({\n        ownerAddress: response.signerAddress,\n        ...request,\n      }),\n    intent: ACCOUNT_PERSONAL_SERVER_REGISTRATION_INTENT,\n  };\n}\n\nfunction assertTypedDataMatchesRequest(\n  typedData: PersonalServerRegistrationTypedData,\n  request: AccountPersonalServerRegistrationRequest,\n  expectedSignerAddress?: Address,\n): void {\n  assertAddress(\n    typedData.message.ownerAddress,\n    \"typedData.message.ownerAddress\",\n  );\n  assertAddress(\n    typedData.message.serverAddress,\n    \"typedData.message.serverAddress\",\n  );\n\n  if (\n    expectedSignerAddress &&\n    !sameAddress(typedData.message.ownerAddress, expectedSignerAddress)\n  ) {\n    throw new Error(\n      \"Account typedData ownerAddress must match the expected signer address\",\n    );\n  }\n\n  if (!sameAddress(typedData.message.serverAddress, request.serverAddress)) {\n    throw new Error(\n      \"Account typedData serverAddress must match the requested serverAddress\",\n    );\n  }\n\n  if (typedData.message.publicKey !== request.serverPublicKey) {\n    throw new Error(\n      \"Account typedData publicKey must match the requested serverPublicKey\",\n    );\n  }\n\n  if (typedData.message.serverUrl !== request.serverUrl) {\n    throw new Error(\n      \"Account typedData serverUrl must match the requested serverUrl\",\n    );\n  }\n\n  if (typedData.primaryType !== \"ServerRegistration\") {\n    throw new Error(\"Account typedData primaryType must be ServerRegistration\");\n  }\n\n  if (\n    JSON.stringify(typedData.types) !==\n    JSON.stringify(SERVER_REGISTRATION_TYPES)\n  ) {\n    throw new Error(\"Account typedData types must be ServerRegistration types\");\n  }\n\n  const expectedDomain = personalServerRegistrationDomain({\n    config: request.config,\n    chainId: request.chainId,\n    verifyingContract: request.verifyingContract,\n  });\n  if (!domainsEqual(typedData.domain, expectedDomain)) {\n    throw new Error(\"Account typedData domain must match the requested domain\");\n  }\n}\n\nfunction sameAddress(a: Address, b: Address): boolean {\n  return a.toLowerCase() === b.toLowerCase();\n}\n\nfunction domainsEqual(\n  a: PersonalServerRegistrationTypedData[\"domain\"],\n  b: PersonalServerRegistrationTypedData[\"domain\"],\n): boolean {\n  if (!a || !b) {\n    return false;\n  }\n\n  return (\n    a.name === b.name &&\n    a.version === b.version &&\n    Number(a.chainId) === Number(b.chainId) &&\n    String(a.verifyingContract ?? \"\").toLowerCase() ===\n      String(b.verifyingContract ?? \"\").toLowerCase() &&\n    a.salt === b.salt\n  );\n}\n\nexport async function signPersonalServerRegistrationWithAccount(\n  config: AccountPersonalServerRegistrationConfig,\n  request: AccountPersonalServerRegistrationRequest,\n): Promise<AccountPersonalServerRegistrationResult> {\n  assertAddress(request.serverAddress, \"serverAddress\");\n\n  const fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);\n  const endpoint = new URL(\n    config.endpointPath ?? DEFAULT_ACCOUNT_PS_REGISTRATION_PATH,\n    `${trimTrailingSlash(config.accountOrigin)}/`,\n  );\n\n  const response = await fetchImpl(endpoint, {\n    method: \"POST\",\n    headers: { \"content-type\": \"application/json\" },\n    credentials: \"include\",\n    body: JSON.stringify({\n      intent: ACCOUNT_PERSONAL_SERVER_REGISTRATION_INTENT,\n      serverAddress: request.serverAddress,\n      serverPublicKey: request.serverPublicKey,\n      serverUrl: request.serverUrl,\n      config: request.config,\n      chainId: request.chainId,\n      verifyingContract: request.verifyingContract,\n    }),\n  });\n  const body = normalizeAccountResponse(await parseAccountResponse(response));\n\n  if (body.status === \"signed\") {\n    if (!body.signature || !body.signerAddress) {\n      throw new Error(\n        \"Account signed response must include signature and signerAddress\",\n      );\n    }\n\n    return {\n      status: \"signed\",\n      result: buildSignedResult(\n        {\n          signature: body.signature,\n          signerAddress: body.signerAddress,\n          typedData: body.typedData,\n        },\n        request,\n      ),\n    };\n  }\n\n  if (body.status === \"confirmation_required\") {\n    if (!body.typedData) {\n      throw new Error(\n        \"Account confirmation_required response must include typedData\",\n      );\n    }\n    assertTypedDataMatchesRequest(body.typedData, request, body.signerAddress);\n\n    if (!config.fallbackSigner) {\n      return {\n        status: \"confirmation_required\",\n        typedData: body.typedData,\n        signerAddress: body.signerAddress,\n      };\n    }\n\n    assertTypedDataMatchesRequest(\n      body.typedData,\n      request,\n      config.fallbackSigner.address,\n    );\n    const signature = await config.fallbackSigner.signTypedData(body.typedData);\n\n    return {\n      status: \"fallback_signed\",\n      accountStatus: \"confirmation_required\",\n      result: {\n        signature,\n        signerAddress: config.fallbackSigner.address,\n        typedData: body.typedData,\n        intent: ACCOUNT_PERSONAL_SERVER_REGISTRATION_INTENT,\n      },\n    };\n  }\n\n  throw new Error(\n    `Unsupported Account PS registration signing status: ${String(body.status)}`,\n  );\n}\n"],"mappings":"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","names":[]}