{"version":3,"sources":["../src/chains/starknet/StarknetClient.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Starknet Chain Client\n *\n * Production-grade implementation of ChainClient interface for Starknet.\n * Supports custom bridge attestation, gasless execution via Hub dispatch.\n *\n * Security:\n * - Native starknet::eth_signature::verify_eth_signature for validation\n * - Custom bridge with multi-relayer threshold attestations\n * - Replay protection via nonce verification on Hub\n * - Bridge validates source_chain == hub_chain_id (10004 = Base Sepolia)\n *\n * Architecture:\n * - Starknet actions MUST be dispatched via Hub (Base Sepolia)\n * - Hub publishes Wormhole message → relayer monitors → relayer submits attestation\n * - Bridge accumulates attestations → threshold reached → spoke executes\n * - Spoke validates source_chain == hubChainId (NOT targetChain)\n * \n * Custom Bridge:\n * - Bridge address: 0x30d2e7f26dc75819cfddcd7caa26a76b681d5918f219c99060c42ce1e3f69e4\n * - Chain ID: 50001 (custom range 50000+, reserved for non-Wormhole chains)\n * - Hub Chain ID: 10004 (Base Sepolia - what bridge validates as source)\n */\n\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n    ChainClient,\n    ChainConfig,\n    TransferParams,\n    ExecuteParams,\n    BridgeParams,\n    DispatchResult,\n    WebAuthnSignature,\n    VaultCreationResult,\n    RegisterSessionParams,\n    RevokeSessionParams,\n    SessionValidationResult,\n} from '../../core/types.js';\nimport { createHash } from 'crypto';\nimport { RpcProvider } from 'starknet';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n// 2^128 for splitting u256 into low/high\nconst U128_MAX = BigInt('0x100000000000000000000000000000000');\n\n/**\n * Convert a 256-bit keyHash to Starknet u256 format (low, high felt252 pair).\n * Starknet u256 is represented as two felt252 values: (low_128_bits, high_128_bits)\n * \n * @param keyHash - 256-bit hex string (with or without 0x prefix)\n * @returns Array of two hex strings [low, high] for Starknet calldata\n */\nfunction toStarknetU256(keyHash: string): [string, string] {\n    const cleanHash = keyHash.replace('0x', '').padStart(64, '0');\n    const value = BigInt('0x' + cleanHash);\n    \n    // Split into low 128 bits and high 128 bits\n    const low = value % U128_MAX;\n    const high = value / U128_MAX;\n    \n    return [\n        '0x' + low.toString(16),\n        '0x' + high.toString(16)\n    ];\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StarknetClientConfig {\n    wormholeChainId: number;\n    rpcUrl: string;\n    spokeContractAddress?: string;\n    bridgeContractAddress?: string;\n    network?: 'mainnet' | 'sepolia' | 'testnet';\n    hubRpcUrl?: string; // Hub chain RPC for session management\n    hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// StarknetClient\n// ============================================================================\n\nexport class StarknetClient implements ChainClient {\n    private config: ChainConfig;\n    private provider: RpcProvider;\n    private hubRpcUrl?: string;\n    private hubContractAddress?: string;\n\n    constructor(config: StarknetClientConfig) {\n        this.config = {\n            name: `Starknet ${config.network || 'mainnet'}`,\n            chainId: 0,\n            wormholeChainId: config.wormholeChainId,\n            rpcUrl: config.rpcUrl,\n            explorerUrl: config.network === 'sepolia'\n                ? 'https://sepolia.starkscan.co'\n                : 'https://starkscan.co',\n            isEvm: false,\n            contracts: {\n                hub: config.spokeContractAddress,\n                wormholeCoreBridge: config.bridgeContractAddress ?? '',\n            },\n        };\n\n        this.hubRpcUrl = config.hubRpcUrl;\n        this.hubContractAddress = config.hubContractAddress;\n\n        this.provider = new RpcProvider({ nodeUrl: config.rpcUrl });\n    }\n\n    getConfig(): ChainConfig {\n        return this.config;\n    }\n\n    async getNonce(_userKeyHash: string): Promise<bigint> {\n        return 0n;\n    }\n\n    async getMessageFee(): Promise<bigint> {\n        return 0n;\n    }\n\n    async buildTransferPayload(params: TransferParams): Promise<string> {\n        return encodeTransferAction(params.token, params.recipient, params.amount);\n    }\n\n    async buildExecutePayload(params: ExecuteParams): Promise<string> {\n        return encodeExecuteAction(params.target, params.value, params.data);\n    }\n\n    async buildBridgePayload(params: BridgeParams): Promise<string> {\n        return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\n    }\n\n    async dispatch(\n        signature: WebAuthnSignature,\n        publicKeyX: bigint,\n        publicKeyY: bigint,\n        targetChain: number,\n        actionPayload: string,\n        nonce: bigint,\n        signer: any\n    ): Promise<DispatchResult> {\n        void signature;\n        void publicKeyX;\n        void publicKeyY;\n        void targetChain;\n        void actionPayload;\n        void nonce;\n        void signer;\n        throw new Error(\n            'Direct dispatch not supported on Starknet. ' +\n            'Starknet actions are executed via the Veridex Hub (Base Sepolia) + custom bridge. ' +\n            'Use dispatchGasless() to route through relayer, which will submit attestations to the bridge.'\n        );\n    }\n\n    async dispatchGasless(\n        signature: WebAuthnSignature,\n        publicKeyX: bigint,\n        publicKeyY: bigint,\n        targetChain: number,\n        actionPayload: string,\n        nonce: bigint,\n        relayerUrl: string\n    ): Promise<DispatchResult> {\n        /**\n         * Starknet gasless execution flow:\n         * 1. User signs action with passkey (on client)\n         * 2. SDK submits to relayer with targetChain=50001 (Starknet)\n         * 3. Relayer dispatches to Hub (Base Sepolia) with targetChain=50001\n         * 4. Hub publishes Wormhole message\n         * 5. Relayer monitors Hub Dispatch event\n         * 6. Relayer submits attestation to Starknet Bridge\n         * 7. Bridge accumulates attestations from multiple relayers\n         * 8. When threshold reached, Bridge calls spoke.execute()\n         * 9. Spoke validates source_chain == hubChainId (10004)\n         * 10. Spoke executes action on user's vault\n         * \n         * Result: Completely gasless for user - relayer pays all fees\n         */\n        const keyHash = this.computeKeyHash(publicKeyX, publicKeyY);\n\n        // Submit to relayer for Hub dispatch + bridge attestation\n        const request = {\n            signature: {\n                r: '0x' + signature.r.toString(16).padStart(64, '0'),\n                s: '0x' + signature.s.toString(16).padStart(64, '0'),\n                authenticatorData: signature.authenticatorData,\n                clientDataJSON: signature.clientDataJSON,\n                challengeIndex: signature.challengeIndex,\n                typeIndex: signature.typeIndex,\n            },\n            publicKeyX: '0x' + publicKeyX.toString(16).padStart(64, '0'),\n            publicKeyY: '0x' + publicKeyY.toString(16).padStart(64, '0'),\n            targetChain, // 50001 for Starknet\n            actionPayload,\n            userNonce: Number(nonce),\n        };\n\n        const response = await fetch(`${relayerUrl}/api/v1/submit`, {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify(request),\n        });\n\n        if (!response.ok) {\n            const errorText = await response.text().catch(() => 'Unknown error');\n            throw new Error(\n                `Relayer submission failed: ${response.status} ${response.statusText}. ` +\n                `Error: ${errorText}`\n            );\n        }\n\n        const result = await response.json();\n\n        return {\n            transactionHash: result.transactionHash ?? result.txHash ?? result.hubTxHash,\n            sequence: BigInt(result.sequence || 0),\n            userKeyHash: keyHash,\n            targetChain,\n        };\n    }\n\n    // Note: getVaultAddress is now defined in the Social Recovery section below\n    // with enhanced spoke contract querying support.\n\n    computeVaultAddress(userKeyHash: string): string {\n        /**\n         * Starknet vault derivation:\n         * - Vaults are created via spoke contract\n         * - Address is deterministic from userKeyHash\n         * - Uses keyHash directly as vault identifier (felt252)\n         * \n         * Note: Actual vault address on Starknet may differ based on\n         * spoke implementation. This is a best-effort derivation.\n         */\n        const clean = userKeyHash.replace(/^0x/, '');\n        return '0x' + clean;\n    }\n\n    async vaultExists(userKeyHash: string): Promise<boolean> {\n        /**\n         * Check if vault exists on Starknet spoke\n         * Best-effort: queries spoke contract if available\n         */\n        if (!this.config.contracts.hub) {\n            return false;\n        }\n\n        try {\n            const vaultAddress = await this.getVaultAddress(userKeyHash);\n            if (!vaultAddress) {\n                return false;\n            }\n\n            // Query Starknet RPC for contract code at vault address\n            const anyProvider = this.provider as any;\n            if (typeof anyProvider.getClassHashAt === 'function') {\n                await anyProvider.getClassHashAt(vaultAddress);\n                return true;\n            }\n        } catch {\n            // Vault doesn't exist or RPC doesn't support query\n        }\n\n        return false;\n    }\n\n    async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n        void signer;\n        throw new Error(\n            'Vault creation on Starknet must be done via Hub dispatch + custom bridge attestation. ' +\n            'Use Hub client (Base Sepolia) to dispatch a CREATE_VAULT action with targetChain=50001. ' +\n            `KeyHash=${userKeyHash}`\n        );\n    }\n\n    async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n        void userKeyHash;\n        void sponsorPrivateKey;\n        void rpcUrl;\n        throw new Error(\n            'Vault creation on Starknet must be done via Hub dispatch + custom bridge attestation. ' +\n            'Use Hub client (Base Sepolia) with sponsor key to dispatch CREATE_VAULT action.'\n        );\n    }\n\n    /**\n     * Create a vault via the relayer (sponsored/gasless)\n     * This is the recommended way to create Starknet vaults\n     * \n     * The relayer will dispatch a vault creation action from Hub via custom bridge to Starknet spoke\n     */\n    async createVaultViaRelayer(\n        userKeyHash: string,\n        relayerUrl: string\n    ): Promise<VaultCreationResult> {\n        const response = await fetch(`${relayerUrl}/api/v1/starknet/vault`, {\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify({\n                userKeyHash,\n                chainId: this.config.wormholeChainId,\n            }),\n        });\n\n        const result = await response.json();\n\n        if (!response.ok || !result.success) {\n            throw new Error(result.error || 'Failed to create vault via relayer');\n        }\n\n        return {\n            address: result.vaultAddress,\n            transactionHash: result.transactionHash || '',\n            blockNumber: 0,\n            gasUsed: 0n,\n            alreadyExisted: result.alreadyExists || false,\n            sponsoredBy: 'relayer',\n        };\n    }\n\n    /**\n     * Get vault info via relayer (includes existence check)\n     */\n    async getVaultViaRelayer(\n        userKeyHash: string,\n        relayerUrl: string\n    ): Promise<{ vaultAddress: string; exists: boolean }> {\n        const response = await fetch(\n            `${relayerUrl}/api/v1/starknet/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n        );\n\n        if (!response.ok) {\n            throw new Error('Failed to get vault info from relayer');\n        }\n\n        const result = await response.json();\n        return {\n            vaultAddress: result.vaultAddress,\n            exists: result.exists,\n        };\n    }\n\n    async estimateVaultCreationGas(_userKeyHash: string): Promise<bigint> {\n        return 0n;\n    }\n\n    getFactoryAddress(): string | undefined {\n        return undefined;\n    }\n\n    getImplementationAddress(): string | undefined {\n        return undefined;\n    }\n\n    // ========================================================================\n    // Balance utility (best-effort)\n    // ========================================================================\n\n    async getNativeBalance(address: string): Promise<bigint> {\n        // Best-effort: some Starknet RPCs support getBalance, but it is not universal.\n        try {\n            const anyProvider = this.provider as any;\n            if (typeof anyProvider.getBalance === 'function') {\n                const res = await anyProvider.getBalance(address);\n                return BigInt(res);\n            }\n        } catch {\n            // ignore\n        }\n        return 0n;\n    }\n\n    getProvider(): RpcProvider {\n        return this.provider;\n    }\n\n    // ========================================================================\n    // Session Management (Issue #13)\n    // ========================================================================\n\n    /**\n     * Register a session key on the Hub (must be called via Hub client)\n     * Starknet spokes validate sessions via CCQ, but registration happens on Hub\n     * \n     * @throws Error - Session management must be done via Hub chain\n     */\n    async registerSession(_params: RegisterSessionParams): Promise<void> {\n        throw new Error(\n            'Session registration must be performed on the Hub chain (Base). ' +\n            'Use EVMClient connected to the Hub to call registerSession().'\n        );\n    }\n\n    /**\n     * Revoke a session key on the Hub (must be called via Hub client)\n     * \n     * @throws Error - Session management must be done via Hub chain\n     */\n    async revokeSession(_params: RevokeSessionParams): Promise<void> {\n        throw new Error(\n            'Session revocation must be performed on the Hub chain (Base). ' +\n            'Use EVMClient connected to the Hub to call revokeSession().'\n        );\n    }\n\n    /**\n     * Check if a session is active by querying the Hub\n     * This method queries the Hub contract directly for session validation\n     * \n     * @param userKeyHash - Hash of user's Passkey public key\n     * @param sessionKeyHash - Hash of session key to validate\n     * @returns Session validation result with expiry and limits\n     */\n    async isSessionActive(\n        _userKeyHash: string,\n        _sessionKeyHash: string\n    ): Promise<SessionValidationResult> {\n        if (!this.hubRpcUrl || !this.hubContractAddress) {\n            throw new Error(\n                'Hub configuration required for session validation. ' +\n                'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n            );\n        }\n\n        // Query Hub contract for session status\n        throw new Error(\n            'isSessionActive requires Hub client integration. ' +\n            'Use EVMClient.isSessionActive() on the Hub chain, ' +\n            'then pass the result to session execution on Starknet.'\n        );\n    }\n\n    /**\n     * Get all sessions for a user from the Hub\n     * \n     * @param userKeyHash - Hash of user's Passkey public key\n     * @returns Array of all sessions (active and expired/revoked)\n     */\n    async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n        if (!this.hubRpcUrl || !this.hubContractAddress) {\n            throw new Error(\n                'Hub configuration required for session queries. ' +\n                'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n            );\n        }\n\n        // Query Hub contract for user sessions\n        throw new Error(\n            'getUserSessions requires Hub client integration. ' +\n            'Use EVMClient.getUserSessions() on the Hub chain. ' +\n            `User: ${userKeyHash}`\n        );\n    }\n\n    // ========================================================================\n    // Query-Based Execution (Issue #9/#10)\n    // ========================================================================\n\n    /**\n     * Get user state from Hub (comprehensive state query)\n     * Returns key hash, nonce, and last action hash for CCQ validation\n     * \n     * @param userKeyHash - Hash of user's Passkey public key\n     * @returns User state with nonce and last action hash\n     */\n    async getUserState(userKeyHash: string): Promise<{\n        keyHash: string;\n        nonce: bigint;\n        lastActionHash: string;\n    }> {\n        if (!this.hubRpcUrl || !this.hubContractAddress) {\n            throw new Error(\n                'Hub configuration required for state queries. ' +\n                'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n            );\n        }\n\n        // Query Hub contract for user state\n        throw new Error(\n            'getUserState requires Hub client integration. ' +\n            'Use EVMClient.getUserState() on the Hub chain. ' +\n            `User: ${userKeyHash}`\n        );\n    }\n\n    /**\n     * Get user's last action hash from Hub\n     * Used for optimistic execution and nonce validation\n     * \n     * @param userKeyHash - Hash of user's Passkey public key\n     * @returns Last action hash (zero hash if no actions)\n     */\n    async getUserLastActionHash(userKeyHash: string): Promise<string> {\n        if (!this.hubRpcUrl || !this.hubContractAddress) {\n            throw new Error(\n                'Hub configuration required for action hash queries. ' +\n                'Provide hubRpcUrl and hubContractAddress in StarknetClientConfig.'\n            );\n        }\n\n        // Query Hub contract for last action hash\n        throw new Error(\n            'getUserLastActionHash requires Hub client integration. ' +\n            'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n            `User: ${userKeyHash}`\n        );\n    }\n\n    /**\n     * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n     * Uses Wormhole CCQ to validate Hub state, then executes on Starknet\n     * \n     * @param params Query execution parameters with CCQ response\n     * @returns Dispatch result with transaction hash\n     * \n     * @remarks\n     * Query-based execution flow:\n     * 1. Query Hub state via Wormhole CCQ\n     * 2. Validate Guardian signatures on query response\n     * 3. Execute on Starknet with validated state\n     * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n     */\n    async executeWithQuery(\n        _params: {\n            userKeyHash: string;\n            queryResponse: Uint8Array; // CCQ Guardian response\n            actionType: number;\n            actionPayload: Uint8Array;\n            relayerUrl?: string;\n        }\n    ): Promise<DispatchResult> {\n        throw new Error(\n            'Query-based execution on Starknet requires relayer integration. ' +\n            'Use relayer API to submit query-validated transactions. ' +\n            'Relayer will call veridex_spoke::execute_with_query on Starknet.'\n        );\n    }\n\n    // ========================================================================\n    // Internal helpers\n    // ========================================================================\n\n    private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n        const xHex = publicKeyX.toString(16).padStart(64, '0');\n        const yHex = publicKeyY.toString(16).padStart(64, '0');\n        const combined = Buffer.from(xHex + yHex, 'hex');\n        const hash = createHash('sha256').update(combined).digest('hex');\n        return '0x' + hash;\n    }\n\n    // ============================================================================\n    // Social Recovery Methods (Issue #23)\n    // ============================================================================\n    // \n    // Note: Social recovery is managed on the Hub chain (EVM).\n    // Starknet spokes receive and execute recovery VAAs broadcast from the Hub.\n    // The relayer service handles submitting recovery transactions to Starknet.\n    //\n    // SDK users should use EVMClient methods for guardian management and\n    // recovery initiation on the Hub chain.\n    // ============================================================================\n\n    /**\n     * Get vault address by owner key hash\n     * \n     * @param ownerKeyHash - Owner's passkey hash\n     * @returns Vault address on Starknet (felt252 as hex string)\n     */\n    async getVaultAddress(ownerKeyHash: string): Promise<string | null> {\n        try {\n            const spokeAddress = this.config.contracts.hub;\n            if (!spokeAddress) {\n                throw new Error('Spoke contract address not configured');\n            }\n\n            // Starknet spoke expects u256 (low, high) format for keyHash\n            const [low, high] = toStarknetU256(ownerKeyHash);\n\n            // Call get_vault on spoke contract with u256 split into [low, high]\n            const result = await this.provider.callContract({\n                contractAddress: spokeAddress,\n                entrypoint: 'get_vault',\n                calldata: [low, high],\n            });\n\n            // result[0] is the vault address (0 if not found)\n            const vaultAddress = result[0];\n            if (vaultAddress === '0x0' || vaultAddress === '0') {\n                return null;\n            }\n\n            return vaultAddress;\n        } catch (error) {\n            console.error('Error getting vault address:', error);\n            return null;\n        }\n    }\n\n    /**\n     * Check if vault exists and get basic info\n     * \n     * @param ownerKeyHash - Owner's passkey hash  \n     * @returns Vault info or null if not found\n     */\n    async getVaultInfo(ownerKeyHash: string): Promise<{\n        address: string;\n        ownerKeyHash: string;\n    } | null> {\n        const vaultAddress = await this.getVaultAddress(ownerKeyHash);\n        if (!vaultAddress) {\n            return null;\n        }\n\n        return {\n            address: vaultAddress,\n            ownerKeyHash,\n        };\n    }\n\n    /**\n     * Check if spoke contract is paused\n     * \n     * @returns Whether the protocol is paused\n     */\n    async isProtocolPaused(): Promise<boolean> {\n        try {\n            const spokeAddress = this.config.contracts.hub;\n            if (!spokeAddress) {\n                throw new Error('Spoke contract address not configured');\n            }\n\n            const result = await this.provider.callContract({\n                contractAddress: spokeAddress,\n                entrypoint: 'is_paused',\n                calldata: [],\n            });\n\n            return result[0] === '0x1' || result[0] === '1';\n        } catch (error) {\n            console.error('Error checking pause status:', error);\n            return false;\n        }\n    }\n}\n"],"mappings":"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","names":[]}