import { c as stringEnum, i as jsonResult, r as errorResult, s as readStringParam, u as Type } from "../../tool-helpers-CVAcqiCy.mjs";
import { getWalletState, isBankrMode, requirePublicClient, requireWalletClient } from "../services/walletconnect-service.mjs";
//#region extensions/crypto/src/tools/permit2.ts
/**
* Permit2 Tool — Manage Uniswap Permit2 token allowances.
*
* Permit2 is the universal token approval system used by Uniswap V4 and other
* modern DeFi protocols. Instead of approving each contract individually,
* you approve Permit2 once per token, then use gas-free signatures for
* individual spender allowances.
*
* Actions:
*   check_allowance — Read current Permit2 allowance for a token/spender pair
*   approve         — Approve a token for Permit2 (ERC-20 → Permit2 max approval)
*   approve_batch   — Approve multiple tokens for Permit2 in sequence
*   revoke          — Set a Permit2 allowance to zero for a specific spender
*   lockdown        — Emergency: revoke all Permit2 allowances for multiple pairs
*
* Uses Permit2Client from @clawnch/clawncher-sdk.
*/
const ACTIONS = [
	"check_allowance",
	"approve",
	"approve_batch",
	"revoke",
	"lockdown"
];
/** Canonical Permit2 address (same on all chains) */
const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
/** Well-known spender addresses on Base */
const KNOWN_SPENDERS = {
	universal_router: "0x198EF79F1F515F02dFE9e3115eD9fC07183f02fC",
	position_manager: "0x7C5f5A4bBd8fD63184577525326123B519429bDc"
};
const Permit2Schema = Type.Object({
	action: stringEnum(ACTIONS, { description: "check_allowance: read current Permit2 allowance for token/spender. approve: approve a token for Permit2 (one-time ERC-20 max approval). approve_batch: approve multiple tokens for Permit2. revoke: set Permit2 allowance to zero for a spender. lockdown: emergency revoke multiple token/spender pairs." }),
	token: Type.Optional(Type.String({ description: "ERC-20 token contract address (0x...). Required for check_allowance, approve, revoke." })),
	amount: Type.Optional(Type.String({ description: "Scoped approval amount in token smallest unit. If omitted, max approval is used. Use to limit Permit2 exposure." })),
	tokens: Type.Optional(Type.Array(Type.String(), { description: "Array of token addresses for approve_batch." })),
	spender: Type.Optional(Type.String({ description: "Spender address (0x...) or alias: \"universal_router\", \"position_manager\". Required for check_allowance, revoke." })),
	pairs: Type.Optional(Type.Array(Type.Object({
		token: Type.String({ description: "Token address" }),
		spender: Type.String({ description: "Spender address or alias" })
	}), { description: "Token/spender pairs for lockdown action." }))
});
function createPermit2Tool() {
	return {
		name: "permit2",
		label: "Permit2",
		ownerOnly: true,
		description: "Manage Uniswap Permit2 token allowances. Check, approve, or revoke Permit2 allowances for DeFi protocols. Use \"lockdown\" for emergency revocation.",
		parameters: Permit2Schema,
		execute: async (_toolCallId, args) => {
			const params = args;
			const action = readStringParam(params, "action", { required: true });
			if (!getWalletState().connected) return errorResult("No wallet connected. Use clawnchconnect tool to connect first.");
			if (isBankrMode() && (action === "approve" || action === "approve_batch")) return jsonResult({
				status: "not_needed",
				mode: "bankr",
				message: "Bankr wallet handles token approvals automatically during swaps. No manual Permit2 approval is needed."
			});
			switch (action) {
				case "check_allowance": return handleCheckAllowance(params);
				case "approve": return handleApprove(params);
				case "approve_batch": return handleApproveBatch(params);
				case "revoke": return handleRevoke(params);
				case "lockdown": return handleLockdown(params);
				default: return errorResult(`Unknown action: ${action}. Use: ${ACTIONS.join(", ")}`);
			}
		}
	};
}
function resolveSpender(input) {
	const alias = KNOWN_SPENDERS[input.toLowerCase()];
	if (alias) return alias;
	if (input.startsWith("0x") && input.length === 42) return input;
	throw new Error(`Invalid spender: "${input}". Use an address (0x...) or alias: ${Object.keys(KNOWN_SPENDERS).join(", ")}`);
}
async function getPermit2Client() {
	const { Permit2Client } = await import("../../dist-CXAY4yCt.mjs");
	return new Permit2Client({
		wallet: requireWalletClient(),
		publicClient: requirePublicClient(),
		chainId: 8453
	});
}
async function handleCheckAllowance(params) {
	const token = readStringParam(params, "token", { required: true });
	const spenderInput = readStringParam(params, "spender", { required: true });
	try {
		const spender = resolveSpender(spenderInput);
		const allowance = await (await getPermit2Client()).getAllowance(token, spender);
		const now = Math.floor(Date.now() / 1e3);
		const isExpired = allowance.expiration > 0 && allowance.expiration < now;
		const isActive = allowance.amount > 0n && !isExpired;
		return jsonResult({
			token,
			spender,
			spenderAlias: KNOWN_SPENDERS[spenderInput.toLowerCase()] ? spenderInput : void 0,
			amount: allowance.amount.toString(),
			amountReadable: allowance.amount === BigInt("0xffffffffffffffffffffffffffffffffffffffff") ? "MAX (uint160)" : allowance.amount.toString(),
			expiration: allowance.expiration,
			expirationDate: allowance.expiration > 0 ? (/* @__PURE__ */ new Date(allowance.expiration * 1e3)).toISOString() : "never",
			nonce: allowance.nonce,
			isExpired,
			isActive,
			permit2Address: PERMIT2_ADDRESS
		});
	} catch (err) {
		return errorResult(`Check allowance failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleApprove(params) {
	const token = readStringParam(params, "token", { required: true });
	if (!token.match(/^0x[a-fA-F0-9]{40}$/)) return errorResult("Invalid token address. Must be a valid 0x... address.");
	try {
		const client = await getPermit2Client();
		const scopedAmount = readStringParam(params, "amount");
		if (scopedAmount) {
			if (!/^\d+$/.test(scopedAmount.trim())) return errorResult(`Invalid amount: "${scopedAmount}". Must be a non-negative integer in the token's smallest unit (e.g. wei).`);
			const spender = resolveSpender(readStringParam(params, "spender") || "universal_router");
			const amount = BigInt(scopedAmount.trim());
			const expiration = Math.floor(Date.now() / 1e3) + 86400 * 30;
			return jsonResult({
				status: "approved",
				token,
				permit2Address: PERMIT2_ADDRESS,
				txHash: await client.directApprove(token, spender, amount, expiration),
				approvedAmount: scopedAmount,
				expiresIn: "30 days",
				message: "Token approved for Permit2 with scoped allowance."
			});
		}
		const txHash = await client.ensureTokenApproval(token);
		if (txHash === null) return jsonResult({
			status: "already_approved",
			token,
			permit2Address: PERMIT2_ADDRESS,
			message: "Token already has max approval for Permit2. No transaction needed."
		});
		return jsonResult({
			status: "approved",
			token,
			permit2Address: PERMIT2_ADDRESS,
			txHash,
			message: "Token approved for Permit2 with max allowance. Use \"amount\" param to scope the approval."
		});
	} catch (err) {
		return errorResult(`Approve failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleApproveBatch(params) {
	const tokensRaw = params.tokens;
	if (!Array.isArray(tokensRaw) || tokensRaw.length === 0) return errorResult("approve_batch requires a non-empty \"tokens\" array of token addresses.");
	const tokens = [];
	for (const t of tokensRaw) {
		const addr = String(t).toLowerCase();
		if (!/^0x[0-9a-f]{40}$/.test(addr)) return errorResult(`Invalid token address: "${t}". Must be a 42-character hex address starting with 0x.`);
		tokens.push(addr);
	}
	try {
		const results = await (await getPermit2Client()).ensureTokenApprovals(tokens);
		const approvals = [];
		for (const token of tokens) {
			const hash = results.get(token);
			approvals.push({
				token,
				txHash: hash ?? null,
				status: hash ? "approved" : "already_approved"
			});
		}
		return jsonResult({
			permit2Address: PERMIT2_ADDRESS,
			totalTokens: tokens.length,
			newApprovals: approvals.filter((a) => a.status === "approved").length,
			alreadyApproved: approvals.filter((a) => a.status === "already_approved").length,
			approvals
		});
	} catch (err) {
		return errorResult(`Batch approve failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleRevoke(params) {
	const token = readStringParam(params, "token", { required: true });
	const spenderInput = readStringParam(params, "spender", { required: true });
	try {
		const spender = resolveSpender(spenderInput);
		return jsonResult({
			status: "revoked",
			token,
			spender,
			txHash: await (await getPermit2Client()).directApprove(token, spender, 0n, 0),
			message: "Permit2 allowance set to zero for this token/spender pair."
		});
	} catch (err) {
		return errorResult(`Revoke failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleLockdown(params) {
	const pairsRaw = params.pairs;
	if (!Array.isArray(pairsRaw) || pairsRaw.length === 0) return errorResult("lockdown requires a non-empty \"pairs\" array of {token, spender} objects.");
	try {
		const pairs = [];
		for (const p of pairsRaw) {
			const tokenAddr = String(p.token ?? "").toLowerCase();
			if (!/^0x[0-9a-f]{40}$/.test(tokenAddr)) return errorResult(`Invalid token address in lockdown pair: "${p.token}".`);
			pairs.push({
				token: tokenAddr,
				spender: resolveSpender(String(p.spender ?? ""))
			});
		}
		const txHash = await (await getPermit2Client()).lockdown(pairs);
		return jsonResult({
			status: "lockdown_complete",
			pairsRevoked: pairs.length,
			pairs: pairs.map((p) => ({
				token: p.token,
				spender: p.spender
			})),
			txHash,
			message: `Emergency lockdown: ${pairs.length} token/spender pair(s) revoked.`
		});
	} catch (err) {
		return errorResult(`Lockdown failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
//#endregion
export { createPermit2Tool };

//# sourceMappingURL=permit2.mjs.map