import { chainIds as e, getNonLocalhostChainId as t } from "../../../constants/chains.constants.mjs";
import { permitSignatureValidFor as n } from "../../../constants/protocol.constants.mjs";
import { ContractType as r } from "../../../types/ethereum-network.types.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 (n, r, i, o, c) => {
	if (t(r) !== e.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 n.waitForTransaction(r, l.hash);
}, f = async (t, s, f, p, m) => {
	let h = t.getContractWithSigner(s, r.ERC20Contract, m.erc20TokenAddress), g = m.approvalType ?? i.Classic;
	if (g === i.Classic || !t.isPermitterAvailable(s)) {
		if (await u(p, f, h)) return;
		await d(t, s, f, m, h);
		let n = s === e.base ? 2 : 1;
		try {
			let e = await h.approve(a(f), p);
			e && "hash" in e && await t.waitForTransaction(s, e.hash, n);
		} catch (e) {
			if (!e?.transactionHash || !await c(o(h), e.transactionHash, n)) throw e;
		}
		return;
	}
	let _ = await t.getEthereumAddressByChain(s), v = t.getContract(s, r.PermitterContract), y = await t.getContractWithFetcher(s, r.ContractWithNonces, m.erc20TokenAddress).nonces(_), b = BigInt(Date.now() + n) / 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 t.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 };
