import { ContractType as e } from "../../types/ethereum-network.types.mjs";
import { CustomJSONStringify as t } from "../../functions/utils/serialize.utils.mjs";
import { isExtension as n } from "../../constants/vite.constants.mjs";
import { HINKAL_SUPPORTED_CHAINS as r, WALLET_SUPPORTED_CHAINS as i, chainIds as a, currentSolanaChainId as o, currentTronChainId as s, isSameOnchainNetwork as c, isSolanaLike as l, isTronLike as u, networkRegistry as d, setHinkalTronChainId as f } from "../../constants/chains.constants.mjs";
import { EventType as p, LoginMessageMode as m } from "../../types/hinkal.types.mjs";
import { API as h } from "../../API/API.mjs";
import { supportedPassportLinks as ee } from "../../constants/kyc.constants.mjs";
import { transactionErrorCodes as te } from "../../error-handling/error-codes.constants.mjs";
import { getErc20TokensForChain as ne } from "../../functions/utils/erc20tokenFunctions.mjs";
import "../../API/index.mjs";
import { poseidonFunction as re } from "../../crypto/poseidon.mjs";
import { UserKeys as g } from "../crypto-keys/keys.mjs";
import { validateAndGetChainId as _ } from "../../functions/utils/token-check.utils.mjs";
import { privateTokensDB as v } from "../TokenDBs/PrivateTokensDB.mjs";
import { getShieldedBalance as y } from "../../functions/web3/events/getShieldedBalance.mjs";
import { getMerkleAccountPublicKey as b } from "../../functions/pre-transaction/solana.mjs";
import { getContractWithFetcherByChainId as x } from "../../functions/web3/getContractMetadata.mjs";
import { reloadPage as S } from "../../functions/utils/reloadPage.mjs";
import { createCacheDevice as C } from "../../functions/utils/cacheDevice.utils.mjs";
import { SolanaProviderAdapter as w } from "../../providers/SolanaProviderAdapter.mjs";
import { storeAndGetSignatureFromEnclave as T } from "../../functions/utils/enclave-signature-storage.mjs";
import { generateHashFromSeedPhrases as E } from "../../functions/utils/mnemonics.mjs";
import { fetchSolanaMerkleTreeRootHash as D } from "../../functions/web3/fetchSolanaMerkleTreeRootHash.mjs";
import { createTransaferEmporiumOpsBatch as O } from "../../functions/private-wallet/emporium.helpers.mjs";
import { hinkalDeposit as k, hinkalDepositForOther as A } from "./hinkalDeposit.mjs";
import { checkTokenLimitsUSD as j } from "../../functions/kyc/checkTokenLimitsUSD.mjs";
import { hinkalDepositAndWithdraw as M } from "./hinkalDepositAndWithdraw.mjs";
import { hinkalSolanaDeposit as N, hinkalSolanaDepositForOther as P, hinkalSolanaProoflessDepositWithPublicFee as F } from "./hinkalSolanaDeposit.mjs";
import { hinkalSwap as I } from "./hinkalSwap.mjs";
import { hinkalWithdraw as L } from "./hinkalWithdraw.mjs";
import { MerkleTree as R } from "../merkle-tree/MerkleTree.mjs";
import "../merkle-tree/index.mjs";
import { resetMerkleTrees as z } from "./resetMerkleTrees.mjs";
import { MultiThreadedUtxoUtils as B } from "../MultiThreadedUtxoUtils/MultiThreadedUtxoUtils.mjs";
import { hinkalPrivateWallet as V } from "./hinkalPrivateWallet.mjs";
import { getRecipientInfo as ie } from "./hinkalGetRecipientInfo.mjs";
import { hinkalSignSubAccount as H } from "./hinkalSignSubAccount.mjs";
import { hinkalActionReceive as U } from "./hinkalActionReceive.mjs";
import "../TokenDBs/index.mjs";
import { hinkalProoflessDeposit as W, hinkalProoflessDepositWithPublicFee as G } from "./hinkalProoflessDeposit.mjs";
import { hinkalProxySwap as K } from "./hinkalProxySwap.mjs";
import { hinkalMultiSendPrivateRecipients as q } from "./hinkalMultiSend.mjs";
import { hinkalTransfer as J } from "./hinkalTransfer.mjs";
import { hinkalProxyToPrivate as Y } from "./hinkalProxyToPrivate.mjs";
import { TronProviderAdapter as X } from "../../providers/TronProviderAdapter.mjs";
import { hinkalSolanaDepositAndWithdraw as ae } from "./hinkalSolanaDepositAndWithdraw.mjs";
import { hinkalSolanaWithdraw as oe } from "./hinkalSolanaWithdraw.mjs";
import { hinkalSolanaTransfer as se } from "./hinkalSolanaTransfer.mjs";
import { hinkalSolanaSwap as ce } from "./hinkalSolanaSwap.mjs";
import { hinkalSolanaProxySend as Z } from "./hinkalSolanaProxySend.mjs";
import { hinkalSolanaProxySwap as le } from "./hinkalSolanaProxySwap.mjs";
import { hinkalSolanaProxyShield as Q } from "./hinkalSolanaProxyShield.mjs";
import { hinkalDepositAndBridge as ue } from "./hinkalDepositAndBridge.mjs";
import { hinkalClaimUtxo as de } from "./hinkalClaimUtxo.mjs";
import { hinkalSolanaProoflessDeposit as fe } from "./hinkalSolanaProoflessDeposit.mjs";
import { hinkalSolanaClaimUtxo as pe } from "./hinkalSolanaClaimUtxo.mjs";
import { hinkalWithdrawStuckUtxos as me } from "./hinkalWithdrawStuckUtxos.mjs";
import { PublicKey as $ } from "@solana/web3.js";
//#region libs/shared/common/src/data-structures/Hinkal/Hinkal.ts
var he = class {
	ethereumProviderAdapter;
	solanaProviderAdapter;
	tronProviderAdapter;
	userKeys;
	signingMessage = "Login to Hinkal Protocol";
	privateTransferSigningMessage = "Login to Hinkal's Private Transfer App";
	merkleTreeHinkalByChain = {};
	nullifiersByChain = {};
	encryptedOutputsByChain = {};
	commitmentsSnapshotServiceByChain = {};
	nullifierSnapshotServiceByChain = {};
	utxoUtils;
	lastCallState = /* @__PURE__ */ new Map();
	cacheDevice;
	generateProofRemotely;
	disableMerkleTreeUpdates;
	constructor(e) {
		this.userKeys = new g(void 0), e?.tronChainOverride && f(e.tronChainOverride), r.forEach((e) => {
			this.merkleTreeHinkalByChain[e] = R.create(re, 0n), this.nullifiersByChain[e] = /* @__PURE__ */ new Set(), this.encryptedOutputsByChain[e] = [];
		}), this.generateProofRemotely = e?.generateProofRemotely ?? !0, this.utxoUtils = new B(), this.cacheDevice = C(e), this.disableMerkleTreeUpdates = e?.disableMerkleTreeUpdates ?? !1;
	}
	enforceRateLimit(e, n, r = 1e3) {
		let i = Date.now(), a = t(n), o = this.lastCallState.get(e);
		if (o && o.argsKey === a && i - o.timestamp < r) throw Error(`${e} was already called with the same arguments`);
		this.lastCallState.set(e, {
			timestamp: i,
			argsKey: a
		});
	}
	getProviderAdapter(e) {
		let t = e;
		t ||= this.ethereumProviderAdapter ? a.ethMainnet : this.solanaProviderAdapter ? o : a.tronMainnet;
		let n;
		if (n = l(t) ? this.solanaProviderAdapter : u(t) ? this.tronProviderAdapter : this.ethereumProviderAdapter, !n) throw Error("ProviderAdapter is not initialized");
		return n;
	}
	async initProviderAdapter(e, t) {
		let n = a.ethMainnet;
		t instanceof w ? n = o : t instanceof X && (n = s), await this.updateProviderAdapter(n, t), t.initConnector(e);
		let r = await t.connectAndPatchProvider(e);
		await t.init(r), await this.setListeners();
	}
	getSigningMessage(e = m.PROTOCOL) {
		switch (e) {
			case m.PRIVATE_TRANSFER: return this.privateTransferSigningMessage;
			case m.PROTOCOL:
			default: return this.signingMessage;
		}
	}
	async signHinkalMessage(e = m.PROTOCOL) {
		let t = this.getSigningMessage(e);
		return this.getProviderAdapter().signMessage(t);
	}
	async initUserKeys(e = m.PROTOCOL) {
		this.userKeys = new g(await this.signHinkalMessage(e));
	}
	initUserKeysWithSignature(e) {
		this.userKeys = new g(e);
	}
	async initUserKeysFromSeedPhrases(e) {
		let t = E(e);
		this.userKeys = new g(t);
	}
	async storeAndGetInitialSignature(e, t, n) {
		let r = await this.getEthereumAddress();
		if (!r) throw Error("Connected address not found");
		return await T(r, e, t, n);
	}
	async resetMerkle(e) {
		this.disableMerkleTreeUpdates || (e?.every((e) => this.isSelectedNetworkSupported(e)) ?? !0) && await z(this, e);
	}
	getTronWeb() {
		let e = this.tronProviderAdapter;
		if (!e) throw Error("Tron provider adapter not initialized");
		if (!(e instanceof X)) throw Error("Tron provider adapter is not a TronProviderAdapter");
		let t = e.getTronWeb();
		if (!t) throw Error("TronWeb not available");
		return t;
	}
	getSupportedChains() {
		return this.ethereumProviderAdapter && this.solanaProviderAdapter ? i : this.ethereumProviderAdapter ? r.filter((e) => !l(e) && !u(e)) : this.solanaProviderAdapter ? r.filter((e) => l(e)) : this.tronProviderAdapter ? [s] : [];
	}
	async waitForTransaction(e, t, n = 1) {
		return !!await this.getProviderAdapter(e).waitForTransaction(e, t, n);
	}
	getContract(e, t, n = void 0) {
		return this.getProviderAdapter(e).getContract(e, t, n);
	}
	getContractWithFetcherByChainId(e, t, n = void 0) {
		return x(e, t, n);
	}
	async signMessage(e) {
		return await this.getProviderAdapter().signMessage(e);
	}
	async signTypedData(e, t, n) {
		return await this.getProviderAdapter().signTypedData(e, t, n);
	}
	async signWithSubAccount(e, t, n, r) {
		return H(e, t, n, r);
	}
	getContractWithSigner(e, t, n = "") {
		return this.getProviderAdapter(e).getContractWithSigner(e, t, n);
	}
	getContractWithFetcher(e, t, n = "") {
		return this.getProviderAdapter(e).getContractWithFetcher(e, t, n);
	}
	isSelectedNetworkSupported(e) {
		return !!d[e];
	}
	async switchNetwork(e) {
		let t = this.getProviderAdapter(), n = t.getChainId(), r = n !== void 0 && c(e.chainId, n);
		if (!(e.chainId === n || r)) try {
			await t.switchNetwork(e);
		} catch {
			throw Error(te.FAILED_TO_SWITCH_NETWORKS);
		}
	}
	isPermitterAvailable(e) {
		return this.getProviderAdapter(e).isPermitterAvailable();
	}
	async disconnectFromConnector() {
		await this.ethereumProviderAdapter?.disconnectFromConnector(), await this.solanaProviderAdapter?.disconnectFromConnector(), await this.tronProviderAdapter?.disconnectFromConnector();
	}
	async resetProviderAdapters() {
		this.ethereumProviderAdapter = void 0, this.solanaProviderAdapter = void 0, this.tronProviderAdapter = void 0;
	}
	async updateProviderAdapter(e, t) {
		try {
			l(e) ? (this.solanaProviderAdapter && this.solanaProviderAdapter.release(), this.solanaProviderAdapter = t) : u(e) ? (this.tronProviderAdapter && this.tronProviderAdapter.release(), this.tronProviderAdapter = t) : (this.ethereumProviderAdapter && this.ethereumProviderAdapter.release(), this.ethereumProviderAdapter = t);
		} catch (e) {
			throw console.error(e), Error("updateProviderAdapter failed, please try again.");
		}
	}
	async setListeners() {
		this.ethereumProviderAdapter?.setChainEventListener({
			onAccountChanged: () => {
				this.onAccountChanged();
			},
			onChainChanged: (e) => {
				this.onChainChanged(e);
			}
		}), this.solanaProviderAdapter?.setChainEventListener({
			onAccountChanged: () => {
				this.onAccountChanged();
			},
			onChainChanged: (e) => {
				this.onChainChanged(e);
			}
		}), this.tronProviderAdapter?.setChainEventListener({
			onAccountChanged: () => {
				this.onAccountChanged();
			},
			onChainChanged: (e) => {
				this.onChainChanged(e);
			}
		});
	}
	async onAccountChanged() {
		await this.ethereumProviderAdapter?.onAccountChanged(), await this.solanaProviderAdapter?.onAccountChanged(), await this.tronProviderAdapter?.onAccountChanged();
		let e = p.AccountChanged;
		typeof document < "u" ? document?.dispatchEvent(new Event(e)) : process?.emit("message", e, void 0);
	}
	async onChainChanged(e) {
		e ? await this.getProviderAdapter(e).onChainChanged(e) : (await this.disconnectFromConnector(), S());
	}
	async monitorConnectedAddress(e) {
		await h.monitor(await this.getEthereumAddressByChain(e));
	}
	async getBalances(e, t, n, r, i = !1, a, o = !1) {
		return y(this, e, t, n, r, i, this.generateProofRemotely, a, o);
	}
	async getTotalBalance(e, t, r, i = !1, a, o = !1) {
		let s = r ?? await this.getEthereumAddressByChain(e), c = t ?? this.userKeys, l = await this.getBalances(e, c.getShieldedPrivateKey(), c.getShieldedPublicKey(), s, i, a, o), u = n ? await v.getPrivateTokens(e, s) : ne(e), d = [];
		return u.forEach((e) => {
			let t = e.erc20TokenAddress.toLowerCase(), n = l.get(t), r = {
				token: e,
				balance: n?.balance ?? 0n,
				timestamp: n?.timestamp || "0",
				nfts: n?.nfts || []
			};
			d.push(r);
		}), d;
	}
	async getStuckShieldedBalances(e, t, n) {
		return (await this.getTotalBalance(e, t, n, !1, !1, !0)).filter((e) => e.balance > 0n);
	}
	getSupportedPassportLinks() {
		return ee;
	}
	checkAccessToken(e, t) {
		return Promise.resolve(!0);
	}
	checkExternalTokenLimitsUSD(e, t, n) {
		return j(e, t, n);
	}
	async getHinkalTreeRootHash(t) {
		if (l(t)) {
			let { hinkalIdl: e, hinkalAddress: n, originalDeployer: r } = d[t].contractData;
			if (!e || !n || !r) throw Error(`Missing Solana configuration for chain ${t}`);
			let i = new $(r), a = b(new $(n), i);
			return D(this.getSolanaProgram(e), a);
		}
		return this.getContractWithFetcherByChainId(t, e.HinkalContract).getRootHash();
	}
	async resetMerkleTreesIfNecessary(e) {
		let t = (await Promise.all((e ?? this.getSupportedChains()).map(async (e) => {
			let t = await this.getHinkalTreeRootHash(e);
			return {
				chainId: e,
				needsReset: BigInt(t) !== this.merkleTreeHinkalByChain[e].getRootHash()
			};
		}))).filter((e) => e.needsReset).map((e) => e.chainId);
		t.length > 0 && (console.log("resetting merkle tree in resetMerkleTreesIfNecessary for chains:", t), await this.resetMerkle(t));
	}
	async getEthereumAddress() {
		let e = this.ethereumProviderAdapter ?? this.solanaProviderAdapter ?? this.tronProviderAdapter;
		if (!e) throw Error("No provider adapter initialized");
		return e.getAddress();
	}
	getEthereumAddressByChain(e) {
		return this.getProviderAdapter(e).getAddress();
	}
	async getRandomRelay(e, t = !1) {
		return (await h.getIdleRelay(e, t)).relay;
	}
	getGasPrice(e) {
		let t = this.getProviderAdapter(e);
		if (!t) throw Error("Illegal State of providerAdapter in Hinkal: no providerAdapter initialized");
		return t.getGasPrice(e);
	}
	getAPI() {
		return h;
	}
	snapshotsClearInterval() {
		this.getSupportedChains().forEach((e) => {
			this.commitmentsSnapshotServiceByChain[e]?.intervalClear(), this.nullifierSnapshotServiceByChain[e]?.intervalClear();
		});
	}
	getRecipientInfo() {
		return ie(this);
	}
	async deposit(e, t, n = !0, r = !1) {
		return k(this, e, t, n, r);
	}
	async depositSolana(e, t, n = !1) {
		return N(this, e, t, n);
	}
	async depositForOther(e, t, n, r = !0, i = !1, a) {
		return this.enforceRateLimit(this.depositForOther.name, [
			e,
			t,
			n
		]), A(this, e, t, n, r, i, a);
	}
	async depositSolanaForOther(e, t, n, r = !1, i) {
		return this.enforceRateLimit(this.depositSolanaForOther.name, [
			e,
			t,
			n
		]), P(this, e, t, n, r, i);
	}
	async depositAndWithdraw(e, t, n, r, i, a, o, s, c = !0) {
		return l(_([e])) ? ae(this, e, t, n, r, i, a, o, s) : M(this, e, t, n, r, i, a, o, s, c);
	}
	async claimUtxo(e, t, n, r) {
		return l(_([e])) ? pe(this, e, t, r, n) : de(this, e, t, r, n);
	}
	async depositAndBridge(e, t, n, r, i, a, o, s = !0) {
		return ue(this, e, t, n, r, i, a, o, s);
	}
	async prooflessDeposit(e, t, n, r, i = !1) {
		return l(_(e)) ? fe(this, e, t, n, r, i) : W(this, e, t, n, r, i);
	}
	async prooflessDepositWithPublicFee(e, t, n, r, i) {
		let a = _([e]);
		return l(a) ? F(this, e, t, n, r, i) : G(this, a, e, t, n, r, i);
	}
	getSolanaProgram(e) {
		if (!this.solanaProviderAdapter) throw Error("No provider adapter initialized");
		if (!("getSolanaProgram" in this.solanaProviderAdapter)) throw Error("Current provider adapter is not a Solana provider adapter");
		return this.solanaProviderAdapter.getSolanaProgram(e);
	}
	getSolanaPublicKey() {
		if (!this.solanaProviderAdapter) throw Error("No provider adapter initialized");
		if (!("getSolanaPublicKey" in this.solanaProviderAdapter)) throw Error("Current provider adapter is not a Solana provider adapter");
		return this.solanaProviderAdapter.getSolanaPublicKey();
	}
	async transfer(e, t, n, r, i, a) {
		return this.enforceRateLimit(this.transfer.name, [
			e,
			t,
			n
		]), l(_(e)) ? se(this, e, t, n, r, i, a) : J(this, e, t, n, r, i, a);
	}
	async withdraw(e, t, n, r, i, a, o) {
		return l(_(e)) ? oe(this, e, t, n, i, a, o) : L(this, e, t, n, r, i, a, o);
	}
	async withdrawStuckUtxos(e, t) {
		return me(this, e, t);
	}
	async swap(e, t, n, r, i, a, o) {
		return l(_(e)) ? this.swapSolana(e, t, r, i, a, o) : I(this, e, t, n, r, i, a, o);
	}
	async swapSolana(e, t, n, r, i, a) {
		let o = JSON.parse(n), s = BigInt(o.swapperAccountSalt), { instructionLists: c, addressLookupTableAccount: l } = o.data;
		return ce(this, e, t, s, c, l, r, i, a);
	}
	async actionReceive(e, t, n, r, i, a) {
		if (!i) throw Error("subAccount is required");
		return l(_(e)) ? Q(this, e[0], t[0], i, void 0, a) : U(this, e, t, n, r, i, a);
	}
	async actionPrivateWallet(e, t, n, r, i, a, o, s, c, l, u = !1, d, f, p) {
		return this.enforceRateLimit(this.actionPrivateWallet.name, [
			e,
			t,
			n,
			r,
			i,
			a,
			o,
			s,
			c,
			p
		]), V(this, e, t, n, r, i, a, o, s, c, l, u, d, f, p);
	}
	async proxySwap(e, t, n, r, i, a, o, s, c = !1, u, d) {
		return l(_(e)) ? le(this, e, t, r, a, n, o, s, d) : K(this, e, t, n, r, i, a, o, s, c, u, d);
	}
	async proxyToPrivate(e, t, n, r, i, a, o) {
		return l(_(e)) ? (this.enforceRateLimit(this.proxyToPrivate.name, [
			e[0],
			t[0],
			n,
			r
		]), Q(this, e[0], t[0], n, r, o)) : Y(this, e, t, r, i, a, n, o);
	}
	async proxySend(e, t, n, r, i, a, o) {
		let s = _(e);
		if (l(s)) return Z(this, e[0], t[0], n, r, o);
		let c = O(this, s, e.map((e) => e.erc20TokenAddress), t, r), u = e.map((e, n) => ({
			token: e,
			amount: -1n * t[n]
		}));
		return await this.actionPrivateWallet(s, [], [], [], c, u, n, i, a, void 0, void 0, void 0, o, void 0);
	}
	async multiSendPrivateRecipients(e, t, n) {
		return this.enforceRateLimit(this.multiSendPrivateRecipients.name, [
			e,
			t,
			n
		]), q(this, e, t, n);
	}
	areMerkleTreeUpdatesDisabled() {
		return this.disableMerkleTreeUpdates;
	}
	updateMerkleTreeUpdates(e) {
		this.disableMerkleTreeUpdates = e;
	}
};
//#endregion
export { he as Hinkal };
