import { ExternalActionId as e } from "../../types/external-action.types.mjs";
import { isSolanaLike as t, isTronLike as n, networkRegistry as r } from "../../constants/chains.constants.mjs";
import "../../constants/protocol.constants.mjs";
import { transactionErrorCodes as i } from "../../error-handling/error-codes.constants.mjs";
import { randomBigInt as a } from "../../functions/web3/etherFunctions.mjs";
import { countTotalAmountInUtxos as o } from "../../functions/utils/amounts.utils.mjs";
import { RELAYER_TX_CONFIRMATION_TIMEOUT as s } from "../../constants/tx-confirmation.constants.mjs";
import { UserKeys as c } from "../crypto-keys/keys.mjs";
import { getCurrentTimeInSeconds as l } from "../../functions/utils/time.utils.mjs";
import { encodeTokenWithId as u } from "../../functions/utils/encodeTokenWithId.mjs";
import { addressToHexFormat as d, reorderZkCallData as f } from "../../functions/utils/tron.utils.mjs";
import { getInputUtxoAndBalancePerToken as p } from "../../functions/web3/events/getInputUtxoAndBalance.mjs";
import { validateAndGetChainId as m } from "../../functions/utils/token-check.utils.mjs";
import { addPaddingToUtxos as h } from "../../functions/web3/events/getShieldedBalance.mjs";
import { outputUtxoProcessing as g } from "../../functions/pre-transaction/outputUtxoProcessing.mjs";
import { calcEncryptedOutputs as _ } from "../../functions/snarkjs/common.snarkjs.mjs";
import { getFeeStructure as v } from "../../functions/pre-transaction/getFeeStructure.mjs";
import { buildCommitmentValidationData as y } from "../../functions/pre-transaction/buildCommitmentValidationData.mjs";
import "../../functions/pre-transaction/index.mjs";
import { waitForTransactionConfirmation as b } from "../../functions/utils/tx-confirmation.utils.mjs";
import { constructZkProof as x } from "../../functions/snarkjs/constructGeneralZkProof.mjs";
import { constructSolanaZkProof as S } from "../../functions/snarkjs/constructSolanaZkProof.mjs";
import { solanaTransactCallRelayer as C, transactCallRelayer as w } from "../../functions/web3/functionCalls/transactCallRelayer.mjs";
import { mergeWithFeeStructure as T } from "../../functions/pre-transaction/merge-with-fee-structure.mjs";
import { ethers as E } from "ethers";
//#region libs/shared/common/src/data-structures/Hinkal/hinkalWithdrawStuckUtxos.ts
var D = async (e, t, n, r) => {
	let i = [...await h(e, t, n, r, void 0, void 0, !1, !0)], a = [], o = l().toString();
	for (let t = 0; t < n.length; t += 1) {
		let { outputUtxos: n } = g(e.userKeys, i[t], r[t], o);
		a.push(n);
	}
	return {
		inputUtxosArray: i,
		outputUtxosArray: a
	};
}, O = async (e, t, n, r) => {
	let i = [...await h(e, t, n, r, 6, void 0, !1, !0)][0], a = l().toString(), { outputUtxos: o } = g(e.userKeys, i, r[0], a);
	return {
		inputUtxos: i,
		outputUtxos: o
	};
}, k = async (t, r, a, o, s) => {
	let c = n(r), l = [a.erc20TokenAddress], u = a.erc20TokenAddress, [p, m] = await Promise.all([v(r, u, l, e.Transact), t.getRandomRelay(r, !0)]);
	if (!m) throw Error(i.RELAYER_NOT_AVAILABLE);
	let h = d(s), g = o - p.flatFee;
	if (g <= 0n) throw Error(`Insufficient balance to cover fee. Balance: ${o}, Fee: ${p.flatFee}`);
	let _ = [-g];
	T(r, l, _, p);
	let b = {
		externalActionId: 0n,
		externalAddress: h,
		externalActionMetadata: "0x00"
	}, { inputUtxosArray: S, outputUtxosArray: C } = await D(t, r, l, _), [{ zkCallData: E, circomData: O, dimData: k }, A] = await Promise.all([x(t.merkleTreeHinkalByChain[r], S, C, t.userKeys, b.externalActionId, b.externalAddress, b.externalActionMetadata, t.generateProofRemotely, p, m, r), y(r, t.userKeys, l, S)]);
	return {
		tx: await w(r, E, k, O, A, void 0, void 0, void 0, await f(c, E, k, O)),
		amountToRecipient: g
	};
}, A = async (t, n, o, s, l, u) => {
	let d = [o.erc20TokenAddress], { originalDeployer: f } = r[n].contractData;
	if (!f) throw Error("missing data");
	let { userKeys: p, merkleTreeHinkalByChain: m } = t, h = o.erc20TokenAddress, [g, b] = await Promise.all([v(n, h, d, e.Transact, void 0, void 0, {
		mintTo: d[0],
		recipient: l,
		nullifierCount: u
	}), t.getRandomRelay(n, !0)]);
	if (!b) throw Error(i.RELAYER_NOT_AVAILABLE);
	let x = s - g.flatFee;
	if (x <= 0n) throw Error(`Insufficient balance to cover fee. Balance: ${s}, Fee: ${g.flatFee}`);
	let w = [-x];
	w[0] -= g.flatFee;
	let { inputUtxos: T, outputUtxos: D } = await O(t, n, d, w), k = c.findCorrectRandomization(a(31), t.userKeys.getShieldedPrivateKey()), A = {
		tokenNumber: d.length,
		nullifierAmount: T.length,
		outputAmount: D.length
	}, j = _([D])[0][0], M = Array.from(E.getBytes(j)), [{ proofAArr: N, proofBArr: P, proofCArr: F, publicInputsArr: I }, L] = await Promise.all([S(t.generateProofRemotely, m[n], p, [d[0]], [T], [D], k, g.flatFee, g.variableRate, l, b, A, [M], n), y(n, p, d, [T])]), R = {
		recipient: l,
		mint: d[0] === "11111111111111111111111111111111" ? void 0 : d[0]
	};
	return {
		tx: await C({
			chainId: n,
			relayAddress: b,
			functionName: "transact",
			args: {
				proofAArr: N,
				proofBArr: P,
				proofCArr: F,
				publicInputsArr: I,
				encryptedOutputs: [M],
				relayerFee: g.flatFee.toString(),
				dimensions: A
			},
			accounts: R,
			commitmentValidationData: L
		}),
		amountToRecipient: x
	};
}, j = async (e, n, r, i, a, o) => t(n) ? A(e, n, r, i, a, o) : k(e, n, r, i, a), M = async (e, t, n) => {
	let r = [], i = m([t]), a = u(i, {
		erc20TokenAddress: t.erc20TokenAddress,
		tokenId: 0
	});
	for (;;) {
		await e.resetMerkleTreesIfNecessary([i]);
		let c = ((await p({
			hinkal: e,
			sliceIfMore6: !1,
			useBlockedUtxos: !0,
			chainId: i,
			allowRemoteDecryption: e.generateProofRemotely
		}))?.get(a) ?? []).filter((e) => e.amount > 0n).sort((e, t) => Number(t.amount - e.amount)).slice(0, 6), l = o(c);
		if (!l) break;
		let { tx: u } = await j(e, i, t, l, n, c.length);
		await b(i, u, {
			solanaCommitment: "finalized",
			evmTimeoutMs: s
		}), r.push(u);
	}
	return r;
};
//#endregion
export { M as hinkalWithdrawStuckUtxos };
