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