@dynamic-labs-sdk/solana 0.23.2 → 0.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{addSolanaWalletStandardExtension-B26Xpl2O.esm.js → addSolanaWalletStandardExtension-B3sMU6WM.esm.js} +2 -2
- package/dist/{addSolanaWalletStandardExtension-B26Xpl2O.esm.js.map → addSolanaWalletStandardExtension-B3sMU6WM.esm.js.map} +1 -1
- package/dist/{addSolanaWalletStandardExtension-BYIsol74.cjs.js → addSolanaWalletStandardExtension-DrbtTeR3.cjs.js} +4 -36
- package/dist/{addSolanaWalletStandardExtension-BYIsol74.cjs.js.map → addSolanaWalletStandardExtension-DrbtTeR3.cjs.js.map} +1 -1
- package/dist/{addWaasSolanaExtension-D4DLAn3x.esm.js → addWaasSolanaExtension-B4u-up-i.esm.js} +2 -2
- package/dist/{addWaasSolanaExtension-D4DLAn3x.esm.js.map → addWaasSolanaExtension-B4u-up-i.esm.js.map} +1 -1
- package/dist/{addWaasSolanaExtension-FgRBy-56.cjs.js → addWaasSolanaExtension-bhJbhe7B.cjs.js} +3 -3
- package/dist/{addWaasSolanaExtension-FgRBy-56.cjs.js.map → addWaasSolanaExtension-bhJbhe7B.cjs.js.map} +1 -1
- package/dist/chunk-BFVW7ptc.cjs.js +34 -0
- package/dist/index.cjs.js +7 -6
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +3 -3
- package/dist/{solanaTransferAmount-BvLEGA-x.esm.js → solanaTransferAmount-EGugT484.esm.js} +2 -2
- package/dist/{solanaTransferAmount-BvLEGA-x.esm.js.map → solanaTransferAmount-EGugT484.esm.js.map} +1 -1
- package/dist/{solanaTransferAmount-BIEZ3hn_.cjs.js → solanaTransferAmount-d27ooag0.cjs.js} +3 -3
- package/dist/{solanaTransferAmount-BIEZ3hn_.cjs.js.map → solanaTransferAmount-d27ooag0.cjs.js.map} +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/waas.cjs.js +3 -3
- package/dist/waas.esm.js +2 -2
- package/dist/walletConnect.cjs.js +333 -0
- package/dist/walletConnect.cjs.js.map +1 -0
- package/dist/walletConnect.esm.js +329 -0
- package/dist/walletConnect.esm.js.map +1 -0
- package/dist/walletStandard.cjs.js +3 -2
- package/dist/walletStandard.cjs.js.map +1 -1
- package/dist/walletStandard.esm.js +2 -2
- package/package.json +5 -5
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","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","nacl","BaseError","decrypted: Uint8Array | null","nacl","methodErrorEventMap: Record<string, keyof PhantomEvents>","sharedSecret: string","nacl","nacl","WalletProviderEnum","connect: SolanaWalletProvider['connect']","disconnect: SolanaWalletProvider['disconnect']","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","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/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/signAndSendTransaction/signAndSendTransaction.ts","../src/signTransaction/signTransaction.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client/core';\n\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 * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @not-instrumented\n */\nexport const addSolanaExtension = (client = getDefaultClient()): void => {\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 * @param networkProvider - The network provider to check.\n * @returns True if the network provider is a Solana network provider, false otherwise.\n * @not-instrumented\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 * @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 * @not-instrumented\n */\n// eslint-disable-next-line custom-rules/one-function-per-file\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 * @not-instrumented\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 * @not-instrumented\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 bs58 from 'bs58';\nimport nacl from 'tweetnacl';\n\nexport type CreateNaClSharedSecretParams = {\n ourSecretKey: string;\n theirPublicKey: string;\n};\n\n/**\n * Creates a shared secret for NaCl box encryption using our secret key and their 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 * @not-instrumented\n */\nexport const createNaClSharedSecret = ({\n ourSecretKey,\n theirPublicKey,\n}: CreateNaClSharedSecretParams): string => {\n const sharedSecret = nacl.box.before(\n bs58.decode(theirPublicKey),\n bs58.decode(ourSecretKey)\n );\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 * @not-instrumented\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 * @not-instrumented\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// eslint-disable-next-line custom-rules/one-function-per-file\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 * @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 * @not-instrumented\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 * @not-instrumented\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 * @not-instrumented\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 * @not-instrumented\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 */\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 * @not-instrumented\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 * @not-instrumented\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 */\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 * @not-instrumented\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 disconnect: SolanaWalletProvider['disconnect'] = async () => {\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 return deferredPromise.promise;\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 disconnect,\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 * @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 * @not-instrumented\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 * @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 * @not-instrumented\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\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 * @not-instrumented\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 * @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 * @not-instrumented\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 {\n SendOptions,\n Transaction,\n VersionedTransaction,\n} from '@solana/web3.js';\n\nimport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nimport { NotSolanaProviderError } from '../errors/NotSolanaProviderError';\nimport { isSolanaWalletProvider } from '../isSolanaWalletProvider';\n\ntype SignAndSendTransactionParams = {\n options?: SendOptions;\n transaction: Transaction | VersionedTransaction;\n walletAccount: SolanaWalletAccount;\n};\n\n/**\n * Signs and sends a Solana transaction\n * @param params.transaction - The transaction to 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 * @not-instrumented\n */\nexport const signAndSendTransaction = async (\n { walletAccount, transaction, options }: SignAndSendTransactionParams,\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 return provider.signAndSendTransaction({\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\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 * @not-instrumented\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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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","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","nacl","BaseError","decrypted: Uint8Array | null","nacl","methodErrorEventMap: Record<string, keyof PhantomEvents>","sharedSecret: string","nacl","nacl","WalletProviderEnum","connect: SolanaWalletProvider['connect']","disconnect: SolanaWalletProvider['disconnect']","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","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/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/signAndSendTransaction/signAndSendTransaction.ts","../src/signTransaction/signTransaction.ts","../src/exports/index.ts"],"sourcesContent":["import { getDefaultClient } from '@dynamic-labs-sdk/client/core';\n\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 * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @not-instrumented\n */\nexport const addSolanaExtension = (client = getDefaultClient()): void => {\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 * @param networkProvider - The network provider to check.\n * @returns True if the network provider is a Solana network provider, false otherwise.\n * @not-instrumented\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 * @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 * @not-instrumented\n */\n// eslint-disable-next-line custom-rules/one-function-per-file\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 * @not-instrumented\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 * @not-instrumented\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 bs58 from 'bs58';\nimport nacl from 'tweetnacl';\n\nexport type CreateNaClSharedSecretParams = {\n ourSecretKey: string;\n theirPublicKey: string;\n};\n\n/**\n * Creates a shared secret for NaCl box encryption using our secret key and their 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 * @not-instrumented\n */\nexport const createNaClSharedSecret = ({\n ourSecretKey,\n theirPublicKey,\n}: CreateNaClSharedSecretParams): string => {\n const sharedSecret = nacl.box.before(\n bs58.decode(theirPublicKey),\n bs58.decode(ourSecretKey)\n );\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 * @not-instrumented\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 * @not-instrumented\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// eslint-disable-next-line custom-rules/one-function-per-file\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 * @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 * @not-instrumented\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 * @not-instrumented\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 * @not-instrumented\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 * @not-instrumented\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 */\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 * @not-instrumented\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 * @not-instrumented\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 */\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 * @not-instrumented\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 disconnect: SolanaWalletProvider['disconnect'] = async () => {\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 return deferredPromise.promise;\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 disconnect,\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 * @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 * @not-instrumented\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 * @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 * @not-instrumented\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\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 * @not-instrumented\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 * @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 * @not-instrumented\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 {\n SendOptions,\n Transaction,\n VersionedTransaction,\n} from '@solana/web3.js';\n\nimport type { SolanaWalletAccount } from '../SolanaWalletAccount.types';\nimport { NotSolanaProviderError } from '../errors/NotSolanaProviderError';\nimport { isSolanaWalletProvider } from '../isSolanaWalletProvider';\n\ntype SignAndSendTransactionParams = {\n options?: SendOptions;\n transaction: Transaction | VersionedTransaction;\n walletAccount: SolanaWalletAccount;\n};\n\n/**\n * Signs and sends a Solana transaction\n * @param params.transaction - The transaction to 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 * @not-instrumented\n */\nexport const signAndSendTransaction = async (\n { walletAccount, transaction, options }: SignAndSendTransactionParams,\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 return provider.signAndSendTransaction({\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\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 * @not-instrumented\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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"}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as isSolanaWalletProvider, c as isVersionedTransaction, d as name, f as version, i as solanaExecuteSwapTransaction, l as getSolanaConnection, n as isSolanaGasSponsorshipEnabled, o as solanaConfirmTransaction, r as NotSolanaProviderError, s as isSolanaWalletAccount, t as solanaTransferAmount, u as registerSolanaNetworkProviderBuilder } from "./solanaTransferAmount-
|
|
2
|
-
import { n as SponsorTransactionError, t as addWaasSolanaExtension } from "./addWaasSolanaExtension-
|
|
3
|
-
import { t as addSolanaWalletStandardExtension } from "./addSolanaWalletStandardExtension-
|
|
1
|
+
import { a as isSolanaWalletProvider, c as isVersionedTransaction, d as name, f as version, i as solanaExecuteSwapTransaction, l as getSolanaConnection, n as isSolanaGasSponsorshipEnabled, o as solanaConfirmTransaction, r as NotSolanaProviderError, s as isSolanaWalletAccount, t as solanaTransferAmount, u as registerSolanaNetworkProviderBuilder } from "./solanaTransferAmount-EGugT484.esm.js";
|
|
2
|
+
import { n as SponsorTransactionError, t as addWaasSolanaExtension } from "./addWaasSolanaExtension-B4u-up-i.esm.js";
|
|
3
|
+
import { t as addSolanaWalletStandardExtension } from "./addSolanaWalletStandardExtension-B3sMU6WM.esm.js";
|
|
4
4
|
import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
|
|
5
5
|
import { MethodNotImplementedError, WalletProviderPriority, assertDefined, createApiClient, createDeferredPromise, createRuntimeServiceAccessKey, createStorageKeySchema, emitEvent, formatWalletProviderGroupKey, formatWalletProviderKey, getActiveNetworkIdFromLastKnownRegistry, getBuffer, getCore, getDefaultClient, getNetworkProviders, getWalletProviderFromWalletAccount, getWalletProviderRegistry, hasExtension, randomString, registerExtension } from "@dynamic-labs-sdk/client/core";
|
|
6
6
|
import { Connection, LAMPORTS_PER_SOL, PublicKey, Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
@@ -5,7 +5,7 @@ import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, createAssociatedTokenAccountIn
|
|
|
5
5
|
|
|
6
6
|
//#region package.json
|
|
7
7
|
var name = "@dynamic-labs-sdk/solana";
|
|
8
|
-
var version = "0.23.
|
|
8
|
+
var version = "0.23.4";
|
|
9
9
|
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/utils/fetchSolBalance/fetchSolBalance.ts
|
|
@@ -250,4 +250,4 @@ const solanaTransferAmount = async ({ amount, recipient, token, walletAccount },
|
|
|
250
250
|
|
|
251
251
|
//#endregion
|
|
252
252
|
export { isSolanaWalletProvider as a, isVersionedTransaction as c, name as d, version as f, solanaExecuteSwapTransaction as i, getSolanaConnection as l, isSolanaGasSponsorshipEnabled as n, solanaConfirmTransaction as o, NotSolanaProviderError as r, isSolanaWalletAccount as s, solanaTransferAmount as t, registerSolanaNetworkProviderBuilder as u };
|
|
253
|
-
//# sourceMappingURL=solanaTransferAmount-
|
|
253
|
+
//# sourceMappingURL=solanaTransferAmount-EGugT484.esm.js.map
|