import { ContractType as e } from "../../../types/ethereum-network.types.mjs";
import { chainIds as t, getNonLocalhostChainId as n } from "../../../constants/chains.constants.mjs";
import { permitSignatureValidFor as r } from "../../../constants/protocol.constants.mjs";
import { ApprovalType as i } from "../../../types/token.types.mjs";
import { getContractAddress as a } from "../../utils/getContractAddress.mjs";
import { getProviderFromContract as o, getSignerFromContract as s } from "../../utils/getSignerFromContract.mjs";
import { recoverTransactionFromError as c } from "./recoverTransactionFromError.mjs";
import { ethers as l } from "ethers";
//#region libs/shared/common/src/functions/web3/functionCalls/approveToken.ts
var u = async (e, t, n) => {
	let r = s(n);
	return await n.allowance(await r.getAddress(), t.target) >= e;
}, d = async (e, r, i, o, c) => {
	if (n(r) !== t.ethMainnet || o.symbol.toLowerCase() !== "usdt" || BigInt(await c.allowance(await s(c).getAddress(), i.target)) === 0n) return;
	let l = await c.approve(a(i), 0n);
	l && "hash" in l && await e.waitForTransaction(r, l.hash);
}, f = async (n, s, f, p, m) => {
	let h = n.getContractWithSigner(s, e.ERC20Contract, m.erc20TokenAddress), g = m.approvalType ?? i.Classic;
	if (g === i.Classic || !n.isPermitterAvailable(s)) {
		if (await u(p, f, h)) return;
		await d(n, s, f, m, h);
		let e = s === t.base ? 2 : 1;
		try {
			let t = await h.approve(a(f), p);
			t && "hash" in t && await n.waitForTransaction(s, t.hash, e);
		} catch (t) {
			if (!t?.transactionHash || !await c(o(h), t.transactionHash, e)) throw t;
		}
		return;
	}
	let _ = await n.getEthereumAddressByChain(s), v = n.getContract(s, e.PermitterContract), y = await n.getContractWithFetcher(s, e.ContractWithNonces, m.erc20TokenAddress).nonces(_), b = BigInt(Date.now() + r) / 1000n, x = {
		owner: _,
		holder: _,
		spender: a(v),
		value: p,
		nonce: y,
		deadline: b,
		expiry: b,
		allowed: !0
	}, { v: S, r: C, s: w } = l.Signature.from(await n.signTypedData({
		name: await h.name(),
		chainId: s,
		version: "1",
		verifyingContract: m.erc20TokenAddress
	}, { Permit: g === i.ERC20Permit ? [
		{
			name: "owner",
			type: "address"
		},
		{
			name: "spender",
			type: "address"
		},
		{
			name: "value",
			type: "uint256"
		},
		{
			name: "nonce",
			type: "uint256"
		},
		{
			name: "deadline",
			type: "uint256"
		}
	] : [
		{
			name: "holder",
			type: "address"
		},
		{
			name: "spender",
			type: "address"
		},
		{
			name: "nonce",
			type: "uint256"
		},
		{
			name: "expiry",
			type: "uint256"
		},
		{
			name: "allowed",
			type: "bool"
		}
	] }, x));
	if (g === i.ERC20Permit) {
		let e = new l.Interface(["function permit(address owner,address spender,uint256 value,uint256 deadline,uint8 v,bytes32 r,bytes32 s) external"]);
		return l.getBytesCopy(e.encodeFunctionData("permit", [
			x.owner,
			x.spender,
			x.value,
			x.deadline,
			S,
			l.getBytesCopy(C),
			l.getBytesCopy(w)
		])).slice(4);
	}
	let T = new l.Interface(["function permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed,uint8 v,bytes32 r,bytes32 s) external"]);
	return l.getBytesCopy(T.encodeFunctionData("permit", [
		x.holder,
		x.spender,
		x.nonce,
		x.expiry,
		x.allowed,
		S,
		l.getBytesCopy(C),
		l.getBytesCopy(w)
	])).slice(4);
};
//#endregion
export { f as approveTokenToHinkal };
