{"version":3,"sources":["../src/utils.ts","../src/swap.ts","../src/types.ts","../src/controller.ts"],"names":["SwapWidgetSearchParamKey"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Helper function to make HTTP requests\n */\nexport async function makeRequest<T>(\n  baseURL: string,\n  endpoint: string,\n  options: RequestInit = {}\n): Promise<T> {\n  const url = `${baseURL}${endpoint}`\n  const response = await fetch(url, {\n    headers: {\n      'Content-Type': 'application/json',\n      ...options.headers\n    },\n    ...options\n  })\n\n  if (!response.ok) {\n    // Try to get error details from response body\n    let errorDetails = ''\n    try {\n      errorDetails = await response.json()\n    } catch {\n      try {\n        errorDetails = await response.text()\n      } catch {\n        errorDetails = 'Unable to read error details'\n      }\n    }\n\n    throw new Error(JSON.stringify(errorDetails))\n  }\n\n  return response.json()\n}\n\n/**\n * Get the base URL for the Pera API based on network\n */\nexport function getPeraBaseUrl(network: 'mainnet' | 'testnet'): string {\n  return network === 'mainnet'\n    ? \"https://mainnet.api.perawallet.app\"\n    : \"https://testnet.api.perawallet.app\"\n}\n\n/**\n * Default widget URL\n */\nexport const DEFAULT_WIDGET_URL = 'https://swap-widget.perawallet.app' ","import { CreateQuoteBody, SwapQuote, PrepareTransactionsResponse, Asset, GetAssetsResponse, UpdateSwapStatusBody } from './types'\nimport { makeRequest, getPeraBaseUrl } from './utils'\n\n/**\n * PeraSwap class for managing swap operations and widget generation\n */\nexport class PeraSwap {\n  private network: 'mainnet' | 'testnet'\n  private baseURL: string\n  private referrerUrl?: string\n  \n  constructor(network: 'mainnet' | 'testnet' = 'mainnet', referrerUrl?: string) {\n    this.network = network\n    this.baseURL = getPeraBaseUrl(network)\n    this.referrerUrl = referrerUrl\n  }\n\n  /**\n   * Update the network for all subsequent operations\n   */\n  updateNetwork(network: 'mainnet' | 'testnet'): void {\n    this.network = network\n    this.baseURL = getPeraBaseUrl(network)\n  }\n\n  /**\n   * Get the current network\n   */\n  getNetwork(): 'mainnet' | 'testnet' {\n    return this.network\n  }\n\n  /**\n   * Create a swap quote\n   */\n  async createQuote(body: CreateQuoteBody, signal?: AbortSignal): Promise<{results: SwapQuote[]}> {\n    const bodyData = {\n      ...body,\n      referrer_url: this.referrerUrl\n    }\n    \n    return makeRequest<{results: SwapQuote[]}>(this.baseURL, \"/v2/dex-swap/quotes/\", {\n      method: 'POST',\n      body: JSON.stringify(bodyData),\n      signal\n    })\n  }\n\n  /**\n   * Update the status of a swap\n   */\n  async updateSwapStatus(swapId: string, body: UpdateSwapStatusBody): Promise<any> {\n    const bodyData = {\n      ...body,\n      platform: \"js-sdk\",\n      swap_version: \"v2\"\n    }\n    return makeRequest(this.baseURL, `/v2/dex-swap/swaps/${swapId}/`, {\n      method: 'PATCH',\n      body: JSON.stringify(bodyData)\n    })\n  }\n\n  /**\n   * Prepare transactions for a swap\n   */\n  async prepareTransactions(quoteId: string, depositAddress?: string): Promise<PrepareTransactionsResponse> {\n    return makeRequest<PrepareTransactionsResponse>(\n      this.baseURL,\n      `/v2/dex-swap/prepare-transactions/`,\n      {\n        method: 'POST',\n        body: JSON.stringify({\n          quote: quoteId,\n          deposit_address: depositAddress\n        })\n      }\n    )\n  }\n\n  /**\n   * Get available assets for swapping\n   */\n  async getAvailableAssets(params: {asset_in_id: number; q?: string}): Promise<{results: Asset[]}> {\n    const searchParams = new URLSearchParams()\n    searchParams.append('asset_in_id', params.asset_in_id.toString())\n    if (params.q) searchParams.append('q', params.q)\n    \n    return makeRequest<{results: Asset[]}>(this.baseURL, `/v1/dex-swap/available-assets/?${searchParams}`)\n  }\n\n  /**\n   * Get assets by IDs or search query\n   */\n  async getAssets(params: {asset_ids?: string[]; q?: string}): Promise<GetAssetsResponse> {\n    const searchParams = new URLSearchParams()\n    if (params.asset_ids) searchParams.append('asset_ids', params.asset_ids.join(','))\n    if (params.q) searchParams.append('q', params.q)\n    \n    return makeRequest<GetAssetsResponse>(this.baseURL, `/v1/assets/?${searchParams}`)\n  }\n\n  /**\n   * Get ALGO price in USD\n   */\n  async getAlgoPrice(): Promise<{exchange_price: string}> {\n    return makeRequest<{exchange_price: string}>(this.baseURL, \"/v1/currencies/USD/\")\n  }\n\n  /**\n   * Get asset information by ID\n   */\n  async getAsset(assetId: number): Promise<Asset | null> {\n    try {\n      const response = await this.getAssets({ asset_ids: [assetId.toString()] })\n      return response.results[0] || null\n    } catch (error) {\n      console.error('Error fetching asset:', error)\n      return null\n    }\n  }\n\n  /**\n   * Search for assets by name\n   */\n  async searchAssets(query: string): Promise<Asset[]> {\n    try {\n      const response = await this.getAssets({ q: query })\n      return response.results\n    } catch (error) {\n      console.error('Error searching assets:', error)\n      return []\n    }\n  }\n} ","/** Search param keys that can be passed to the widget for configuration */\nexport enum SwapWidgetSearchParamKey {\n  /** When set to `true`, the widget will always try to\n   * communicate with the parent app to get the txns signed */\n  USE_PARENT_SIGNER = \"useParentSigner\",\n\n  /** Should be passed if `useParentSigner` is `true`, (otherwise it will be ignored)\n   * the widget will use this address as the signer of the txns */\n  ACCOUNT_ADDRESS = \"accountAddress\",\n\n  /** The preferred Algorand network that will be used by the widget */\n  NETWORK = \"network\",\n\n  /** The preferred theme of the widget */\n  THEME = \"theme\",\n\n  /** ID of the asset to be used as the input asset for the swap, default = ALGO */\n  ASSET_IN = \"assetIn\",\n\n  /** ID of the asset to be used as the output asset for the swap, default = USDC */\n  ASSET_OUT = \"assetOut\",\n\n  /** Background color of the widget, default = #FFFFFF */\n  IFRAME_BACKGROUND = \"iframeBg\"\n}\n\nexport type WidgetAppTheme = \"light\" | \"dark\"\n\nexport type WidgetNetwork = \"mainnet\" | \"testnet\"\n\nexport interface WidgetConfig {\n  /** The preferred Algorand network that will be used by the widget */\n  network?: WidgetNetwork;\n  \n  /** The preferred theme of the widget */\n  theme?: WidgetAppTheme;\n  \n  /** ID of the asset to be used as the input asset for the swap, default = ALGO */\n  assetIn?: string | number;\n  \n  /** ID of the asset to be used as the output asset for the swap, default = USDC */\n  assetOut?: string | number;\n  \n  /** Background color of the widget, default = #FFFFFF */\n  iframeBg?: string;\n  \n  /** When set to `true`, the widget will always try to\n   * communicate with the parent app to get the txns signed */\n  useParentSigner?: boolean;\n  \n  /** Should be passed if `useParentSigner` is `true`, (otherwise it will be ignored)\n   * the widget will use this address as the signer of the txns */\n  accountAddress?: string;\n}\n\nexport interface WidgetThemeColorVariables {\n  theme: WidgetAppTheme | null;\n  iframeBg: string | null;\n}\n\nexport type WidgetThemeVariables = WidgetThemeColorVariables;\n\n// Swap API Types\nexport type SwapProvider = \"tinyman\" | \"tinyman-swap-router\" | \"vestige-v4\"\n\nexport type SwapType = \"fixed-input\" | \"fixed-output\"\n\nexport type VerificationTier = \"verified\" | \"unverified\" | \"suspicious\"\n\nexport interface Asset {\n  asset_id: number\n  name: string\n  logo: string\n  unit_name: string\n  fraction_decimals: number\n  usd_value: string | null\n  is_verified: boolean\n  verification_tier: VerificationTier\n  type: \"standard_asset\" | \"collectible\" | \"dapp_asset\"\n}\n\nexport interface SwapQuote {\n  id: number\n  quote_id_str: string\n  provider: SwapProvider\n  swap_type: SwapType\n  swapper_address: string\n  asset_in: Asset\n  asset_out: Asset\n  amount_in: string\n  amount_in_with_slippage: string\n  amount_in_usd_value: null | string\n  amount_out: string\n  amount_out_with_slippage: string\n  amount_out_usd_value: null | string\n  slippage: string\n  price: string\n  price_impact: string\n  pera_fee_amount: string\n  exchange_fee_amount: string\n}\n\nexport interface CreateQuoteBody {\n  providers: SwapProvider[]\n  swapper_address: string\n  swap_type: SwapType\n  asset_in_id: number\n  asset_out_id: number\n  amount: string\n  slippage: string\n}\n\nexport interface SwapTransactionGroup {\n  purpose: \"opt-in\" | \"swap\" | \"fee\"\n  transaction_group_id: string\n  transactions: string[]\n  signed_transactions: string[]\n}\n\nexport interface PrepareTransactionsResponse {\n  swap_id: number;\n  swap_version: string;\n  transaction_groups: SwapTransactionGroup[]\n}\n\nexport interface UpdateSwapStatusBody {\n  status: \"failed\" | \"in_progress\";\n  submitted_transaction_ids?: string[];\n  reason?: \"other\" | \"user_cancelled\" | \"invalid_submission\" | \"blockchain_error\";\n  platform?: string;\n  swap_version?: \"v1\" | \"v2\";\n}\n\nexport interface GetAssetsResponse {\n  next: string | null\n  previous: string | null\n  results: Asset[]\n}\n\n// Message types for iframe communication\nexport interface TxnSignRequestMessage {\n  message: {\n    type: 'TXN_SIGN_REQUEST'\n    txGroups: Uint8Array[][]\n  }\n}\n\nexport interface TxnSignResponseMessage {\n  message: {\n    type: 'TXN_SIGN_RESPONSE'\n    signedTxns: Uint8Array[]\n  }\n}\n\nexport interface FailedTxnSignMessage {\n  message: {\n    type: 'FAILED_TXN_SIGN'\n    error: Error\n  }\n}\n\nexport interface TxnSignRequestTimeoutMessage {\n  message: {\n    type: 'TXN_SIGN_REQUEST_TIMEOUT'\n  }\n}\n\nexport interface SwapSuccessMessage {\n  message: {\n    type: 'SWAP_SUCCESS'\n    data: Uint8Array[]\n  }\n}\n\nexport type WidgetMessage = \n  | TxnSignRequestMessage\n  | TxnSignResponseMessage\n  | FailedTxnSignMessage\n  | TxnSignRequestTimeoutMessage\n  | SwapSuccessMessage ","import algosdk, { Transaction } from 'algosdk'\nimport { WidgetConfig } from './types'\nimport { DEFAULT_WIDGET_URL } from './utils'\n\nexport interface WidgetControllerConfig {\n  onTxnSignRequest?: (data: { txGroups: Transaction[][] }) => Promise<Uint8Array[]>\n  onTxnSignRequestTimeout?: () => void\n  onSwapSuccess?: (response: Uint8Array[]) => void\n}\n\n\n\nexport class WidgetController {\n  private config: WidgetControllerConfig\n\n  constructor(config: WidgetControllerConfig = {}) {\n    this.config = config\n  }\n\n  /**\n   * Generate a URL for the Pera Swap Widget iframe\n   */\n  static generateWidgetUrl(config: WidgetConfig = {}): string {\n    const url = new URL(DEFAULT_WIDGET_URL)\n    \n    // Add search parameters based on config\n    if (config.network) {\n      url.searchParams.set('network', config.network)\n    }\n    \n    if (config.theme) {\n      url.searchParams.set('theme', config.theme)\n    }\n    \n    if (config.assetIn !== undefined) {\n      url.searchParams.set('assetIn', String(config.assetIn))\n    }\n    \n    if (config.assetOut !== undefined) {\n      url.searchParams.set('assetOut', String(config.assetOut))\n    }\n    \n    if (config.iframeBg) {\n      url.searchParams.set('iframeBg', config.iframeBg)\n    }\n    \n    if (config.useParentSigner) {\n      url.searchParams.set('useParentSigner', 'true')\n      \n      if (config.accountAddress) {\n        url.searchParams.set('accountAddress', config.accountAddress)\n      }\n    }\n    \n    return url.toString()\n  }\n\n\n\n  /**\n   * Create an iframe element with the swap widget\n   */\n  static createWidgetIframe(\n    config: WidgetConfig = {},\n    options: {\n      width?: string;\n      height?: string;\n      className?: string;\n      id?: string;\n    } = {}\n  ): HTMLIFrameElement {\n    const iframe = document.createElement('iframe')\n    \n    iframe.src = WidgetController.generateWidgetUrl(config)\n    iframe.width = options.width || '100%'\n    iframe.height = options.height || '488px'\n    \n    if (options.className) {\n      iframe.className = options.className\n    }\n    \n    if (options.id) {\n      iframe.id = options.id\n    }\n    \n    return iframe\n  }\n\n  /**\n   * Send message to widget iframe\n   */\n  static sendMessageToWidget({\n    data,\n    targetWindow\n  }: {\n    data: { message: { type: string; [key: string]: unknown } }\n    targetWindow?: Window | null\n  }): void {\n    if (targetWindow) {\n      targetWindow.postMessage(data, '*')\n    }\n  }\n\n  /**\n   * Add event listeners for widget communication\n   */\n  addWidgetEventListeners(): void {\n    window.addEventListener('message', this.handleMessage.bind(this))\n  }\n\n  /**\n   * Remove event listeners\n   */\n  removeWidgetEventListeners(): void {\n    window.removeEventListener('message', this.handleMessage.bind(this))\n  }\n\n  /**\n   * Handle messages from the widget\n   */\n  private handleMessage(event: MessageEvent): void {\n    // Accept messages from the widget iframe; only require a structured payload\n    if (!event.data || !event.data.type || !event.data.message) {\n      return\n    }\n\n    switch (event.data.type) {\n      case 'TXN_SIGN_REQUEST': {\n        const { txGroups } = event.data.message as { txGroups: Uint8Array[][] }\n\n        // Decode bytes to Transaction objects before handing to consumer\n        const decodedTxGroups: Transaction[][] = txGroups.map((group) =>\n          group.map((bytes) => algosdk.decodeUnsignedTransaction(bytes))\n        )\n\n        if (this.config.onTxnSignRequest) {\n          this.config.onTxnSignRequest({ txGroups: decodedTxGroups })\n            .then((signedTxns) => {\n              WidgetController.sendMessageToWidget({\n                data: {\n                  message: {\n                    type: 'TXN_SIGN_RESPONSE',\n                    signedTxns\n                  }\n                },\n                targetWindow: event.source as Window\n              })\n            })\n            .catch((error) => {\n              WidgetController.sendMessageToWidget({\n                data: {\n                  message: {\n                    type: 'FAILED_TXN_SIGN',\n                    error\n                  }\n                },\n                targetWindow: event.source as Window\n              })\n            })\n        }\n        break\n      }\n\n      case 'TXN_SIGN_REQUEST_TIMEOUT': {\n        if (this.config.onTxnSignRequestTimeout) {\n          this.config.onTxnSignRequestTimeout()\n        }\n        break\n      }\n\n      case 'SWAP_SUCCESS': {\n        if (this.config.onSwapSuccess) {\n          this.config.onSwapSuccess(event.data.message)\n        }\n        break\n      }\n\n      default:\n        break\n    }\n  }\n}\n"]}