/** * @module utils/rpc-strategy * @description Dual-connection RPC strategy and idempotent ATA creation. * * Solves two interoperability problems: * * 1. **WebSocket 400 loop**: Some authenticated RPCs reject WebSocket * connections for SPL token operations. This module exposes a * dual-connection strategy: primary RPC for SAP program calls, * fallback public RPC for token operations. * * 2. **Idempotent ATA creation**: Wraps `getOrCreateAssociatedTokenAccount` * with retries so "account already exists" doesn't surface as a * hard error. * * @category Utils * @since v0.6.0 */ import { Connection, type Commitment, PublicKey, type TransactionSignature } from "@solana/web3.js"; /** * @interface RpcConfig * @description Configuration for dual-connection RPC strategy. * @category Utils * @since v0.6.0 */ export interface RpcConfig { /** Primary RPC URL (for SAP program calls). */ readonly primaryUrl: string; /** Fallback RPC URL (for SPL token ops, public RPCs). */ readonly fallbackUrl?: string; /** Commitment level. */ readonly commitment?: Commitment; } /** * @interface DualConnection * @description Dual RPC connections: primary for SAP, fallback for tokens. * @category Utils * @since v0.6.0 */ export interface DualConnection { /** Primary connection for SAP program calls. */ readonly primary: Connection; /** Fallback connection for SPL token operations. */ readonly fallback: Connection; } /** * @name getRpcUrl * @description Get the primary RPC URL from environment or config. * * Resolution order: * 1. Explicit `config.primaryUrl` * 2. `SOLANA_RPC_URL` env var * 3. Cluster-appropriate public RPC * * @param config - Optional RPC configuration. * @param cluster - Cluster hint (defaults to "mainnet-beta"). * @returns The resolved primary RPC URL. * * @category Utils * @since v0.6.0 */ export declare function getRpcUrl(config?: Partial, cluster?: string): string; /** * @name getFallbackRpcUrl * @description Get the fallback RPC URL for SPL token operations. * * This avoids the WebSocket-400 loop when the primary RPC is * an authenticated endpoint that rejects token-related WebSocket * subscriptions. * * @param config - Optional RPC configuration. * @param cluster - Cluster hint (defaults to "mainnet-beta"). * @returns The resolved fallback RPC URL. * * @category Utils * @since v0.6.0 */ export declare function getFallbackRpcUrl(config?: Partial, cluster?: string): string; /** * @name createDualConnection * @description Create a dual-connection pair: primary for SAP program calls, * fallback for SPL token operations. * * @param config - RPC configuration. * @param cluster - Cluster hint. * @returns A {@link DualConnection} with both connections. * * @category Utils * @since v0.6.0 * * @example * ```ts * const { primary, fallback } = createDualConnection({ * primaryUrl: "https://my-rpc.example.com", * }, "mainnet-beta"); * * // Use primary for SAP calls * const provider = new AnchorProvider(primary, wallet, {}); * * // Use fallback for SPL token account creation * const ata = await getOrCreateATA(fallback, mint, owner); * ``` */ export declare function createDualConnection(config: Partial, cluster?: string): DualConnection; /** * @interface AtaResult * @description Result of idempotent ATA creation attempt. * @category Utils * @since v0.6.0 */ export interface AtaResult { /** The ATA public key (exists or newly created). */ readonly address: PublicKey; /** Whether the ATA already existed. */ readonly existed: boolean; /** Transaction signature (only if newly created). */ readonly txSignature?: TransactionSignature; } /** * @name findATA * @description Derive the Associated Token Account address. * Uses the standard ATA PDA derivation without importing the full * `@solana/spl-token` package. * * @param owner - The token account owner. * @param mint - The token mint. * @param programId - Token program ID (defaults to TOKEN_PROGRAM_ID). * @returns The derived ATA public key. * * @category Utils * @since v0.6.0 */ export declare function findATA(owner: PublicKey, mint: PublicKey, programId?: PublicKey): PublicKey; /** * @name classifyAnchorError * @description Convert an Anchor error code into a friendly, actionable message. * * @param errorCode - The numeric Anchor error code. * @returns A human-readable error message, or a generic message for unknown codes. * * @category Utils * @since v0.6.0 * * @example * ```ts * try { * await client.escrow.create(...); * } catch (err) { * const code = extractAnchorErrorCode(err); * if (code !== null) { * console.error(classifyAnchorError(code)); * } * } * ``` */ export declare function classifyAnchorError(errorCode: number): string; /** * @name extractAnchorErrorCode * @description Attempt to extract an Anchor error code from an Error object. * * Anchor errors typically have the structure `{ code: number, msg: string }`. * This function handles both the direct `error.code` pattern and the * `error.error.errorCode.number` nested pattern. * * @param err - The caught error object. * @returns The numeric error code, or `null` if not an Anchor error. * * @category Utils * @since v0.6.0 */ export declare function extractAnchorErrorCode(err: unknown): number | null; //# sourceMappingURL=rpc-strategy.d.ts.map