import { guardedFetch } from "./endpoint-allowlist.mjs";
import { M as formatUnits } from "../../chain-dTUyiOxD.mjs";
import { AAVE, AERODROME, ENS, UNISWAP } from "../lib/contract-registry.mjs";
//#region extensions/crypto/src/services/governance-service.ts
/**
* Governance Service — Snapshot (off-chain) + on-chain Governor integration.
*
* Snapshot: GraphQL API at hub.snapshot.org/graphql (off-chain votes, gasless).
* Tally: REST API at api.tally.xyz (on-chain Governor proposals, voting power).
* Direct Governor contract calls for on-chain voting via viem.
*
* No new dependencies — uses guardedFetch for HTTP, viem for contract calls.
*/
const KNOWN_GOVERNORS = {
	"aerodrome": {
		address: AERODROME.governor,
		chainId: 8453,
		name: "Aerodrome Finance",
		tokenAddress: AERODROME.token
	},
	"uniswap": {
		address: UNISWAP.governance.governor,
		chainId: 1,
		name: "Uniswap Governor Bravo",
		tokenAddress: UNISWAP.governance.token
	},
	"aave": {
		address: AAVE.governance.governor,
		chainId: 1,
		name: "Aave Governance V2",
		tokenAddress: AAVE.governance.token
	},
	"ens": {
		address: ENS.governor,
		chainId: 1,
		name: "ENS Governor",
		tokenAddress: ENS.token
	}
};
const GOVERNOR_ABI = [
	{
		name: "castVote",
		type: "function",
		stateMutability: "nonpayable",
		inputs: [{
			name: "proposalId",
			type: "uint256"
		}, {
			name: "support",
			type: "uint8"
		}],
		outputs: [{
			name: "",
			type: "uint256"
		}]
	},
	{
		name: "castVoteWithReason",
		type: "function",
		stateMutability: "nonpayable",
		inputs: [
			{
				name: "proposalId",
				type: "uint256"
			},
			{
				name: "support",
				type: "uint8"
			},
			{
				name: "reason",
				type: "string"
			}
		],
		outputs: [{
			name: "",
			type: "uint256"
		}]
	},
	{
		name: "getVotes",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "account",
			type: "address"
		}, {
			name: "timepoint",
			type: "uint256"
		}],
		outputs: [{
			name: "",
			type: "uint256"
		}]
	},
	{
		name: "state",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "proposalId",
			type: "uint256"
		}],
		outputs: [{
			name: "",
			type: "uint8"
		}]
	},
	{
		name: "proposalDeadline",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "proposalId",
			type: "uint256"
		}],
		outputs: [{
			name: "",
			type: "uint256"
		}]
	}
];
const ERC20_VOTES_ABI = [
	{
		name: "delegates",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "account",
			type: "address"
		}],
		outputs: [{
			name: "",
			type: "address"
		}]
	},
	{
		name: "delegate",
		type: "function",
		stateMutability: "nonpayable",
		inputs: [{
			name: "delegatee",
			type: "address"
		}],
		outputs: []
	},
	{
		name: "getVotes",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "account",
			type: "address"
		}],
		outputs: [{
			name: "",
			type: "uint256"
		}]
	},
	{
		name: "balanceOf",
		type: "function",
		stateMutability: "view",
		inputs: [{
			name: "account",
			type: "address"
		}],
		outputs: [{
			name: "",
			type: "uint256"
		}]
	}
];
const PROPOSAL_STATES = [
	"Pending",
	"Active",
	"Canceled",
	"Defeated",
	"Succeeded",
	"Queued",
	"Expired",
	"Executed"
];
var GovernanceService = class {
	/**
	* Fetch proposals from a Snapshot space.
	*/
	async getSnapshotProposals(space, state, limit = 10) {
		const query = `{
      proposals(
        first: ${limit},
        skip: 0,
        where: { space: "${space}", ${state === "all" ? "" : `state: "${state ?? "active"}"`} },
        orderBy: "created",
        orderDirection: desc
      ) {
        id title body state choices scores scores_total
        start end author votes quorum
        space { id name }
      }
    }`;
		const response = await guardedFetch("https://hub.snapshot.org/graphql", {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ query }),
			signal: AbortSignal.timeout(15e3)
		});
		if (!response.ok) throw new Error(`Snapshot API error: ${response.status}`);
		return ((await response.json())?.data?.proposals ?? []).map((p) => ({
			id: p.id,
			title: p.title,
			body: (p.body ?? "").slice(0, 500),
			state: p.state,
			choices: p.choices ?? [],
			scores: p.scores ?? [],
			scoresTotal: p.scores_total ?? 0,
			start: p.start,
			end: p.end,
			author: p.author,
			space: p.space ?? {
				id: space,
				name: space
			},
			votes: p.votes ?? 0,
			quorum: p.quorum ?? 0,
			link: `https://snapshot.org/#/${space}/proposal/${p.id}`
		}));
	}
	/**
	* Get voting power on a Snapshot space.
	*/
	async getSnapshotVotingPower(space, voter) {
		const query = `{
      vp(voter: "${voter}", space: "${space}") {
        vp vp_by_strategy vp_state
      }
    }`;
		const response = await guardedFetch("https://hub.snapshot.org/graphql", {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ query }),
			signal: AbortSignal.timeout(1e4)
		});
		if (!response.ok) throw new Error(`Snapshot VP query failed: ${response.status}`);
		const vp = (await response.json())?.data?.vp;
		return {
			space,
			vp: vp?.vp ?? 0,
			vpByStrategy: vp?.vp_by_strategy ?? [],
			vpState: vp?.vp_state ?? "unknown"
		};
	}
	/**
	* Resolve a governor name or address.
	*/
	resolveGovernor(input) {
		const lower = input.toLowerCase();
		if (KNOWN_GOVERNORS[lower]) return KNOWN_GOVERNORS[lower];
		for (const gov of Object.values(KNOWN_GOVERNORS)) if (gov.address.toLowerCase() === lower) return gov;
		return null;
	}
	/**
	* Get all known governors.
	*/
	getKnownGovernors() {
		return Object.entries(KNOWN_GOVERNORS).map(([id, g]) => ({
			id,
			name: g.name,
			address: g.address,
			chainId: g.chainId
		}));
	}
	/**
	* Cast an on-chain vote.
	* Support: 0 = Against, 1 = For, 2 = Abstain
	*/
	async castVote(governorAddress, proposalId, support, reason, walletClient, publicClient) {
		let hash;
		if (reason) hash = await walletClient.writeContract({
			address: governorAddress,
			abi: GOVERNOR_ABI,
			functionName: "castVoteWithReason",
			args: [
				proposalId,
				support,
				reason
			]
		});
		else hash = await walletClient.writeContract({
			address: governorAddress,
			abi: GOVERNOR_ABI,
			functionName: "castVote",
			args: [proposalId, support]
		});
		await publicClient.waitForTransactionReceipt({ hash });
		return { hash };
	}
	/**
	* Delegate voting power on a governance token.
	*/
	async delegate(tokenAddress, delegatee, walletClient, publicClient) {
		const hash = await walletClient.writeContract({
			address: tokenAddress,
			abi: ERC20_VOTES_ABI,
			functionName: "delegate",
			args: [delegatee]
		});
		await publicClient.waitForTransactionReceipt({ hash });
		return { hash };
	}
	/**
	* Get on-chain voting power for an address on a governance token.
	*/
	async getOnchainVotingPower(tokenAddress, userAddress, publicClient) {
		const [votes, balance, delegateTo] = await Promise.all([
			publicClient.readContract({
				address: tokenAddress,
				abi: ERC20_VOTES_ABI,
				functionName: "getVotes",
				args: [userAddress]
			}),
			publicClient.readContract({
				address: tokenAddress,
				abi: ERC20_VOTES_ABI,
				functionName: "balanceOf",
				args: [userAddress]
			}),
			publicClient.readContract({
				address: tokenAddress,
				abi: ERC20_VOTES_ABI,
				functionName: "delegates",
				args: [userAddress]
			})
		]);
		return {
			votes: formatUnits(votes, 18),
			balance: formatUnits(balance, 18),
			delegate: delegateTo
		};
	}
	/**
	* Get proposal state from an on-chain Governor.
	*/
	async getProposalState(governorAddress, proposalId, publicClient) {
		const stateIndex = await publicClient.readContract({
			address: governorAddress,
			abi: GOVERNOR_ABI,
			functionName: "state",
			args: [proposalId]
		});
		return PROPOSAL_STATES[stateIndex] ?? `Unknown (${stateIndex})`;
	}
};
let _instance = null;
function getGovernanceService() {
	if (!_instance) _instance = new GovernanceService();
	return _instance;
}
function resetGovernanceService() {
	_instance = null;
}
//#endregion
export { GOVERNOR_ABI, GovernanceService, KNOWN_GOVERNORS, getGovernanceService, resetGovernanceService };

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