import { c as stringEnum, i as jsonResult, l as textResult, r as errorResult, s as readStringParam, u as Type } from "../../tool-helpers-CVAcqiCy.mjs";
import { addPolicy, clearPolicies, disconnectWallet, getTransactionHistory, getWCSigner, getWalletState, initWalletService, isBankrMode, waitForWalletSession } from "../services/walletconnect-service.mjs";
import { getCredentialVault } from "../services/credential-vault.mjs";
//#region extensions/crypto/src/tools/clawnchconnect.ts
/**
* ClawnchConnect Tool — wallet connection and transaction signing
* 
* The core security model. The agent never holds private keys.
* Every transaction goes to the user's phone wallet for approval,
* unless spending policies auto-approve it.
*/
const ACTIONS = [
	"connect",
	"status",
	"disconnect",
	"send_tx",
	"set_policy",
	"sign_message"
];
const WALLETS = [
	"metamask",
	"rainbow",
	"coinbase",
	"trust",
	"zerion",
	"uniswap",
	"rabby",
	"bankr",
	"other"
];
const WALLET_DEEPLINKS = {
	metamask: "https://metamask.app.link/wc?uri=",
	rainbow: "https://rnbwapp.com/wc?uri=",
	coinbase: "https://go.cb-w.com/wc?uri=",
	trust: "https://link.trustwallet.com/wc?uri=",
	zerion: "https://wallet.zerion.io/wc?uri=",
	uniswap: "https://uniswap.org/app/wc?uri="
};
const DESKTOP_WALLETS = new Set(["rabby", "other"]);
const ClawnchConnectSchema = Type.Object({
	action: stringEnum(ACTIONS, { description: "The action to perform" }),
	wallet: Type.Optional(stringEnum(WALLETS, { description: "Which wallet app the user wants to connect. ASK THE USER which wallet they use before calling connect. Mobile: metamask, rainbow, coinbase, trust, zerion, uniswap. Desktop: rabby, other." })),
	project_id: Type.Optional(Type.String({ description: "WalletConnect project ID (if not set via env)" })),
	to: Type.Optional(Type.String({ description: "Target contract or wallet address (0x...)" })),
	value: Type.Optional(Type.String({ description: "ETH value to send (in ETH, e.g. \"0.01\")" })),
	data: Type.Optional(Type.String({ description: "Transaction calldata (hex)" })),
	summary: Type.Optional(Type.String({ description: "Human-readable description of the transaction" })),
	policy: Type.Optional(Type.String({ description: "Spending policy in natural language, e.g. \"approve under 0.05 ETH, max 10/hour\"" })),
	message: Type.Optional(Type.String({ description: "Message to sign" }))
});
/**
* @param api - OpenClawPluginApi instance (optional). When provided, the connect
*   action sends the WalletConnect link directly to the user via the channel,
*   bypassing LLM summarization which tends to drop URLs.
*/
function createClawnchConnectTool(api) {
	return {
		name: "clawnchconnect",
		label: "ClawnchConnect",
		ownerOnly: true,
		description: "Connect a wallet for human-approved blockchain transactions. IMPORTANT: For the connect action, you MUST ask the user which wallet app they use BEFORE calling this tool, then pass it as the wallet parameter. Actions: connect (pair wallet — requires wallet param), status (check connection), disconnect, send_tx (submit transaction for approval), set_policy (configure auto-approval rules in natural language), sign_message (request signature).",
		parameters: ClawnchConnectSchema,
		execute: async (_toolCallId, args) => {
			const params = args;
			const action = readStringParam(params, "action", { required: true });
			switch (action) {
				case "connect": return handleConnect(params, api);
				case "status": return handleStatus();
				case "disconnect": return handleDisconnect();
				case "send_tx": return handleSendTx(params);
				case "set_policy": return handleSetPolicy(params);
				case "sign_message": return handleSignMessage(params);
				default: return errorResult(`Unknown action: ${action}`);
			}
		}
	};
}
async function handleConnect(params, api) {
	const state = getWalletState();
	console.log(`[clawnchconnect:connect] state: connected=${state.connected} mode=${state.mode} address=${state.address}`);
	if (state.connected && state.address) return jsonResult({
		status: "already_connected",
		address: state.address,
		chainId: state.chainId,
		mode: state.mode,
		bankrEvmAddress: state.bankrEvmAddress,
		bankrSolAddress: state.bankrSolAddress
	});
	if ((readStringParam(params, "wallet") || "other") === "bankr") {
		const bankrApiKey = getCredentialVault().getSecret("bankr.apiKey", "clawnchconnect");
		if (!bankrApiKey) return errorResult("BANKR_API_KEY not set. Get a key at bankr.bot/api with Agent API enabled, then set: fly secrets set BANKR_API_KEY=\"bk_your_key\" -a <your-app>");
		try {
			const result = await initWalletService({ bankrApiKey });
			if (result.mode === "bankr") return jsonResult({
				status: "connected",
				mode: "bankr",
				address: result.address,
				solAddress: result.solAddress,
				note: "Connected via Bankr custodial wallet. Transactions execute server-side."
			});
			return errorResult("Bankr wallet initialization failed.");
		} catch (err) {
			return errorResult(`Bankr connect failed: ${err instanceof Error ? err.message : String(err)}`);
		}
	}
	const projectId = readStringParam(params, "project_id") || (getCredentialVault().getSecret("walletconnect.projectId", "clawnchconnect") ?? void 0);
	const privateKey = getCredentialVault().getSecret("wallet.privateKey", "clawnchconnect") ?? void 0;
	if (!projectId && !privateKey) return errorResult("No wallet configuration found. Set WALLETCONNECT_PROJECT_ID env var or pass project_id parameter to connect via WalletConnect. For testing, set CLAWNCHER_PRIVATE_KEY.");
	try {
		console.log(`[clawnchconnect:connect] Calling initWalletService (fresh)`);
		const result = await initWalletService({
			privateKey,
			walletConnectProjectId: projectId,
			rpcUrl: process.env.CLAWNCHER_RPC_URL,
			network: process.env.CLAWNCHER_NETWORK || "mainnet",
			sessionPath: process.env.WALLETCONNECT_SESSION || `${process.env.HOME ?? ""}/.openclawnch/wc-session.json`
		});
		console.log(`[clawnchconnect:connect] initWalletService result: mode=${result.mode} hasUri=${!!result.pairingUri} hasAddress=${!!result.address}`);
		if (result.mode === "private_key") return jsonResult({
			status: "connected",
			mode: "private_key",
			address: result.address,
			note: "Using private key (headless mode). Transactions are auto-signed."
		});
		if (result.pairingUri) {
			const wallet = readStringParam(params, "wallet") || "other";
			waitForWalletSession(3e5).then((session) => {
				console.log(`[clawnchconnect] Session established: ${session.address} (chain ${session.chainId})`);
				if (api) {
					const sendFn = api.runtime?.channel?.telegram?.sendMessageTelegram;
					const chatId = params._chatId ?? params._senderId;
					const chatIdStr = chatId != null ? String(chatId) : "";
					if (sendFn && chatIdStr && /^\d+$/.test(chatIdStr)) sendFn(chatIdStr, `Wallet connected!\n\nAddress: ${session.address.slice(0, 6)}...${session.address.slice(-4)}\nChain: ${session.chainId}\n\nYou're ready to trade. Try: "What's the price of ETH?" or "Show my balance"`, { accountId: "default" }).catch((err) => console.log(`[clawnchconnect] Failed to send confirmation: ${err}`));
					else api.logger?.info?.(`[clawnchconnect] Wallet connected: ${session.address} — no chatId available to send confirmation`);
				}
			}).catch((err) => {
				console.log(`[clawnchconnect] Session wait failed: ${err instanceof Error ? err.message : String(err)}`);
			});
			return returnConnectLink(result.pairingUri, wallet);
		}
		if (result.address) return jsonResult({
			status: "connected",
			mode: "walletconnect",
			address: result.address,
			note: "Session restored from previous connection."
		});
		return errorResult("WalletConnect failed to generate a pairing link. The relay server may be down. Try again in a minute.");
	} catch (err) {
		const msg = err instanceof Error ? err.message : String(err);
		console.log(`[clawnchconnect:connect] Error: ${msg}`);
		return errorResult(`Connection failed: ${msg}`);
	}
}
/**
* Build a wallet-specific connect link and return it.
* Mobile wallets get a tappable deep link. Desktop/extension wallets get the raw wc: URI to paste.
*/
function returnConnectLink(pairingUri, wallet) {
	const encodedUri = encodeURIComponent(pairingUri);
	if (DESKTOP_WALLETS.has(wallet)) {
		console.log(`[clawnchconnect] Desktop wallet "${wallet}" — returning raw URI`);
		return textResult(`Copy this connection code and paste it in your wallet's WalletConnect input:\n\n${pairingUri}\n\nExpires in 5 minutes.`);
	}
	const deepLinkBase = WALLET_DEEPLINKS[wallet];
	if (deepLinkBase) {
		const deepLink = `${deepLinkBase}${encodedUri}`;
		console.log(`[clawnchconnect] Deep link for "${wallet}" (${deepLink.length} chars)`);
		return textResult(deepLink);
	}
	console.log(`[clawnchconnect] Unknown wallet "${wallet}" — returning raw URI`);
	return textResult(`Copy this connection code and paste it in your wallet's WalletConnect scanner:\n\n${pairingUri}\n\nExpires in 5 minutes.`);
}
async function handleStatus() {
	const state = getWalletState();
	if (!state.connected) return jsonResult({
		status: "disconnected",
		message: "No wallet connected. Use action \"connect\" to pair a wallet."
	});
	if (state.mode === "bankr") return jsonResult({
		status: "connected",
		mode: "bankr",
		evmAddress: state.bankrEvmAddress,
		solanaAddress: state.bankrSolAddress,
		bankrClub: state.bankrClub,
		chains: [
			"base",
			"ethereum",
			"polygon",
			"unichain",
			"solana"
		],
		security: "Bankr Sentinel (server-side transaction screening)",
		note: "Custodial wallet — transactions execute server-side. No phone approval needed."
	});
	let ethBalance;
	try {
		const { requirePublicClient } = await import("../services/walletconnect-service.mjs");
		const balance = await requirePublicClient().getBalance({ address: state.address });
		const { formatEther } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
		ethBalance = formatEther(balance);
	} catch {}
	const txHistory = getTransactionHistory();
	const recentTxs = txHistory.slice(-5).reverse().map((tx) => ({
		status: tx.status,
		summary: tx.summary,
		hash: tx.hash,
		policyLabel: tx.policyLabel
	}));
	return jsonResult({
		status: "connected",
		address: state.address,
		chainId: state.chainId,
		mode: state.mode,
		ethBalance,
		policies: state.policies.map((p) => ({
			label: p.label,
			maxValueEth: p.maxValueWei ? Number(p.maxValueWei) / 0xde0b6b3a7640000 : "unlimited",
			allowedContracts: p.allowedContracts?.length ?? "any",
			maxPerHour: p.maxPerHour ?? "unlimited",
			enabled: p.enabled !== false
		})),
		recentTransactions: recentTxs.length > 0 ? recentTxs : void 0,
		transactionCount: txHistory.length || void 0
	});
}
async function handleDisconnect() {
	const state = getWalletState();
	if (!state.connected) return textResult("No wallet is currently connected.");
	await disconnectWallet();
	return textResult(`Disconnected wallet ${state.address}. Session cleared.`);
}
function isValidAddress(addr) {
	return /^0x[a-fA-F0-9]{40}$/.test(addr);
}
async function handleSendTx(params) {
	if (!getWalletState().connected) return errorResult("No wallet connected. Use action \"connect\" first.");
	if (isBankrMode()) {
		const to = readStringParam(params, "to", { required: true });
		if (!isValidAddress(to)) return errorResult(`Invalid target address: "${to}". Must be a valid 0x... Ethereum address.`);
		const valueStr = readStringParam(params, "value");
		const summary = readStringParam(params, "summary") || "Transaction submitted by agent";
		try {
			const { bankrPromptAndPoll } = await import("../services/bankr-api.mjs");
			const result = await bankrPromptAndPoll(valueStr ? `send ${valueStr} ETH to ${to}` : `send transaction to ${to}`, { timeoutMs: 6e4 });
			if (result.status === "failed") return errorResult(`Transaction failed: ${result.error ?? "Unknown error"}`);
			const txData = result.transactions?.[0];
			return jsonResult({
				status: "sent",
				mode: "bankr",
				hash: txData?.hash,
				summary,
				response: result.response
			});
		} catch (err) {
			return errorResult(`Transaction failed: ${err instanceof Error ? err.message : String(err)}`);
		}
	}
	const signer = getWCSigner();
	const to = readStringParam(params, "to", { required: true });
	if (!isValidAddress(to)) return errorResult(`Invalid target address: "${to}". Must be a valid 0x... Ethereum address.`);
	const valueStr = readStringParam(params, "value");
	const data = readStringParam(params, "data");
	const summary = readStringParam(params, "summary") || "Transaction submitted by agent";
	if (valueStr && !/^\d+(\.\d+)?$/.test(valueStr.trim())) return errorResult(`Invalid value: "${valueStr}". Must be a positive number (in ETH).`);
	try {
		const { parseEther } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
		const value = valueStr ? parseEther(valueStr) : void 0;
		if (signer) {
			const result = await signer.sendTransaction({
				to,
				value,
				data
			}, {
				summary,
				estimatedGasCostEth: "estimating..."
			});
			const { requirePublicClient } = await import("../services/walletconnect-service.mjs");
			const receipt = await requirePublicClient().waitForTransactionReceipt({ hash: result.hash });
			return jsonResult({
				status: receipt.status === "reverted" ? "reverted" : result.autoApproved ? "auto_approved" : "approved",
				hash: result.hash,
				policyLabel: result.policyLabel,
				summary,
				blockNumber: receipt.blockNumber.toString(),
				gasUsed: receipt.gasUsed.toString()
			});
		} else {
			const { requireWalletClient, requirePublicClient } = await import("../services/walletconnect-service.mjs");
			const wallet = requireWalletClient();
			const publicClient = requirePublicClient();
			const hash = await wallet.sendTransaction({
				to,
				value,
				data
			});
			const receipt = await publicClient.waitForTransactionReceipt({ hash });
			return jsonResult({
				status: receipt.status === "reverted" ? "reverted" : "sent",
				hash,
				summary,
				blockNumber: receipt.blockNumber.toString(),
				gasUsed: receipt.gasUsed.toString(),
				note: "Sent directly (private key mode, no approval required)"
			});
		}
	} catch (err) {
		return errorResult(`Transaction failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleSetPolicy(params) {
	const policyInput = readStringParam(params, "policy", { required: true });
	try {
		const { parsePolicies, formatPolicy } = await import("../../dist-B8YQn00c.mjs").then((n) => n.t);
		const result = parsePolicies(policyInput);
		if (result.clearAll) {
			clearPolicies();
			return textResult("All spending policies cleared. Every transaction will require manual approval.");
		}
		if (result.unrecognized.length > 0 && result.policies.length === 0) return errorResult(`Could not parse policy: "${policyInput}"\n\nExamples:
  "approve under 0.05 ETH"
  "auto-approve below 0.01 ETH, max 10/hour"
  "allow only 0xABC...DEF"
  "no auto-approve" (clear all)`);
		for (const policy of result.policies) addPolicy(policy);
		return jsonResult({
			status: "policies_updated",
			added: result.policies.map((p) => formatPolicy(p)),
			unrecognized: result.unrecognized.length > 0 ? result.unrecognized : void 0,
			allPolicies: getWalletState().policies.map((p) => formatPolicy(p))
		});
	} catch (err) {
		return errorResult(`Failed to set policy: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleSignMessage(params) {
	const message = readStringParam(params, "message", { required: true });
	if (isBankrMode()) try {
		const { bankrSign } = await import("../services/bankr-api.mjs");
		const result = await bankrSign({
			signatureType: "personal_sign",
			message
		});
		return jsonResult({
			status: "signed",
			signature: result.signature,
			signer: result.signer,
			mode: "bankr",
			message
		});
	} catch (err) {
		return errorResult(`Bankr signing failed: ${err instanceof Error ? err.message : String(err)}`);
	}
	const signer = getWCSigner();
	if (!signer) return errorResult("Message signing requires WalletConnect or Bankr. Not available in private key mode.");
	try {
		return jsonResult({
			status: "signed",
			signature: (await signer.signMessage(message)).signature,
			message
		});
	} catch (err) {
		return errorResult(`Signing failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
//#endregion
export { createClawnchConnectTool };

//# sourceMappingURL=clawnchconnect.mjs.map