{"version":3,"file":"index.cjs","names":["Connection","isVersionedTransaction","lastError: Error | undefined","FeeEstimationFailedError","LAMPORTS_PER_SOL","isSolanaWalletAccount","InvalidParamError","isVersionedTransaction","feeData: SolanaSimulationResult['feeData']","PublicKey","FeeEstimationFailedError","SimulationFailedError","BaseError","BaseError","BaseError","BaseError","z","z","BaseError","CURVE25519_LOW_ORDER_POINTS: readonly Uint8Array[]","nacl","BaseError","decrypted: Uint8Array | null","nacl","methodErrorEventMap: Record<string, keyof PhantomEvents>","sharedSecret: string","nacl","nacl","WalletProviderEnum","connect: SolanaWalletProvider['connect']","destroy: SolanaWalletProvider['destroy']","getActiveNetworkId: SolanaWalletProvider['getActiveNetworkId']","getConnectedAddresses: SolanaWalletProvider['getConnectedAddresses']","signMessage: SolanaWalletProvider['signMessage']","signTransaction: SolanaWalletProvider['signTransaction']","VersionedTransaction","Transaction","signAllTransactions: SolanaWalletProvider['signAllTransactions']","signAndSendTransaction: SolanaWalletProvider['signAndSendTransaction']","signTransaction","getSolanaConnection","solanaConfirmTransaction","solanaExecuteSwapTransaction","solanaTransferAmount","WalletProviderPriority","isSolanaWalletProvider","NotSolanaProviderError","isSolanaWalletProvider","NotSolanaProviderError","MethodNotImplementedError","isSolanaWalletProvider","NotSolanaProviderError","packageName","packageVersion"],"sources":["../src/addSolanaExtension/addSolanaExtension.ts","../src/isSolanaNetworkProvider/isSolanaNetworkProvider.ts","../src/utils/calculateSolanaTransactionFee/calculateSolanaTransactionFee.ts","../src/simulateSolanaTransaction/simulateSolanaTransaction.ts","../src/phantomRedirect/errors/NoPendingPhantomRequestError.ts","../src/phantomRedirect/errors/NoPhantomSessionError.ts","../src/phantomRedirect/errors/PhantomMissingEncryptionParamsError.ts","../src/phantomRedirect/errors/PhantomRedirectRejectedError.ts","../src/phantomRedirect/phantomRedirect.constants.ts","../src/phantomRedirect/storage/pendingRequestStorageSchema/pendingRequestStorageSchema.ts","../src/phantomRedirect/storage/phantomSessionStorageSchema/phantomSessionStorageSchema.ts","../src/phantomRedirect/utils/broadcastPhantomEvent/broadcastPhantomEvent.ts","../src/phantomRedirect/errors/PhantomInvalidEncryptionPublicKeyError.ts","../src/phantomRedirect/utils/crypto/createNaClSharedSecret/createNaClSharedSecret.ts","../src/phantomRedirect/errors/PhantomRedirectDecryptionError.ts","../src/phantomRedirect/utils/crypto/decryptPayload/decryptPayload.ts","../src/phantomRedirect/utils/getPhantomOriginTab/getPhantomOriginTab.ts","../src/phantomRedirect/utils/parsePhantomRedirectParams/parsePhantomRedirectParams.ts","../src/phantomRedirect/completePhantomRedirect/completePhantomRedirect.ts","../src/phantomRedirect/utils/buildPhantomDeepLink/buildPhantomDeepLink.ts","../src/phantomRedirect/utils/crypto/encryptPayload/encryptPayload.ts","../src/phantomRedirect/utils/crypto/generateNaClKeyPair/generateNaClKeyPair.ts","../src/phantomRedirect/utils/getPhantomCluster/getPhantomCluster.ts","../src/phantomRedirect/utils/listenForPhantomBroadcast/listenForPhantomBroadcast.ts","../src/phantomRedirect/createPhantomRedirectWalletProvider/createPhantomRedirectWalletProvider.ts","../src/phantomRedirect/detectPhantomRedirect/detectPhantomRedirect.ts","../src/phantomRedirect/addPhantomRedirectSolanaExtension/addPhantomRedirectSolanaExtension.ts","../src/signAllTransactions/signAllTransactions.ts","../src/signAndSendSponsoredTransaction/signAndSendSponsoredTransaction.ts","../src/signTransaction/signTransaction.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client/core';\n\nimport { assertBufferAvailable } from '../utils/assertBufferAvailable/assertBufferAvailable';\nimport { addWaasSolanaExtension } from '../waas/addWaasSolanaExtension';\nimport { addSolanaWalletStandardExtension } from '../walletStandard/addSolanaWalletStandardExtension';\n\n/**\n * Adds the Solana extension to the Dynamic client.\n *\n * This is a convenience function that adds both the Solana Wallet Standard extension\n * and the Dynamic WaaS Solana extension, enabling support for all Solana wallet types\n * including standard wallets and embedded wallets managed by Dynamic's infrastructure.\n *\n * @example\n * ```ts\n * const client = createDynamicClient({ environmentId: 'env-123' });\n * addSolanaExtension(client);\n * ```\n *\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns void\n * @see isSolanaWalletAccount\n * @see isSolanaNetworkProvider\n * @notInstrumented\n */\nexport const addSolanaExtension = (client = getDefaultClient()): void => {\n  assertBufferAvailable();\n\n  addSolanaWalletStandardExtension(client);\n  addWaasSolanaExtension(client);\n};\n","import type { NetworkProvider } from '@dynamic-labs-sdk/client';\n\nimport type { SolanaNetworkProvider } from '../SolanaNetworkProvider.types';\n\n/**\n * Type guard function to check if a network provider is a Solana network provider.\n *\n * @example\n * ```ts\n * if (isSolanaNetworkProvider(networkProvider)) {\n *   const connection = getSolanaConnection({ networkData });\n * }\n * ```\n *\n * @param networkProvider - The network provider to check.\n * @returns True if the network provider is a Solana network provider, false otherwise.\n * @see isSolanaWalletAccount\n * @see addSolanaExtension\n * @notInstrumented\n */\nexport const isSolanaNetworkProvider = (\n  networkProvider: NetworkProvider\n): networkProvider is SolanaNetworkProvider => networkProvider.chain === 'SOL';\n","import type { NetworkData } from '@dynamic-labs-sdk/client';\nimport { FeeEstimationFailedError } from '@dynamic-labs-sdk/client';\nimport { Connection, LAMPORTS_PER_SOL, type Transaction, type VersionedTransaction } from '@solana/web3.js';\n\nimport type { SolanaTransactionFeeData } from '../../transactionSimulation.types';\nimport { isVersionedTransaction } from '../isVersionedTransaction';\n\ntype CalculateSolanaTransactionFeeParams = {\n  nativeTokenPriceUsd?: number;\n  networkData: NetworkData;\n  transaction: Transaction | VersionedTransaction;\n};\n\nconst MAX_RETRIES = 5;\nconst RETRY_DELAY_MS = 500;\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => {\n  setTimeout(resolve, ms);\n});\n\n/**\n * Calculates the estimated fee for a Solana transaction.\n *\n * This function fetches the transaction fee by compiling the transaction message\n * and querying the network. It handles both legacy Transaction and VersionedTransaction\n * formats and includes retry logic for network requests.\n *\n * @example\n * ```ts\n * const feeData = await calculateSolanaTransactionFee({\n *   transaction,\n *   networkData,\n *   nativeTokenPriceUsd: 150,\n * });\n * ```\n *\n * @param params.transaction - The Solana transaction to estimate fees for.\n * @param params.networkData - Network configuration for RPC connection.\n * @param params.nativeTokenPriceUsd - Optional USD price of SOL for fee conversion.\n * @returns Fee data in lamports and human-readable SOL format.\n * @throws {FeeEstimationFailedError} If fee retrieval fails after retries.\n * @see simulateSolanaTransaction\n * @see getSolanaConnection\n * @notInstrumented\n */\n \nexport const calculateSolanaTransactionFee = async ({\n  transaction,\n  networkData,\n  nativeTokenPriceUsd,\n}: CalculateSolanaTransactionFeeParams): Promise<SolanaTransactionFeeData> => {\n  try {\n    const connection = new Connection(networkData.rpcUrls.http[0]);\n\n    // Ensure transaction has a recent blockhash\n    if (isVersionedTransaction(transaction)) {\n      if (!transaction.message.recentBlockhash) {\n        const { blockhash } = await connection.getLatestBlockhash();\n        transaction.message.recentBlockhash = blockhash;\n      }\n    } else {\n      if (!transaction.recentBlockhash) {\n        const { blockhash } = await connection.getLatestBlockhash();\n        transaction.recentBlockhash = blockhash;\n      }\n    }\n\n    // Compile the transaction message\n    const message = isVersionedTransaction(transaction)\n      ? transaction.message\n      : transaction.compileMessage();\n\n    // Get fee with retry logic\n    let lastError: Error | undefined;\n\n    for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n      try {\n        const feeResponse = await connection.getFeeForMessage(message);\n\n        if (feeResponse.value === null) {\n          throw new FeeEstimationFailedError({\n            message: 'Fee calculation returned null',\n          });\n        }\n\n        const nativeAmount = BigInt(feeResponse.value);\n        const humanReadableAmount = (Number(nativeAmount) / LAMPORTS_PER_SOL).toString();\n\n        // Calculate USD amount if price data available\n        const usdAmount = nativeTokenPriceUsd\n          ? (Number(humanReadableAmount) * nativeTokenPriceUsd).toFixed(2)\n          : undefined;\n\n        return {\n          humanReadableAmount,\n          nativeAmount,\n          usdAmount,\n        };\n      } catch (error) {\n        lastError = error instanceof Error ? error : undefined;\n\n        if (attempt < MAX_RETRIES - 1) {\n          await sleep(RETRY_DELAY_MS * (attempt + 1));\n        }\n      }\n    }\n\n    throw new FeeEstimationFailedError({\n      cause: lastError,\n      message: 'Failed to get fee after retries',\n    });\n  } catch (error) {\n    throw new FeeEstimationFailedError({\n      cause: error instanceof Error ? error : undefined,\n      message: 'Failed to estimate Solana transaction fee',\n    });\n  }\n};\n","import {\n  FeeEstimationFailedError,\n  InvalidParamError,\n  SimulationFailedError,\n  getActiveNetworkData,\n  getDefaultClient,\n} from '@dynamic-labs-sdk/client';\nimport { createApiClient, getCore } from '@dynamic-labs-sdk/client/core';\nimport {\n  PublicKey,\n  type Transaction,\n  type VersionedTransaction,\n} from '@solana/web3.js';\nimport bs58 from 'bs58';\n\nimport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nimport { isSolanaWalletAccount } from '../isSolanaWalletAccount';\nimport type { SolanaSimulationResult } from '../transactionSimulation.types';\nimport { calculateSolanaTransactionFee } from '../utils/calculateSolanaTransactionFee';\nimport { isVersionedTransaction } from '../utils/isVersionedTransaction';\n\ntype SimulateSolanaTransactionParams = {\n  includeFees?: boolean;\n  transaction: Transaction | VersionedTransaction;\n  walletAccount: SolanaWalletAccount;\n};\n\n/**\n * Simulates a Solana transaction to preview its effects before execution.\n *\n * This function uses the Blockaid API to analyze the transaction and returns\n * information about asset transfers, security validation, and optionally fee estimates.\n * The simulation shows what will happen when the transaction is executed without\n * actually sending it to the blockchain.\n *\n * **Important**: A successful simulation does not guarantee the transaction will succeed.\n * The simulation may succeed but indicate the transaction would fail (e.g., due to\n * insufficient balance). Check the `validation` field in the result for potential issues.\n *\n * @example\n * ```typescript\n * const result = await simulateSolanaTransaction({\n *   walletAccount,\n *   transaction,\n *   includeFees: true\n * });\n *\n * // Check if transaction would fail\n * if (result.validation?.reason?.includes('not enough SOL')) {\n *   console.log('Transaction would fail due to insufficient balance');\n * }\n * ```\n *\n * @param params.walletAccount - The Solana wallet account that will sign the transaction.\n * @param params.transaction - The Solana transaction (legacy or versioned) to simulate.\n * @param params.includeFees - Whether to calculate transaction fees (default: false).\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns Simulation result with asset diffs, security validation, and optional fee data.\n * @throws {InvalidParamError} If wallet account is not a Solana account.\n * @throws {SimulationFailedError} If the simulation API call fails.\n * @throws {FeeEstimationFailedError} If includeFees is true and fee calculation fails.\n * @see calculateSolanaTransactionFee\n * @see isSolanaWalletAccount\n * @notInstrumented\n */\nexport const simulateSolanaTransaction = async (\n  {\n    walletAccount,\n    transaction,\n    includeFees = false,\n  }: SimulateSolanaTransactionParams,\n  client = getDefaultClient()\n): Promise<SolanaSimulationResult> => {\n  // Validate wallet account type\n  if (!isSolanaWalletAccount(walletAccount)) {\n    throw new InvalidParamError(\n      'Wallet account must be a Solana wallet account'\n    );\n  }\n\n  // Get active network data for the wallet\n  const { networkData } = await getActiveNetworkData({ walletAccount }, client);\n\n  if (!networkData) {\n    throw new InvalidParamError('Network data not found for wallet account');\n  }\n\n  try {\n    // Serialize full transaction to base58 for API\n    const transactionBytes = isVersionedTransaction(transaction)\n      ? transaction.serialize()\n      : transaction.serialize({\n          requireAllSignatures: false,\n          verifySignatures: false,\n        });\n\n    const serialized = bs58.encode(transactionBytes as Uint8Array);\n\n    // eslint-disable-next-line no-console\n    console.log('[SIMULATE SOLANA TX] Serialization details:', {\n      accountAddress: walletAccount.address,\n      isVersioned: isVersionedTransaction(transaction),\n      serializedBase58: serialized,\n      serializedLength: serialized.length,\n      transactionLength: transactionBytes.length,\n    });\n\n    // Create API client and call simulation endpoint\n    const core = getCore(client);\n    const apiClient = createApiClient({}, client);\n\n    const requestPayload = {\n      environmentId: core.environmentId,\n      simulateSVMTransactionRequest: {\n        accountAddress: walletAccount.address,\n        chain: 'solana',\n        method: 'solana_signTransaction',\n        transactions: [serialized],\n      },\n    };\n\n    // eslint-disable-next-line no-console\n    console.log('[SIMULATE SOLANA TX] API Request:', requestPayload);\n\n    const response = await apiClient.simulateSVMTransaction(requestPayload);\n\n    // Calculate fees if requested\n    let feeData: SolanaSimulationResult['feeData'];\n\n    if (includeFees) {\n      // Check if transaction is sponsored (fee payer != wallet address)\n      const walletPublicKey = new PublicKey(walletAccount.address);\n      const feePayer = isVersionedTransaction(transaction)\n        ? transaction.message.staticAccountKeys[0]\n        : transaction.feePayer;\n\n      const isSponsored = feePayer && !feePayer.equals(walletPublicKey);\n\n      if (isSponsored) {\n        // Sponsored transaction - no fee for user\n        feeData = {\n          humanReadableAmount: '0',\n          nativeAmount: 0n,\n          usdAmount: '0.00',\n        };\n      } else {\n        // User pays fee - calculate it\n        feeData = await calculateSolanaTransactionFee({\n          nativeTokenPriceUsd: response.priceData?.nativeTokenUsdPrice,\n          networkData,\n          transaction,\n        });\n      }\n    }\n\n    // Map API response to simulation result\n    return {\n      counterparties: response.counterparties,\n      feeData,\n      inAssets: response.inAssets || [],\n      outAssets: response.outAssets || [],\n      priceData: response.priceData,\n      showTotalFiat: response.showTotalFiat,\n      validation: response.validation\n        ? {\n            description: response.validation.description,\n            reason: response.validation.reason,\n            result: response.validation.result as\n              | 'benign'\n              | 'warning'\n              | 'malicious',\n          }\n        : undefined,\n    };\n  } catch (error) {\n    // Re-throw FeeEstimationFailedError as-is\n    if (error instanceof FeeEstimationFailedError) {\n      throw error;\n    }\n\n    throw new SimulationFailedError({\n      cause: error instanceof Error ? error : undefined,\n      message: 'Failed to simulate Solana transaction',\n    });\n  }\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class NoPendingPhantomRequestError extends BaseError {\n  constructor() {\n    super({\n      cause: null,\n      code: 'no_pending_phantom_request_error',\n      docsUrl: null,\n      name: 'NoPendingPhantomRequestError',\n      shortMessage:\n        'No pending Phantom request found. The request may have already been processed or expired.',\n    });\n  }\n}\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class NoPhantomSessionError extends BaseError {\n  constructor() {\n    super({\n      cause: null,\n      code: 'no_phantom_session_error',\n      docsUrl: null,\n      name: 'NoPhantomSessionError',\n      shortMessage: 'No Phantom session found. Please connect first.',\n    });\n  }\n}\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class PhantomMissingEncryptionParamsError extends BaseError {\n  constructor() {\n    super({\n      cause: null,\n      code: 'phantom_missing_encryption_params_error',\n      docsUrl: null,\n      name: 'PhantomMissingEncryptionParamsError',\n      shortMessage:\n        'Phantom redirect response is missing required encryption parameters (phantomPublicKey, data, or nonce).',\n    });\n  }\n}\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport type PhantomRedirectRejectedErrorParams = {\n  errorCode: string;\n  errorMessage?: string;\n};\n\nexport class PhantomRedirectRejectedError extends BaseError {\n  constructor({ errorCode, errorMessage }: PhantomRedirectRejectedErrorParams) {\n    super({\n      cause: null,\n      code: 'phantom_redirect_rejected_error',\n      details: errorMessage,\n      docsUrl: null,\n      metaMessages: [`Error Code: ${errorCode}`],\n      name: 'PhantomRedirectRejectedError',\n      shortMessage: 'User rejected the request in Phantom wallet.',\n    });\n  }\n}\n","export const PHANTOM_DEEPLINK_BASE_URL = 'https://phantom.app/ul/v1';\n\nexport const PHANTOM_SESSION_STORAGE_KEY = 'phantom_session';\n\nexport const PHANTOM_PENDING_REQUEST_STORAGE_KEY = 'phantom_pending_request';\n\nexport const PHANTOM_REDIRECT_TIMEOUT_MS = 300000; // 5 minutes\n","import { createStorageKeySchema } from '@dynamic-labs-sdk/client/core';\nimport * as z from 'zod/mini';\n\nimport { PHANTOM_PENDING_REQUEST_STORAGE_KEY } from '../../phantomRedirect.constants';\n\n/**\n * Storage schema for tracking pending Phantom wallet requests.\n * This temporary data is used to match redirect responses with their\n * originating requests and includes the encryption keys needed for decryption.\n */\nexport const pendingRequestStorageKeySchema = createStorageKeySchema({\n  key: PHANTOM_PENDING_REQUEST_STORAGE_KEY,\n  schema: z.object({\n    dappPublicKey: z.string(),\n    dappSecretKey: z.string(),\n    message: z.optional(z.string()),\n    method: z.string(),\n    requestId: z.string(),\n    timestamp: z.number(),\n    walletAddress: z.optional(z.string()),\n  }),\n});\n","import { createStorageKeySchema } from '@dynamic-labs-sdk/client/core';\nimport * as z from 'zod/mini';\n\nimport { PHANTOM_SESSION_STORAGE_KEY } from '../../phantomRedirect.constants';\n\n/**\n * Storage schema for persisting Phantom wallet session data.\n * This includes the encryption keys and session information needed\n * for subsequent operations after the initial connection.\n */\nexport const phantomSessionStorageKeySchema = createStorageKeySchema({\n  key: PHANTOM_SESSION_STORAGE_KEY,\n  schema: z.object({\n    dappPublicKey: z.string(),\n    dappSecretKey: z.string(),\n    phantomPublicKey: z.string(),\n    sessionToken: z.string(),\n    sharedSecret: z.string(),\n    walletAddress: z.string(),\n  }),\n});\n","import type { DynamicClient } from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\n\nimport type {\n  PhantomBroadcastMessage,\n  PhantomEvents,\n} from '../../phantomRedirect.broadcast.types';\n\n/**\n * Broadcasts a Phantom redirect event to other tabs via the crossTabBroadcast\n * service.\n *\n * Used by the redirect-completion tab to notify the originating tab that\n * an operation has finished, since onceEvent listeners are in-memory and\n * do not cross tab boundaries.\n *\n * @param params.event - The DynamicEvents event name to broadcast\n * @param params.args - The event arguments to include in the message\n * @param client - The Dynamic client instance\n  * @notInstrumented\n */\nexport const broadcastPhantomEvent = <K extends keyof PhantomEvents>(\n  { args, event }: PhantomBroadcastMessage<K>,\n  client: DynamicClient\n): void => {\n  getCore(client).crossTabBroadcast.send({ args, event });\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class PhantomInvalidEncryptionPublicKeyError extends BaseError {\n  constructor() {\n    super({\n      cause: null,\n      code: 'phantom_invalid_encryption_public_key_error',\n      docsUrl: null,\n      name: 'PhantomInvalidEncryptionPublicKeyError',\n      shortMessage:\n        'Invalid Phantom encryption public key (low-order point rejected).',\n    });\n  }\n}\n","import bs58 from 'bs58';\nimport nacl from 'tweetnacl';\n\nimport { PhantomInvalidEncryptionPublicKeyError } from '../../../errors/PhantomInvalidEncryptionPublicKeyError';\n\nexport type CreateNaClSharedSecretParams = {\n  ourSecretKey: string;\n  theirPublicKey: string;\n};\n\n/**\n * The length, in bytes, of a Curve25519 public key.\n */\nconst CURVE25519_PUBLIC_KEY_LENGTH = 32;\n\n/**\n * The complete set of known Curve25519 low-order point encodings.\n *\n * A malicious Phantom redirect can supply one of these as\n * `phantom_encryption_public_key`. X25519 with a low-order base point produces\n * a small, universally-known shared secret (independent of our secret key),\n * letting an attacker decrypt/forge the connect response and overwrite the\n * connected wallet address. We reject them before deriving the box secret.\n *\n * Source: RFC 7748 / the canonical list of the 8 Curve25519 low-order points.\n */\nconst CURVE25519_LOW_ORDER_POINTS: readonly Uint8Array[] = [\n  // 0 (order 1)\n  new Uint8Array([\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0,\n  ]),\n  // 1 (order 4)\n  new Uint8Array([\n    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0,\n  ]),\n  // 325606250916557431795983626356110631294008115727848805560023387167927233504 (order 8)\n  new Uint8Array([\n    224, 235, 122, 124, 59, 65, 184, 174, 22, 86, 227, 250, 241, 159, 196, 106,\n    218, 9, 141, 235, 156, 50, 177, 253, 134, 98, 5, 22, 95, 73, 184, 0,\n  ]),\n  // 39382357235489614581723060781553021112529911719440698176882885853963445705823 (order 8)\n  new Uint8Array([\n    95, 156, 149, 188, 163, 80, 140, 36, 177, 208, 177, 85, 156, 131, 239, 91,\n    4, 68, 92, 196, 88, 28, 142, 134, 216, 34, 78, 221, 208, 159, 17, 87,\n  ]),\n  // p - 1 (order 2)\n  new Uint8Array([\n    236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 127,\n  ]),\n  // p (order 4)\n  new Uint8Array([\n    237, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 127,\n  ]),\n  // p + 1 (order 1)\n  new Uint8Array([\n    238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n    255, 127,\n  ]),\n  // p + (325606250916557431795983626356110631294008115727848805560023387167927233504) (order 8)\n  new Uint8Array([\n    205, 235, 122, 124, 59, 65, 184, 174, 22, 86, 227, 250, 241, 159, 196, 106,\n    218, 9, 141, 235, 156, 50, 177, 253, 134, 98, 5, 22, 95, 73, 184, 128,\n  ]),\n];\n\n/**\n * Constant-time equality check for two byte arrays. No early-exit branches so\n * comparison duration does not leak the content being compared.\n */\nconst bytesEqual = ({ a, b }: { a: Uint8Array; b: Uint8Array }): boolean => {\n  // Fold length mismatch into the accumulator rather than branching, preserving\n  // constant-time behavior even for mismatched lengths.\n  let diff = a.length ^ b.length;\n  const length = Math.min(a.length, b.length);\n\n  for (let i = 0; i < length; i += 1) {\n    diff |= a[i] ^ b[i];\n  }\n\n  return diff === 0;\n};\n\n/**\n * Validates that a decoded Curve25519 public key is safe to use for X25519 key\n * agreement, rejecting low-order / contributory points.\n *\n * Defense in depth:\n *   1. Enforce the canonical 32-byte length.\n *   2. Reject the known small set of low-order point encodings (blocklist).\n *   3. Reject any input whose raw X25519 output (`nacl.scalarMult`) is all-zero,\n *      which catches low-order inputs regardless of encoding.\n *\n * @param params.theirPublicKey - The decoded (32-byte) peer public key\n * @param params.ourSecretKey - The decoded (32-byte) local secret key\n * @throws {PhantomInvalidEncryptionPublicKeyError} If the key is invalid or low-order\n */\n// eslint-disable-next-line custom-rules/one-function-per-file -- small local crypto helper\nconst assertValidCurve25519PublicKey = ({\n  theirPublicKey,\n  ourSecretKey,\n}: {\n  ourSecretKey: Uint8Array;\n  theirPublicKey: Uint8Array;\n}): void => {\n  if (theirPublicKey.length !== CURVE25519_PUBLIC_KEY_LENGTH) {\n    throw new PhantomInvalidEncryptionPublicKeyError();\n  }\n\n  for (const lowOrderPoint of CURVE25519_LOW_ORDER_POINTS) {\n    if (bytesEqual({ a: theirPublicKey, b: lowOrderPoint })) {\n      throw new PhantomInvalidEncryptionPublicKeyError();\n    }\n  }\n\n  // Even if an encoding slips past the blocklist, an all-zero X25519 output\n  // means the peer forced the shared secret to a known constant.\n  const scalarMultOutput = nacl.scalarMult(ourSecretKey, theirPublicKey);\n  const zero = new Uint8Array(scalarMultOutput.length);\n\n  if (bytesEqual({ a: scalarMultOutput, b: zero })) {\n    throw new PhantomInvalidEncryptionPublicKeyError();\n  }\n};\n\n/**\n * Creates a shared secret for NaCl box encryption using our secret key and their public key.\n *\n * Rejects low-order / invalid Curve25519 public keys before deriving the shared\n * secret, preventing an attacker from forcing the X25519 output to a known\n * constant via a malicious `phantom_encryption_public_key`.\n *\n * @param params.ourSecretKey - Our base58-encoded secret key\n * @param params.theirPublicKey - Their base58-encoded public key\n * @returns The base58-encoded shared secret\n * @throws {PhantomInvalidEncryptionPublicKeyError} If their public key is invalid or a low-order point\n * @notInstrumented\n */\n// eslint-disable-next-line custom-rules/one-function-per-file -- co-located with its small crypto validation helpers\nexport const createNaClSharedSecret = ({\n  ourSecretKey,\n  theirPublicKey,\n}: CreateNaClSharedSecretParams): string => {\n  const theirPublicKeyBytes = bs58.decode(theirPublicKey);\n  const ourSecretKeyBytes = bs58.decode(ourSecretKey);\n\n  assertValidCurve25519PublicKey({\n    ourSecretKey: ourSecretKeyBytes,\n    theirPublicKey: theirPublicKeyBytes,\n  });\n\n  const sharedSecret = nacl.box.before(theirPublicKeyBytes, ourSecretKeyBytes);\n\n  return bs58.encode(sharedSecret);\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class PhantomRedirectDecryptionError extends BaseError {\n  constructor() {\n    super({\n      cause: null,\n      code: 'phantom_redirect_decryption_error',\n      docsUrl: null,\n      name: 'PhantomRedirectDecryptionError',\n      shortMessage:\n        'Failed to decrypt Phantom redirect response. The encryption keys may be invalid.',\n    });\n  }\n}\n","import { getBuffer } from '@dynamic-labs-sdk/client/core';\nimport bs58 from 'bs58';\nimport nacl from 'tweetnacl';\n\nimport { PhantomRedirectDecryptionError } from '../../../errors/PhantomRedirectDecryptionError';\n\nexport type DecryptPayloadParams = {\n  data: string;\n  nonce: string;\n  sharedSecret: string;\n};\n\n/**\n * Decrypts a payload using NaCl box encryption with a shared secret.\n *\n * @param params.data - The base58-encoded encrypted data\n * @param params.nonce - The base58-encoded nonce\n * @param params.sharedSecret - The base58-encoded shared secret\n * @returns The decrypted payload object\n * @throws {PhantomRedirectDecryptionError} If decryption fails\n  * @notInstrumented\n */\nexport const decryptPayload = ({\n  data,\n  nonce,\n  sharedSecret,\n}: DecryptPayloadParams): Record<string, unknown> => {\n  let decrypted: Uint8Array | null;\n\n  try {\n    decrypted = nacl.box.open.after(\n      bs58.decode(data),\n      bs58.decode(nonce),\n      bs58.decode(sharedSecret)\n    );\n  } catch {\n    throw new PhantomRedirectDecryptionError();\n  }\n\n  if (!decrypted) {\n    throw new PhantomRedirectDecryptionError();\n  }\n\n  const decryptedString = getBuffer().from(decrypted).toString('utf-8');\n\n  try {\n    return JSON.parse(decryptedString) as Record<string, unknown>;\n  } catch {\n    throw new PhantomRedirectDecryptionError();\n  }\n};\n","import { createRuntimeServiceAccessKey } from '@dynamic-labs-sdk/client/core';\n\nexport type PhantomOriginTabService = {\n  isOriginTab: boolean;\n};\n\n/**\n * Per-client service that tracks whether this JavaScript context is the\n * **originating tab** that initiated a Phantom redirect request.\n *\n * Calling `getPhantomOriginTab(client)` for the first time lazily creates the\n * service with `isOriginTab: false`. `setupPhantomListeners` sets it to `true`\n * immediately when a request is initiated, so `completePhantomRedirect` can\n * detect clone tabs by checking this flag.\n *\n * Because the service is stored in the client's `runtimeServices` Map (one\n * entry per client instance), it is naturally scoped to the current JavaScript\n * context — no browser globals (`sessionStorage`, `window`) are needed, making\n * this approach compatible with SSR and React Native.\n */\nexport const getPhantomOriginTab = createRuntimeServiceAccessKey(\n  'phantomOriginTab',\n  (): PhantomOriginTabService => ({ isOriginTab: false })\n);\n","export type PhantomRedirectParams = {\n  data?: string;\n  errorCode?: string;\n  errorMessage?: string;\n  nonce?: string;\n  phantomPublicKey?: string;\n  requestId?: string;\n};\n\nexport type ParsePhantomRedirectParamsParams = {\n  url: URL;\n};\n\n/**\n * Parses Phantom wallet redirect parameters from a URL.\n *\n * Extracts both success and error parameters from the redirect URL,\n * including encrypted response data or error information.\n *\n * @param params.url - The redirect URL containing Phantom parameters\n * @returns Object containing the parsed redirect parameters\n  * @notInstrumented\n */\nexport const parsePhantomRedirectParams = ({\n  url,\n}: ParsePhantomRedirectParamsParams): PhantomRedirectParams => {\n  const searchParams = url.searchParams;\n\n  return {\n    data: searchParams.get('data') ?? undefined,\n    errorCode: searchParams.get('errorCode') ?? undefined,\n    errorMessage: searchParams.get('errorMessage') ?? undefined,\n    nonce: searchParams.get('nonce') ?? undefined,\n    phantomPublicKey:\n      searchParams.get('phantom_encryption_public_key') ?? undefined,\n    requestId: searchParams.get('request_id') ?? undefined,\n  };\n};\n","import type { DynamicClient } from '@dynamic-labs-sdk/client';\nimport { emitEvent, getCore, getDefaultClient } from '@dynamic-labs-sdk/client/core';\n\nimport { NoPendingPhantomRequestError } from '../errors/NoPendingPhantomRequestError';\nimport { NoPhantomSessionError } from '../errors/NoPhantomSessionError';\nimport { PhantomMissingEncryptionParamsError } from '../errors/PhantomMissingEncryptionParamsError';\nimport { PhantomRedirectRejectedError } from '../errors/PhantomRedirectRejectedError';\nimport type {\n  PhantomBroadcastMessage,\n  PhantomEvents,\n} from '../phantomRedirect.broadcast.types';\nimport type {\n  PhantomConnectResponse,\n  PhantomSignAllTransactionsResponse,\n  PhantomSignAndSendTransactionResponse,\n  PhantomSignMessageResponse,\n  PhantomSignTransactionResponse,\n} from '../PhantomRedirectWalletProvider.types';\nimport { pendingRequestStorageKeySchema } from '../storage/pendingRequestStorageSchema';\nimport { phantomSessionStorageKeySchema } from '../storage/phantomSessionStorageSchema';\nimport { broadcastPhantomEvent } from '../utils/broadcastPhantomEvent';\nimport { createNaClSharedSecret } from '../utils/crypto/createNaClSharedSecret';\nimport { decryptPayload } from '../utils/crypto/decryptPayload';\nimport { getPhantomOriginTab } from '../utils/getPhantomOriginTab';\nimport { parsePhantomRedirectParams } from '../utils/parsePhantomRedirectParams';\n\nconst methodErrorEventMap: Record<string, keyof PhantomEvents> = {\n  connect: 'phantomRedirectConnectionError',\n  disconnect: 'phantomRedirectDisconnectError',\n  signAllTransactions: 'phantomRedirectSignAllTransactionsError',\n  signAndSendTransaction: 'phantomRedirectSignAndSendTransactionError',\n  signMessage: 'phantomRedirectSignMessageError',\n  signTransaction: 'phantomRedirectSignTransactionError',\n};\n\nexport type CompletePhantomRedirectParams = {\n  url: URL;\n};\n\n/**\n * Returns true when the current JavaScript context is a **clone tab** —\n * a new browser tab that Phantom opened to deliver the redirect callback on\n * mobile browsers.\n *\n * ## Detection mechanism\n *\n * When a wallet operation is initiated (`connect`, `signMessage`, etc.)\n * `setupPhantomListeners` sets `isOriginTab = true` on the per-client\n * `phantomOriginTabService`. Because each browser tab (and each native mobile\n * context) has its own JavaScript heap, the clone tab's client starts with\n * `isOriginTab = false` and will never have it set to `true`.\n *\n * - `isOriginTab === false` → clone tab (mobile browser redirect) → should close\n * - `isOriginTab === true` → originating tab or native mobile context → should stay open\n */\nconst isCloneTab = (client: DynamicClient): boolean =>\n  !getPhantomOriginTab(client).isOriginTab;\n\n/**\n * Removes the pending request from storage, emits a Phantom redirect event to\n * the local client, broadcasts it to the originating tab via `BroadcastChannel`,\n * and — when running in a clone tab — emits `phantomRedirectCloseTab` so that\n * the customer's `onCloseTab` callback can close the tab.\n *\n * This is the single point of truth for all cleanup and event delivery in the\n * redirect flow. Every code path calls this exactly once, ensuring a consistent\n * ordering: remove pending request → emit → broadcast → (maybe) close tab.\n */\n \nconst completeAndEmitPhantomRedirectEvent = async <\n  K extends keyof PhantomEvents\n>(\n  { args, event }: PhantomBroadcastMessage<K>,\n  client: DynamicClient\n): Promise<void> => {\n  const core = getCore(client);\n  const cloneTab = isCloneTab(client);\n\n  await core.storage.removeItem(pendingRequestStorageKeySchema);\n\n  emitEvent({ args, event }, client);\n\n  core.logger.debug('[PHANTOM] completeAndEmitPhantomRedirectEvent: broadcasting', { event });\n  broadcastPhantomEvent({ args, event }, client);\n\n  if (cloneTab) {\n    core.logger.debug('[PHANTOM] completeAndEmitPhantomRedirectEvent: emitting closeTab (clone tab)');\n    emitEvent({ args: {}, event: 'phantomRedirectCloseTab' }, client);\n  }\n};\n\n/**\n * Completes the Phantom wallet redirect flow after the deep link callback.\n *\n * This function is called on the page that Phantom redirects back to after the\n * user approves or rejects a wallet operation. It processes the redirect URL,\n * decrypts the response, updates session storage, and emits the appropriate\n * events so that waiting callers (in this tab or the originating tab) can\n * resolve or reject their pending promises.\n *\n * ## Cross-tab delivery\n *\n * On mobile browsers, Phantom opens the redirect URL in a **new tab** (the\n * clone tab). Events are delivered to the originating tab via the\n * `BroadcastChannel` API. Once delivery is complete this function emits\n * `phantomRedirectCloseTab` so that the clone tab can be closed and the user\n * is returned to the originating tab. See the `phantomRedirectCloseTab` event\n * JSDoc for details on how to handle tab closing.\n *\n * @example\n * ```ts\n * const url = new URL(window.location.href);\n * if (await detectPhantomRedirect({ url })) {\n *   await completePhantomRedirect({ url });\n *   // Close this clone tab; the originating tab already received the result\n *   // via BroadcastChannel and will resolve its pending promise.\n *   window.close();\n * }\n * ```\n *\n * @param params.url - The callback URL received from Phantom\n * @param client - The Dynamic client instance\n * @throws {NoPendingPhantomRequestError} If no pending request is found in storage\n * @throws {PhantomMissingEncryptionParamsError} If the URL is missing the\n *   required encryption parameters (`phantom_encryption_public_key`, `data`,\n *   `nonce`) and does not carry an error code either\n * @throws {PhantomRedirectRejectedError} If the user rejected the request in Phantom\n * @returns void\n * @see detectPhantomRedirect\n * @see addPhantomRedirectSolanaExtension\n * @notInstrumented\n */\n// eslint-disable-next-line custom-rules/one-function-per-file\nexport const completePhantomRedirect = async (\n  { url }: CompletePhantomRedirectParams,\n  client: DynamicClient = getDefaultClient()\n): Promise<void> => {\n  const core = getCore(client);\n\n  const params = parsePhantomRedirectParams({ url });\n\n  const pendingRequest = await core.storage.getItem(\n    pendingRequestStorageKeySchema\n  );\n\n  if (!pendingRequest) {\n    throw new NoPendingPhantomRequestError();\n  }\n\n  if (params.errorCode) {\n    const error = new PhantomRedirectRejectedError({\n      errorCode: params.errorCode,\n      errorMessage: params.errorMessage,\n    });\n\n    const event = methodErrorEventMap[pendingRequest.method];\n\n    await completeAndEmitPhantomRedirectEvent(\n      { args: { error }, event },\n      client\n    );\n\n    return;\n  }\n\n  // Disconnect success: Phantom returns an empty callback URL (no data, nonce,\n  // or phantom_encryption_public_key). Handle it before the data/nonce guard\n  // so we don't throw PhantomMissingEncryptionParamsError for a valid response.\n  if (pendingRequest.method === 'disconnect') {\n    await completeAndEmitPhantomRedirectEvent(\n      { args: {}, event: 'phantomRedirectDisconnectComplete' },\n      client\n    );\n\n    return;\n  }\n\n  if (!params.data || !params.nonce) {\n    await core.storage.removeItem(pendingRequestStorageKeySchema);\n    throw new PhantomMissingEncryptionParamsError();\n  }\n\n  let sharedSecret: string;\n\n  if (pendingRequest.method === 'connect') {\n    // The connect response includes phantom_encryption_public_key so we can\n    // establish the shared secret for the first time.\n    if (!params.phantomPublicKey) {\n      throw new PhantomMissingEncryptionParamsError();\n    }\n\n    sharedSecret = createNaClSharedSecret({\n      ourSecretKey: pendingRequest.dappSecretKey,\n      theirPublicKey: params.phantomPublicKey,\n    });\n  } else {\n    // Sign callbacks (signMessage, signTransaction, etc.) do NOT include\n    // phantom_encryption_public_key — the session is already established.\n    // Use the shared secret stored during connect.\n    const session = await core.storage.getItem(phantomSessionStorageKeySchema);\n\n    if (!session) {\n      throw new NoPhantomSessionError();\n    }\n\n    sharedSecret = session.sharedSecret;\n  }\n\n  const decryptedData = decryptPayload({\n    data: params.data,\n    nonce: params.nonce,\n    sharedSecret,\n  });\n\n  if (pendingRequest.method === 'connect') {\n    const connectData = decryptedData as PhantomConnectResponse;\n\n    await core.storage.setItem(phantomSessionStorageKeySchema, {\n      dappPublicKey: pendingRequest.dappPublicKey,\n      dappSecretKey: pendingRequest.dappSecretKey,\n      phantomPublicKey: params.phantomPublicKey,\n      sessionToken: connectData.session,\n      sharedSecret,\n      walletAddress: connectData.public_key,\n    });\n\n    await completeAndEmitPhantomRedirectEvent(\n      {\n        args: {\n          address: connectData.public_key,\n          publicKey: connectData.public_key,\n        },\n        event: 'phantomRedirectConnectionComplete',\n      },\n      client\n    );\n  } else if (pendingRequest.method === 'signMessage') {\n    const signData = decryptedData as PhantomSignMessageResponse;\n    await completeAndEmitPhantomRedirectEvent(\n      {\n        args: {\n          message: pendingRequest.message,\n          signature: signData.signature,\n        },\n        event: 'phantomRedirectSignMessageComplete',\n      },\n      client\n    );\n  } else if (pendingRequest.method === 'signTransaction') {\n    const signData = decryptedData as PhantomSignTransactionResponse;\n    await completeAndEmitPhantomRedirectEvent(\n      {\n        args: { transaction: signData.transaction },\n        event: 'phantomRedirectSignTransactionComplete',\n      },\n      client\n    );\n  } else if (pendingRequest.method === 'signAllTransactions') {\n    const signData = decryptedData as PhantomSignAllTransactionsResponse;\n    await completeAndEmitPhantomRedirectEvent(\n      {\n        args: { transactions: signData.transactions },\n        event: 'phantomRedirectSignAllTransactionsComplete',\n      },\n      client\n    );\n  } else {\n    const signData = decryptedData as PhantomSignAndSendTransactionResponse;\n    await completeAndEmitPhantomRedirectEvent(\n      {\n        args: { signature: signData.signature },\n        event: 'phantomRedirectSignAndSendTransactionComplete',\n      },\n      client\n    );\n  }\n};\n","import { PHANTOM_DEEPLINK_BASE_URL } from '../../phantomRedirect.constants';\n\nexport type BuildPhantomDeepLinkParams = {\n  appUrl?: string;\n  cluster?: string;\n  dappPublicKey: string;\n  method: string;\n  nonce?: string;\n  payload?: string;\n  redirectUrl: string;\n};\n\n/**\n * Builds a Phantom wallet deep link URL for wallet operations.\n *\n * @param params.method - The operation method (connect, signMessage, signTransaction, etc.)\n * @param params.appUrl - Optional dApp URL shown in Phantom's UI\n * @param params.dappPublicKey - The dApp's base58-encoded public encryption key\n * @param params.redirectUrl - The URL to redirect back to after the operation\n * @param params.cluster - Optional Solana cluster (mainnet-beta, devnet, testnet)\n * @param params.payload - Optional encrypted payload for signing operations\n * @param params.nonce - Optional nonce for encrypted payload\n * @returns The complete Phantom deep link URL\n  * @notInstrumented\n */\nexport const buildPhantomDeepLink = ({\n  appUrl,\n  cluster,\n  dappPublicKey,\n  method,\n  nonce,\n  payload,\n  redirectUrl,\n}: BuildPhantomDeepLinkParams): URL => {\n  const url = new URL(`${PHANTOM_DEEPLINK_BASE_URL}/${method}`);\n\n  url.searchParams.set('dapp_encryption_public_key', dappPublicKey);\n  url.searchParams.set('redirect_link', redirectUrl);\n\n  if (appUrl) {\n    url.searchParams.set('app_url', appUrl);\n  }\n\n  if (cluster) {\n    url.searchParams.set('cluster', cluster);\n  }\n\n  if (payload) {\n    url.searchParams.set('payload', payload);\n  }\n\n  if (nonce) {\n    url.searchParams.set('nonce', nonce);\n  }\n\n  return url;\n};\n","import { getBuffer } from '@dynamic-labs-sdk/client/core';\nimport bs58 from 'bs58';\nimport nacl from 'tweetnacl';\n\nexport type EncryptPayloadParams = {\n  payload: Record<string, unknown>;\n  sharedSecret: string;\n};\n\nexport type EncryptedPayload = {\n  data: string;\n  nonce: string;\n};\n\n/**\n * Encrypts a payload using NaCl box encryption with a shared secret.\n *\n * @param params.payload - The payload object to encrypt\n * @param params.sharedSecret - The base58-encoded shared secret\n * @returns The encrypted data and nonce, both base58-encoded\n  * @notInstrumented\n */\nexport const encryptPayload = ({\n  payload,\n  sharedSecret,\n}: EncryptPayloadParams): EncryptedPayload => {\n  const nonce = nacl.randomBytes(nacl.box.nonceLength);\n  const payloadString = JSON.stringify(payload);\n  const payloadBytes = new Uint8Array(getBuffer().from(payloadString, 'utf8'));\n\n  const encrypted = nacl.box.after(\n    payloadBytes,\n    nonce,\n    bs58.decode(sharedSecret)\n  );\n\n  return {\n    data: bs58.encode(encrypted),\n    nonce: bs58.encode(nonce),\n  };\n};\n","import bs58 from 'bs58';\nimport nacl from 'tweetnacl';\n\nexport type NaClKeyPair = {\n  publicKey: string;\n  secretKey: string;\n};\n\n/**\n * Generates a new NaCl key pair for encryption.\n *\n * @returns A key pair with base58-encoded public and secret keys\n  * @notInstrumented\n */\nexport const generateNaClKeyPair = (): NaClKeyPair => {\n  const keyPair = nacl.box.keyPair();\n\n  return {\n    publicKey: bs58.encode(keyPair.publicKey),\n    secretKey: bs58.encode(keyPair.secretKey),\n  };\n};\n","import type { DynamicClient, WalletAccount } from '@dynamic-labs-sdk/client';\nimport { getActiveNetworkData } from '@dynamic-labs-sdk/client';\nimport { getNetworkProviders } from '@dynamic-labs-sdk/client/core';\n\ntype GetPhantomClusterParams =\n  | { dynamicClient: DynamicClient; walletAccount: WalletAccount }\n  | { dynamicClient: DynamicClient; walletAccount?: never };\n\n/**\n * Normalizes a cluster string to the value expected by Phantom's deep link protocol.\n * Our API returns \"mainnet\" but Phantom expects \"mainnet-beta\".\n */\n// eslint-disable-next-line custom-rules/require-single-object-param\nconst normalizeCluster = (cluster: string | undefined): string | undefined => {\n  if (cluster === 'mainnet') return 'mainnet-beta';\n  return cluster;\n};\n\n/**\n * Returns the Solana cluster name expected by Phantom's deep link protocol\n * (e.g. \"mainnet-beta\", \"devnet\", \"testnet\").\n *\n * - When a `walletAccount` is provided, reads the cluster from the active network\n *   data for that account.\n * - When no `walletAccount` is provided (e.g. during `connect` before an account\n *   exists), falls back to the first registered SOL network provider's cluster.\n *\n * Returns `undefined` if no cluster can be determined; Phantom will use the\n * wallet's default in that case.\n * @notInstrumented\n */\n// eslint-disable-next-line custom-rules/one-function-per-file\nexport const getPhantomCluster = async ({\n  dynamicClient,\n  walletAccount,\n}: GetPhantomClusterParams): Promise<string | undefined> => {\n  if (walletAccount) {\n    const { networkData } = await getActiveNetworkData(\n      { walletAccount },\n      dynamicClient\n    );\n\n    return normalizeCluster(networkData?.cluster);\n  }\n\n  const networkProviders = getNetworkProviders(dynamicClient);\n  const solProvider = networkProviders.find((p) => p.chain === 'SOL');\n\n  return normalizeCluster(solProvider?.cluster);\n};\n","import type { DynamicClient } from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\n\nimport type { PhantomEvents } from '../../phantomRedirect.broadcast.types';\n\n/**\n * Registers listeners for Phantom redirect events broadcast from other tabs\n * (e.g. the redirect-completion tab), using the crossTabBroadcast service.\n *\n * Returns a cleanup function that unregisters all listeners — call it when the\n * operation is no longer pending (e.g. in a promise `.finally()`).\n *\n * @param listeners - Map of event names to handler functions\n * @param client - The Dynamic client instance\n * @returns Cleanup function that removes all registered listeners\n  * @notInstrumented\n */\nexport const listenForPhantomBroadcast = (\n  listeners: Partial<PhantomEvents>,\n  client: DynamicClient\n): (() => void) => {\n  const { crossTabBroadcast } = getCore(client);\n\n  const wrappedListeners = Object.entries(listeners).map(\n    ([event, listener]) => {\n      const wrapped = (args?: unknown) => {\n        (listener as (args: unknown) => void)(\n          args as Parameters<PhantomEvents[keyof PhantomEvents]>[0]\n        );\n      };\n\n      crossTabBroadcast.on(event, wrapped);\n\n      return { event, wrapped };\n    }\n  );\n\n  return () => {\n    wrappedListeners.forEach(({ event, wrapped }) => {\n      crossTabBroadcast.off(event, wrapped);\n    });\n  };\n};\n","import type { DynamicClient } from '@dynamic-labs-sdk/client';\nimport { getActiveNetworkData, onceEvent } from '@dynamic-labs-sdk/client';\nimport {\n  assertDefined,\n  createDeferredPromise,\n  formatWalletProviderGroupKey,\n  formatWalletProviderKey,\n  getActiveNetworkIdFromLastKnownRegistry,\n  getBuffer,\n  getCore,\n  randomString,\n} from '@dynamic-labs-sdk/client/core';\nimport { WalletProviderEnum } from '@dynamic-labs/sdk-api-core';\nimport { Transaction, VersionedTransaction } from '@solana/web3.js';\nimport bs58 from 'bs58';\n\nimport { getSolanaConnection } from '../../getSolanaConnection';\nimport type { SolanaWalletProvider } from '../../SolanaWalletProvider.types';\nimport { solanaConfirmTransaction } from '../../utils/solanaConfirmTransaction';\nimport { solanaExecuteSwapTransaction } from '../../utils/solanaExecuteSwapTransaction';\nimport { solanaTransferAmount } from '../../utils/solanaTransferAmount';\nimport { NoPhantomSessionError } from '../errors/NoPhantomSessionError';\nimport type { PhantomEvents } from '../phantomRedirect.broadcast.types';\nimport type {\n  PhantomPendingRequest,\n  PhantomSession,\n} from '../PhantomRedirectWalletProvider.types';\nimport { pendingRequestStorageKeySchema } from '../storage/pendingRequestStorageSchema';\nimport { phantomSessionStorageKeySchema } from '../storage/phantomSessionStorageSchema';\nimport { buildPhantomDeepLink } from '../utils/buildPhantomDeepLink';\nimport { encryptPayload } from '../utils/crypto/encryptPayload';\nimport { generateNaClKeyPair } from '../utils/crypto/generateNaClKeyPair';\nimport { getPhantomCluster } from '../utils/getPhantomCluster/getPhantomCluster';\nimport { getPhantomOriginTab } from '../utils/getPhantomOriginTab';\nimport { listenForPhantomBroadcast } from '../utils/listenForPhantomBroadcast';\n\nexport type CreatePhantomRedirectWalletProviderParams = {\n  baseRedirectUrl: string;\n  dynamicClient: DynamicClient;\n};\n\n/**\n * Extracts the dApp URL from a redirect URL.\n */\n// eslint-disable-next-line custom-rules/require-single-object-param\nconst extractDappUrl = (redirectUrl: string): string => {\n  const url = new URL(redirectUrl);\n\n  return `${url.protocol}//${url.host}`;\n};\n\n/**\n * Creates a Phantom redirect-based Solana wallet provider.\n *\n * This wallet provider uses Phantom's deep link protocol for mobile wallet\n * interactions with end-to-end encryption using NaCl.\n *\n * @param params.dynamicClient - The Dynamic client instance\n * @returns A Phantom redirect wallet provider\n * @notInstrumented\n */\n// eslint-disable-next-line custom-rules/one-function-per-file\nexport const createPhantomRedirectWalletProvider = ({\n  baseRedirectUrl,\n  dynamicClient,\n}: CreatePhantomRedirectWalletProviderParams): SolanaWalletProvider => {\n  const core = getCore(dynamicClient);\n\n  const walletProviderType = WalletProviderEnum.DeepLink;\n\n  const key = formatWalletProviderKey({\n    chain: 'SOL',\n    displayName: 'Phantom',\n    walletProviderType,\n  });\n\n  const groupKey = formatWalletProviderGroupKey('Phantom');\n\n  const metadata = {\n    displayName: 'Phantom',\n    icon: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiB2aWV3Qm94PSIwIDAgMTA4IDEwOCIgZmlsbD0ibm9uZSI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ni41MjY3IDY5LjkyMjlDNDIuMDA1NCA3Ni44NTA5IDM0LjQyOTIgODUuNjE4MiAyNC4zNDggODUuNjE4MkMxOS41ODI0IDg1LjYxODIgMTUgODMuNjU2MyAxNSA3NS4xMzQyQzE1IDUzLjQzMDUgNDQuNjMyNiAxOS44MzI3IDcyLjEyNjggMTkuODMyN0M4Ny43NjggMTkuODMyNyA5NCAzMC42ODQ2IDk0IDQzLjAwNzlDOTQgNTguODI1OCA4My43MzU1IDc2LjkxMjIgNzMuNTMyMSA3Ni45MTIyQzcwLjI5MzkgNzYuOTEyMiA2OC43MDUzIDc1LjEzNDIgNjguNzA1MyA3Mi4zMTRDNjguNzA1MyA3MS41NzgzIDY4LjgyNzUgNzAuNzgxMiA2OS4wNzE5IDY5LjkyMjlDNjUuNTg5MyA3NS44Njk5IDU4Ljg2ODUgODEuMzg3OCA1Mi41NzU0IDgxLjM4NzhDNDcuOTkzIDgxLjM4NzggNDUuNjcxMyA3OC41MDYzIDQ1LjY3MTMgNzQuNDU5OEM0NS42NzEzIDcyLjk4ODQgNDUuOTc2OCA3MS40NTU2IDQ2LjUyNjcgNjkuOTIyOVpNODMuNjc2MSA0Mi41Nzk0QzgzLjY3NjEgNDYuMTcwNCA4MS41NTc1IDQ3Ljk2NTggNzkuMTg3NSA0Ny45NjU4Qzc2Ljc4MTYgNDcuOTY1OCA3NC42OTg5IDQ2LjE3MDQgNzQuNjk4OSA0Mi41Nzk0Qzc0LjY5ODkgMzguOTg4NSA3Ni43ODE2IDM3LjE5MzEgNzkuMTg3NSAzNy4xOTMxQzgxLjU1NzUgMzcuMTkzMSA4My42NzYxIDM4Ljk4ODUgODMuNjc2MSA0Mi41Nzk0Wk03MC4yMTAzIDQyLjU3OTVDNzAuMjEwMyA0Ni4xNzA0IDY4LjA5MTYgNDcuOTY1OCA2NS43MjE2IDQ3Ljk2NThDNjMuMzE1NyA0Ny45NjU4IDYxLjIzMyA0Ni4xNzA0IDYxLjIzMyA0Mi41Nzk1QzYxLjIzMyAzOC45ODg1IDYzLjMxNTcgMzcuMTkzMSA2NS43MjE2IDM3LjE5MzFDNjguMDkxNiAzNy4xOTMxIDcwLjIxMDMgMzguOTg4NSA3MC4yMTAzIDQyLjU3OTVaIiBmaWxsPSIjRkZGREY4Ii8+Cjwvc3ZnPg==',\n  };\n\n  // Helper to get session from storage\n  const getSession = async (): Promise<PhantomSession> => {\n    const session = await core.storage.getItem(phantomSessionStorageKeySchema);\n\n    if (!session) {\n      throw new NoPhantomSessionError();\n    }\n\n    return session;\n  };\n\n  // Helper to set pending request in storage\n  const setPendingRequest = async (request: PhantomPendingRequest) => {\n    await core.storage.setItem(pendingRequestStorageKeySchema, request);\n  };\n\n  type SetupPhantomBroadcastListenersParams<\n    K extends keyof PhantomEvents,\n    E extends keyof PhantomEvents\n  > = {\n    completeEvent: K;\n    deferredPromise: { promise: Promise<unknown> };\n    errorEvent: E;\n    onComplete: (args: Parameters<PhantomEvents[K]>[0]) => void;\n    onError: (args: Parameters<PhantomEvents[E]>[0]) => void;\n  };\n\n  /**\n   * Registers listeners for both delivery paths Phantom uses depending on platform:\n   * - In mobile native, we get redirected back to the same context, so onceEvent suffices.\n   * - In mobile browsers, we get redirected back to a new tab, so a BroadcastChannel listener\n   *   is also needed to receive the completion event from that tab.\n   *\n   * The broadcast channel is closed once the deferred promise settles.\n   */\n  const setupPhantomListeners = <\n    K extends keyof PhantomEvents,\n    E extends keyof PhantomEvents\n  >({\n    completeEvent,\n    deferredPromise,\n    errorEvent,\n    onComplete,\n    onError,\n  }: SetupPhantomBroadcastListenersParams<K, E>): void => {\n    // Mark this client context as the origin so completePhantomRedirect can\n    // distinguish it from the clone tab opened by Phantom in a mobile browser.\n    getPhantomOriginTab(dynamicClient).isOriginTab = true;\n\n    onceEvent({ event: completeEvent, listener: onComplete }, dynamicClient);\n    onceEvent({ event: errorEvent, listener: onError }, dynamicClient);\n\n    const closeChannel = listenForPhantomBroadcast(\n      {\n        [completeEvent]: onComplete,\n        [errorEvent]: onError,\n      },\n      dynamicClient\n    );\n\n    void deferredPromise.promise\n      .finally(() => {\n        core.logger.debug(\n          '[PHANTOM] setupPhantomListeners: deferred promise settled, closing channel'\n        );\n        closeChannel();\n      })\n      .catch(() => {\n        // Rejection already propagates via deferredPromise.promise — suppress here\n      });\n  };\n\n  const connect: SolanaWalletProvider['connect'] = async () => {\n    const redirectUrl = baseRedirectUrl;\n\n    const { publicKey: dappPublicKey, secretKey: dappSecretKey } =\n      generateNaClKeyPair();\n    const requestId = randomString({ length: 32 });\n\n    await setPendingRequest({\n      dappPublicKey,\n      dappSecretKey,\n      method: 'connect',\n      requestId,\n      timestamp: Date.now(),\n    });\n\n    const deferredPromise = createDeferredPromise<{\n      addresses: Array<{ address: string; publicKey: string }>;\n    }>();\n\n    setupPhantomListeners({\n      completeEvent: 'phantomRedirectConnectionComplete',\n      deferredPromise,\n      errorEvent: 'phantomRedirectConnectionError',\n      onComplete: ({ address, publicKey }) => {\n        core.logger.debug('[PHANTOM] connect: onComplete called', { address });\n        deferredPromise.resolve({ addresses: [{ address, publicKey }] });\n      },\n      onError: ({ error }) => {\n        core.logger.debug('[PHANTOM] connect: onError called', { error });\n        deferredPromise.reject(error);\n      },\n    });\n\n    const cluster = await getPhantomCluster({ dynamicClient });\n\n    const deepLinkUrl = buildPhantomDeepLink({\n      appUrl: extractDappUrl(redirectUrl),\n      cluster,\n      dappPublicKey,\n      method: 'connect',\n      redirectUrl,\n    });\n\n    core.logger.debug('[PHANTOM] connect: opening deeplink', { redirectUrl });\n\n    await core.openDeeplink(deepLinkUrl.toString());\n\n    return deferredPromise.promise;\n  };\n\n  const destroy: SolanaWalletProvider['destroy'] = async () => {\n    try {\n      const session = await getSession();\n      const redirectUrl = baseRedirectUrl;\n\n      const { data, nonce } = encryptPayload({\n        payload: { session: session.sessionToken },\n        sharedSecret: session.sharedSecret,\n      });\n\n      const requestId = randomString({ length: 32 });\n\n      await setPendingRequest({\n        dappPublicKey: session.dappPublicKey,\n        dappSecretKey: session.dappSecretKey,\n        method: 'disconnect',\n        requestId,\n        timestamp: Date.now(),\n      });\n\n      const deferredPromise = createDeferredPromise<void>();\n\n      setupPhantomListeners({\n        completeEvent: 'phantomRedirectDisconnectComplete',\n        deferredPromise,\n        errorEvent: 'phantomRedirectDisconnectError',\n        onComplete: async () => {\n          await core.storage.removeItem(phantomSessionStorageKeySchema);\n          deferredPromise.resolve();\n        },\n        onError: ({ error }) => {\n          deferredPromise.reject(error);\n        },\n      });\n\n      const deepLinkUrl = buildPhantomDeepLink({\n        appUrl: extractDappUrl(redirectUrl),\n        dappPublicKey: session.dappPublicKey,\n        method: 'disconnect',\n        nonce,\n        payload: data,\n        redirectUrl,\n      });\n\n      await core.openDeeplink(deepLinkUrl.toString());\n\n      await deferredPromise.promise;\n    } catch (err) {\n      core.logger.error(`[${key}] destroy: remote signal failed`, err);\n    }\n  };\n\n  const getActiveNetworkId: SolanaWalletProvider['getActiveNetworkId'] =\n    async () =>\n      getActiveNetworkIdFromLastKnownRegistry({\n        client: dynamicClient,\n        walletProviderKey: key,\n      });\n\n  const getConnectedAddresses: SolanaWalletProvider['getConnectedAddresses'] =\n    async () => {\n      const session = await getSession();\n\n      return {\n        addresses: [session.walletAddress],\n      };\n    };\n\n  const signMessage: SolanaWalletProvider['signMessage'] = async ({\n    message,\n    walletAccount,\n  }) => {\n    assertDefined(\n      walletAccount,\n      'Wallet account is required for Phantom redirect'\n    );\n\n    const redirectUrl = baseRedirectUrl;\n    const session = await getSession();\n\n    const messageBase58 = bs58.encode(\n      new Uint8Array(getBuffer().from(message))\n    );\n\n    const { data, nonce } = encryptPayload({\n      payload: { message: messageBase58, session: session.sessionToken },\n      sharedSecret: session.sharedSecret,\n    });\n\n    const requestId = randomString({ length: 32 });\n\n    await setPendingRequest({\n      dappPublicKey: session.dappPublicKey,\n      dappSecretKey: session.dappSecretKey,\n      message,\n      method: 'signMessage',\n      requestId,\n      timestamp: Date.now(),\n      walletAddress: walletAccount.address,\n    });\n\n    const deferredPromise = createDeferredPromise<{ signature: string }>();\n\n    setupPhantomListeners({\n      completeEvent: 'phantomRedirectSignMessageComplete',\n      deferredPromise,\n      errorEvent: 'phantomRedirectSignMessageError',\n      onComplete: ({ signature }) => {\n        deferredPromise.resolve({ signature });\n      },\n      onError: ({ error }) => {\n        deferredPromise.reject(error);\n      },\n    });\n\n    const cluster = await getPhantomCluster({ dynamicClient, walletAccount });\n\n    const deepLinkUrl = buildPhantomDeepLink({\n      appUrl: extractDappUrl(redirectUrl),\n      cluster,\n      dappPublicKey: session.dappPublicKey,\n      method: 'signMessage',\n      nonce,\n      payload: data,\n      redirectUrl,\n    });\n\n    await core.openDeeplink(deepLinkUrl.toString());\n\n    return deferredPromise.promise;\n  };\n\n  const signTransaction: SolanaWalletProvider['signTransaction'] = async ({\n    transaction,\n    walletAccount,\n  }) => {\n    assertDefined(\n      walletAccount,\n      'Wallet account is required for Phantom redirect'\n    );\n\n    const redirectUrl = baseRedirectUrl;\n    const session = await getSession();\n\n    const serialized =\n      transaction instanceof VersionedTransaction\n        ? transaction.serialize()\n        : (transaction as Transaction).serialize({\n            requireAllSignatures: false,\n            verifySignatures: false,\n          });\n\n    const transactionBase58 = bs58.encode(new Uint8Array(serialized));\n\n    const { data, nonce } = encryptPayload({\n      payload: {\n        session: session.sessionToken,\n        transaction: transactionBase58,\n      },\n      sharedSecret: session.sharedSecret,\n    });\n\n    const requestId = randomString({ length: 32 });\n\n    await setPendingRequest({\n      dappPublicKey: session.dappPublicKey,\n      dappSecretKey: session.dappSecretKey,\n      method: 'signTransaction',\n      requestId,\n      timestamp: Date.now(),\n      walletAddress: walletAccount.address,\n    });\n\n    const deferredPromise = createDeferredPromise<{\n      signedTransaction: typeof transaction;\n    }>();\n\n    const deserializeTransaction = ({\n      transaction: signedTransactionBase58,\n    }: {\n      transaction: string;\n    }) => {\n      const decoded = bs58.decode(signedTransactionBase58);\n      const signedTransaction = (\n        transaction instanceof VersionedTransaction\n          ? VersionedTransaction.deserialize(decoded)\n          : Transaction.from(decoded)\n      ) as typeof transaction;\n\n      deferredPromise.resolve({ signedTransaction });\n    };\n\n    setupPhantomListeners({\n      completeEvent: 'phantomRedirectSignTransactionComplete',\n      deferredPromise,\n      errorEvent: 'phantomRedirectSignTransactionError',\n      onComplete: deserializeTransaction,\n      onError: ({ error }) => {\n        deferredPromise.reject(error);\n      },\n    });\n\n    const cluster = await getPhantomCluster({ dynamicClient, walletAccount });\n\n    const deepLinkUrl = buildPhantomDeepLink({\n      appUrl: extractDappUrl(redirectUrl),\n      cluster,\n      dappPublicKey: session.dappPublicKey,\n      method: 'signTransaction',\n      nonce,\n      payload: data,\n      redirectUrl,\n    });\n\n    await core.openDeeplink(deepLinkUrl.toString());\n\n    return deferredPromise.promise;\n  };\n\n  const signAllTransactions: SolanaWalletProvider['signAllTransactions'] =\n    async ({ transactions, walletAccount }) => {\n      assertDefined(\n        walletAccount,\n        'Wallet account is required for Phantom redirect'\n      );\n\n      const redirectUrl = baseRedirectUrl;\n      const session = await getSession();\n\n      const serialized = transactions.map((tx) =>\n        tx instanceof VersionedTransaction\n          ? tx.serialize()\n          : (tx as Transaction).serialize({\n              requireAllSignatures: false,\n              verifySignatures: false,\n            })\n      );\n\n      const transactionsBase58 = serialized.map((s) =>\n        bs58.encode(new Uint8Array(s))\n      );\n\n      const { data, nonce } = encryptPayload({\n        payload: {\n          session: session.sessionToken,\n          transactions: transactionsBase58,\n        },\n        sharedSecret: session.sharedSecret,\n      });\n\n      const requestId = randomString({ length: 32 });\n\n      await setPendingRequest({\n        dappPublicKey: session.dappPublicKey,\n        dappSecretKey: session.dappSecretKey,\n        method: 'signAllTransactions',\n        requestId,\n        timestamp: Date.now(),\n        walletAddress: walletAccount.address,\n      });\n\n      const deferredPromise = createDeferredPromise<{\n        signedTransactions: typeof transactions;\n      }>();\n\n      const deserializeTransactions = ({\n        transactions: signedTransactionsBase58,\n      }: {\n        transactions: string[];\n      }) => {\n        const signedTransactions = signedTransactionsBase58.map(\n          (txBase58, i) => {\n            const decoded = bs58.decode(txBase58);\n\n            return transactions[i] instanceof VersionedTransaction\n              ? VersionedTransaction.deserialize(decoded)\n              : Transaction.from(decoded);\n          }\n        ) as typeof transactions;\n\n        deferredPromise.resolve({ signedTransactions });\n      };\n\n      setupPhantomListeners({\n        completeEvent: 'phantomRedirectSignAllTransactionsComplete',\n        deferredPromise,\n        errorEvent: 'phantomRedirectSignAllTransactionsError',\n        onComplete: deserializeTransactions,\n        onError: ({ error }) => {\n          deferredPromise.reject(error);\n        },\n      });\n\n      const cluster = await getPhantomCluster({ dynamicClient, walletAccount });\n\n      const deepLinkUrl = buildPhantomDeepLink({\n        appUrl: extractDappUrl(redirectUrl),\n        cluster,\n        dappPublicKey: session.dappPublicKey,\n        method: 'signAllTransactions',\n        nonce,\n        payload: data,\n        redirectUrl,\n      });\n\n      await core.openDeeplink(deepLinkUrl.toString());\n\n      return deferredPromise.promise;\n    };\n\n  // Phantom's signAndSendTransaction deeplink is deprecated. We implement it by\n  // calling signTransaction (Phantom signs only) and then broadcasting the\n  // signed transaction ourselves via the Solana RPC — the same pattern used by\n  // the WaaS provider.\n  const signAndSendTransaction: SolanaWalletProvider['signAndSendTransaction'] =\n    async ({ options, transaction, walletAccount }) => {\n      const { signedTransaction } = await signTransaction({\n        transaction,\n        walletAccount,\n      });\n\n      const { networkData } = await getActiveNetworkData(\n        { walletAccount },\n        dynamicClient\n      );\n\n      assertDefined(\n        networkData,\n        'Network data is required to broadcast transaction'\n      );\n\n      const connection = getSolanaConnection({ networkData });\n\n      const rawTransaction = signedTransaction.serialize();\n\n      const signature = await connection.sendRawTransaction(\n        rawTransaction,\n        options\n      );\n\n      return { signature };\n    };\n\n  return {\n    chain: 'SOL',\n    confirmTransaction: (args) => solanaConfirmTransaction(args, dynamicClient),\n    connect,\n    destroy,\n    executeSwapTransaction: (args) =>\n      solanaExecuteSwapTransaction(args, dynamicClient),\n    getActiveNetworkId,\n    getConnectedAddresses,\n    groupKey,\n    key,\n    metadata,\n    signAllTransactions,\n    signAndSendTransaction,\n    signMessage,\n    signTransaction,\n    transferAmount: (args) => solanaTransferAmount(args, dynamicClient),\n    walletProviderType,\n  };\n};\n","import type { DynamicClient } from '@dynamic-labs-sdk/client';\nimport { getCore, getDefaultClient } from '@dynamic-labs-sdk/client/core';\n\nimport { pendingRequestStorageKeySchema } from '../storage/pendingRequestStorageSchema';\n\nexport type DetectPhantomRedirectParams = {\n  url: URL;\n};\n\n/**\n * Detects if the current URL is a Phantom wallet redirect.\n *\n * This function examines the URL parameters to determine if it contains\n * redirect data from a Phantom wallet deep link operation, and validates\n * that there is a corresponding pending request in storage.\n *\n * Most Phantom callbacks include recognizable query parameters:\n * - **Connect**: `phantom_encryption_public_key`\n * - **Sign** (signMessage, signTransaction, etc.): `nonce` + `data`\n * - **Error** (any method): `errorCode`\n *\n * **Disconnect is the exception**: on success, Phantom redirects back to the\n * bare `redirect_link` with NO query parameters at all. To detect this case,\n * we fall back to checking whether a pending disconnect request exists in\n * storage.\n *\n * @example\n * ```ts\n * const url = new URL(window.location.href);\n * const isPhantomRedirect = await detectPhantomRedirect({ url });\n * ```\n *\n * @param params.url - The URL to check for Phantom redirect parameters\n * @param client - The Dynamic client instance\n * @returns A promise that resolves to true if the URL is a valid Phantom redirect, false otherwise\n * @see completePhantomRedirect\n * @see addPhantomRedirectSolanaExtension\n * @notInstrumented\n */\nexport const detectPhantomRedirect = async (\n  { url }: DetectPhantomRedirectParams,\n  client: DynamicClient = getDefaultClient()\n): Promise<boolean> => {\n  const core = getCore(client);\n\n  // Phantom's connect callback includes phantom_encryption_public_key.\n  // Sign callbacks (signMessage, signTransaction, etc.) only include nonce + data\n  // — no phantom_encryption_public_key — because the session is already established.\n  // Error callbacks from any method include errorCode.\n  const hasPhantomParams =\n    url.searchParams.has('phantom_encryption_public_key') ||\n    url.searchParams.has('errorCode') ||\n    (url.searchParams.has('nonce') && url.searchParams.has('data'));\n\n  await core.initTrack.waitForAll();\n\n  const pendingRequest = await core.storage.getItem(\n    pendingRequestStorageKeySchema\n  );\n\n  if (!pendingRequest) {\n    return false;\n  }\n\n  if (hasPhantomParams) {\n    return true;\n  }\n\n  // Phantom's disconnect callback is unique: on success it redirects back to\n  // the app with NO query parameters at all — no data, nonce,\n  // phantom_encryption_public_key, or errorCode. The URL is just the bare\n  // redirect_link. A pending disconnect request in storage confirms this\n  // empty redirect is the disconnect callback.\n  return pendingRequest.method === 'disconnect';\n};\n","import type { DynamicClient } from '@dynamic-labs-sdk/client';\nimport { onEvent, onceEvent } from '@dynamic-labs-sdk/client';\nimport {\n  WalletProviderPriority,\n  getCore,\n  getDefaultClient,\n  getWalletProviderRegistry,\n  hasExtension,\n  registerExtension,\n} from '@dynamic-labs-sdk/client/core';\n\nimport { registerSolanaNetworkProviderBuilder } from '../../registerSolanaNetworkProviderBuilder';\nimport { completePhantomRedirect } from '../completePhantomRedirect';\nimport { createPhantomRedirectWalletProvider } from '../createPhantomRedirectWalletProvider';\nimport { detectPhantomRedirect } from '../detectPhantomRedirect';\n\nexport const PHANTOM_REDIRECT_SOLANA_EXTENSION_KEY = 'phantomRedirectSolana';\n\nexport type AddPhantomRedirectSolanaExtensionParams = {\n  /**\n   * When `true`, the extension will **not** automatically detect or complete\n   * Phantom redirects on initialization. Use this when you want to call\n   * `completePhantomRedirect` yourself at a custom point in your app's\n   * lifecycle.\n   *\n   * When `disableAutoRedirectCompletion` is `true` the `onCloseTab` callback\n   * is not auto-registered by the extension, so you are responsible for\n   * listening to `phantomRedirectCloseTab` manually if needed.\n   */\n  disableAutoRedirectCompletion?: boolean;\n\n  /**\n   * Called when the SDK determines that the current tab is a **clone tab** —\n   * a new browser tab that Phantom opened to deliver the redirect callback on\n   * mobile browsers. Once this fires, the clone tab has served its purpose and\n   * should be closed so the user is returned to the originating tab.\n   *\n   * ### Typical usage\n   *\n   * ```ts\n   * addPhantomRedirectSolanaExtension({\n   *   url: new URL(window.location.href),\n   *   onCloseTab: () => window.close(),\n   * });\n   * ```\n   *\n   * ### Opting out\n   *\n   * If you deliberately do not want automatic tab closing (e.g. you handle\n   * navigation yourself), pass an explicit no-op to make the intent clear:\n   *\n   * ```ts\n   * onCloseTab: () => {}\n   * ```\n   *\n   * ### When is this NOT called?\n   *\n   * - **Mobile native** (React Native, Capacitor, etc.): the deep link is\n   *   handled in the same JavaScript context as the originating page, so no\n   *   clone tab is created and this callback is never invoked.\n   * - **`disableAutoRedirectCompletion: true`**: the extension does not\n   *   auto-register this callback. Subscribe to `phantomRedirectCloseTab`\n   *   yourself in that case.\n   *\n   * ### Advanced: subscribing directly to the event\n   *\n   * For more control you can listen to the underlying `phantomRedirectCloseTab`\n   * event directly. This is useful when you need to perform async work before\n   * closing:\n   *\n   * ```ts\n   * onEvent(\n   *   { event: 'phantomRedirectCloseTab', listener: () => {\n   *     await flushAnalytics();\n   *     window.close();\n   *   }},\n   *   dynamicClient\n   * );\n   * ```\n   */\n  onCloseTab: () => void;\n\n  /**\n   * The current page URL. Used both to detect an incoming Phantom redirect\n   * callback and to derive the `baseRedirectUrl` for deep links.\n   */\n  url: URL;\n};\n\n/**\n * Adds the Phantom redirect Solana extension to the Dynamic client.\n *\n * ### What this extension does\n *\n * This extension enables Phantom wallet integration via deep link redirects,\n * designed for mobile environments where a browser extension is not available.\n *\n * On initialization it:\n * 1. Registers the internal Dynamic extension logic handlers.\n * 2. Detects whether the current URL is a Phantom redirect callback and, if\n *    so, completes the pending operation (decrypt response, emit events,\n *    broadcast to originating tab).\n * 3. Sets up the `onCloseTab` listener so that the clone tab is closed after completion.\n *\n * ### Mobile browser redirect flow\n *\n * ```\n * [Tab 1 — your app]              [Phantom app / PWA]      [Tab 2 — clone]\n *   connect()\n *   openDeeplink(phantomUrl) ─────────────►\n *                                  user approves\n *                                  redirect to app ───────────────►\n *                                                           completePhantomRedirect()\n *                                                           broadcastPhantomEvent()\n *                                                           emits phantomRedirectCloseTab\n *                                                           onCloseTab() → window.close()\n *   BroadcastChannel receives ◄──────────────────────────────────────────────\n *   deferredPromise.resolve()\n * ```\n *\n * ### Mobile native flow (React Native / Capacitor)\n *\n * The deep link is delivered to the same JavaScript context, so `Tab 2` never\n * exists. `completePhantomRedirect` detects this via a `sessionStorage`\n * marker written during request initiation and does **not** emit\n * `phantomRedirectCloseTab`.\n *\n * @example\n * ```ts\n * addPhantomRedirectSolanaExtension({\n *   url: new URL(window.location.href),\n *   onCloseTab: () => window.close(),\n * });\n * ```\n *\n * @param params.url - The current page URL\n * @param params.onCloseTab - Callback invoked when the clone tab should close\n * @param params.disableAutoRedirectCompletion - Skip auto detection/completion\n * @param [client] - The Dynamic client. Only required for multiple clients.\n * @returns void\n * @see completePhantomRedirect\n * @see detectPhantomRedirect\n * @notInstrumented\n */\nexport const addPhantomRedirectSolanaExtension = async (\n  {\n    disableAutoRedirectCompletion,\n    onCloseTab,\n    url,\n  }: AddPhantomRedirectSolanaExtensionParams,\n  client: DynamicClient = getDefaultClient()\n): Promise<void> => {\n  if (\n    hasExtension(\n      { extensionKey: PHANTOM_REDIRECT_SOLANA_EXTENSION_KEY },\n      client\n    )\n  ) {\n    getCore(client).logger.debug(\n      '[PHANTOM] addPhantomRedirectSolanaExtension: already registered, skipping'\n    );\n    return;\n  }\n\n  registerExtension(\n    { extensionKey: PHANTOM_REDIRECT_SOLANA_EXTENSION_KEY },\n    client\n  );\n  registerSolanaNetworkProviderBuilder(client);\n\n  const core = getCore(client);\n\n  if (!disableAutoRedirectCompletion) {\n    const isRedirect = await detectPhantomRedirect({ url }, client);\n\n    if (isRedirect) {\n      // Register the close-tab handler before completion starts so it is\n      // guaranteed to be in place when completePhantomRedirect emits the event.\n      onceEvent(\n        { event: 'phantomRedirectCloseTab', listener: onCloseTab },\n        client\n      );\n\n      core.initTrack.track({\n        name: 'phantomRedirectCompletion',\n        promise: completePhantomRedirect({ url }, client).catch((error) => {\n          core.logger.debug(\n            '[PHANTOM] addPhantomRedirectSolanaExtension: completion failed',\n            { error }\n          );\n          core.logger.error('Phantom redirect completion failed:', error);\n        }),\n      });\n    }\n  }\n\n  const baseRedirectUrl = `${url.protocol}//${url.host}${url.pathname}`;\n\n  const walletProvider = createPhantomRedirectWalletProvider({\n    baseRedirectUrl,\n    dynamicClient: client,\n  });\n\n  const walletProviderRegistry = getWalletProviderRegistry(client);\n\n  const isConflictingProvider = (provider: {\n    chain: string;\n    groupKey: string;\n    key: string;\n  }) =>\n    provider.chain === walletProvider.chain &&\n    provider.groupKey === walletProvider.groupKey &&\n    provider.key !== walletProvider.key;\n\n  const existingConflict = walletProviderRegistry\n    .listProviders()\n    .find(isConflictingProvider);\n\n  if (existingConflict) {\n    core.logger.debug(\n      '[PHANTOM] addPhantomRedirectSolanaExtension: skipping registration, conflicting provider exists',\n      { conflictingKey: existingConflict.key }\n    );\n    return;\n  }\n\n  walletProviderRegistry.register({\n    priority: WalletProviderPriority.WINDOW_INJECT,\n    walletProvider,\n  });\n\n  const removeListener = onEvent(\n    {\n      event: 'walletProviderRegistered',\n      listener: ({ walletProvider: newProvider }) => {\n        if (isConflictingProvider(newProvider)) {\n          core.logger.debug(\n            '[PHANTOM] addPhantomRedirectSolanaExtension: unregistering, conflicting provider registered',\n            { conflictingKey: newProvider.key }\n          );\n          walletProviderRegistry.unregister(walletProvider.key);\n          removeListener();\n        }\n      },\n    },\n    client\n  );\n};\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { getWalletProviderFromWalletAccount } from '@dynamic-labs-sdk/client/core';\nimport type { Transaction, VersionedTransaction } from '@solana/web3.js';\n\nimport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nimport { NotSolanaProviderError } from '../errors/NotSolanaProviderError';\nimport { isSolanaWalletProvider } from '../isSolanaWalletProvider';\n\ntype SignAllTransactionsParams = {\n  transactions: (Transaction | VersionedTransaction)[];\n  walletAccount: SolanaWalletAccount;\n};\n\n/**\n * Signs multiple Solana transactions in a single call.\n *\n * @example\n * ```ts\n * const { signedTransactions } = await signAllTransactions({\n *   walletAccount: solAccount,\n *   transactions: [tx1, tx2, tx3],\n * });\n * ```\n *\n * @param params.transactions - The transactions to sign.\n * @param params.walletAccount - The wallet account to sign the transactions with.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns An object containing the signed transactions.\n * @throws {NotSolanaProviderError} If the wallet provider is not a Solana provider.\n * @see signTransaction\n * @see signAndSendTransaction\n * @notInstrumented\n */\nexport const signAllTransactions = async (\n  { walletAccount, transactions }: SignAllTransactionsParams,\n  client = getDefaultClient()\n): Promise<{ signedTransactions: (Transaction | VersionedTransaction)[] }> => {\n  const provider = getWalletProviderFromWalletAccount(\n    {\n      walletAccount,\n    },\n    client\n  );\n\n  if (!isSolanaWalletProvider(provider)) {\n    throw new NotSolanaProviderError({ providerKey: provider.key });\n  }\n\n  return provider.signAllTransactions({ transactions, walletAccount });\n};\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport {\n  MethodNotImplementedError,\n  getWalletProviderFromWalletAccount,\n} from '@dynamic-labs-sdk/client/core';\nimport type {\n  SendOptions,\n  Transaction,\n  VersionedTransaction,\n} from '@solana/web3.js';\n\nimport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nimport { isSolanaWalletProvider } from '../isSolanaWalletProvider';\nimport { NotSolanaProviderError } from '../errors/NotSolanaProviderError';\n\ntype SignAndSendSponsoredTransactionParams = {\n  options?: SendOptions;\n  transaction: Transaction | VersionedTransaction;\n  walletAccount: SolanaWalletAccount;\n};\n\n/**\n * Signs and sends a sponsored Solana transaction.\n * The transaction will be sponsored via Dynamic's gas sponsorship API.\n *\n * @example\n * ```ts\n * const { signature } = await signAndSendSponsoredTransaction({\n *   walletAccount: solAccount,\n *   transaction,\n * });\n * ```\n *\n * @param params.transaction - The transaction to sponsor, sign, and send.\n * @param params.walletAccount - The wallet account to sign and send the transaction with.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns An object containing the signature.\n * @throws {NotSolanaProviderError} If the wallet provider is not a Solana provider.\n * @throws {MethodNotImplementedError} If the wallet provider does not implement signAndSendSponsoredTransaction.\n * @see signAndSendTransaction\n * @see isSolanaGasSponsorshipEnabled\n * @notInstrumented\n */\nexport const signAndSendSponsoredTransaction = async (\n  {\n    walletAccount,\n    transaction,\n    options,\n  }: SignAndSendSponsoredTransactionParams,\n  client = getDefaultClient()\n): Promise<{ signature: string }> => {\n  const provider = getWalletProviderFromWalletAccount(\n    {\n      walletAccount,\n    },\n    client\n  );\n\n  if (!isSolanaWalletProvider(provider)) {\n    throw new NotSolanaProviderError({ providerKey: provider.key });\n  }\n\n  if (!provider.signAndSendSponsoredTransaction) {\n    throw new MethodNotImplementedError('signAndSendSponsoredTransaction');\n  }\n\n  return provider.signAndSendSponsoredTransaction({\n    options,\n    transaction,\n    walletAccount,\n  });\n};\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { getWalletProviderFromWalletAccount } from '@dynamic-labs-sdk/client/core';\nimport type { Transaction, VersionedTransaction } from '@solana/web3.js';\n\nimport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nimport { NotSolanaProviderError } from '../errors/NotSolanaProviderError';\nimport { isSolanaWalletProvider } from '../isSolanaWalletProvider';\n\ntype SignTransactionParams = {\n  transaction: Transaction | VersionedTransaction;\n  walletAccount: SolanaWalletAccount;\n};\n\n/**\n * Signs a Solana transaction without sending it.\n *\n * @example\n * ```ts\n * const { signedTransaction } = await signTransaction({\n *   walletAccount: solAccount,\n *   transaction,\n * });\n * ```\n *\n * @param params.transaction - The transaction to sign.\n * @param params.walletAccount - The wallet account to sign the transaction with.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns An object containing the signed transaction.\n * @throws {NotSolanaProviderError} If the wallet provider is not a Solana provider.\n * @see signAndSendTransaction\n * @see signAllTransactions\n * @notInstrumented\n */\nexport const signTransaction = async (\n  { walletAccount, transaction }: SignTransactionParams,\n  client = getDefaultClient()\n): Promise<{ signedTransaction: Transaction | VersionedTransaction }> => {\n  const provider = getWalletProviderFromWalletAccount(\n    {\n      walletAccount,\n    },\n    client\n  );\n\n  if (!isSolanaWalletProvider(provider)) {\n    throw new NotSolanaProviderError({ providerKey: provider.key });\n  }\n\n  return provider.signTransaction({ transaction, walletAccount });\n};\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport {\n  name as packageName,\n  version as packageVersion,\n} from '../../package.json';\nassertPackageVersion(packageName, packageVersion);\n\nexport { addSolanaExtension } from '../addSolanaExtension';\nexport { NotSolanaProviderError } from '../errors/NotSolanaProviderError';\nexport { SponsorTransactionError } from '../errors/SponsorTransactionError/SponsorTransactionError';\nexport { getSolanaConnection } from '../getSolanaConnection';\nexport { isSolanaNetworkProvider } from '../isSolanaNetworkProvider';\nexport { isSolanaWalletAccount } from '../isSolanaWalletAccount';\nexport { simulateSolanaTransaction } from '../simulateSolanaTransaction';\nexport type {\n  SolanaSimulationResult,\n  SolanaTransactionFeeData,\n} from '../transactionSimulation.types';\n\nexport { isSolanaGasSponsorshipEnabled } from '../isSolanaGasSponsorshipEnabled';\nexport { addPhantomRedirectSolanaExtension } from '../phantomRedirect/addPhantomRedirectSolanaExtension';\nexport { completePhantomRedirect } from '../phantomRedirect/completePhantomRedirect';\nexport { detectPhantomRedirect } from '../phantomRedirect/detectPhantomRedirect';\nexport type {\n  PhantomRedirectWalletProvider,\n  PhantomSession,\n} from '../phantomRedirect/PhantomRedirectWalletProvider.types';\nexport { signAllTransactions } from '../signAllTransactions';\nexport { signAndSendSponsoredTransaction } from '../signAndSendSponsoredTransaction';\nexport { signAndSendTransaction } from '../signAndSendTransaction';\nexport { signTransaction } from '../signTransaction';\nexport type { SolanaNetworkProvider } from '../SolanaNetworkProvider.types';\nexport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nexport { calculateSolanaTransactionFee } from '../utils/calculateSolanaTransactionFee';\n"],"mappings":"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"}