import { guardedFetch } from "./endpoint-allowlist.mjs";
//#region extensions/crypto/src/services/safe-service.ts
/**
* Safe Multisig Service — Safe Transaction Service API client.
*
* Interacts with Safe{Wallet} (formerly Gnosis Safe) multisig wallets via
* the Safe Transaction Service REST API. Supports Ethereum and Base.
*
* API: https://safe-transaction-service.safe.global
* No SDK dependency — direct REST calls via guardedFetch.
*/
const SAFE_API_URLS = {
	1: "https://safe-transaction-mainnet.safe.global/api",
	8453: "https://safe-transaction-base.safe.global/api",
	42161: "https://safe-transaction-arbitrum.safe.global/api",
	10: "https://safe-transaction-optimism.safe.global/api",
	137: "https://safe-transaction-polygon.safe.global/api"
};
var SafeService = class {
	/**
	* Get Safe info (threshold, owners, nonce, version).
	*/
	async getInfo(safeAddress, chainId = 1) {
		const data = await this.apiGet(`/v1/safes/${safeAddress}/`, chainId);
		return {
			address: data.address,
			nonce: data.nonce ?? 0,
			threshold: data.threshold ?? 0,
			owners: data.owners ?? [],
			modules: data.modules ?? [],
			fallbackHandler: data.fallbackHandler ?? "",
			guard: data.guard ?? "",
			version: data.version ?? "",
			chainId
		};
	}
	/**
	* Get Safe balances (ETH + ERC-20 tokens).
	*/
	async getBalances(safeAddress, chainId = 1) {
		return (await this.apiGet(`/v1/safes/${safeAddress}/balances/?trusted=true&exclude_spam=true`, chainId) ?? []).map((b) => ({
			tokenAddress: b.tokenAddress,
			token: b.token ? {
				name: b.token.name,
				symbol: b.token.symbol,
				decimals: b.token.decimals
			} : null,
			balance: b.balance ?? "0"
		}));
	}
	/**
	* Get pending (queued) transactions for a Safe.
	*/
	async getPendingTransactions(safeAddress, chainId = 1, limit = 20) {
		return ((await this.apiGet(`/v1/safes/${safeAddress}/multisig-transactions/?executed=false&limit=${limit}&ordering=-nonce`, chainId))?.results ?? []).map(this.mapTransaction);
	}
	/**
	* Get transaction history for a Safe.
	*/
	async getTransactionHistory(safeAddress, chainId = 1, limit = 20) {
		return ((await this.apiGet(`/v1/safes/${safeAddress}/multisig-transactions/?executed=true&limit=${limit}&ordering=-executionDate`, chainId))?.results ?? []).map(this.mapTransaction);
	}
	/**
	* Get a specific transaction by safeTxHash.
	*/
	async getTransaction(safeTxHash, chainId = 1) {
		const data = await this.apiGet(`/v1/multisig-transactions/${safeTxHash}/`, chainId);
		return this.mapTransaction(data);
	}
	/**
	* Confirm (sign) a pending transaction.
	* The signature must be generated off-chain using the Safe signing scheme.
	*/
	async confirmTransaction(safeTxHash, signature, chainId = 1) {
		const response = await guardedFetch(`${this.getApiUrl(chainId)}/v1/multisig-transactions/${safeTxHash}/confirmations/`, {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ signature }),
			signal: AbortSignal.timeout(15e3)
		});
		if (!response.ok) {
			const text = await response.text().catch(() => "");
			throw new Error(`Confirm failed (${response.status}): ${text.slice(0, 200)}`);
		}
		return { success: true };
	}
	/**
	* Propose a new transaction to a Safe.
	* Requires off-chain signature of the Safe transaction hash.
	*/
	async proposeTransaction(params, chainId = 1) {
		const response = await guardedFetch(`${this.getApiUrl(chainId)}/v1/safes/${params.safeAddress}/multisig-transactions/`, {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({
				to: params.to,
				value: params.value,
				data: params.data || "0x",
				operation: params.operation ?? 0,
				safeTxGas: params.safeTxGas ?? "0",
				baseGas: params.baseGas ?? "0",
				gasPrice: params.gasPrice ?? "0",
				gasToken: params.gasToken ?? "0x0000000000000000000000000000000000000000",
				refundReceiver: params.refundReceiver ?? "0x0000000000000000000000000000000000000000",
				nonce: params.nonce,
				contractTransactionHash: null,
				sender: params.sender,
				signature: params.signature,
				origin: "openclawnch"
			}),
			signal: AbortSignal.timeout(15e3)
		});
		if (!response.ok) {
			const text = await response.text().catch(() => "");
			throw new Error(`Propose failed (${response.status}): ${text.slice(0, 200)}`);
		}
		return { success: true };
	}
	/**
	* Check if an address is an owner of a Safe.
	*/
	async isOwner(safeAddress, ownerAddress, chainId = 1) {
		return (await this.getInfo(safeAddress, chainId)).owners.some((o) => o.toLowerCase() === ownerAddress.toLowerCase());
	}
	/**
	* Resolve chain from input string.
	*/
	resolveChainId(chain) {
		if (!chain) return 1;
		switch (chain.toLowerCase()) {
			case "base": return 8453;
			case "arbitrum":
			case "arb": return 42161;
			case "optimism":
			case "op": return 10;
			case "polygon":
			case "matic": return 137;
			default: return 1;
		}
	}
	getApiUrl(chainId) {
		const url = SAFE_API_URLS[chainId];
		if (!url) throw new Error(`Safe Transaction Service not available for chain ${chainId}.`);
		return url;
	}
	async apiGet(path, chainId) {
		const response = await guardedFetch(`${this.getApiUrl(chainId)}${path}`, {
			headers: { accept: "application/json" },
			signal: AbortSignal.timeout(15e3)
		});
		if (!response.ok) {
			const text = await response.text().catch(() => "");
			throw new Error(`Safe API ${response.status}: ${text.slice(0, 200)}`);
		}
		return response.json();
	}
	mapTransaction(tx) {
		return {
			safeTxHash: tx.safeTxHash ?? "",
			to: tx.to ?? "",
			value: tx.value ?? "0",
			data: tx.data,
			operation: tx.operation ?? 0,
			nonce: tx.nonce ?? 0,
			submissionDate: tx.submissionDate ?? "",
			executionDate: tx.executionDate,
			isExecuted: tx.isExecuted ?? false,
			isSuccessful: tx.isSuccessful,
			confirmationsRequired: tx.confirmationsRequired ?? 0,
			confirmations: (tx.confirmations ?? []).map((c) => ({
				owner: c.owner ?? "",
				submissionDate: c.submissionDate ?? "",
				signatureType: c.signatureType ?? ""
			})),
			executor: tx.executor,
			transactionHash: tx.transactionHash,
			dataDecoded: tx.dataDecoded
		};
	}
};
let _instance = null;
function getSafeService() {
	if (!_instance) _instance = new SafeService();
	return _instance;
}
function resetSafeService() {
	_instance = null;
}
//#endregion
export { SafeService, getSafeService, resetSafeService };

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