import { c as stringEnum, i as jsonResult, r as errorResult, s as readStringParam, u as Type } from "../../tool-helpers-CVAcqiCy.mjs";
import { getMevWalletClient, getWalletState, requirePublicClient, requireWalletClient } from "../services/walletconnect-service.mjs";
import { isEnsName, resolveAddressOrEns } from "../lib/ens-resolver.mjs";
import { checkBalance } from "../services/safety-service.mjs";
//#region extensions/crypto/src/tools/transfer.ts
/**
* Transfer Tool — Send ETH or ERC-20 tokens to a recipient address.
*
* The most fundamental wallet operation. Uses viem directly for ETH transfers,
* and the erc20Abi for ERC-20 transfers. Reads token metadata (decimals, symbol)
* via ClawnchSwapper. All transactions go through ClawnchConnect for approval.
*
* Safety: pre-flight balance check via safety-service.
*/
const TransferSchema = Type.Object({
	action: stringEnum(["send", "estimate"], { description: "send: execute the transfer. estimate: check balance and estimate gas without sending." }),
	to: Type.String({ description: "Recipient address (0x...) or ENS name (e.g. vitalik.eth)" }),
	amount: Type.String({ description: "Amount to send in human-readable units (e.g. \"0.1\" for 0.1 ETH, \"100\" for 100 USDC)" }),
	token: Type.Optional(Type.String({ description: "ERC-20 token contract address (0x...). Omit for native ETH transfer." }))
});
function createTransferTool() {
	return {
		name: "transfer",
		label: "Transfer",
		ownerOnly: true,
		description: "Send ETH or ERC-20 tokens to a recipient address. Use action \"estimate\" to preview gas costs and check balance, or \"send\" to execute. All transactions go through ClawnchConnect for approval.",
		parameters: TransferSchema,
		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.");
			switch (action) {
				case "send": return handleSend(params);
				case "estimate": return handleEstimate(params);
				default: return errorResult(`Unknown action: ${action}. Use: send, estimate`);
			}
		}
	};
}
function isValidAddress(addr) {
	return /^0x[a-fA-F0-9]{40}$/.test(addr);
}
const BASE_TOKENS = {
	USDC: {
		address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
		decimals: 6,
		symbol: "USDC"
	},
	USDT: {
		address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
		decimals: 6,
		symbol: "USDT"
	},
	DAI: {
		address: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
		decimals: 18,
		symbol: "DAI"
	},
	WETH: {
		address: "0x4200000000000000000000000000000000000006",
		decimals: 18,
		symbol: "WETH"
	},
	CLAWNCH: {
		address: "0xa1F72459dfA10BAD200Ac160eCd78C6b77a747be",
		decimals: 18,
		symbol: "CLAWNCH"
	}
};
async function getTokenInfo(tokenAddress) {
	for (const info of Object.values(BASE_TOKENS)) if (info.address.toLowerCase() === tokenAddress.toLowerCase()) return {
		decimals: info.decimals,
		symbol: info.symbol
	};
	try {
		const { ClawnchSwapper } = await import("../../dist-CXAY4yCt.mjs");
		const swapper = new ClawnchSwapper({
			wallet: requireWalletClient(),
			publicClient: requirePublicClient(),
			network: "mainnet"
		});
		const [decimals, symbol] = await Promise.all([swapper.getDecimals(tokenAddress), swapper.getSymbol(tokenAddress)]);
		return {
			decimals,
			symbol
		};
	} catch {
		return {
			decimals: 18,
			symbol: "UNKNOWN"
		};
	}
}
function parseTokenAmount(amount, decimals) {
	const trimmed = amount.trim();
	if (!trimmed || !/^\d+(\.\d+)?$/.test(trimmed)) throw new Error(`Invalid amount: "${amount}". Must be a positive number (e.g. "1.5" or "100").`);
	const parts = trimmed.split(".");
	const whole = parts[0] ?? "0";
	let fraction = parts[1] ?? "";
	if (fraction.length > decimals) fraction = fraction.slice(0, decimals);
	else fraction = fraction.padEnd(decimals, "0");
	return BigInt(whole + fraction);
}
async function handleEstimate(params) {
	const toInput = readStringParam(params, "to", { required: true });
	const amount = readStringParam(params, "amount", { required: true });
	if (!/^\d+(\.\d+)?$/.test(amount.trim())) return errorResult(`Invalid amount: "${amount}". Must be a positive number (e.g. "1.5" or "100").`);
	const tokenAddr = readStringParam(params, "token");
	if (tokenAddr && !isValidAddress(tokenAddr)) return errorResult(`Invalid token address: "${tokenAddr}". Must be a valid 0x... address.`);
	if (!isValidAddress(toInput) && !isEnsName(toInput)) return errorResult(`Invalid recipient address: "${toInput}". Must be a valid 0x... Ethereum address (40 hex chars) or ENS name (e.g. vitalik.eth).`);
	let to;
	try {
		const resolved = await resolveAddressOrEns(toInput, requirePublicClient());
		to = resolved.address;
		resolved.ensName;
	} catch (err) {
		return errorResult(err instanceof Error ? err.message : String(err));
	}
	const isErc20 = !!tokenAddr;
	try {
		const publicClient = requirePublicClient();
		const state = getWalletState();
		const { formatEther, formatUnits, erc20Abi } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
		const ethBalanceFormatted = formatEther(await publicClient.getBalance({ address: state.address }));
		const result = {
			to,
			amount,
			type: isErc20 ? "ERC-20" : "ETH",
			ethBalance: ethBalanceFormatted
		};
		if (isErc20) {
			const info = await getTokenInfo(tokenAddr);
			result.token = {
				address: tokenAddr,
				symbol: info.symbol,
				decimals: info.decimals
			};
			try {
				const tokenBalance = await publicClient.readContract({
					address: tokenAddr,
					abi: erc20Abi,
					functionName: "balanceOf",
					args: [state.address]
				});
				result.tokenBalance = formatUnits(tokenBalance, info.decimals);
				const amountWei = parseTokenAmount(amount, info.decimals);
				if (amountWei > tokenBalance) {
					result.sufficientTokenBalance = false;
					result.shortfall = formatUnits(amountWei - tokenBalance, info.decimals);
				} else result.sufficientTokenBalance = true;
			} catch (err) {
				result.tokenBalanceError = err instanceof Error ? err.message : String(err);
			}
			const safety = await checkBalance({ requiredEth: 0 });
			result.sufficientGas = safety.safe;
			if (!safety.safe) result.gasWarning = safety.blockers.join("; ");
		} else {
			const safety = await checkBalance({ requiredEth: parseFloat(amount) });
			result.sufficientBalance = safety.safe;
			if (!safety.safe) result.balanceWarning = safety.blockers.join("; ");
			if (safety.warnings.length > 0) result.warnings = safety.warnings;
		}
		try {
			if (isErc20) {
				const amountWei = parseTokenAmount(amount, result.token.decimals);
				result.estimatedGas = (await publicClient.estimateGas({
					account: state.address,
					to: tokenAddr,
					data: encodeFunctionData_transfer(to, amountWei)
				})).toString();
			} else {
				const { parseEther } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
				result.estimatedGas = (await publicClient.estimateGas({
					account: state.address,
					to,
					value: parseEther(amount)
				})).toString();
			}
		} catch (err) {
			result.gasEstimateError = err instanceof Error ? err.message : String(err);
		}
		return jsonResult(result);
	} catch (err) {
		return errorResult(`Estimate failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
async function handleSend(params) {
	const toInput = readStringParam(params, "to", { required: true });
	const amount = readStringParam(params, "amount", { required: true });
	if (!/^\d+(\.\d+)?$/.test(amount.trim())) return errorResult(`Invalid amount: "${amount}". Must be a positive number (e.g. "1.5" or "100").`);
	const tokenAddr = readStringParam(params, "token");
	if (tokenAddr && !isValidAddress(tokenAddr)) return errorResult(`Invalid token address: "${tokenAddr}". Must be a valid 0x... address.`);
	if (!isValidAddress(toInput) && !isEnsName(toInput)) return errorResult(`Invalid recipient address: "${toInput}". Must be a valid 0x... Ethereum address (40 hex chars) or ENS name (e.g. vitalik.eth).`);
	let to;
	let ensName;
	try {
		const resolved = await resolveAddressOrEns(toInput, requirePublicClient());
		to = resolved.address;
		ensName = resolved.ensName;
	} catch (err) {
		return errorResult(err instanceof Error ? err.message : String(err));
	}
	const isErc20 = !!tokenAddr;
	try {
		const wallet = await getMevWalletClient();
		const publicClient = requirePublicClient();
		if (isErc20) {
			const info = await getTokenInfo(tokenAddr);
			const amountWei = parseTokenAmount(amount, info.decimals);
			const { erc20Abi, formatUnits } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
			const state = getWalletState();
			const tokenBalance = await publicClient.readContract({
				address: tokenAddr,
				abi: erc20Abi,
				functionName: "balanceOf",
				args: [state.address]
			});
			if (amountWei > tokenBalance) return errorResult(`Insufficient ${info.symbol} balance. Have: ${formatUnits(tokenBalance, info.decimals)}, need: ${amount}`);
			const safety = await checkBalance({ requiredEth: 0 });
			if (!safety.safe) return errorResult(`Insufficient gas: ${safety.blockers.join("; ")}`);
			const txHash = await wallet.writeContract({
				address: tokenAddr,
				abi: erc20Abi,
				functionName: "transfer",
				args: [to, amountWei]
			});
			const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
			if (receipt.status === "reverted") return errorResult(`Transfer reverted. TX: ${txHash}`);
			return jsonResult({
				status: "success",
				type: "ERC-20",
				token: {
					address: tokenAddr,
					symbol: info.symbol,
					decimals: info.decimals
				},
				to,
				...ensName ? { ensName } : {},
				amount,
				amountWei: amountWei.toString(),
				txHash,
				blockNumber: receipt.blockNumber.toString(),
				gasUsed: receipt.gasUsed.toString()
			});
		} else {
			const safety = await checkBalance({ requiredEth: parseFloat(amount) });
			if (!safety.safe) return errorResult(`Insufficient balance: ${safety.blockers.join("; ")}`);
			const { parseEther } = await import("../../_esm-BrzUp3yp.mjs").then((n) => n.t);
			const value = parseEther(amount);
			const txHash = await wallet.sendTransaction({
				to,
				value
			});
			const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
			if (receipt.status === "reverted") return errorResult(`Transfer reverted. TX: ${txHash}`);
			return jsonResult({
				status: "success",
				type: "ETH",
				to,
				...ensName ? { ensName } : {},
				amount,
				amountWei: value.toString(),
				txHash,
				blockNumber: receipt.blockNumber.toString(),
				gasUsed: receipt.gasUsed.toString()
			});
		}
	} catch (err) {
		return errorResult(`Transfer failed: ${err instanceof Error ? err.message : String(err)}`);
	}
}
/**
* Minimal ERC-20 transfer calldata encoder (avoids importing encodeFunctionData).
* transfer(address,uint256) = 0xa9059cbb
*/
function encodeFunctionData_transfer(to, amount) {
	return `0xa9059cbb${to.slice(2).toLowerCase().padStart(64, "0")}${amount.toString(16).padStart(64, "0")}`;
}
//#endregion
export { createTransferTool };

//# sourceMappingURL=transfer.mjs.map