{"version":3,"file":"portal.cjs","names":["z","UrlOrPathSchema","ApplicationAccessTokenSchema","GraphQLClient"],"sources":["../src/utils/websocket-client.ts","../src/utils/wait-for-transaction-receipt.ts","../src/utils/wallet-verification-challenge.ts","../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n  /**\n   * The GraphQL endpoint URL for the Portal API\n   */\n  portalGraphqlEndpoint: string;\n  /**\n   * The access token for authentication with the Portal API\n   */\n  accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n *   portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n *   accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n  if (!portalGraphqlEndpoint) {\n    throw new Error(\"portalGraphqlEndpoint is required\");\n  }\n  const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n  return createClient({\n    url: accessToken\n      ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n      : graphqlEndpoint.toString(),\n  });\n}\n\nfunction setWsProtocol(url: URL) {\n  if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n    return url;\n  }\n  if (url.protocol === \"http:\") {\n    url.protocol = \"ws:\";\n  } else {\n    url.protocol = \"wss:\";\n  }\n  return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n  /** The name of the event that was emitted */\n  eventName: string;\n  /** The arguments emitted by the event */\n  args: Record<string, unknown>;\n  /** Indexed event parameters used for filtering and searching */\n  topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n  /** The raw reason for transaction reversion, if applicable */\n  revertReason: string;\n  /** Human-readable version of the revert reason */\n  revertReasonDecoded: string;\n  /** Array of events emitted during the transaction */\n  events: TransactionEvent[];\n  /** The address of the contract deployed in the transaction */\n  contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n  receipt: TransactionReceipt;\n  /** The hash of the transaction (duplicate of receipt.transactionHash) */\n  transactionHash: string;\n  /** The sender address (duplicate of receipt.from) */\n  from: string;\n  /** Timestamp when the transaction was created */\n  createdAt: string;\n  /** The contract address involved in the transaction */\n  address: string;\n  /** The name of the function called in the transaction */\n  functionName: string;\n  /** Whether the transaction is a contract deployment */\n  isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n  getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n  /** Optional timeout in milliseconds before the operation fails */\n  timeout?: number;\n}\n\n/**\n * Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.\n * This function polls until the transaction is confirmed or the timeout is reached.\n *\n * @param transactionHash - The hash of the transaction to wait for\n * @param options - Configuration options for the waiting process\n * @returns The transaction details including receipt information when the transaction is confirmed\n * @throws Error if the transaction receipt cannot be retrieved within the specified timeout\n *\n * @example\n * import { waitForTransactionReceipt } from \"@settlemint/sdk-portal\";\n *\n * const transaction = await waitForTransactionReceipt(\"0x123...\", {\n *   portalGraphqlEndpoint: \"https://example.settlemint.com/graphql\",\n *   accessToken: \"your-access-token\",\n *   timeout: 30000 // 30 seconds timeout\n * });\n */\nexport async function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions) {\n  const wsClient = getWebsocketClient(options);\n  const subscription = wsClient.iterate<GetTransactionResponse>({\n    query: `subscription getTransaction($transactionHash: String!) {\n        getTransaction(transactionHash: $transactionHash) {\n          receipt {\n            transactionHash\n            to\n            status\n            from\n            type\n            revertReason\n            revertReasonDecoded\n            logs\n            events\n            contractAddress\n          }\n          transactionHash\n          from\n          createdAt\n          address\n          functionName\n          isContract\n        }\n      }`,\n    variables: { transactionHash },\n  });\n  const promises = [getTransactionFromSubscription(subscription)];\n  if (options.timeout) {\n    promises.push(createTimeoutPromise(options.timeout));\n  }\n\n  return Promise.race(promises);\n}\n\nfunction createTimeoutPromise(timeout: number): Promise<never> {\n  return new Promise((_, reject) => {\n    setTimeout(() => reject(new Error(\"Transaction receipt not found\")), timeout);\n  });\n}\n\nasync function getTransactionFromSubscription(\n  subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>,\n): Promise<Transaction> {\n  for await (const result of subscription) {\n    if (result?.data?.getTransaction?.receipt) {\n      return result.data.getTransaction;\n    }\n  }\n  throw new Error(\"No transaction found\");\n}\n","import { createHash } from \"node:crypto\";\nimport type { AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport type { GraphQLClient } from \"graphql-request\";\nimport type { Address } from \"viem\";\n\n/**\n * Type representing the different types of wallet verification methods\n */\nexport type WalletVerificationType = \"PINCODE\" | \"OTP\" | \"SECRET_CODES\";\n\n/**\n * Custom error class for challenge-related errors\n */\nexport class WalletVerificationChallengeError extends Error {\n  readonly code: string;\n\n  constructor(message: string, code: string) {\n    super(message);\n    this.name = \"ChallengeError\";\n    this.code = code;\n  }\n}\n\n/**\n * Represents the structure of a wallet verification challenge\n */\ninterface WalletVerificationChallenge {\n  id: string;\n  name: string;\n  verificationId: string;\n  verificationType: WalletVerificationType;\n  challenge?: {\n    salt: string;\n    secret: string;\n  };\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenge mutation\n */\ninterface CreateWalletVerificationChallengeResponse {\n  createWalletVerificationChallenge: WalletVerificationChallenge;\n}\n\n/**\n * Hashes a pincode with a salt using SHA-256\n * @param pincode - The pincode to hash\n * @param salt - The salt to use in hashing\n * @returns The hashed pincode as a hex string\n */\nfunction hashPincode(pincode: string, salt: string): string {\n  return createHash(\"sha256\").update(`${salt}${pincode}`).digest(\"hex\");\n}\n\n/**\n * Generates a challenge response by combining a hashed pincode with a challenge\n * @param pincode - The user's pincode\n * @param salt - The salt provided in the challenge\n * @param challenge - The challenge secret\n * @returns The challenge response as a hex string\n */\nfunction generateResponse(pincode: string, salt: string, challenge: string): string {\n  const hashedPincode = hashPincode(pincode, salt);\n  return createHash(\"sha256\").update(`${hashedPincode}_${challenge}`).digest(\"hex\");\n}\n\n/**\n * Options for handling a wallet verification challenge\n */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n  /** The portal client instance */\n  portalClient: GraphQLClient;\n  /** The GraphQL query builder */\n  portalGraphql: initGraphQLTada<Setup>;\n  /** The ID of the verification challenge */\n  verificationId: string;\n  /** The wallet address to verify */\n  userWalletAddress: Address;\n  /** The verification code provided by the user */\n  code: string | number;\n  /** The type of verification being performed */\n  verificationType: WalletVerificationType;\n  /** Request id which can be added for tracing purposes */\n  requestId?: string;\n}\n\n/**\n * Handles a wallet verification challenge by generating an appropriate response\n *\n * @param options - The options for handling the wallet verification challenge\n * @returns Promise resolving to an object containing the challenge response and optionally the verification ID\n * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid\n * @example\n * import { createPortalClient } from \"@settlemint/sdk-portal\";\n * import { handleWalletVerificationChallenge } from \"@settlemint/sdk-portal\";\n *\n * const { client, graphql } = createPortalClient({\n *   instance: \"https://portal.example.com/graphql\",\n *   accessToken: \"your-access-token\"\n * });\n *\n * const result = await handleWalletVerificationChallenge({\n *   portalClient: client,\n *   portalGraphql: graphql,\n *   verificationId: \"verification-123\",\n *   userWalletAddress: \"0x123...\",\n *   code: \"123456\",\n *   verificationType: \"OTP\"\n * });\n */\nexport async function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({\n  portalClient,\n  portalGraphql,\n  verificationId,\n  userWalletAddress,\n  code,\n  verificationType,\n  requestId,\n}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n  challengeResponse: string;\n  challengeId: string;\n}> {\n  try {\n    const requestHeaders = new Headers();\n    if (requestId) {\n      requestHeaders.append(\"x-request-id\", requestId);\n    }\n    const verificationChallenge = await portalClient.request<CreateWalletVerificationChallengeResponse>(\n      portalGraphql(`\n        mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {\n          createWalletVerificationChallenge(\n            userWalletAddress: $userWalletAddress\n            verificationId: $verificationId\n          ) {\n            id\n            name\n            verificationId\n            verificationType\n            challenge {\n              salt\n              secret\n            }\n          }\n        }\n      `),\n      {\n        userWalletAddress,\n        verificationId,\n      },\n      requestHeaders,\n    );\n\n    if (!verificationChallenge.createWalletVerificationChallenge) {\n      throw new WalletVerificationChallengeError(\"No verification challenge received\", \"NO_CHALLENGES\");\n    }\n\n    if (verificationType === \"OTP\") {\n      return {\n        challengeResponse: code.toString(),\n        challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n      };\n    }\n\n    if (verificationType === \"SECRET_CODES\") {\n      // Add a hyphen after every 5 characters to format the secret code\n      const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n      return {\n        challengeResponse: formattedCode,\n        challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n      };\n    }\n\n    const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};\n\n    if (!secret || !salt) {\n      throw new WalletVerificationChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n    }\n\n    const challengeResponse = generateResponse(code.toString(), salt, secret);\n    return {\n      challengeResponse,\n      challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n    };\n  } catch (error) {\n    if (error instanceof WalletVerificationChallengeError) {\n      throw error;\n    }\n    throw new WalletVerificationChallengeError(\n      \"Failed to process wallet verification challenge\",\n      \"CHALLENGE_PROCESSING_ERROR\",\n    );\n  }\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating Portal client configuration options.\n */\nexport const ClientOptionsSchema = z.object({\n  instance: UrlOrPathSchema,\n  accessToken: ApplicationAccessTokenSchema.optional(),\n  cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type representing the validated client options.\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Creates a Portal GraphQL client with the provided configuration.\n *\n * @param options - Configuration options for the Portal client\n * @param clientOptions - Additional GraphQL client configuration options\n * @returns An object containing the configured GraphQL client and graphql helper function\n * @throws If the provided options fail validation\n *\n * @example\n * import { createPortalClient } from \"@settlemint/sdk-portal\";\n * import { loadEnv } from \"@settlemint/sdk-utils/environment\";\n * import { createLogger, requestLogger } from \"@settlemint/sdk-utils/logging\";\n * import type { introspection } from \"@schemas/portal-env\";\n *\n * const env = await loadEnv(false, false);\n * const logger = createLogger();\n *\n * const { client: portalClient, graphql: portalGraphql } = createPortalClient<{\n *   introspection: introspection;\n *   disableMasking: true;\n *   scalars: {\n *     // Change unknown to the type you are using to store metadata\n *     JSON: unknown;\n *   };\n * }>(\n *   {\n *     instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,\n *     accessToken: env.SETTLEMINT_ACCESS_TOKEN!,\n *   },\n *   {\n *     fetch: requestLogger(logger, \"portal\", fetch) as typeof fetch,\n *   },\n * );\n *\n * // Making GraphQL queries\n * const query = portalGraphql(`\n *   query GetPendingTransactions {\n *     getPendingTransactions {\n *       count\n *     }\n *   }\n * `);\n *\n * const result = await portalClient.request(query);\n */\nexport function createPortalClient<const Setup extends AbstractSetupSchema>(\n  options: ClientOptions,\n  clientOptions?: RequestConfig,\n): {\n  client: GraphQLClient;\n  graphql: initGraphQLTada<Setup>;\n} {\n  ensureServer();\n  const validatedOptions = validate(ClientOptionsSchema, options);\n  const graphql = initGraphQLTada<Setup>();\n  const fullUrl = new URL(validatedOptions.instance).toString();\n\n  return {\n    client: new GraphQLClient(fullUrl, {\n      ...clientOptions,\n      headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n    }),\n    graphql,\n  };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n  type Transaction,\n  type TransactionEvent,\n  type TransactionReceipt,\n  type WaitForTransactionReceiptOptions,\n  waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n  type HandleWalletVerificationChallengeOptions,\n  handleWalletVerificationChallenge,\n  WalletVerificationChallengeError,\n  type WalletVerificationType,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":"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"}