import { wrapWithBuilderCode } from "./builder-code.mjs";
import { hasKeychainWallet, loadAndDecrypt } from "./keychain-wallet.mjs";
//#region extensions/crypto/src/services/walletconnect-service.ts
/** viem WalletClient — untyped to avoid cross-package viem version conflicts */
let _walletClient = null;
/** viem PublicClient — untyped for the same reason */
let _publicClient = null;
let _wcSigner = null;
let _connectedAddress = null;
let _mode = "none";
let _transactionHistory = [];
let _bankrEvmAddress = null;
let _bankrSolAddress = null;
let _bankrClub = false;
let _accountType;
let _hasCode;
let _delegationDesignation;
/**
* Initialize the wallet service. Called at gateway startup.
* 
* Priority:
* 1. Private key env var (headless/testing)
* 2. WalletConnect (production)
* 3. Bankr API key (custodial wallet)
*/
let _initPromise = null;
async function initWalletService(config) {
	if (_initPromise) return _initPromise;
	_initPromise = _doInitWalletService(config);
	try {
		return await _initPromise;
	} finally {
		_initPromise = null;
	}
}
async function _doInitWalletService(config) {
	const { createPublicClient, http } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
	const { base, baseSepolia } = await import("../../chains-DtOuO1lR.mjs").then((n) => n.t);
	const chain = config.network === "sepolia" ? baseSepolia : base;
	const rpcUrl = config.rpcUrl || void 0;
	_publicClient = createPublicClient({
		chain,
		transport: http(rpcUrl)
	});
	if (config.privateKey) {
		const { createWalletClient } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
		const { privateKeyToAccount } = await import("../../accounts-CgUUF-_i.mjs");
		const account = privateKeyToAccount(config.privateKey);
		_walletClient = createWalletClient({
			account,
			chain,
			transport: http(rpcUrl)
		});
		_walletClient = wrapWithBuilderCode(_walletClient, chain.id);
		_connectedAddress = account.address;
		_mode = "private_key";
		return {
			mode: "private_key",
			address: account.address
		};
	}
	if (!config.privateKey && hasKeychainWallet()) {
		const walletPassword = process.env.CLAWNCHER_WALLET_PASSWORD;
		if (walletPassword) try {
			const { account: keychainAccount } = await loadAndDecrypt(walletPassword);
			const { createWalletClient } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
			_walletClient = createWalletClient({
				account: keychainAccount,
				chain,
				transport: http(rpcUrl)
			});
			_walletClient = wrapWithBuilderCode(_walletClient, chain.id);
			_connectedAddress = keychainAccount.address;
			_mode = "private_key";
			return {
				mode: "private_key",
				address: keychainAccount.address
			};
		} catch (err) {
			console.warn(`[wallet] Keychain wallet decrypt failed: ${err instanceof Error ? err.message : String(err)}`);
		}
		else console.info("[wallet] Keychain wallet found but CLAWNCHER_WALLET_PASSWORD not set — skipping auto-unlock. Set CLAWNCHER_WALLET_PASSWORD env var for headless mode, or use onboarding to unlock interactively.");
	}
	if (config.walletConnectProjectId) {
		const { WalletConnectSigner } = await import("../../dist-B8YQn00c.mjs").then((n) => n.t);
		const sessionPath = config.sessionPath || `${process.env.HOME ?? ""}/.openclawnch/wc-session.json`;
		_wcSigner = new WalletConnectSigner({
			projectId: config.walletConnectProjectId,
			chain,
			sessionPath,
			policies: config.policies ?? [],
			metadata: {
				name: "OpenClawnch",
				description: "OpenClaw for crypto — AI assistant with DeFi capabilities",
				url: "https://clawn.ch",
				icons: ["https://clawn.ch/icon.png"]
			},
			requestTimeout: 18e4,
			onSessionChange: (state) => {
				if (state.status === "connected") _connectedAddress = state.address;
				else if (state.status === "disconnected" || state.status === "expired") {
					_connectedAddress = null;
					_walletClient = null;
				}
				config.onSessionChange?.(state);
			},
			onTransactionQueued: (tx) => {
				_transactionHistory.push({
					id: tx.id,
					status: "pending",
					summary: tx.context?.summary ?? "Transaction submitted",
					timestamp: tx.queuedAt,
					to: tx.transaction.to,
					value: tx.transaction.value?.toString()
				});
				config.onTransactionQueued?.(tx);
			},
			onTransactionApproved: (tx, hash) => {
				const record = _transactionHistory.find((r) => r.id === tx.id);
				if (record) {
					record.status = tx.policyLabel ? "auto_approved" : "approved";
					record.hash = hash;
					record.policyLabel = tx.policyLabel;
				}
				config.onTransactionApproved?.(tx, hash);
			},
			onTransactionRejected: (tx, reason) => {
				const record = _transactionHistory.find((r) => r.id === tx.id);
				if (record) record.status = "rejected";
				config.onTransactionRejected?.(tx, reason);
			}
		});
		const { uri, restored } = await _wcSigner.connect();
		if (restored) {
			_walletClient = await _wcSigner.toWalletClient(_publicClient);
			_walletClient = wrapWithBuilderCode(_walletClient, chain.id);
			_connectedAddress = _wcSigner.address;
			_mode = "walletconnect";
			return {
				mode: "walletconnect",
				address: _connectedAddress ?? void 0
			};
		}
		if (uri) {
			_mode = "walletconnect";
			return {
				mode: "walletconnect",
				pairingUri: uri
			};
		}
	}
	if (config.bankrApiKey) try {
		const { getBankrUserInfo } = await import("./bankr-api.mjs");
		if (!process.env.BANKR_API_KEY) process.env.BANKR_API_KEY = config.bankrApiKey;
		const userInfo = await getBankrUserInfo();
		const { isBankrClubActive } = await import("./bankr-types.mjs");
		const evmWallet = userInfo.wallets.find((w) => w.chain === "evm");
		const solWallet = userInfo.wallets.find((w) => w.chain === "solana");
		_bankrEvmAddress = evmWallet?.address ?? null;
		_bankrSolAddress = solWallet?.address ?? null;
		_bankrClub = isBankrClubActive(userInfo);
		_connectedAddress = _bankrEvmAddress ?? null;
		_mode = "bankr";
		return {
			mode: "bankr",
			address: _connectedAddress ?? void 0,
			solAddress: _bankrSolAddress ?? void 0
		};
	} catch (err) {
		console.warn(`[wallet] Bankr init failed: ${err instanceof Error ? err.message : String(err)}`);
	}
	_mode = "none";
	return { mode: "none" };
}
/**
* Wait for WalletConnect session to be established (after wallet approval).
*/
async function waitForWalletSession(timeoutMs = 3e5) {
	if (!_wcSigner) throw new Error("WalletConnect not initialized. Set WALLETCONNECT_PROJECT_ID.");
	const result = await _wcSigner.waitForSession(timeoutMs);
	_walletClient = await _wcSigner.toWalletClient(_publicClient);
	_walletClient = wrapWithBuilderCode(_walletClient, _publicClient?.chain?.id);
	_connectedAddress = result.address;
	return result;
}
function getWalletClient() {
	return _walletClient;
}
function getPublicClient() {
	return _publicClient;
}
function getWCSigner() {
	return _wcSigner;
}
function getWalletState() {
	return {
		connected: _connectedAddress !== null,
		address: _connectedAddress,
		chainId: _mode === "bankr" ? 8453 : _publicClient ? _publicClient.chain?.id ?? null : null,
		mode: _mode,
		policies: _wcSigner?.getPolicies() ?? [],
		wcState: _wcSigner?.getState() ?? null,
		bankrEvmAddress: _bankrEvmAddress ?? void 0,
		bankrSolAddress: _bankrSolAddress ?? void 0,
		bankrClub: _bankrClub || void 0,
		accountType: _accountType,
		hasCode: _hasCode,
		delegationDesignation: _delegationDesignation
	};
}
/**
* Check if the wallet is in Bankr custodial mode.
*/
function isBankrMode() {
	return _mode === "bankr";
}
/**
* Returns the appropriate execution context for tools that support both
* local wallet and Bankr paths.
*/
function requireBankrOrWallet() {
	if (_mode === "bankr") return { mode: "bankr" };
	if (_walletClient) return {
		mode: "local",
		client: _walletClient
	};
	throw new Error("No wallet connected. Use /connect or /connect_bankr to connect a wallet first.");
}
function getTransactionHistory() {
	return [..._transactionHistory];
}
function requireWalletClient() {
	if (!_walletClient) throw new Error("No wallet connected. Use the clawnchconnect tool with action \"connect\" first, or set CLAWNCHER_PRIVATE_KEY for headless mode.");
	return _walletClient;
}
function requirePublicClient() {
	if (!_publicClient) throw new Error("Public client not initialized. The wallet service must be started first.");
	return _publicClient;
}
/**
* Get a wallet client that routes write transactions through MEV-protected RPCs
* (Flashbots Protect, MEV Blocker) when available. Protects against sandwich
* attacks and frontrunning by bypassing the public mempool.
*
* Only effective in private_key mode — WalletConnect transactions are broadcast
* by the phone wallet (out of our control), and Bankr transactions are broadcast
* by the Bankr API.
*
* Falls back to the regular wallet client if:
* - MEV protection is disabled in RpcManager config
* - No MEV RPCs are available for the current chain
* - Mode is not private_key (WC, Bankr)
*/
async function getMevWalletClient() {
	const wallet = requireWalletClient();
	if (_mode !== "private_key") return wallet;
	try {
		const { getRpcManager } = await import("./rpc-provider.mjs");
		const rpcManager = getRpcManager();
		const chainId = _publicClient?.chain?.id ?? 8453;
		if (!rpcManager.isMevProtectionEnabled()) return wallet;
		const mevTransport = rpcManager.getMevTransport(chainId);
		if (!mevTransport) return wallet;
		const { createWalletClient } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
		return wrapWithBuilderCode(createWalletClient({
			account: wallet.account,
			chain: _publicClient?.chain,
			transport: mevTransport
		}), chainId);
	} catch (err) {
		console.warn("[wallet] MEV protection unavailable, using standard RPC:", err instanceof Error ? err.message : String(err));
		return wallet;
	}
}
/**
* EIP-7702 delegation designation prefix.
* An EIP-7702 delegated EOA has code: 0xef0100 + 20-byte implementation address.
* Total bytecode length = 23 bytes = 46 hex chars + '0x' prefix = 48 chars.
*/
const EIP7702_PREFIX = "0xef0100";
const EIP7702_CODE_LENGTH = 48;
/**
* Detect the account type of the connected wallet via eth_getCode.
*
* - EOA: getCode returns '0x' (no code)
* - Smart Account: getCode returns arbitrary bytecode (not EIP-7702 prefix)
* - EIP-7702: getCode returns 0xef0100 + 20-byte implementation address
*
* Results are cached on the wallet state. Call with `force: true` to re-detect.
* Returns null if no wallet is connected or no public client is available.
*/
async function detectAccountType(opts) {
	if (!opts?.force && _accountType !== void 0) return {
		accountType: _accountType,
		hasCode: _hasCode ?? false,
		delegationDesignation: _delegationDesignation
	};
	if (!_connectedAddress || !_publicClient) return null;
	try {
		const codeHex = await _publicClient.getCode({ address: _connectedAddress }) ?? "0x";
		if (codeHex === "0x" || codeHex === "0x0") {
			_accountType = "eoa";
			_hasCode = false;
			_delegationDesignation = void 0;
		} else if (codeHex.toLowerCase().startsWith(EIP7702_PREFIX) && codeHex.length === EIP7702_CODE_LENGTH) {
			_accountType = "eip7702";
			_hasCode = true;
			_delegationDesignation = "0x" + codeHex.slice(8);
		} else {
			_accountType = "smart_account";
			_hasCode = true;
			_delegationDesignation = void 0;
		}
		return {
			accountType: _accountType,
			hasCode: _hasCode,
			delegationDesignation: _delegationDesignation
		};
	} catch {
		return null;
	}
}
/**
* Clear the cached account type detection. Called on disconnect.
*/
function clearAccountTypeCache() {
	_accountType = void 0;
	_hasCode = void 0;
	_delegationDesignation = void 0;
}
async function disconnectWallet() {
	if (_wcSigner) await _wcSigner.disconnect();
	_walletClient = null;
	_connectedAddress = null;
	_bankrEvmAddress = null;
	_bankrSolAddress = null;
	_bankrClub = false;
	_mode = "none";
	clearAccountTypeCache();
}
function addPolicy(policy) {
	_wcSigner?.addPolicy(policy);
}
function removePolicy(label) {
	return _wcSigner?.removePolicy(label) ?? false;
}
function clearPolicies() {
	const policies = _wcSigner?.getPolicies() ?? [];
	for (const p of policies) _wcSigner?.removePolicy(p.label);
}
//#endregion
export { addPolicy, clearAccountTypeCache, clearPolicies, detectAccountType, disconnectWallet, getMevWalletClient, getPublicClient, getTransactionHistory, getWCSigner, getWalletClient, getWalletState, initWalletService, isBankrMode, removePolicy, requireBankrOrWallet, requirePublicClient, requireWalletClient, waitForWalletSession };

//# sourceMappingURL=walletconnect-service.mjs.map