import { networkRegistry as e } from "../../constants/chains.constants.mjs";
import { solanaNativeAddress as t } from "../../constants/protocol.constants.mjs";
import { buildAnchorStealthAddressStructure as n, getMerkleAccountPublicKey as r, getStorageAccountPublicKey as i, getStorageVaultPublicKey as a, getTokenLimitStorageAccountPublicKey as o } from "../../functions/pre-transaction/solana.mjs";
import { hinkalCheckSolanaTokenRegistry as s } from "./hinkalCheckSolanaTokenRegistry.mjs";
import { ExternalActionId as c } from "../../types/external-action.types.mjs";
import { DepositAndWithdrawPhase as l } from "../../types/scheduled-transactions.types.mjs";
import "../../types/index.mjs";
import { transactionErrorCodes as u } from "../../error-handling/error-codes.constants.mjs";
import { randomBigInt as d } from "../../functions/web3/etherFunctions.mjs";
import { getCurrentTimeInSeconds as f } from "../../functions/utils/time.utils.mjs";
import { Utxo as p } from "../utxo/Utxo.mjs";
import { formatMintAddress as m } from "../../functions/utils/solanaMint.utils.mjs";
import { hashEthereumAddress as h, hashString as g } from "../../functions/utils/addresses.mjs";
import { API as _ } from "../../API/API.mjs";
import { validateAndGetChainId as v } from "../../functions/utils/token-check.utils.mjs";
import { calcEncryptedOutputs as y, calcStealthAddressStructure as b } from "../../functions/snarkjs/common.snarkjs.mjs";
import { calculateTotalFee as x } from "../../functions/utils/fees.utils.mjs";
import { constructAdminData as S } from "../../functions/pre-transaction/constructAdminData.mjs";
import { fetchSolanaTransaction as C } from "../../functions/pre-transaction/sendV0Transaction.mjs";
import { getFeeStructure as w } from "../../functions/pre-transaction/getFeeStructure.mjs";
import { waitForDepositedUtxosInMerkleTree as T } from "../../functions/pre-transaction/waitForDepositedUtxosInMerkleTree.mjs";
import { buildCommitmentValidationData as E } from "../../functions/pre-transaction/buildCommitmentValidationData.mjs";
import "../../functions/pre-transaction/index.mjs";
import { getOnChainUtxosFromReceiptSolana as D } from "../../functions/utils/getUtxosFromReceiptSolana.mjs";
import { constructSolanaZkProof as O } from "../../functions/snarkjs/constructSolanaZkProof.mjs";
import { solanaTransactCallRelayerBatch as k } from "../../functions/web3/functionCalls/transactCallRelayer.mjs";
import { safeUpdateDepositAndWithdrawStatus as A, updateDepositAndWithdrawStatus as j } from "../../API/deposit-and-withdraw-status-calls.mjs";
import { signAndSendSerializedTransaction as M } from "../../functions/web3/signAndSendSerializedTransaction.mjs";
import "../../functions/web3/index.mjs";
import "../../functions/index.mjs";
import { ethers as N } from "ethers";
import { BN as P } from "@coral-xyz/anchor";
import { PublicKey as F } from "@solana/web3.js";
//#region libs/shared/common/src/data-structures/Hinkal/hinkalSolanaDepositAndWithdraw.ts
var I = async (t, c, u, f, h, g, v) => {
	let y = u.erc20TokenAddress, S = f.map((e) => e + x(e, g)), { hinkalIdl: w, hinkalAddress: T, originalDeployer: E } = e[c].contractData;
	if (!w) throw Error("No IDL configured for Solana program on this network");
	if (!E) throw Error("missing original deployer");
	let O = t.userKeys.getShieldedPrivateKey(), k = t.getSolanaProgram(w), N = t.getSolanaPublicKey(), I = new F(E), L = new F(T), { mintPublicKey: R } = m(y), z = R.toString(), B = i(L, I), V = a(L, I), H = r(L, I), U = S.map(() => n(b(p.findCorrectRandomization(d(31), O), O))), W = S.reduce((e, t) => e + t, 0n), G = await s(k, new F(I), [y], [W]), K = S.map((e) => `${e}`), q = "", J = (await j({
		chainId: c,
		hashedEthereumAddress: v,
		phase: l.BEFORE_DEPOSIT
	})).id ?? void 0;
	if (G) {
		let { serializedTransaction: e, blockhash: n, lastValidBlockHeight: r } = await _.generateMultiPaymentDepositLimitless({
			amounts: K,
			payer: t.getSolanaPublicKey().toBase58(),
			ethereumAddress: await t.getEthereumAddressByChain(c),
			mint: y,
			stealthAddressStructures: U,
			chainId: c,
			createBlockedUtxos: !0
		}), { wallet: i } = k.provider;
		if (!i) throw Error("missing wallet");
		q = await M(k.provider, e, n, r);
	} else {
		let e = o(k.programId, I, R), t = z === "11111111111111111111111111111111" ? null : R, n = z === "11111111111111111111111111111111" ? null : void 0;
		q = await k.methods.multiPaymentDeposit(K.map((e) => new P(e)), U, !0).accounts({
			mint: t,
			signer: N,
			signerAta: n,
			originalDeployer: I,
			storageAccount: B,
			storageVault: V,
			merkleAccount: H,
			tokenLimitStorage: e,
			storageVaultAta: n,
			accessTokenOwner: null
		}).rpc();
		let r = await k.provider.connection.getLatestBlockhash();
		await k.provider.connection.confirmTransaction({
			blockhash: r.blockhash,
			lastValidBlockHeight: r.lastValidBlockHeight,
			signature: q
		}, "finalized");
	}
	let Y = await C(k.provider.connection, q, "finalized");
	if (!Y) throw Error("Transaction missing");
	await A({
		id: J,
		chainId: c,
		hashedEthereumAddress: v,
		phase: l.AFTER_DEPOSIT,
		depositTxHash: q
	});
	let { compressedAddress: X } = m(u.erc20TokenAddress), Z = D(Y, k, t.userKeys, X), Q = [], $ = [...Z];
	return h.forEach((e, t) => {
		let n = S[t], r = $.find((e) => e.amount === n);
		if (!r) throw Error(`Could not find newly created UTXO with amount ${n} for recipient ${e}.`);
		Q.push({
			recipientAddress: e,
			utxo: r
		});
		let i = $.indexOf(r);
		$.splice(i, 1);
	}), {
		userDepositedUtxos: Q,
		depositTxHash: q,
		statusId: J
	};
}, L = async (n, r, i, a, o, s, c, h, g, _, v, b) => {
	let C = i.erc20TokenAddress;
	if (a.length === 0) throw Error("userDepositedUtxos must not be empty");
	let { hinkalIdl: w, originalDeployer: T } = e[r].contractData;
	if (!T || !w) throw Error("missing data");
	let D = n.getSolanaProgram(w), j = await n.getRandomRelay(r, !0);
	if (!j) throw Error(u.RELAYER_NOT_AVAILABLE);
	let M = f().toString(), P = n.generateProofRemotely ? 5 : 1, F = [];
	for (let e = 0; e < a.length; e += P) {
		let i = a.slice(e, e + P), s = await Promise.all(i.map(async ({ recipientAddress: e, utxo: i }, a) => {
			let { compressedAddress: s } = m(t), l = new p({
				amount: 0n,
				mintAddress: C,
				erc20TokenAddress: s,
				shieldedPrivateKey: n.userKeys.getShieldedPrivateKey(),
				timeStamp: M,
				tokenId: 0
			}), u = [i, l], f = [l], h = p.findCorrectRandomization(d(31), n.userKeys.getShieldedPrivateKey()), g = {
				tokenNumber: 1,
				nullifierAmount: u.length,
				outputAmount: f.length
			}, _ = y([f])[0][0], b = Array.from(N.getBytes(_)), w = x(c[a], o), k = {
				feeToken: o.feeToken,
				flatFee: w,
				variableRate: 0n
			}, A = S(v, r, [C], [c[a]], await n.getEthereumAddress()), [{ proofAArr: P, proofBArr: F, proofCArr: I, publicInputsArr: L }, R] = await Promise.all([O(n.generateProofRemotely, T, n.merkleTreeHinkalByChain[r], n.merkleTreeAccessTokenByChain[r], n.userKeys, D, [C], [u], [f], h, k.flatFee, k.variableRate, e, j, g, [b], r), E(r, n.userKeys, [C], [u])]), z = {
				recipient: e,
				mint: C === "11111111111111111111111111111111" ? void 0 : C
			};
			return {
				relayAddress: j,
				functionName: "transact",
				chainId: r,
				recipientAmount: c[a].toString(),
				args: {
					proofAArr: P,
					proofBArr: F,
					proofCArr: I,
					publicInputsArr: L,
					encryptedOutputs: [b],
					relayerFee: k.flatFee.toString(),
					dimensions: g
				},
				accounts: z,
				adminData: A,
				commitmentValidationData: R
			};
		}));
		F.push(...s);
	}
	await A({
		id: h,
		chainId: r,
		hashedEthereumAddress: s,
		phase: l.BEFORE_SCHEDULE_WITHDRAW
	});
	let I = await k(r, F, s, g, _, b);
	return await A({
		id: h,
		chainId: r,
		hashedEthereumAddress: s,
		phase: l.AFTER_SCHEDULE_WITHDRAW,
		scheduleId: I
	}), I;
}, R = async (e, t, n, r, i, a, o, s, l) => {
	let u = v([t]), d = t.erc20TokenAddress, f = h(await e.getEthereumAddressByChain(u)), p = l ? g(l) : void 0, m = a ?? await w(u, d, [d], c.Transact, [], 5n), { userDepositedUtxos: _, depositTxHash: y, statusId: b } = await I(e, u, t, n, r, m, f);
	return await T(e, u, _), await L(e, u, t, _, m, f, n, b, i, o, s, p), y;
};
//#endregion
export { R as hinkalSolanaDepositAndWithdraw };
