import { isTronLike as e, networkRegistry as t } from "../../constants/chains.constants.mjs";
import { TRON_DEFAULT_FEE_LIMIT_SUN as n, zeroAddress as r } from "../../constants/protocol.constants.mjs";
import { ContractType as i } from "../../types/ethereum-network.types.mjs";
import { insufficientResourcesErrorCodes as a } from "../../error-handling/error-codes.constants.mjs";
import { randomBigInt as o } from "../../functions/web3/etherFunctions.mjs";
import { caseInsensitiveEqual as s } from "../../functions/utils/caseInsensitive.utils.mjs";
import { Utxo as c } from "../utxo/Utxo.mjs";
import { getContractAddress as l } from "../../functions/utils/getContractAddress.mjs";
import { createTronCallData as u, estimateTronFeeSunWithPadding as d, evmHexToTronBase58Address as f } from "../../functions/utils/tron.utils.mjs";
import { Logger as p } from "../../error-handling/logger.mjs";
import { isSameERC20Token as m, validateAndGetChainId as h } from "../../functions/utils/token-check.utils.mjs";
import { calcStealthAddressStructure as g } from "../../functions/snarkjs/common.snarkjs.mjs";
import { constructAdminData as _ } from "../../functions/pre-transaction/constructAdminData.mjs";
import { ERC20ABI as v } from "../../externalABIs/index.mjs";
import { waitForEthereumTransactionConfirmation as y } from "../../functions/utils/tx-confirmation.utils.mjs";
import { simulateTronTransaction as b } from "../../functions/utils/tronSimulation.utils.mjs";
import { buildApproveAndProoflessDepositCalls as x } from "../../functions/web3/functionCalls/constructBatchCall.mjs";
import { waitForErc20Approvals as S, waitForTronErc20Approvals as C } from "../../functions/web3/functionCalls/waitForErc20Approvals.mjs";
import { emitTxPublicData as w } from "../../API/admin-calls.mjs";
//#region libs/shared/common/src/data-structures/Hinkal/hinkalProoflessDeposit.ts
var T = (e, t) => {
	let n = [], r = 0;
	for (let i = 0; i < e.length; i += 1) {
		let a = !1;
		for (let o = 0; o < r; o += 1) if (m(n[o].token, e[i])) {
			n[o].balance += t[i], a = !0;
			break;
		}
		a || (n[r] = {
			token: e[i],
			balance: t[i]
		}, r += 1);
	}
	return n;
}, E = async (e, t, n, a) => {
	for (let o = 0; o < a.length; o += 1) s(a[o].token.erc20TokenAddress, r) || await y(t, (await e.getContractWithSigner(t, i.ERC20Contract, a[o].token.erc20TokenAddress).approve(n, a[o].balance)).hash);
}, D = async (e, t, r, i) => {
	let a = Array.from(i.entries());
	for (let i = 0; i < a.length; i += 1) {
		let [o, s] = a[i], c = await e.contract(v, o).allowance(t, r).call({ from: t });
		if (BigInt(String(c)) < s) {
			let { transaction: i } = await e.transactionBuilder.triggerSmartContract(o, "approve(address,uint256)", { feeLimit: n }, [{
				type: "address",
				value: r
			}, {
				type: "uint256",
				value: s.toString()
			}], t), a = await e.trx.sign(i), c = await e.trx.sendRawTransaction(a);
			if (!c.result) {
				let e = c.code ?? "UNKNOWN", t = c.message ? Buffer.from(c.message, "hex").toString() : "no message";
				throw Error(`Tron token approval failed: ${e} - ${t}`);
			}
		}
	}
}, O = (e) => {
	let t = /* @__PURE__ */ new Set();
	e.forEach(({ extraRandomization: e, stealthAddress: n }) => {
		let r = `${e.toString()}:${n.toString()}`;
		if (t.has(r)) throw Error("Duplicate randomization and stealth address pair detected in stealthAddressStructures");
		t.add(r);
	});
}, k = async (e, i, o, c, l) => {
	let m = e.getTronWeb(), { hinkalAddress: h } = t[i].contractData, g = f(h), _ = await e.getEthereumAddressByChain(i), v = o.map((e) => e.erc20TokenAddress), y = o.map(() => 0n), x = 0n, S = /* @__PURE__ */ new Map();
	for (let e = 0; e < o.length; e += 1) {
		let t = f(o[e].erc20TokenAddress);
		if (s(o[e].erc20TokenAddress, r)) x += c[e];
		else {
			let n = S.get(t) ?? 0n;
			S.set(t, n + c[e]);
		}
	}
	await D(m, _, g, S), await C(m, _, g, Array.from(S.entries()).map(([e, t]) => ({
		tokenAddress: e,
		requiredAmount: t
	})));
	let w = l.map((e) => ({
		extraRandomization: e.extraRandomization.toString(),
		stealthAddress: e.stealthAddress.toString(),
		H0: e.H0.toString(),
		H1: e.H1.toString()
	}));
	if (await b(i, g, "prooflessDeposit", t[i].contractData.hinkalABI, [
		v,
		c.map(String),
		y.map(String),
		l.map((e) => [
			e.extraRandomization.toString(),
			e.stealthAddress.toString(),
			e.H0.toString(),
			e.H1.toString()
		])
	], _, x > 0n ? x : void 0), x > 0n) {
		let e = BigInt(await m.trx.getBalance(_)), r = BigInt(n);
		try {
			let { hinkalABI: e } = t[i].contractData;
			if (!e) throw Error("Hinkal ABI not found");
			r = await d(m, i, g, _, u(e, "prooflessDeposit", [
				v,
				c.map(String),
				y.map(String),
				l.map((e) => [
					e.extraRandomization.toString(),
					e.stealthAddress.toString(),
					e.H0.toString(),
					e.H1.toString()
				])
			]), x);
		} catch (e) {
			p.error("Error estimating Tron prooflessDeposit fee", e);
		}
		if (e < x + r) throw Error(a.INSUFFICIENT_TRON_BALANCE_FOR_FEE);
	}
	let { transaction: T } = await m.transactionBuilder.triggerSmartContract(g, "prooflessDeposit(address[],uint256[],uint256[],(uint256,uint256,uint256,uint256)[])", {
		feeLimit: n,
		callValue: x > 0n ? Number(x) : 0
	}, [
		{
			type: "address[]",
			value: v
		},
		{
			type: "uint256[]",
			value: c.map(String)
		},
		{
			type: "uint256[]",
			value: y.map(String)
		},
		{
			type: "tuple(uint256,uint256,uint256,uint256)[]",
			value: w.map((e) => [
				e.extraRandomization,
				e.stealthAddress,
				e.H0,
				e.H1
			])
		}
	], _), E = await m.trx.sign(T), O = await m.trx.sendRawTransaction(E);
	if (!O.result) throw p.error("Tron prooflessDeposit broadcast failed", O), Error("Tron prooflessDeposit broadcast failed");
	let k = typeof O == "string" ? O : O?.txid ?? O?.transaction?.txID;
	if (!k) throw Error("Tron prooflessDeposit failed (missing txid)");
	return k;
}, A = async (t, n, a, u, d) => {
	let f = h(n), p = e(f), m = await t.getEthereumAddressByChain(f), v = t.userKeys.getShieldedPrivateKey(), y = u ?? n.map(() => g(c.findCorrectRandomization(o(31), v), v));
	if (y.length !== n.length) throw Error("Stealth address structures length must be equal to erc20 tokens length");
	O(y);
	let b;
	if (p) b = await k(t, f, n, a, y);
	else {
		let e = t.getContractWithSigner(f, i.HinkalContract), o = t.getProviderAdapter(f), c = T(n, a), u = n.reduce((e, t, n) => s(t.erc20TokenAddress, r) ? e + a[n] : e, 0n), d = c.filter(({ token: e, balance: t }) => !s(e.erc20TokenAddress, r) && t > 0n), p;
		if (d.length > 0 && await o.supportsBatchCall?.(f) && o.sendBatchCallsTransaction) {
			let t = x(d.map(({ token: e }) => e.erc20TokenAddress), d.map(({ balance: e }) => e), l(e), e, n.map(({ erc20TokenAddress: e }) => e), a, n.map(() => 0n), y, u);
			p = await o.sendBatchCallsTransaction(f, t);
		} else {
			await E(t, f, l(e), c);
			let r = await t.getEthereumAddressByChain(f), i = c.map(({ token: e, balance: t }) => ({
				tokenAddress: e.erc20TokenAddress,
				requiredAmount: t
			}));
			await S(t, f, r, l(e), i), p = await e.prooflessDeposit(n.map(({ erc20TokenAddress: e }) => e), a, n.map(() => 0n), y, { value: u > 0n ? u : void 0 });
		}
		b = p.hash;
	}
	return w(_(d, f, n.map(({ erc20TokenAddress: e }) => e), a, m)), b;
};
//#endregion
export { A as hinkalProoflessDeposit };
