import { n as __exportAll } from "./chunk-BEJ448es.mjs";
import { q as decodeAbiParameters } from "./getCallError-CUwV9zg3.mjs";
import { i as createPublicClient, n as http, o as encodePacked, r as createWalletClient } from "./_esm-BKtdEVdT.mjs";
import { R as encodeAbiParameters } from "./chain-CFT4ZwjV.mjs";
import { a as mainnet, c as base, i as optimism, l as arbitrum, n as sepolia, o as linea, r as polygon, s as baseSepolia } from "./chains-Bx4KIVmV.mjs";
import { t as getPolicyStore } from "./policy-store-Buwyt3oE.mjs";
import { n as getDelegationStore } from "./delegation-store-CLeIO327.mjs";
//#region extensions/crypto/src/services/delegation-types.ts
const DELEGATION_CONTRACTS = {
	DelegationManager: "0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3",
	EIP7702StatelessDeleGator: "0x63c0c19a282a1B52b07dD5a65b58948A07DAE32B",
	HybridDeleGator: "0x48dBe696A4D990079e039489bA2053B36E8FFEC4",
	MultiSigDeleGator: "0x56a9EdB16a0105eb5a4C54f4C062e2868844f3A7",
	ERC20TransferAmountEnforcer: "0xf100b0819427117EcF76Ed94B358B1A5b5C6D2Fc",
	ERC20PeriodTransferEnforcer: "0x474e3Ae7E169e940607cC624Da8A15Eb120139aB",
	LimitedCallsEnforcer: "0x04658B29F6b82ed55274221a06Fc97D318E25416",
	AllowedTargetsEnforcer: "0x7F20f61b1f09b08D970938F6fa563634d65c4EeB",
	AllowedMethodsEnforcer: "0x2c21fD0Cb9DC8445CB3fb0DC5E7Bb0Aca01842B5",
	TimestampEnforcer: "0x1046bb45C8d673d4ea75321280DB34899413c069",
	NativeTokenTransferAmountEnforcer: "0xF71af580b9c3078fbc2BBF16FbB8EEd82b330320",
	NativeTokenPeriodTransferEnforcer: "0x9BC0FAf4Aca5AE429F4c06aEEaC517520CB16BD9",
	ValueLteEnforcer: "0x92Bf12322527cAA612fd31a0e810472BBB106A8F",
	NonceEnforcer: "0xDE4f2FAC4B3D87A1d9953Ca5FC09FCa7F366254f"
};
const SUPPORTED_CHAIN_IDS = new Set([
	1,
	8453,
	42161,
	10,
	137,
	59144,
	11155111,
	84532
]);
const CHAIN_NAMES = {
	1: "Ethereum",
	8453: "Base",
	42161: "Arbitrum",
	10: "Optimism",
	137: "Polygon",
	59144: "Linea",
	11155111: "Sepolia",
	84532: "Base Sepolia"
};
const DELEGATION_EIP712_TYPES = {
	Delegation: [
		{
			name: "delegate",
			type: "address"
		},
		{
			name: "delegator",
			type: "address"
		},
		{
			name: "authority",
			type: "bytes32"
		},
		{
			name: "caveats",
			type: "Caveat[]"
		},
		{
			name: "salt",
			type: "uint256"
		}
	],
	Caveat: [{
		name: "enforcer",
		type: "address"
	}, {
		name: "terms",
		type: "bytes"
	}]
};
/**
* Build the EIP-712 domain for a DelegationManager on a specific chain.
*/
function getDelegationDomain(chainId) {
	return {
		name: "DelegationManager",
		version: "1",
		chainId,
		verifyingContract: DELEGATION_CONTRACTS.DelegationManager
	};
}
"" + "f".repeat(64);
/**
* Default single-call execution mode.
* callType=0x00 (single), execType=0x00 (default), rest zeros.
*/
const EXECUTE_MODE_DEFAULT = "0x" + "0".repeat(64);
/**
* Well-known period durations in seconds, for on-chain period enforcers.
*/
const PERIOD_SECONDS = {
	hourly: 3600,
	daily: 86400,
	weekly: 604800,
	monthly: 2592e3
};
const DELEGATION_MANAGER_ABI = [
	{
		name: "redeemDelegations",
		type: "function",
		stateMutability: "nonpayable",
		inputs: [
			{
				name: "_permissionContexts",
				type: "bytes[]"
			},
			{
				name: "_modes",
				type: "bytes32[]"
			},
			{
				name: "_executionCallData",
				type: "bytes[]"
			}
		],
		outputs: []
	},
	{
		name: "disableDelegation",
		type: "function",
		stateMutability: "nonpayable",
		inputs: [{
			name: "_delegation",
			type: "tuple",
			components: [
				{
					name: "delegate",
					type: "address"
				},
				{
					name: "delegator",
					type: "address"
				},
				{
					name: "authority",
					type: "bytes32"
				},
				{
					name: "caveats",
					type: "tuple[]",
					components: [
						{
							name: "enforcer",
							type: "address"
						},
						{
							name: "terms",
							type: "bytes"
						},
						{
							name: "args",
							type: "bytes"
						}
					]
				},
				{
					name: "salt",
					type: "uint256"
				},
				{
					name: "signature",
					type: "bytes"
				}
			]
		}],
		outputs: []
	},
	{
		name: "getDelegationHash",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "_delegation",
			type: "tuple",
			components: [
				{
					name: "delegate",
					type: "address"
				},
				{
					name: "delegator",
					type: "address"
				},
				{
					name: "authority",
					type: "bytes32"
				},
				{
					name: "caveats",
					type: "tuple[]",
					components: [
						{
							name: "enforcer",
							type: "address"
						},
						{
							name: "terms",
							type: "bytes"
						},
						{
							name: "args",
							type: "bytes"
						}
					]
				},
				{
					name: "salt",
					type: "uint256"
				},
				{
					name: "signature",
					type: "bytes"
				}
			]
		}],
		outputs: [{
			name: "",
			type: "bytes32"
		}]
	},
	{
		name: "disabledDelegations",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "_delegationHash",
			type: "bytes32"
		}],
		outputs: [{
			name: "",
			type: "bool"
		}]
	}
];
/** ABI for NativeTokenPeriodTransferEnforcer.spentMap (read cumulative ETH usage). */
const NATIVE_PERIOD_ENFORCER_ABI = [{
	name: "spentMap",
	type: "function",
	stateMutability: "view",
	inputs: [{
		name: "_delegationManager",
		type: "address"
	}, {
		name: "_delegationHash",
		type: "bytes32"
	}],
	outputs: [{
		name: "spent",
		type: "uint256"
	}, {
		name: "lastUpdated",
		type: "uint256"
	}]
}];
/** ABI for ERC20PeriodTransferEnforcer.spentMap (read cumulative ERC-20 usage). */
const ERC20_PERIOD_ENFORCER_ABI = [{
	name: "spentMap",
	type: "function",
	stateMutability: "view",
	inputs: [{
		name: "_delegationManager",
		type: "address"
	}, {
		name: "_delegationHash",
		type: "bytes32"
	}],
	outputs: [{
		name: "spent",
		type: "uint256"
	}, {
		name: "lastUpdated",
		type: "uint256"
	}]
}];
/** ABI for LimitedCallsEnforcer.callCounts (read cumulative call count). */
const LIMITED_CALLS_ENFORCER_ABI = [{
	name: "callCounts",
	type: "function",
	stateMutability: "view",
	inputs: [{
		name: "_delegationManager",
		type: "address"
	}, {
		name: "_delegationHash",
		type: "bytes32"
	}],
	outputs: [{
		name: "",
		type: "uint256"
	}]
}];
//#endregion
//#region extensions/crypto/src/services/delegation-compiler.ts
/**
* Delegation Compiler — Converts openclawnch policies to EIP-7710 delegations.
*
* Takes a Policy (with its PolicyRules) and produces an UnsignedDelegation
* containing the corresponding on-chain caveat enforcers.
*
* Rules without a direct on-chain mapping (blocklist, approval_threshold)
* are flagged as "app-layer only" — they're still enforced by the policy
* engine but won't have on-chain caveats.
*
* Uses viem's encodeAbiParameters for terms encoding. No external SDK needed.
*/
let _compCtx = {};
/** Set compilation context (prices) before compiling. */
function setCompilationContext(ctx) {
	_compCtx = ctx;
}
/** Get current compilation context. */
function getCompilationContext() {
	return _compCtx;
}
/**
* Convert a USD amount to native token (ETH) wei.
* Returns the placeholder (usd * 1e18) if no ETH price is available.
*/
function usdToNativeWei(usdAmount) {
	const ethPrice = _compCtx.ethPriceUsd;
	if (ethPrice && ethPrice > 0) {
		const ethAmount = usdAmount / ethPrice;
		return {
			wei: BigInt(Math.floor(ethAmount * 0xde0b6b3a7640000)),
			converted: true,
			ethPrice
		};
	}
	return {
		wei: BigInt(Math.floor(usdAmount * 0xde0b6b3a7640000)),
		converted: false
	};
}
/**
* Compile a single PolicyRule into zero or more on-chain caveats.
*/
function compileRuleToCaveats(rule) {
	switch (rule.type) {
		case "spending_limit": return compileSpendingLimit(rule);
		case "max_amount": return compileMaxAmount(rule);
		case "rate_limit": return compileRateLimit(rule);
		case "allowlist": return compileAllowlist(rule);
		case "time_window": return compileTimeWindow(rule);
		case "erc20_limit": return compileErc20Limit(rule);
		case "blocklist": return {
			type: "app_layer_only",
			reason: "Blocklist has no direct on-chain enforcer. The delegation framework uses allowlists (AllowedTargetsEnforcer). Blocklists are enforced at the app layer only."
		};
		case "approval_threshold": return {
			type: "app_layer_only",
			reason: "Approval threshold is an app-layer concept (human confirmation). On-chain, use max_amount to hard-block above a threshold instead."
		};
		default: return {
			type: "app_layer_only",
			reason: `Unknown rule type: ${rule.type}`
		};
	}
}
/**
* spending_limit → NativeTokenPeriodTransferEnforcer.
*
* Converts USD to ETH wei using live price when available.
* Falls back to USD * 1e18 placeholder when no price context is set.
*/
function compileSpendingLimit(rule) {
	const periodSec = PERIOD_SECONDS[rule.period];
	if (!periodSec) return {
		type: "app_layer_only",
		reason: `Unknown period: ${rule.period}`
	};
	const { wei: allowanceWei } = usdToNativeWei(rule.maxAmountUsd);
	const terms = encodeAbiParameters([
		{
			type: "uint256",
			name: "allowance"
		},
		{
			type: "uint256",
			name: "startTime"
		},
		{
			type: "uint256",
			name: "period"
		}
	], [
		allowanceWei,
		0n,
		BigInt(periodSec)
	]);
	return {
		type: "mapped",
		caveats: [{
			enforcer: DELEGATION_CONTRACTS.NativeTokenPeriodTransferEnforcer,
			terms,
			args: "0x"
		}]
	};
}
/**
* max_amount → ValueLteEnforcer + NativeTokenTransferAmountEnforcer.
*
* ValueLteEnforcer caps msg.value per call. NativeTokenTransferAmountEnforcer
* caps cumulative native token transfers. Both use ETH wei.
*/
function compileMaxAmount(rule) {
	const { wei: maxValueWei } = usdToNativeWei(rule.maxAmountUsd);
	const valueLteTerms = encodeAbiParameters([{
		type: "uint256",
		name: "maxValue"
	}], [maxValueWei]);
	const nativeCapTerms = encodeAbiParameters([{
		type: "uint256",
		name: "amount"
	}], [maxValueWei]);
	return {
		type: "mapped",
		caveats: [{
			enforcer: DELEGATION_CONTRACTS.ValueLteEnforcer,
			terms: valueLteTerms,
			args: "0x"
		}, {
			enforcer: DELEGATION_CONTRACTS.NativeTokenTransferAmountEnforcer,
			terms: nativeCapTerms,
			args: "0x"
		}]
	};
}
/**
* erc20_limit → ERC20TransferAmountEnforcer.
*
* Caps cumulative ERC-20 transfers for a specific token.
* Terms: encodePacked(address token, uint256 maxAmount) — 52 bytes.
* The enforcer tracks cumulative transfer(to, amount) calldata
* and reverts when the total exceeds the cap.
*
* Example: "max 100 USDC" becomes:
*   - ERC20TransferAmountEnforcer(USDC_address, 100_000_000)
*/
function compileErc20Limit(rule) {
	if (!rule.token || !/^0x[0-9a-fA-F]{40}$/.test(rule.token)) return {
		type: "app_layer_only",
		reason: `Invalid token address: ${rule.token}`
	};
	const [whole = "0", frac = ""] = rule.maxAmount.split(".");
	const paddedFrac = (frac + "0".repeat(rule.decimals)).slice(0, rule.decimals);
	const amountSmallest = BigInt(whole + paddedFrac);
	if (amountSmallest <= 0n) return {
		type: "app_layer_only",
		reason: "ERC-20 limit amount must be positive."
	};
	const terms = encodePacked(["address", "uint256"], [rule.token, amountSmallest]);
	return {
		type: "mapped",
		caveats: [{
			enforcer: DELEGATION_CONTRACTS.ERC20TransferAmountEnforcer,
			terms,
			args: "0x"
		}]
	};
}
/**
* rate_limit → LimitedCallsEnforcer + TimestampEnforcer.
*
* LimitedCallsEnforcer is a lifetime cap — it never resets. To approximate
* a windowed rate limit, we pair it with a TimestampEnforcer that expires
* the delegation at the end of the current window. The user must create
* a new delegation for the next window.
*
* Example: "max 10 calls per day" becomes:
*   - LimitedCallsEnforcer(10)
*   - TimestampEnforcer(now, now + 86400)
*/
function compileRateLimit(rule) {
	const callsTerms = encodeAbiParameters([{
		type: "uint256",
		name: "count"
	}], [BigInt(rule.maxCalls)]);
	const caveats = [{
		enforcer: DELEGATION_CONTRACTS.LimitedCallsEnforcer,
		terms: callsTerms,
		args: "0x"
	}];
	if (rule.periodMs > 0) {
		const nowSec = BigInt(Math.floor(Date.now() / 1e3));
		const timestampTerms = encodeAbiParameters([{
			type: "uint128",
			name: "executeAfter"
		}, {
			type: "uint128",
			name: "executeBefore"
		}], [nowSec, nowSec + BigInt(Math.floor(rule.periodMs / 1e3))]);
		caveats.push({
			enforcer: DELEGATION_CONTRACTS.TimestampEnforcer,
			terms: timestampTerms,
			args: "0x"
		});
	}
	return {
		type: "mapped",
		caveats
	};
}
/**
* allowlist (addresses/contracts) → AllowedTargetsEnforcer.
* allowlist (tokens) → ERC20TransferAmountEnforcer per token (if addresses known).
* allowlist (chains) → App-layer only (delegation is per-chain).
*/
function compileAllowlist(rule) {
	if (rule.field === "addresses" || rule.field === "contracts") {
		const addresses = rule.values.filter((v) => /^0x[0-9a-fA-F]{40}$/.test(v)).map((v) => v);
		if (addresses.length === 0) return {
			type: "app_layer_only",
			reason: "No valid addresses in allowlist."
		};
		const terms = encodeAbiParameters([{
			type: "address[]",
			name: "targets"
		}], [addresses]);
		return {
			type: "mapped",
			caveats: [{
				enforcer: DELEGATION_CONTRACTS.AllowedTargetsEnforcer,
				terms,
				args: "0x"
			}]
		};
	}
	if (rule.field === "tokens") {
		const tokenAddresses = rule.values.filter((v) => /^0x[0-9a-fA-F]{40}$/.test(v)).map((v) => v);
		if (tokenAddresses.length > 0) {
			const terms = encodeAbiParameters([{
				type: "address[]",
				name: "targets"
			}], [tokenAddresses]);
			return {
				type: "mapped",
				caveats: [{
					enforcer: DELEGATION_CONTRACTS.AllowedTargetsEnforcer,
					terms,
					args: "0x"
				}]
			};
		}
		return {
			type: "app_layer_only",
			reason: "Token allowlist with symbols only (no contract addresses) cannot be enforced on-chain. Use token contract addresses for on-chain enforcement."
		};
	}
	if (rule.field === "chains") return {
		type: "app_layer_only",
		reason: "Chain restrictions are inherent to delegation scope (each delegation is per-chain). No enforcer needed."
	};
	return {
		type: "app_layer_only",
		reason: `Unknown allowlist field: ${rule.field}`
	};
}
/**
* time_window → TimestampEnforcer.
*
* TimestampEnforcer uses (uint128 executeAfter, uint128 executeBefore).
* Recurring windows (weekdays, hours) are enforced at app layer only.
*/
function compileTimeWindow(rule) {
	if (rule.allowedDays && rule.allowedDays.length > 0) return {
		type: "app_layer_only",
		reason: "Recurring day-of-week restrictions have no on-chain equivalent. TimestampEnforcer only supports absolute time ranges. Enforced at app layer."
	};
	if (rule.allowedHours) return {
		type: "app_layer_only",
		reason: "Recurring hour-of-day restrictions have no on-chain equivalent. TimestampEnforcer only supports absolute time ranges. Enforced at app layer."
	};
	return {
		type: "app_layer_only",
		reason: "No time constraints to enforce on-chain."
	};
}
/**
* Compile a full Policy into an UnsignedDelegation.
*
* @param policy - The policy to compile
* @param delegator - The user's wallet address (who grants the delegation)
* @param delegate - The agent's wallet address (who receives the delegation)
* @param chainId - Target chain ID
* @returns CompilationResult with the delegation and mapping details, or error
*/
function compilePolicyToDelegation(policy, delegator, delegate, chainId) {
	if (!SUPPORTED_CHAIN_IDS.has(chainId)) return {
		type: "error",
		message: `Chain ${chainId} is not supported by the MetaMask Delegation Framework. Supported: ${[...SUPPORTED_CHAIN_IDS].join(", ")}`
	};
	if (!policy.rules || policy.rules.length === 0) return {
		type: "error",
		message: `Policy "${policy.name}" has no rules to compile.`
	};
	if (policy.status !== "active") return {
		type: "error",
		message: `Policy "${policy.name}" is not active (status: ${policy.status}). Enable it first.`
	};
	const allCaveats = [];
	const mappedRules = [];
	const unmappedRules = [];
	const warnings = [];
	for (const rule of policy.rules) {
		const result = compileRuleToCaveats(rule);
		if (result.type === "mapped") {
			allCaveats.push(...result.caveats);
			mappedRules.push({
				rule,
				caveats: result.caveats
			});
		} else unmappedRules.push({
			rule,
			reason: result.reason
		});
	}
	if (allCaveats.length === 0) warnings.push("No policy rules mapped to on-chain caveats. All rules are app-layer only. The delegation would have NO on-chain restrictions. This is likely not what you want.");
	if (policy.rules.some((r) => r.type === "spending_limit" || r.type === "max_amount")) {
		const ctx = getCompilationContext();
		if (ctx.ethPriceUsd) warnings.push(`Spending limits converted at ETH = $${ctx.ethPriceUsd.toFixed(2)}. On-chain enforcers use token amounts, not USD. Re-compile if price drifts significantly.`);
		else warnings.push("No ETH price available at compile time. Amounts use placeholder encoding (USD * 1e18). Re-compile with a connected network to get accurate token amounts.");
	}
	if (policy.rules.some((r) => r.type === "rate_limit")) warnings.push("Rate limits use LimitedCallsEnforcer (lifetime cap) + TimestampEnforcer (expiry). The delegation expires at the end of the rate limit window. Create a new delegation for the next window.");
	const saltBytes = Buffer.from(`${policy.id}-${Date.now()}`);
	const salt = BigInt("0x" + saltBytes.subarray(0, 32).toString("hex").padEnd(64, "0"));
	return {
		delegation: {
			delegate,
			delegator,
			authority: "0x" + "f".repeat(64),
			caveats: allCaveats,
			salt
		},
		mappedRules,
		unmappedRules,
		warnings
	};
}
/**
* Generate a human-readable compilation summary for user review.
*/
function formatCompilationSummary(result, chainId) {
	const lines = [];
	lines.push("**Delegation Compilation Summary**");
	lines.push("");
	lines.push(`Chain: ${chainId}`);
	lines.push(`Delegate: \`${result.delegation.delegate}\``);
	lines.push(`Delegator: \`${result.delegation.delegator}\``);
	lines.push(`Caveats: ${result.delegation.caveats.length}`);
	lines.push("");
	if (result.mappedRules.length > 0) {
		lines.push("**On-chain enforced rules:**");
		for (const { rule, caveats } of result.mappedRules) {
			const enforcerNames = caveats.map((c) => {
				const entry = Object.entries(DELEGATION_CONTRACTS).find(([, addr]) => addr === c.enforcer);
				return entry ? entry[0] : c.enforcer;
			});
			lines.push(`  - ${rule.type} -> ${enforcerNames.join(", ")}`);
		}
		lines.push("");
	}
	if (result.unmappedRules.length > 0) {
		lines.push("**App-layer only rules** (not enforced on-chain):");
		for (const { rule, reason } of result.unmappedRules) lines.push(`  - ${rule.type}: ${reason}`);
		lines.push("");
	}
	if (result.warnings.length > 0) {
		lines.push("**Warnings:**");
		for (const w of result.warnings) lines.push(`  - ${w}`);
	}
	return lines.join("\n");
}
//#endregion
//#region extensions/crypto/src/services/delegation-service.ts
/**
* Delegation Service — On-chain delegation lifecycle management.
*
* Handles creating, signing, revoking, and checking delegations via the
* MetaMask DelegationManager contract. Uses viem for all chain interaction.
*
* Delegation flow:
*   1. Policy is compiled to caveats (delegation-compiler.ts)
*   2. User signs the delegation (EIP-712 via wallet client)
*   3. Signed delegation is stored in the policy metadata
*   4. Agent can redeem the delegation to execute actions on-chain
*   5. User or agent can revoke via disableDelegation()
*
* Signing paths:
*   - Private key mode: walletClient.signTypedData() (auto-sign)
*   - WalletConnect: walletClient.signTypedData() (prompts user's wallet)
*   - Bankr: bankrSign({ signatureType: 'eth_signTypedData_v4', ... })
*/
var delegation_service_exports = /* @__PURE__ */ __exportAll({
	canRedeem: () => canRedeem,
	checkDelegationStatus: () => checkDelegationStatus,
	createSubDelegation: () => createSubDelegation,
	encodePermissionContextChain: () => encodePermissionContextChain,
	formatDelegationStatus: () => formatDelegationStatus,
	formatSupportedChains: () => formatSupportedChains,
	getDelegatedPolicies: () => getDelegatedPolicies,
	prepareDelegation: () => prepareDelegation,
	redeemDelegation: () => redeemDelegation,
	refreshDelegationStatus: () => refreshDelegationStatus,
	revokeByPolicy: () => revokeByPolicy,
	revokeDelegationOnChain: () => revokeDelegationOnChain,
	signDelegation: () => signDelegation,
	storeDelegation: () => storeDelegation
});
const CHAIN_CONFIGS = {
	1: mainnet,
	8453: base,
	42161: arbitrum,
	10: optimism,
	137: polygon,
	59144: linea,
	11155111: sepolia,
	84532: baseSepolia
};
/** Default chain for delegation operations. */
const DEFAULT_CHAIN_ID = 8453;
const clientCache = /* @__PURE__ */ new Map();
function getDelegationPublicClient(chainId) {
	let client = clientCache.get(chainId);
	if (client) return client;
	const chain = CHAIN_CONFIGS[chainId];
	if (!chain) throw new Error(`No chain config for chainId ${chainId}`);
	client = createPublicClient({
		chain,
		transport: http()
	});
	clientCache.set(chainId, client);
	return client;
}
/**
* Get the wallet state from the wallet service.
* Uses dynamic import to avoid circular dependency.
*/
async function getWallet() {
	try {
		const { getWalletState, getWalletClient } = await import("./walletconnect-service-nx9kD9tm.mjs").then((n) => n.g);
		const state = getWalletState();
		if (!state.connected || !state.address) return {
			mode: "none",
			address: null,
			walletClient: null
		};
		let wc = null;
		try {
			wc = getWalletClient();
		} catch {}
		return {
			mode: state.mode,
			address: state.address,
			walletClient: wc
		};
	} catch {
		return {
			mode: "none",
			address: null,
			walletClient: null
		};
	}
}
/**
* Step 1: Compile a policy into a delegation and return it for user review.
* Fetches live ETH price for USD→wei conversion when possible.
* Does NOT sign or store — the user must review and approve first.
*/
async function prepareDelegation(input) {
	const chainId = input.chainId ?? DEFAULT_CHAIN_ID;
	const wallet = await getWallet();
	const zeroAddr = "0x" + "0".repeat(40);
	let delegator = input.delegator ?? zeroAddr;
	let delegate = input.delegate ?? process.env.CLAWNCHER_ADDRESS ?? zeroAddr;
	try {
		const { loadMeta } = await import("./agent-keystore-DqRgf0jk.mjs").then((n) => n.t);
		const meta = loadMeta();
		if (meta) {
			if (delegator === zeroAddr) delegator = meta.smartAccountAddress;
			if (delegate === zeroAddr) delegate = meta.agentAddress;
		}
	} catch {}
	if (delegator === zeroAddr && wallet.address) delegator = wallet.address;
	let ethPriceUsd = 0;
	try {
		const { getEthPrice } = await import("./price-service-3xN2ZZh7.mjs").then((n) => n.r);
		ethPriceUsd = await getEthPrice();
	} catch {}
	if (ethPriceUsd <= 0) try {
		const data = await (await fetch("https://api.dexscreener.com/latest/dex/pairs/base/0xd0b53D9277642d899DF5C87A3966A349A798F224")).json();
		const price = parseFloat(data?.pair?.priceUsd ?? data?.pairs?.[0]?.priceUsd ?? "0");
		if (price > 0) ethPriceUsd = price;
	} catch {}
	if (ethPriceUsd > 0) setCompilationContext({ ethPriceUsd });
	else setCompilationContext({});
	const result = compilePolicyToDelegation(input.policy, delegator, delegate, chainId);
	if ("type" in result && result.type === "error") return { error: result.message };
	const compilation = result;
	return {
		compilation,
		summary: formatCompilationSummary(compilation, chainId),
		chainId
	};
}
/**
* Step 2: Sign a delegation using the connected wallet.
*
* Supports three modes:
*   - private_key: auto-sign via viem WalletClient.signTypedData()
*   - walletconnect: prompts user's external wallet for EIP-712 signature
*   - bankr: signs via Bankr Agent API (eth_signTypedData_v4)
*
* Returns the signed delegation or an error string.
*/
async function signDelegation(unsigned, chainId) {
	const wallet = await getWallet();
	try {
		const { loadAgentKey } = await import("./agent-keystore-DqRgf0jk.mjs").then((n) => n.t);
		const agentKey = loadAgentKey();
		if (agentKey) {
			const { privateKeyToAccount } = await import("./accounts-CbW6PDSZ.mjs");
			const { createWalletClient, http } = await import("./_esm-BKtdEVdT.mjs").then((n) => n.t);
			const { base, baseSepolia } = await import("./chains-Bx4KIVmV.mjs").then((n) => n.t);
			const agentWallet = createWalletClient({
				account: privateKeyToAccount(agentKey),
				chain: chainId === 84532 ? baseSepolia : base,
				transport: http()
			});
			const domain = getDelegationDomain(chainId);
			const sig = await agentWallet.signTypedData({
				domain,
				types: DELEGATION_EIP712_TYPES,
				primaryType: "Delegation",
				message: {
					delegate: unsigned.delegate,
					delegator: unsigned.delegator,
					authority: unsigned.authority,
					caveats: unsigned.caveats.map((c) => ({
						enforcer: c.enforcer,
						terms: c.terms
					})),
					salt: unsigned.salt
				}
			});
			return { signed: {
				...unsigned,
				signature: sig
			} };
		}
	} catch {}
	if (wallet.mode === "none" || !wallet.address) return { error: "No wallet connected and no agent key available. Use /connect, set CLAWNCHER_PRIVATE_KEY, or run /delegator create." };
	const domain = getDelegationDomain(chainId);
	const message = {
		delegate: unsigned.delegate,
		delegator: unsigned.delegator,
		authority: unsigned.authority,
		caveats: unsigned.caveats.map((c) => ({
			enforcer: c.enforcer,
			terms: c.terms
		})),
		salt: unsigned.salt
	};
	try {
		let signature;
		if (wallet.mode === "bankr") {
			const { bankrSign } = await import("./bankr-api-ClsXaFmq.mjs").then((n) => n.t);
			signature = (await bankrSign({
				signatureType: "eth_signTypedData_v4",
				typedData: {
					domain,
					types: DELEGATION_EIP712_TYPES,
					primaryType: "Delegation",
					message
				},
				chainId
			})).signature;
		} else if (wallet.walletClient) signature = await wallet.walletClient.signTypedData({
			domain,
			types: DELEGATION_EIP712_TYPES,
			primaryType: "Delegation",
			message
		});
		else return { error: `Wallet mode "${wallet.mode}" connected but no wallet client available for signing.` };
		return { signed: {
			...unsigned,
			signature
		} };
	} catch (err) {
		return { error: `Signing failed: ${err instanceof Error ? err.message : String(err)}` };
	}
}
/**
* Extract the earliest expiry timestamp from TimestampEnforcer caveats.
* TimestampEnforcer terms are: (uint128 executeAfter, uint128 executeBefore).
* Returns ISO string for the earliest executeBefore, or undefined if none.
*/
function extractExpiryFromCaveats(caveats) {
	const timestampEnforcerAddr = DELEGATION_CONTRACTS.TimestampEnforcer.toLowerCase();
	let earliestExpiry;
	for (const caveat of caveats) {
		if (caveat.enforcer.toLowerCase() !== timestampEnforcerAddr) continue;
		try {
			const executeBefore = decodeAbiParameters([{
				type: "uint128",
				name: "executeAfter"
			}, {
				type: "uint128",
				name: "executeBefore"
			}], caveat.terms)[1];
			if (executeBefore > 0n) {
				if (earliestExpiry === void 0 || executeBefore < earliestExpiry) earliestExpiry = executeBefore;
			}
		} catch {}
	}
	if (earliestExpiry !== void 0) return (/* @__PURE__ */ new Date(Number(earliestExpiry) * 1e3)).toISOString();
}
/**
* Step 3: Store a signed delegation in the policy metadata and get its hash.
* Persists the full SignedDelegation struct to the delegation store (for
* later redemption and on-chain revocation) and lightweight metadata on
* the policy. Attempts to read the delegation hash from DelegationManager.
*/
async function storeDelegation(policy, userId, delegation, chainId, unmappedRules, expiresAt) {
	const policyStore = getPolicyStore();
	getDelegationStore().save(delegation, chainId, policy.id);
	let hash = "0x";
	try {
		hash = await getDelegationPublicClient(chainId).readContract({
			address: DELEGATION_CONTRACTS.DelegationManager,
			abi: DELEGATION_MANAGER_ABI,
			functionName: "getDelegationHash",
			args: [{
				delegate: delegation.delegate,
				delegator: delegation.delegator,
				authority: delegation.authority,
				caveats: delegation.caveats,
				salt: delegation.salt,
				signature: delegation.signature
			}]
		});
	} catch {}
	const info = {
		chainId,
		hash,
		delegationManager: DELEGATION_CONTRACTS.DelegationManager,
		status: "signed",
		delegate: delegation.delegate,
		delegator: delegation.delegator,
		salt: delegation.salt.toString(),
		createdAt: (/* @__PURE__ */ new Date()).toISOString(),
		expiresAt: expiresAt ?? extractExpiryFromCaveats(delegation.caveats),
		unmappedRules: unmappedRules.length > 0 ? unmappedRules : void 0
	};
	policy.delegation = info;
	policy.updatedAt = Date.now();
	policyStore.savePolicy(policy);
	return info;
}
/**
* Create a sub-delegation from a parent delegation.
*
* Sub-delegation narrows the parent's permissions by:
* 1. Setting the `authority` field to the parent delegation's hash
*    (creating a delegation chain)
* 2. Inheriting the parent's caveats (optionally filtered)
* 3. Adding additional restricting caveats (narrowing only — cannot expand)
*
* The parent agent (current delegate) signs the sub-delegation, granting
* the sub-agent a subset of its own permissions.
*
* DelegationManager verifies the full chain during redemption:
*   User → Agent (parent) → Sub-Agent (child)
*
* Important: caveats can only be made MORE restrictive in sub-delegations.
* The on-chain enforcers check both the parent and child caveats during
* redemption. Adding a wider spending limit on the child delegation is
* harmless — the parent's enforcer still caps the total.
*/
async function createSubDelegation(input) {
	const { parentDelegation, parentHash, chainId, subAgentAddress, subAgentPrivateKey, additionalCaveats, caveatFilter } = input;
	let childCaveats = [];
	if (caveatFilter && caveatFilter.length > 0) {
		const filterSet = new Set(caveatFilter.map((a) => a.toLowerCase()));
		childCaveats = parentDelegation.caveats.filter((c) => filterSet.has(c.enforcer.toLowerCase()));
	} else childCaveats = [...parentDelegation.caveats];
	if (additionalCaveats && additionalCaveats.length > 0) childCaveats.push(...additionalCaveats);
	const salt = BigInt("0x" + Array.from({ length: 32 }, () => Math.floor(Math.random() * 256).toString(16).padStart(2, "0")).join(""));
	const unsigned = {
		delegate: subAgentAddress,
		delegator: parentDelegation.delegate,
		authority: parentHash,
		caveats: childCaveats,
		salt
	};
	const domain = getDelegationDomain(chainId);
	const message = {
		delegate: unsigned.delegate,
		delegator: unsigned.delegator,
		authority: unsigned.authority,
		caveats: unsigned.caveats.map((c) => ({
			enforcer: c.enforcer,
			terms: c.terms,
			args: c.args
		})),
		salt: unsigned.salt
	};
	try {
		const agentPrivateKey = process.env.CLAWNCHER_PRIVATE_KEY;
		if (!agentPrivateKey) return { error: "CLAWNCHER_PRIVATE_KEY is required for sub-delegation signing. The agent must have its own private key." };
		const chain = CHAIN_CONFIGS[chainId];
		if (!chain) return { error: `No chain config for chainId ${chainId}` };
		const { privateKeyToAccount } = await import("./accounts-CbW6PDSZ.mjs");
		const signature = await createWalletClient({
			account: privateKeyToAccount(agentPrivateKey),
			chain,
			transport: http()
		}).signTypedData({
			domain,
			types: DELEGATION_EIP712_TYPES,
			primaryType: "Delegation",
			message
		});
		const signed = {
			...unsigned,
			signature
		};
		return {
			delegation: signed,
			chain: [parentDelegation, signed],
			authority: parentHash
		};
	} catch (err) {
		return { error: `Sub-delegation signing failed: ${err instanceof Error ? err.message : String(err)}` };
	}
}
/**
* Revoke a delegation on-chain via DelegationManager.disableDelegation().
* Requires the delegator's wallet to send the transaction.
*/
async function revokeDelegationOnChain(delegation, chainId) {
	const wallet = await getWallet();
	if (wallet.mode === "none" || !wallet.walletClient) return { error: "No wallet connected. Connect a wallet to revoke on-chain." };
	try {
		return { txHash: await wallet.walletClient.writeContract({
			address: DELEGATION_CONTRACTS.DelegationManager,
			abi: DELEGATION_MANAGER_ABI,
			functionName: "disableDelegation",
			args: [{
				delegate: delegation.delegate,
				delegator: delegation.delegator,
				authority: delegation.authority,
				caveats: delegation.caveats,
				salt: delegation.salt,
				signature: delegation.signature
			}],
			chain: CHAIN_CONFIGS[chainId]
		}) };
	} catch (err) {
		return { error: `On-chain revocation failed: ${err instanceof Error ? err.message : String(err)}` };
	}
}
/**
* Check delegation status on-chain.
* Reads the `disabledDelegations` mapping on DelegationManager.
*/
async function checkDelegationStatus(delegationHash, chainId) {
	if (!SUPPORTED_CHAIN_IDS.has(chainId)) throw new Error(`Chain ${chainId} not supported`);
	try {
		return await getDelegationPublicClient(chainId).readContract({
			address: DELEGATION_CONTRACTS.DelegationManager,
			abi: DELEGATION_MANAGER_ABI,
			functionName: "disabledDelegations",
			args: [delegationHash]
		}) ? "revoked" : "active";
	} catch {
		return "signed";
	}
}
/**
* Refresh delegation status for a policy and persist the result.
*/
async function refreshDelegationStatus(policy, userId) {
	if (!policy.delegation) return null;
	if (!policy.delegation.hash || policy.delegation.hash === "0x") return policy.delegation;
	try {
		const status = await checkDelegationStatus(policy.delegation.hash, policy.delegation.chainId);
		policy.delegation.status = status;
		policy.delegation.lastCheckedAt = (/* @__PURE__ */ new Date()).toISOString();
		getPolicyStore().savePolicy(policy);
		return policy.delegation;
	} catch {
		return policy.delegation;
	}
}
/**
* Revoke a delegation by policy ID. Loads the full SignedDelegation from the
* delegation store and calls disableDelegation() on-chain. Also updates the
* policy metadata and cleans up the stored struct.
*
* Returns { txHash } on success, or { error } if wallet/store/chain fails.
* Falls back to local-only revocation if the full struct isn't stored.
*/
async function revokeByPolicy(policy, userId) {
	if (!policy.delegation) return { error: "Policy has no delegation to revoke." };
	const delegationStore = getDelegationStore();
	const stored = delegationStore.load(policy.id);
	if (!stored) {
		policy.delegation.status = "revoked";
		policy.updatedAt = Date.now();
		getPolicyStore().savePolicy(policy);
		return { localOnly: true };
	}
	const result = await revokeDelegationOnChain(stored.delegation, stored.chainId);
	if ("error" in result) {
		policy.delegation.status = "revoked";
		policy.updatedAt = Date.now();
		getPolicyStore().savePolicy(policy);
		return result;
	}
	policy.delegation.status = "revoked";
	policy.delegation.lastCheckedAt = (/* @__PURE__ */ new Date()).toISOString();
	policy.updatedAt = Date.now();
	getPolicyStore().savePolicy(policy);
	delegationStore.delete(policy.id);
	return result;
}
/**
* Encode the permissionContext for redeemDelegations().
*
* The permissionContext is an ABI-encoded delegation chain. Supports both
* single-delegation (root) and multi-delegation (sub-delegation) chains.
*
* For a single root delegation:
*   abi.encode(Delegation[1])
*
* For a sub-delegation chain (User → Agent → Sub-Agent):
*   abi.encode(Delegation[2])  — ordered [parent, child]
*
* The DelegationManager walks the chain, verifying each delegation's
* authority field matches the hash of its parent.
*/
function encodePermissionContext(delegation) {
	return encodePermissionContextChain([delegation]);
}
/**
* Encode a delegation chain as permissionContext.
* Accepts an array of SignedDelegations ordered from root (parent) to leaf (child).
* Internally reverses to leaf-first order as required by the DelegationManager
* (delegations[0].delegate must equal msg.sender).
* For a single root delegation, pass a 1-element array (no reversal needed).
*/
function encodePermissionContextChain(chain) {
	return encodeAbiParameters([{
		type: "tuple[]",
		components: [
			{
				name: "delegate",
				type: "address"
			},
			{
				name: "delegator",
				type: "address"
			},
			{
				name: "authority",
				type: "bytes32"
			},
			{
				name: "caveats",
				type: "tuple[]",
				components: [
					{
						name: "enforcer",
						type: "address"
					},
					{
						name: "terms",
						type: "bytes"
					},
					{
						name: "args",
						type: "bytes"
					}
				]
			},
			{
				name: "salt",
				type: "uint256"
			},
			{
				name: "signature",
				type: "bytes"
			}
		]
	}], [(chain.length > 1 ? [...chain].reverse() : chain).map((d) => ({
		delegate: d.delegate,
		delegator: d.delegator,
		authority: d.authority,
		caveats: d.caveats.map((c) => ({
			enforcer: c.enforcer,
			terms: c.terms,
			args: c.args
		})),
		salt: d.salt,
		signature: d.signature
	}))]);
}
/**
* Encode execution calldata for a single action.
* ERC-7579 single execution: abi.encodePacked(target, value, callData).
*/
function encodeExecution(action) {
	return encodePacked([
		"address",
		"uint256",
		"bytes"
	], [
		action.target,
		action.value,
		action.callData
	]);
}
/** Known DelegationManager error signatures → human-readable messages. */
const DELEGATION_ERROR_SIGS = {
	"0x155ff427": "Signature verification failed (InvalidERC1271Signature). The delegation signature does not match the delegator account.",
	"0xded4370e": "Invalid authority chain (InvalidAuthority). Root delegations must use authority 0xfff...f.",
	"0x8baa579f": "Invalid signature (InvalidSignature). ECDSA recovery did not match the delegator.",
	"0xb5863604": "Invalid delegate (InvalidDelegate). The caller is not the authorized delegate.",
	"0xa9e649e9": "Invalid delegation struct (InvalidDelegation).",
	"0xac241e11": "Empty signature (EmptySignature). The delegation has no signature.",
	"0x0ab29062": "No delegations provided (NoDelegations)."
};
function parseDelegationError(errMsg) {
	for (const [sig, humanMsg] of Object.entries(DELEGATION_ERROR_SIGS)) if (errMsg.includes(sig)) return `Delegation simulation reverted: ${humanMsg}`;
	if (errMsg.includes("revert")) return `Delegation simulation reverted: ${errMsg.slice(0, 200)}`;
	return `Delegation simulation failed: ${errMsg.slice(0, 200)}`;
}
/**
* Redeem a delegation to execute an action on-chain.
*
* This is the core execution path: the agent calls redeemDelegations() on the
* DelegationManager, which verifies all caveats and executes the action through
* the delegator's smart account.
*
* The caller must have the delegate's wallet (agent wallet) connected, since
* the agent is the one redeeming.
*
* @param policyId - The policy whose delegation to redeem
* @param action   - The execution action (target, value, calldata)
* @returns        - Transaction hash or error
*/
async function redeemDelegation(policyId, action) {
	const stored = getDelegationStore().load(policyId);
	if (!stored) return { error: `No signed delegation found for policy "${policyId}". Create and sign a delegation first.` };
	const { delegation, chainId } = stored;
	const policyStore = getPolicyStore();
	const wallet = await getWallet();
	const userId = wallet.address?.toLowerCase() ?? "owner";
	let policies = policyStore.listPolicies(userId);
	if (policies.length === 0 && userId !== "owner") policies = policyStore.listPolicies("owner");
	const policy = policies.find((p) => p.id === policyId);
	if (policy?.delegation?.status === "revoked") return { error: "Delegation has been revoked. Cannot redeem." };
	try {
		const publicClient = getDelegationPublicClient(chainId);
		const revocationCheck = async () => {
			const delegationHash = await publicClient.readContract({
				address: DELEGATION_CONTRACTS.DelegationManager,
				abi: DELEGATION_MANAGER_ABI,
				functionName: "getDelegationHash",
				args: [delegation]
			});
			return publicClient.readContract({
				address: DELEGATION_CONTRACTS.DelegationManager,
				abi: DELEGATION_MANAGER_ABI,
				functionName: "disabledDelegations",
				args: [delegationHash]
			});
		};
		const timeout = new Promise((resolve) => setTimeout(() => resolve(false), 5e3));
		if (await Promise.race([revocationCheck(), timeout])) {
			if (policy?.delegation) policy.delegation.status = "revoked";
			return { error: "Delegation has been revoked on-chain. Cannot redeem." };
		}
	} catch {}
	if (wallet.mode === "none" || !wallet.walletClient) return { error: "No wallet connected. The agent needs a connected wallet to redeem delegations." };
	const permissionContext = encodePermissionContext(delegation);
	const executionCallData = encodeExecution(action);
	const contractCallArgs = {
		address: DELEGATION_CONTRACTS.DelegationManager,
		abi: DELEGATION_MANAGER_ABI,
		functionName: "redeemDelegations",
		args: [
			[permissionContext],
			[EXECUTE_MODE_DEFAULT],
			[executionCallData]
		],
		chain: CHAIN_CONFIGS[chainId]
	};
	try {
		const publicClient = getDelegationPublicClient(chainId);
		if (publicClient) await publicClient.simulateContract({
			...contractCallArgs,
			account: wallet.address
		});
	} catch (simErr) {
		return { error: parseDelegationError(simErr instanceof Error ? simErr.message : String(simErr)) };
	}
	try {
		return {
			txHash: await wallet.walletClient.writeContract(contractCallArgs),
			chainId
		};
	} catch (err) {
		return { error: `Redemption failed: ${err instanceof Error ? err.message : String(err)}` };
	}
}
/**
* Check if a delegation is available for redemption (stored and not revoked).
*/
function canRedeem(policyId) {
	const delegationStore = getDelegationStore();
	if (!delegationStore.has(policyId)) return {
		ready: false,
		reason: "No signed delegation stored for this policy."
	};
	if (!delegationStore.load(policyId)) return {
		ready: false,
		reason: "Delegation file corrupted or unreadable."
	};
	return { ready: true };
}
/**
* Format delegation info as a human-readable status block.
*/
function formatDelegationStatus(meta) {
	const lines = [];
	const statusLabel = {
		unsigned: "UNSIGNED (not yet signed)",
		signed: "SIGNED (ready for on-chain use)",
		active: "ACTIVE (verified on-chain)",
		revoked: "REVOKED (disabled on-chain)",
		expired: "EXPIRED"
	}[meta.status] ?? meta.status;
	lines.push(`  Delegation: [${statusLabel}]`);
	lines.push(`  Chain: ${CHAIN_NAMES[meta.chainId] ?? meta.chainId}`);
	lines.push(`  Delegate: \`${meta.delegate}\``);
	lines.push(`  Delegator: \`${meta.delegator}\``);
	if (meta.hash && meta.hash !== "0x") lines.push(`  Hash: \`${meta.hash}\``);
	if (meta.unmappedRules && meta.unmappedRules.length > 0) lines.push(`  App-layer only: ${meta.unmappedRules.join(", ")}`);
	if (meta.lastCheckedAt) lines.push(`  Last verified: ${meta.lastCheckedAt}`);
	return lines.join("\n");
}
/**
* Get all policies with delegations for a user.
*/
function getDelegatedPolicies(userId) {
	return getPolicyStore().listPolicies(userId).filter((p) => p.delegation != null);
}
/**
* Get supported chains as a formatted string.
*/
function formatSupportedChains() {
	return [...SUPPORTED_CHAIN_IDS].map((id) => `${CHAIN_NAMES[id] ?? id} (${id})`).join(", ");
}
//#endregion
export { SUPPORTED_CHAIN_IDS as _, getDelegatedPolicies as a, refreshDelegationStatus as c, storeDelegation as d, CHAIN_NAMES as f, NATIVE_PERIOD_ENFORCER_ABI as g, LIMITED_CALLS_ENFORCER_ABI as h, formatSupportedChains as i, revokeByPolicy as l, ERC20_PERIOD_ENFORCER_ABI as m, delegation_service_exports as n, prepareDelegation as o, DELEGATION_CONTRACTS as p, formatDelegationStatus as r, redeemDelegation as s, canRedeem as t, signDelegation as u };

//# sourceMappingURL=delegation-service-BCFUCnJs.mjs.map