{"version":3,"file":"portal.cjs","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","UrlOrPathSchema","options: ClientOptions","clientOptions?: RequestConfig","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 * Custom error class for challenge-related errors\n */\nexport class ChallengeError 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  challenge: {\n    secret: string;\n    salt: string;\n  };\n  id: string;\n  name: string;\n  verificationType: string;\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenges mutation\n */\ninterface CreateWalletVerificationChallengesResponse {\n  createWalletVerificationChallenges: 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: \"otp\" | \"secret-code\" | \"pincode\";\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 {ChallengeError} 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}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n  challengeResponse: string;\n  verificationId?: string;\n}> {\n  try {\n    if (verificationType === \"otp\") {\n      return {\n        challengeResponse: code.toString(),\n        verificationId,\n      };\n    }\n\n    if (verificationType === \"secret-code\") {\n      // Add - separator to the code\n      const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n      return {\n        challengeResponse: formattedCode,\n        verificationId,\n      };\n    }\n\n    const verificationChallenges = await portalClient.request<CreateWalletVerificationChallengesResponse>(\n      portalGraphql(`\n        mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {\n          createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {\n            challenge\n            id\n            name\n            verificationType\n          }\n        }\n      `),\n      {\n        userWalletAddress,\n        verificationId,\n      },\n    );\n\n    if (!verificationChallenges.createWalletVerificationChallenges?.length) {\n      throw new ChallengeError(\"No verification challenges received\", \"NO_CHALLENGES\");\n    }\n\n    const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find(\n      (challenge) => challenge.id === verificationId,\n    );\n\n    if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {\n      throw new ChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n    }\n\n    const { secret, salt } = walletVerificationChallenge.challenge;\n    const challengeResponse = generateResponse(code.toString(), salt, secret);\n    return {\n      challengeResponse,\n      verificationId,\n    };\n  } catch (error) {\n    if (error instanceof ChallengeError) {\n      throw error;\n    }\n    throw new ChallengeError(\"Failed to process wallet verification challenge\", \"CHALLENGE_PROCESSING_ERROR\");\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/v4\";\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 { readFragment } from \"gql.tada\";\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport {\n  waitForTransactionReceipt,\n  type Transaction,\n  type TransactionEvent,\n  type TransactionReceipt,\n  type WaitForTransactionReceiptOptions,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n  handleWalletVerificationChallenge,\n  type HandleWalletVerificationChallengeOptions,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":"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"}