@vechain/vechain-kit 2.4.2 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AccountModal-CK-qcPlQ.js +1 -0
- package/dist/AccountModal-ChuVFqPc.js +20 -0
- package/dist/AccountModal-ChuVFqPc.js.map +1 -0
- package/dist/AccountModal-DNK0IbiE.cjs +1 -0
- package/dist/AccountModal-DjAS4w6z.cjs +20 -0
- package/dist/AccountModal-DjAS4w6z.cjs.map +1 -0
- package/dist/BaseModal-CWAI9-Bi.js +2 -0
- package/dist/BaseModal-CWAI9-Bi.js.map +1 -0
- package/dist/BaseModal-yevRjczw.cjs +2 -0
- package/dist/BaseModal-yevRjczw.cjs.map +1 -0
- package/dist/ConnectModal-BXbiUwnz.js +1 -0
- package/dist/ConnectModal-C50EF9gE.js +2 -0
- package/dist/ConnectModal-C50EF9gE.js.map +1 -0
- package/dist/ConnectModal-CvkkVALe.cjs +1 -0
- package/dist/ConnectModal-DmIkWb1i.cjs +2 -0
- package/dist/ConnectModal-DmIkWb1i.cjs.map +1 -0
- package/dist/DisconnectConfirmContent-B4qahKqQ.cjs +2 -0
- package/dist/DisconnectConfirmContent-B4qahKqQ.cjs.map +1 -0
- package/dist/DisconnectConfirmContent-C9qLnI-m.js +2 -0
- package/dist/DisconnectConfirmContent-C9qLnI-m.js.map +1 -0
- package/dist/LegalDocumentsModal-5sNOrJI9.js +1 -0
- package/dist/LegalDocumentsModal-aWgfKwIL.js +2 -0
- package/dist/LegalDocumentsModal-aWgfKwIL.js.map +1 -0
- package/dist/LegalDocumentsModal-fnhM40y6.cjs +2 -0
- package/dist/LegalDocumentsModal-fnhM40y6.cjs.map +1 -0
- package/dist/LegalDocumentsModal-g54lP0U7.cjs +1 -0
- package/dist/PrivyCrossAppProvider-B6oIXeWL.js +2 -0
- package/dist/PrivyCrossAppProvider-B6oIXeWL.js.map +1 -0
- package/dist/PrivyCrossAppProvider-C6aL4Qor.cjs +1 -0
- package/dist/PrivyCrossAppProvider-Ccu2yH99.js +1 -0
- package/dist/PrivyCrossAppProvider-DSuzrbqs.cjs +2 -0
- package/dist/PrivyCrossAppProvider-DSuzrbqs.cjs.map +1 -0
- package/dist/PrivyWalletProvider-BkqWSj75.cjs +2 -0
- package/dist/PrivyWalletProvider-BkqWSj75.cjs.map +1 -0
- package/dist/PrivyWalletProvider-DToo_u0W.js +2 -0
- package/dist/PrivyWalletProvider-DToo_u0W.js.map +1 -0
- package/dist/ShareButtons-B92JZp47.js +2 -0
- package/dist/ShareButtons-B92JZp47.js.map +1 -0
- package/dist/ShareButtons-CRMNerbz.cjs +2 -0
- package/dist/ShareButtons-CRMNerbz.cjs.map +1 -0
- package/dist/UpgradeSmartAccountModal-BAzmVxeJ.js +2 -0
- package/dist/UpgradeSmartAccountModal-BAzmVxeJ.js.map +1 -0
- package/dist/UpgradeSmartAccountModal-BGjTzYAm.cjs +1 -0
- package/dist/UpgradeSmartAccountModal-CpZo27Uk.js +1 -0
- package/dist/UpgradeSmartAccountModal-IMcihO0d.cjs +2 -0
- package/dist/UpgradeSmartAccountModal-IMcihO0d.cjs.map +1 -0
- package/dist/VechainKitThemeProvider-BM5258oA.cjs +75 -0
- package/dist/VechainKitThemeProvider-BM5258oA.cjs.map +1 -0
- package/dist/VechainKitThemeProvider-Di9a04Es.js +75 -0
- package/dist/VechainKitThemeProvider-Di9a04Es.js.map +1 -0
- package/dist/assets/index.cjs +1 -1
- package/dist/assets/index.d.cts +1 -1
- package/dist/assets/{index.d.mts → index.d.ts} +1 -1
- package/dist/assets/index.js +1 -0
- package/dist/{assets-BL24r-Yp.mjs → assets-CXk1qRDd.js} +5 -5
- package/dist/assets-CXk1qRDd.js.map +1 -0
- package/dist/{assets-DNJsQD7_.cjs → assets-YPd7adzM.cjs} +7 -7
- package/dist/assets-YPd7adzM.cjs.map +1 -0
- package/dist/chunk-DjWAcSYV.cjs +1 -0
- package/dist/components/index.cjs +1 -0
- package/dist/components/index.d.cts +6 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +1 -0
- package/dist/components-QKLypcU1.cjs +2 -0
- package/dist/components-QKLypcU1.cjs.map +1 -0
- package/dist/components-k36uDisW.js +2 -0
- package/dist/components-k36uDisW.js.map +1 -0
- package/dist/hooks/index.cjs +1 -0
- package/dist/hooks/index.d.cts +6 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks-C8eXQYIN.cjs +8 -0
- package/dist/hooks-C8eXQYIN.cjs.map +1 -0
- package/dist/hooks-DuTew9oP.js +8 -0
- package/dist/hooks-DuTew9oP.js.map +1 -0
- package/dist/{index-CpRbZET6.d.mts → index-BGQS0a81.d.ts} +564 -1581
- package/dist/index-BGQS0a81.d.ts.map +1 -0
- package/dist/index-Bqw0Cz5n.d.cts +587 -0
- package/dist/index-Bqw0Cz5n.d.cts.map +1 -0
- package/dist/index-BugHmddr.d.ts +587 -0
- package/dist/index-BugHmddr.d.ts.map +1 -0
- package/dist/{index-D4rz985m.d.cts → index-C8wbz8af.d.cts} +561 -1578
- package/dist/index-C8wbz8af.d.cts.map +1 -0
- package/dist/{index-CWViOs1U.d.mts → index-COoeacay.d.ts} +5 -5
- package/dist/index-COoeacay.d.ts.map +1 -0
- package/dist/{index-u3CPquCV.d.cts → index-CmGg4iaS.d.cts} +4 -4
- package/dist/{index-CWViOs1U.d.mts.map → index-CmGg4iaS.d.cts.map} +1 -1
- package/dist/index-DI_IPiLX.d.ts +324 -0
- package/dist/index-DI_IPiLX.d.ts.map +1 -0
- package/dist/index-DVxlUr9t.d.cts +324 -0
- package/dist/index-DVxlUr9t.d.cts.map +1 -0
- package/dist/index.cjs +1 -221
- package/dist/index.d.cts +6 -3
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -0
- package/dist/network-Cs9YqDJ1.d.cts +536 -0
- package/dist/network-Cs9YqDJ1.d.cts.map +1 -0
- package/dist/network-yA5VWcPq.d.ts +536 -0
- package/dist/network-yA5VWcPq.d.ts.map +1 -0
- package/dist/providers/index.cjs +1 -0
- package/dist/providers/index.d.cts +3 -0
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.js +1 -0
- package/dist/providers-DImdr6Kk.cjs +124 -0
- package/dist/providers-DImdr6Kk.cjs.map +1 -0
- package/dist/providers-kA0lotaM.js +124 -0
- package/dist/providers-kA0lotaM.js.map +1 -0
- package/dist/ssrUtils-C_5ZY26i.cjs +2 -0
- package/dist/ssrUtils-C_5ZY26i.cjs.map +1 -0
- package/dist/ssrUtils-DSwxhTtm.js +2 -0
- package/dist/ssrUtils-DSwxhTtm.js.map +1 -0
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +2 -2
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils-B2Eg9TD3.js +2 -0
- package/dist/utils-B2Eg9TD3.js.map +1 -0
- package/dist/utils-jW13BhAb.cjs +2 -0
- package/dist/utils-jW13BhAb.cjs.map +1 -0
- package/package.json +46 -9
- package/dist/assets/index.mjs +0 -1
- package/dist/assets-BL24r-Yp.mjs.map +0 -1
- package/dist/assets-DNJsQD7_.cjs.map +0 -1
- package/dist/index-CpRbZET6.d.mts.map +0 -1
- package/dist/index-D4rz985m.d.cts.map +0 -1
- package/dist/index-u3CPquCV.d.cts.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.mts +0 -3
- package/dist/index.mjs +0 -221
- package/dist/index.mjs.map +0 -1
- package/dist/utils/index.d.mts +0 -3
- package/dist/utils/index.mjs +0 -1
- package/dist/utils-BQ9mZctf.cjs +0 -2
- package/dist/utils-BQ9mZctf.cjs.map +0 -1
- package/dist/utils-BxZj2QIg.mjs +0 -2
- package/dist/utils-BxZj2QIg.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-C8eXQYIN.cjs","names":["useLocalStorage","LocalStorageKey","PRIVY_AUTH_BASE_URL","DEFAULT_PRIVY_ECOSYSTEM_APPS","PRIVY_STATUS_BASE_URL","getConfig","VetDomainsRegistry__factory","useOptionalThor","useVeChainKitConfig","TIME","useOptionalThor","useOptionalThor","useOptionalDAppKitWallet","useWallet","useVeChainKitConfig","useGetNodeUrl","useOptionalPrivyWalletProvider","clauses","privyUIOptions","Revision","delegationUrl","error","txReceipt","useVeChainKitConfig","useVeChainKitConfig","getTextRecordsQueryKey","getAvatarOfAddressQueryKey","z","getConfig","useVeChainKitConfig","getVechainDomainQueryKey","getTextRecordsQueryKey","getAvatarOfAddressQueryKey","VeworldSubdomainClaimer__factory","ReverseRegistrarInterface","VetDomainsReverseRegistrar__factory","clausesArray: any[]","getConfig","humanAddress","useWallet","useVeChainKitConfig","ReverseRegistrarInterface","VetDomainsReverseRegistrar__factory","clausesArray: any[]","getConfig","humanAddress","useVeChainKitConfig","useWallet","ABIContract","VeworldSubdomainClaimer__factory","getConfig","useOptionalThor","useVeChainKitConfig","nameInterface","Interface","useVeChainKitConfig","useCallClause","getConfig","VetDomainsRegistry__factory","Interface","getConfig","convertUriToUrl","useVeChainKitConfig","VetDomainsReverseRegistrar__factory","clausesArray: any[]","getConfig","humanAddress","useWallet","useVeChainKitConfig","Address","useOptionalThor","useVeChainKitConfig","formatTokenBalance","useVeChainKitConfig","formatTokenBalance","useVeChainKitConfig","formatTokenBalance","useVeChainKitConfig","useLocalStorage","LocalStorageKey","useVeChainKitConfig","token: CustomTokenInfo","compareAddresses","getConfig","useVeChainKitConfig","formatTokenBalance","useVeChainKitConfig","getConfig","baseTokens: WalletTokenBalance[]","customTokens: WalletTokenBalance[]","getConfig","OracleVechainEnergy__factory","BigNumber","useOptionalThor","useVeChainKitConfig","useVeChainKitConfig","getConfig","defaultOptions: Intl.NumberFormatOptions","bcp47LanguageCodes","i18n","allCurrencies: CURRENCY[]","useVeChainKitConfig","abi","XAllocationVoting__factory","method","getCallClauseQueryKey","useVeChainKitConfig","getConfig","useCallClause","useVeChainKitConfig","abi","XAllocationVoting__factory","method","getCallClauseQueryKeyWithArgs","getConfig","useVeChainKitConfig","useCallClause","abi","XAllocationPool__factory","useOptionalThor","useVeChainKitConfig","getConfig","executeMultipleClausesCall","useWallet","useOptionalDAppKitWallet","useWallet","useWalletStorage","isBrowser","convertUriToUrl","X2EarnApps__factory","useOptionalThor","useVeChainKitConfig","getConfig","convertUriToUrl","useVeChainKitConfig","convertUriToUrl","resolveMediaTypeFromMimeType","useVeChainKitConfig","useVeChainKitConfig","imageCompressionOptions: CompressOptions","compressedImages: File[]","parsedUploads: UploadedImage[]","compressImages","image: UploadedImage","image: UploadedImage","useWallet","zeroAddress","flowsByToken: Record<string, { inflow: bigint; outflow: bigint }>","ERC20_ABI","revertReason: string | undefined","aggregatedFlows: Record<\n string,\n { inflow: bigint; outflow: bigint }\n >","abi","aggregator: SwapAggregator","quoteData: APIQuoteResponse","VETRADE_ADDRESSES: Record<NETWORK_TYPE, { supportedAddresses: Address[] }>","isVET","VETRADE_BASE_URL","React","VeTradeLogo","clauses: TransactionClause[]","ABIContract","IERC20__factory","VeChainAddress","Clause","VET","Units","aggregator: SwapAggregator","path: Address[]","UniswapV2Router__factory","ABIContract","clauses: TransactionClause[]","Clause","VeChainAddress","VET","Units","IERC20__factory","BETTERSWAP_ADDRESSES: Record<NETWORK_TYPE, { routerAddress: Address; wrappedVET: Address }>","zeroAddress","React","BetterSwapLogo","useOptionalThor","useWallet","zeroAddress","params: SwapParams | null","amountInRaw: bigint","error","best: SwapQuote | null","DEFAULT_DAPPKIT_WALLET_MODAL_STATE: UseOptionalDAppKitWalletModalReturnType","useVeChainKitConfig","dappKitModalResult: ReturnType<typeof useWalletModal> | null","useVeChainKitConfig","useModal","useModal","useModal","useModal","useWallet","useModal","useModal","useModal","useModal","useModal","useModal","useModal","useModal","useModal","useVeChainKitConfig","VECHAIN_PRIVY_APP_ID","method","baseConfig: LoginModalContentConfig","useModal","useModal","useModal","useModal","DEFAULT_NOTIFICATIONS: Notification[]","useWallet","isBrowser","getLocalStorageItem","newNotification: Notification","getConfig","SocialLoginSmartAccountFactory__factory","useOptionalThor","useVeChainKitConfig","useWallet","useWallet","useOptionalDAppKitWallet","useOptionalPrivyWalletProvider","sig: string | null","error","useOptionalDAppKitWallet","useWallet","useOptionalPrivyWalletProvider","sig: string","error","useOptionalPrivyCrossAppSdk","useCrossAppConnectionCache","VECHAIN_PRIVY_APP_ID","VEBETTERDAO_GOVERNANCE_BASE_URL","handlePopupError","getLocalStorageItem","APP_HUB_GITHUB_API_BASE_URL","APP_HUB_GITHUB_RAW_REPO_BASE_URL","useVeChainKitConfig","useVeChainKitConfig","CACHE_KEY","getLocalStorageItem","isBrowser","getConfig","SocialLoginSmartAccountFactory__factory","implementationAddressPromise:\n | ReturnType<typeof contract.read.accountImplementationV1>\n | ReturnType<typeof contract.read.accountImplementationV3>","useOptionalThor","useVeChainKitConfig","getConfig","SocialLoginSmartAccountFactory__factory","useOptionalThor","useVeChainKitConfig","getConfig","SocialLoginSmartAccountFactory__factory","useOptionalThor","useVeChainKitConfig","Address","useGetNodeUrl","ThorClient","getConfig","SocialLoginSmartAccountFactory__factory","useOptionalThor","useVeChainKitConfig","useWallet","useVeChainKitConfig","getAccountVersionQueryKey","getHasV1SmartAccountQueryKey","useWallet","getSmartAccountQueryKey","SocialLoginSmartAccount__factory","buildClauses","isValidAddress","humanAddress","TIME","useOptionalThor","allEvents: EventLogs[]","IERC20__factory","isValidAddress","clausesArray: any[]","humanAddress","isValidAddress","clausesArray: EnhancedClause[]","humanAddress","useWallet","useOptionalThor","abi","useWallet","useSmartAccount","useVeChainKitConfig","useGasTokenSelection","lastError: Error | null","estimateGas","useWallet","useSmartAccount","useVeChainKitConfig","estimates: Record<\n GasTokenType,\n { cost: number; loading: boolean; error?: string }\n >","estimateGas"],"sources":["../src/hooks/cache/useEcosystemShortcuts.ts","../src/hooks/api/privy/useFetchAppInfo.ts","../src/hooks/api/privy/useFetchPrivyStatus.ts","../src/hooks/api/vetDomains/useEnsRecordExists.ts","../src/hooks/thor/transactions/useTxReceipt.ts","../src/hooks/thor/transactions/useGasEstimate.ts","../src/hooks/thor/transactions/useSendTransaction.ts","../src/hooks/api/vetDomains/useGetAvatar.ts","../src/hooks/api/wallet/useRefreshMetadata.ts","../src/hooks/api/vetDomains/useGetDomainsOfAddress.ts","../src/hooks/api/vetDomains/utils/domainQueryUtils.ts","../src/hooks/api/vetDomains/useClaimVeWorldSubdomain.ts","../src/hooks/api/vetDomains/useClaimVetDomain.ts","../src/hooks/api/vetDomains/useIsDomainProtected.ts","../src/hooks/api/vetDomains/useUpdateTextRecord.ts","../src/hooks/api/vetDomains/useGetResolverAddress.ts","../src/hooks/api/vetDomains/useGetAvatarLegacy.ts","../src/hooks/api/vetDomains/useUnsetDomain.ts","../src/hooks/thor/accounts/useAccountBalance.ts","../src/hooks/api/wallet/useGetB3trBalance.ts","../src/hooks/api/wallet/useGetVot3Balance.ts","../src/hooks/api/wallet/useGetErc20Balance.ts","../src/hooks/api/wallet/useGetCustomTokenInfo.ts","../src/hooks/api/wallet/useCustomTokens.ts","../src/hooks/api/wallet/useGetCustomTokenBalances.ts","../src/hooks/api/wallet/useTokenBalances.ts","../src/hooks/api/wallet/useGetTokenUsdPrice.ts","../src/hooks/api/wallet/useTokenPrices.ts","../src/utils/currencyUtils.ts","../src/hooks/utils/useCurrency.ts","../src/hooks/api/wallet/useTokensWithValues.ts","../src/hooks/api/wallet/useTotalBalance.ts","../src/hooks/api/wallet/useCurrentAllocationsRoundId.ts","../src/hooks/api/wallet/useIsPerson.ts","../src/hooks/api/wallet/useRoundXApps.ts","../src/hooks/api/wallet/useXAppShares.ts","../src/hooks/api/wallet/useMostVotedAppsInRound.ts","../src/hooks/api/wallet/useRefreshBalances.ts","../src/hooks/api/wallet/useSwitchWallet.ts","../src/hooks/api/wallet/useXAppMetadata.tsx","../src/hooks/api/ipfs/useIpfsMetadata.ts","../src/hooks/api/ipfs/useIpfsImage.ts","../src/hooks/api/ipfs/useIpfsMetadatas.ts","../src/hooks/api/ipfs/useUploadImages.ts","../src/hooks/api/ipfs/useSingleImageUpload.ts","../src/hooks/api/swap/useSwapTransaction.ts","../src/utils/swap/simulateSwap.ts","../src/utils/swap/apiAggregator.ts","../src/utils/swap/veTrade.tsx","../src/utils/swap/uniswapV2Aggregator.ts","../src/utils/swap/betterSwap.tsx","../src/config/swapAggregators.ts","../src/hooks/api/swap/useSwapQuotes.ts","../src/hooks/api/dappkit/useOptionalDAppKitWalletModal.ts","../src/hooks/modals/useConnectModal.tsx","../src/hooks/modals/useAccountModal.tsx","../src/hooks/modals/useTransactionModal.tsx","../src/hooks/modals/useTransactionToast.tsx","../src/hooks/modals/useWalletModal.tsx","../src/hooks/modals/useChooseNameModal.tsx","../src/hooks/modals/useSendTokenModal.tsx","../src/hooks/modals/useSwapTokenModal.tsx","../src/hooks/modals/useExploreEcosystemModal.tsx","../src/hooks/modals/useNotificationsModal.tsx","../src/hooks/modals/useFAQModal.tsx","../src/hooks/modals/useAccountCustomizationModal.tsx","../src/hooks/modals/useReceiveModal.tsx","../src/hooks/modals/useLoginModalContent.ts","../src/hooks/modals/useUpgradeSmartAccountModal.tsx","../src/hooks/modals/useProfileModal.tsx","../src/hooks/modals/useAccountModalOptions.tsx","../src/hooks/modals/useSettingsModal.tsx","../src/hooks/notifications/types.ts","../src/hooks/notifications/useNotifications.ts","../src/hooks/thor/smartAccounts/useUpgradeRequiredForAccount.ts","../src/hooks/notifications/useNotificationAlerts.ts","../src/hooks/signing/useSignMessage.ts","../src/hooks/signing/useSignTypedData.ts","../src/hooks/login/useLoginWithPasskey.ts","../src/hooks/login/useLoginWithOAuth.ts","../src/hooks/login/useLoginWithVeChain.ts","../src/hooks/utils/useAppHubApps.ts","../src/hooks/utils/useCurrentLanguage.ts","../src/hooks/utils/useCurrentCurrency.ts","../src/hooks/utils/useFeatureAnnouncement.ts","../src/hooks/utils/useIsPwa.ts","../src/hooks/utils/useScrollToTop.ts","../src/hooks/thor/smartAccounts/useAccountImplementationAddress.ts","../src/hooks/thor/smartAccounts/useCurrentAccountImplementationVersion.ts","../src/hooks/thor/smartAccounts/useGetAccountAddress.ts","../src/hooks/thor/smartAccounts/useIsSmartAccountDeployed.ts","../src/hooks/thor/smartAccounts/useUpgradeRequired.ts","../src/hooks/thor/smartAccounts/useRefreshFactoryQueries.ts","../src/hooks/thor/smartAccounts/useRefreshSmartAccountQueries.ts","../src/hooks/thor/smartAccounts/useUpgradeSmartAccount.ts","../src/hooks/thor/blocks/useCurrentBlock.ts","../src/hooks/thor/logs/logUtils.ts","../src/hooks/thor/transactions/useTransferERC20.ts","../src/hooks/thor/transactions/useTransferVET.ts","../src/hooks/thor/transactions/useBuildTransaction.ts","../src/hooks/utils/useEvents.ts","../src/hooks/generic-delegator/useGenericDelegatorFeeEstimation.ts","../src/hooks/generic-delegator/useEstimateAllTokens.ts"],"sourcesContent":["import { useLocalStorage, LocalStorageKey } from './useLocalStorage';\n\nexport type EcosystemShortcut = {\n name: string;\n image: string;\n url: string;\n description?: string;\n};\n\nexport const useEcosystemShortcuts = () => {\n const [shortcuts, setShortcuts] = useLocalStorage<EcosystemShortcut[]>(\n LocalStorageKey.ECOSYSTEM_SHORTCUTS,\n [],\n );\n\n const addShortcut = (shortcut: EcosystemShortcut) => {\n if (!shortcuts.some((s: EcosystemShortcut) => s.url === shortcut.url)) {\n setShortcuts([...shortcuts, shortcut]);\n }\n };\n\n const removeShortcut = (url: string) => {\n setShortcuts(shortcuts.filter((s: EcosystemShortcut) => s.url !== url));\n };\n\n const isShortcut = (url: string) => {\n return shortcuts.some((s: EcosystemShortcut) => s.url === url);\n };\n\n return {\n shortcuts,\n addShortcut,\n removeShortcut,\n isShortcut,\n };\n};\n","import type { PrivyAppInfo } from '../../../types';\nimport { useQuery } from '@tanstack/react-query';\nimport { DEFAULT_PRIVY_ECOSYSTEM_APPS } from '../../../utils/constants';\nimport { PRIVY_AUTH_BASE_URL } from '../../../constants';\n\nexport const fetchPrivyAppInfo = async (\n appId: string,\n): Promise<PrivyAppInfo> => {\n const appInfoUrl = new URL(`/api/v1/apps/${appId}`, PRIVY_AUTH_BASE_URL);\n const response = await fetch(appInfoUrl, {\n headers: {\n 'privy-app-id': appId,\n },\n });\n\n if (!response.ok) {\n throw new Error('Failed to fetch Privy app info');\n }\n\n return response.json();\n};\n\nexport const getPrivyAppInfoQueryKey = (appIds: string | string[]) => [\n 'VECHAIN_KIT_PRIVY_APP_INFO',\n ...(Array.isArray(appIds) ? appIds : [appIds]),\n];\n\nexport const useFetchAppInfo = (appIds: string | string[]) => {\n const normalizedIds = Array.isArray(appIds) ? appIds : [appIds];\n\n return useQuery({\n queryKey: getPrivyAppInfoQueryKey(appIds),\n queryFn: async () => {\n const results = await Promise.all(\n normalizedIds.map((id) => fetchPrivyAppInfo(id)),\n );\n\n return Object.fromEntries(\n results.map((result, index) => {\n const id = normalizedIds[index];\n const defaultApp = DEFAULT_PRIVY_ECOSYSTEM_APPS.find(\n (app) => app.id === id,\n );\n return [\n id,\n {\n ...result,\n website: defaultApp?.website,\n },\n ];\n }),\n );\n },\n enabled: normalizedIds.length > 0,\n retry: (failureCount, error) => {\n // Don't retry on cancellation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || errorMessage.includes('abort')) {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { PRIVY_STATUS_BASE_URL } from '../../../constants';\n\nexport const fetchPrivyStatus = async (): Promise<string> => {\n try {\n const statusUrl = new URL('summary.json', PRIVY_STATUS_BASE_URL);\n const response = await fetch(statusUrl);\n\n if (!response.ok) {\n throw new Error('Failed to fetch Privy status');\n }\n\n const data = await response.json();\n return data.page.status ?? 'No data';\n } catch (error) {\n console.error('Error fetching data:', error);\n return 'Error fetching data';\n }\n};\n\nexport const useFetchPrivyStatus = () => {\n return useQuery({\n queryKey: ['PRIVY_STATUS'],\n queryFn: fetchPrivyStatus,\n retry: (failureCount, error) => {\n // Don't retry on cancellation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || errorMessage.includes('abort')) {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","import { getConfig } from '../../../config';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { VetDomainsRegistry__factory } from '@vechain/vechain-contract-types';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { useQuery } from '@tanstack/react-query';\nimport { useOptionalThor } from '../dappkit/useOptionalThor';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { concat, keccak256, toBytes } from 'viem';\n\nconst getEnsRecordExists = async (\n thor: ThorClient,\n network: NETWORK_TYPE,\n name: string,\n): Promise<boolean> => {\n // .veworld.vet\n const hashedNode =\n '0x571e15b4bbf879cf28e5075190137be8e18500e3d38543bf0cbcdb54e00b02cc';\n\n // First hash the label using keccak256(bytes(name))\n const labelHash = keccak256(toBytes(name));\n\n // Then combine node and label exactly as in the contract:\n // bytes32 subnode = keccak256(abi.encodePacked(node, label));\n const subnode = keccak256(concat([hashedNode, labelHash]));\n\n const res = await thor.contracts\n .load(\n getConfig(network).vetDomainsContractAddress,\n VetDomainsRegistry__factory.abi,\n )\n .read.recordExists(subnode);\n\n if (!res) throw new Error(`Failed to get ENS record exists for ${name}`);\n\n return res[0] as boolean;\n};\n\nexport const getEnsRecordExistsQueryKey = (name: string) => [\n 'VECHAIN_KIT_ENS_RECORD_VE_WORLD_EXISTS',\n name,\n];\n\nexport const useEnsRecordExists = (name: string) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getEnsRecordExistsQueryKey(name),\n queryFn: () => getEnsRecordExists(thor!, network.type, name),\n enabled: !!thor && !!name,\n retry: (failureCount, error) => {\n // Don't retry on cancellation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || errorMessage.includes('abort')) {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","'use client';\n\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { useQuery } from '@tanstack/react-query';\nimport { TIME } from '../../../utils';\n\nconst BLOCK_GENERATION_INTERVAL = 10 * TIME.SECOND;\n\nexport const txReceiptQueryKey = (txId: string) => [\n 'VECHAIN_KIT',\n 'TX_RECEIPT',\n txId,\n];\n\n/**\n * Retrieve the receipt of a transaction identified by its ID.\n * If the transaction is not found, the response will be null.\n * @param txId The ID of the transaction to retrieve the receipt for\n * @param blockTimeout Optional timeout in milliseconds to stop polling for receipt\n * @returns Query result containing the transaction receipt\n */\nexport const useTxReceipt = (txId: string, blockTimeout = 5) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n\n return useQuery({\n queryKey: txReceiptQueryKey(txId),\n queryFn: async () => {\n if (!thor) throw new Error('Thor client not available');\n const response = await thor.transactions.waitForTransaction(txId, {\n timeoutMs: blockTimeout * BLOCK_GENERATION_INTERVAL,\n intervalMs: 3000\n });\n\n if (!response) throw new Error('Transaction receipt not found');\n\n return response;\n },\n enabled: !!thor && !!txId,\n });\n};\n","import type { Revision, TransactionClause } from '@vechain/sdk-core';\nimport type { ThorClient } from '@vechain/sdk-network';\n\nexport const useGasEstimate = async (\n thor: ThorClient,\n clauses: TransactionClause[],\n caller: string,\n options?: {\n revision?: Revision;\n gasPadding?: number;\n },\n) => {\n const response = await thor.transactions.estimateGas(\n clauses,\n caller,\n options,\n );\n\n if (response.reverted) throw new Error('Failed to estimate gas');\n\n let totalGas = response?.totalGas ?? 0;\n // Ensure it covers the case where the gas estimation is not a number\n if (!totalGas || Number.isNaN(totalGas)) {\n totalGas = 0;\n }\n\n return Math.ceil(totalGas);\n};\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { TransactionMessage } from '@vechain/dapp-kit';\n// Import from specific provider files to avoid circular dependencies\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { useOptionalPrivyWalletProvider } from '../../../providers/PrivyWalletProvider';\nimport type { TransactionStatus, TransactionStatusErrorType } from '../../../types';\n// Direct imports to avoid circular dependencies\nimport { useGetNodeUrl } from '../../utils/useGetNodeUrl';\nimport { useTxReceipt } from './useTxReceipt';\nimport { useWallet } from '../../api/wallet/useWallet';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { useOptionalDAppKitWallet } from '../../api/dappkit/useOptionalDAppKitWallet';\nimport { useGasEstimate } from './useGasEstimate';\nimport { TransactionReceipt } from '@vechain/sdk-network';\nimport { Revision, TransactionClause } from '@vechain/sdk-core';\n\n/**\n * Props for the {@link useSendTransaction} hook\n * @param signerAccountAddress the signer account to use\n * @param clauses clauses to send in the transaction\n * @param onTxConfirmed callback to run when the tx is confirmed\n * @param onTxFailedOrCancelled callback to run when the tx fails or is cancelled\n * @param suggestedMaxGas the suggested max gas for the transaction\n * @param privyUIOptions options to pass to the Privy UI\n * @param gasPadding the gas padding to use for the transaction (Eg. 0.1 for 10%)\n * @param delegationUrl the dApp sponsored delegator url.\n */\ntype UseSendTransactionProps = {\n signerAccountAddress?: string | null;\n clauses?: TransactionClause[];\n onTxConfirmed?: () => void | Promise<void>;\n onTxFailedOrCancelled?: (error?: Error | string) => void | Promise<void>;\n suggestedMaxGas?: number;\n privyUIOptions?: {\n title?: string;\n description?: string;\n buttonText?: string;\n };\n gasPadding?: number;\n delegationUrl?: string;\n};\n\n/**\n * Return value of the {@link useSendTransaction} hook\n * @param sendTransaction function to trigger the transaction\n * @param isTransactionPending boolean indicating if the transaction is waiting for the wallet to sign it\n * @param isWaitingForWalletConfirmation boolean indicating if the transaction is waiting for the wallet to confirm it\n * @param txReceipt the transaction receipt\n * @param status the status of the transaction (see {@link TransactionStatus})\n * @param resetStatus function to reset the status to \"ready\"\n * @param error error that occurred while sending the transaction\n */\nexport type UseSendTransactionReturnValue = {\n sendTransaction: (\n clauses?: TransactionClause[],\n delegationUrl?: string,\n privyUIOptions?: {\n title?: string;\n description?: string;\n buttonText?: string;\n },\n ) => Promise<void>;\n isTransactionPending: boolean;\n isWaitingForWalletConfirmation: boolean;\n txReceipt: TransactionReceipt | null;\n status: TransactionStatus;\n resetStatus: () => void;\n error?: TransactionStatusErrorType;\n};\n\n/**\n * Generic hook to send a transaction using dapp-kit-react.\n * This hook supports both Privy and VeChain wallets.\n *\n * It returns a function to send the transaction and a status to indicate the state\n * of the transaction (together with the transaction id).\n *\n * * ⚠️ IMPORTANT: When using this hook with Privy cross-app connections, ensure all\n * data fetching is done before triggering the transaction. Fetching data after\n * the transaction is triggered may cause browser popup blocking. Pre-fetch any\n * required data and pass it to your transaction building logic.\n *\n * @example\n * ```typescript\n * // ❌ Bad: Fetching during transaction\n * const sendTx = async () => {\n * const data = await fetchSomeData(); // May cause popup blocking\n * return sendTransaction(data);\n * };\n *\n * // ✅ Good: Pre-fetch data\n * const { data } = useQuery(['someData'], fetchSomeData);\n * const sendTx = () => sendTransaction(data); // No async operations\n * ```\n *\n * @param signerAccount the signer account to use\n * @param clauses clauses to send in the transaction\n * @param onTxConfirmed callback to run when the tx is confirmed\n * @param onTxFailedOrCancelled callback to run when the tx fails or is cancelled\n * @param suggestedMaxGas the suggested max gas for the transaction\n * @param privyUIOptions options to pass to the Privy UI\n * @param gasPadding the gas padding to use for the transaction (Eg. 0.1 for 10%)\n * @param delegationUrl the dApp sponsored delegator url.\n * @returns see {@link UseSendTransactionReturnValue}\n */\nexport const useSendTransaction = ({\n signerAccountAddress,\n clauses,\n onTxConfirmed,\n onTxFailedOrCancelled,\n suggestedMaxGas,\n privyUIOptions,\n gasPadding,\n delegationUrl,\n}: UseSendTransactionProps): UseSendTransactionReturnValue => {\n // Use optional hooks that handle missing providers gracefully\n const thor = useOptionalThor();\n const { signer, requestTransaction } = useOptionalDAppKitWallet();\n const { connection } = useWallet();\n const { feeDelegation } = useVeChainKitConfig();\n const nodeUrl = useGetNodeUrl();\n // Use optional provider - returns null when Privy is not configured\n const privyWalletProvider = useOptionalPrivyWalletProvider();\n\n /**\n * Send a transaction with the given clauses (in case you need to pass data to build the clauses to mutate directly)\n * If the wallet is connected with Privy, the smart account provider will be used to send the transaction\n * @returns see {@link UseSendTransactionReturnValue}\n */\n const sendTransaction = useCallback(\n async (\n clauses?:\n | TransactionClause[]\n | (() => TransactionClause[])\n | (() => Promise<TransactionClause[]>),\n delegationUrl?: string,\n privyUIOptions?: {\n title?: string;\n description?: string;\n buttonText?: string;\n },\n ) => {\n const _clauses =\n typeof clauses === 'function' ? await clauses() : clauses ?? [];\n if (connection.isConnectedWithPrivy) {\n if (!privyWalletProvider) {\n throw new Error(\n 'Privy is not configured. Please configure the privy prop in VeChainKitContext to use this feature.',\n );\n }\n return await privyWalletProvider.sendTransaction({\n txClauses: _clauses,\n ...privyUIOptions,\n delegationUrl,\n });\n }\n\n if (!signerAccountAddress) {\n throw new Error('signerAccountAddress is required');\n }\n\n let estimatedGas = 0;\n try {\n if (thor) {\n estimatedGas = await useGasEstimate(\n thor,\n [..._clauses],\n signerAccountAddress,\n {\n revision: Revision.NEXT,\n ...(gasPadding ? { gasPadding } : {}), //If gasPadding is provided, use it, otherwise it will apply only revision\n },\n );\n }\n } catch (e) {\n console.error('Gas estimation failed', e);\n }\n\n // Use signerAccountAddress (stored active wallet) as signer when on desktop with dappkit\n // This ensures the extension uses the correct wallet that the user selected\n const signerAddress = connection.isConnectedWithDappKit && !connection.isInAppBrowser && signerAccountAddress\n ? signerAccountAddress\n : signer.address;\n\n const response = await requestTransaction(\n _clauses as TransactionMessage[],\n {\n signer: signerAddress,\n gas: suggestedMaxGas ?? estimatedGas,\n ...(feeDelegation?.delegateAllTransactions || delegationUrl ? {\n delegator: {\n url: delegationUrl ?? feeDelegation?.delegatorUrl ?? '',\n signer: signerAccountAddress,\n }\n } : {}),\n }\n );\n return response.txid;\n },\n [\n signerAccountAddress,\n suggestedMaxGas,\n nodeUrl,\n privyWalletProvider,\n privyUIOptions,\n feeDelegation,\n thor,\n signer,\n gasPadding,\n delegationUrl,\n requestTransaction,\n connection.isConnectedWithDappKit,\n connection.isInAppBrowser,\n ],\n );\n\n /**\n * Adapter to send the transaction with the clauses passed to the hook or the ones passed to the function,\n * and to store the transaction id and the status of the transaction (pending, success, error).\n */\n const [txHash, setTxHash] = useState<string | null>(null);\n const [sendTransactionPending, setSendTransactionPending] = useState(false);\n const [sendTransactionError, setSendTransactionError] = useState<\n string | null\n >(null);\n\n const sendTransactionAdapter = useCallback(\n async (_clauses?: TransactionClause[], _delegationUrl?: string): Promise<void> => {\n if (!_clauses && !clauses) throw new Error('clauses are required');\n try {\n setTxHash(null);\n setSendTransactionPending(true);\n setSendTransactionError(null);\n setError(undefined);\n const response = await sendTransaction(_clauses ?? [], _delegationUrl, {\n ...privyUIOptions,\n });\n\n setTxHash(response);\n } catch (error) {\n setSendTransactionError(\n error && typeof error === 'object' && 'message' in error\n ? (error.message as string)\n : String(error),\n );\n onTxFailedOrCancelled?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n } finally {\n setSendTransactionPending(false);\n }\n },\n [sendTransaction, clauses, privyUIOptions, delegationUrl],\n );\n\n /**\n * Fetch the transaction receipt once the transaction is broadcasted\n */\n const {\n data: txReceipt,\n isLoading: isTxReceiptLoading,\n error: txReceiptError,\n } = useTxReceipt(txHash ?? '');\n\n /**\n * Explain the revert reason of the transaction\n * @param txReceipt the transaction receipt\n * @returns the revert reason\n */\n const explainTxRevertReason = useCallback(\n async (txReceipt: TransactionReceipt) => {\n if (!txReceipt.reverted || !txReceipt.meta.txID || !thor) return;\n\n return await thor.transactions.getRevertReason(txReceipt.meta.txID);\n },\n [thor],\n );\n\n /**\n * General error that is set when\n * - unable to send the tx\n * - unable to fetch the receipt\n * - the transaction is reverted\n */\n const [error, setError] = useState<TransactionStatusErrorType>();\n\n /**\n * The status of the transaction\n */\n const status = useMemo(() => {\n if (sendTransactionPending) return 'pending';\n\n if (sendTransactionError) {\n return 'error';\n }\n\n if (txHash) {\n if (isTxReceiptLoading) return 'waitingConfirmation';\n if (txReceiptError) {\n return 'error';\n }\n if (txReceipt) {\n if (txReceipt.reverted) {\n return 'error';\n }\n return 'success';\n }\n }\n\n return 'ready';\n }, [\n isTxReceiptLoading,\n sendTransactionError,\n sendTransactionPending,\n txHash,\n txReceipt,\n txReceiptError,\n ]);\n\n /**\n * If the transaction is successful or in error, explain the revert reason\n */\n useEffect(() => {\n if (status === 'success' || status === 'error') {\n if (sendTransactionError && !error) {\n setError({\n type: 'UserRejectedError',\n reason: sendTransactionError,\n });\n return;\n }\n\n if (txReceipt?.reverted && !error?.type) {\n (async () => {\n const revertReason = await explainTxRevertReason(txReceipt);\n\n setError({\n type: 'RevertReasonError',\n reason: revertReason\n ? 'Transaction reverted with: ' + revertReason\n : 'Transaction reverted',\n });\n })();\n return;\n }\n\n if (txReceipt && !txReceipt.reverted) {\n onTxConfirmed?.();\n }\n }\n }, [\n status,\n txReceipt,\n onTxConfirmed,\n explainTxRevertReason,\n sendTransactionError,\n ]);\n\n /**\n * Reset the status of the transaction\n */\n const resetStatus = useCallback(() => {\n setTxHash(null);\n setSendTransactionPending(false);\n setSendTransactionError(null);\n setError(undefined);\n }, []);\n\n /**\n * Check if the transaction is pending\n */\n const isTransactionPending = useMemo(() => {\n return (\n sendTransactionPending ||\n isTxReceiptLoading ||\n status === 'pending' ||\n status === 'waitingConfirmation'\n );\n }, [sendTransactionPending, isTxReceiptLoading, status]);\n\n const isWaitingForWalletConfirmation = useMemo(() => {\n return status === 'pending';\n }, [sendTransactionPending, status]);\n\n return {\n sendTransaction: sendTransactionAdapter,\n isTransactionPending,\n isWaitingForWalletConfirmation,\n txReceipt: txReceipt ?? null,\n status,\n resetStatus,\n error,\n };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { getAvatar } from '@vechain/contract-getters';\n\nexport const getAvatarQueryKey = (name: string, networkType: NETWORK_TYPE) => [\n 'VECHAIN_KIT',\n 'VET_DOMAINS',\n 'AVATAR',\n name,\n networkType,\n];\n\n/**\n * Hook to fetch the avatar URL for a VET domain name\n * @param name - The VET domain name\n * @returns The resolved avatar URL\n */\nexport const useGetAvatar = (name: string) => {\n const { network } = useVeChainKitConfig();\n\n const avatarQuery = useQuery({\n queryKey: getAvatarQueryKey(name ?? '', network.type),\n queryFn: async () => {\n if (!name) return null;\n\n return getAvatar(name, {\n networkUrl: network.nodeUrl,\n });\n },\n enabled: !!name && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || errorMessage.includes('abort')) {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n\n return avatarQuery;\n};\n","import { useQueryClient } from '@tanstack/react-query';\n// Direct imports to avoid circular dependency through barrel exports\nimport { getAvatarOfAddressQueryKey } from '../vetDomains/useGetAvatarOfAddress';\nimport { getAvatarQueryKey } from '../vetDomains/useGetAvatar';\nimport { getTextRecordsQueryKey } from '../vetDomains/useGetTextRecords';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n\nexport const useRefreshMetadata = (domain: string, address: string) => {\n const queryClient = useQueryClient();\n const { network } = useVeChainKitConfig();\n\n const refresh = async () => {\n await Promise.all([\n queryClient.invalidateQueries({\n queryKey: getAvatarQueryKey(domain ?? '', network.type),\n }),\n queryClient.invalidateQueries({\n queryKey: getTextRecordsQueryKey(domain, network.type),\n }),\n queryClient.invalidateQueries({\n queryKey: getAvatarOfAddressQueryKey(address),\n }),\n ]);\n };\n\n return { refresh };\n};\n","import { getConfig } from '../../../config';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { useQuery } from '@tanstack/react-query';\nimport { z } from 'zod';\n\n// Schema for the domain response\nconst DomainSchema = z.object({\n name: z.string(),\n});\n\nconst DomainsResponseSchema = z.object({\n domains: z.array(DomainSchema),\n});\n\nexport type Domain = z.infer<typeof DomainSchema>;\nexport type DomainsResponse = z.infer<typeof DomainsResponseSchema>;\n\n/**\n * Fetches all domains owned by an address\n * @param networkType The network type\n * @param address The owner's address\n * @param parentDomain The parent domain (e.g., \"veworld.vet\")\n * @returns The domains owned by the address\n */\nexport const getDomainsOfAddress = async (\n networkType: NETWORK_TYPE,\n address?: string,\n parentDomain?: string,\n): Promise<DomainsResponse> => {\n if (!address) throw new Error('Address is required');\n\n const graphQlIndexerUrl = getConfig(networkType).graphQlIndexerUrl;\n\n const whereCondition = parentDomain\n ? `{owner: \"${address.toLowerCase()}\", parent_: {name: \"${parentDomain}\"}}`\n : `{owner: \"${address.toLowerCase()}\"}`;\n\n const query = `query Registrations {\n domains(\n where: ${whereCondition}\n ) {\n name\n }\n }`;\n\n const response = await fetch(graphQlIndexerUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify({\n operationName: 'Registrations',\n query,\n extensions: {},\n }),\n });\n\n if (!response.ok) {\n throw new Error('Failed to fetch domains');\n }\n\n const json = await response.json();\n\n // Filter out domains ending with \"addr.reverse\" before parsing\n if (json.data && json.data.domains) {\n json.data.domains = json.data.domains.filter(\n (domain: any) => !domain.name.endsWith('addr.reverse'),\n );\n }\n\n return DomainsResponseSchema.parse(json.data);\n};\n\nexport const getDomainsOfAddressQueryKey = (\n address?: string,\n parentDomain?: string,\n) => ['VECHAIN_KIT', 'VET_DOMAINS', address, parentDomain];\n\n/**\n * Hook to fetch all domains owned by an address\n * @param address The owner's address\n * @param parentDomain The parent domain (e.g., \"veworld.vet\")\n * @returns The domains owned by the address\n */\nexport const useGetDomainsOfAddress = (\n address?: string,\n parentDomain?: string,\n) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getDomainsOfAddressQueryKey(address, parentDomain),\n queryFn: () => getDomainsOfAddress(network.type, address, parentDomain),\n enabled: !!address && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'address is required') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","// Import directly to avoid circular dependency with hooks barrel\nimport { getAvatarOfAddressQueryKey } from '../useGetAvatarOfAddress';\nimport { getDomainsOfAddressQueryKey } from '../useGetDomainsOfAddress';\nimport { getEnsRecordExistsQueryKey } from '../useEnsRecordExists';\nimport { getTextRecordsQueryKey } from '../useGetTextRecords';\nimport { getVechainDomainQueryKey } from '../useVechainDomain';\nimport { getAvatarQueryKey } from '../useGetAvatar';\nimport { QueryClient } from '@tanstack/react-query';\nimport { NETWORK_TYPE } from '../../../../config/network';\n\n/**\n * Invalidates and refetches all domain-related queries\n *\n * @param queryClient - The React Query client\n * @param address - The user's address\n * @param fullDomain - The full domain name (e.g. 'subdomain.veworld.vet')\n * @param subdomain - The subdomain part\n * @param domain - The domain part (e.g. 'veworld.vet')\n * @param networkType - The network type\n */\nexport const invalidateAndRefetchDomainQueries = async (\n queryClient: QueryClient,\n address: string,\n fullDomain: string,\n subdomain: string,\n domain: string,\n networkType: NETWORK_TYPE,\n): Promise<void> => {\n // First invalidate all related queries\n await Promise.all([\n queryClient.invalidateQueries({\n queryKey: getVechainDomainQueryKey(address),\n }),\n queryClient.invalidateQueries({\n queryKey: getVechainDomainQueryKey(fullDomain),\n }),\n queryClient.invalidateQueries({\n queryKey: getEnsRecordExistsQueryKey(subdomain),\n }),\n queryClient.invalidateQueries({\n queryKey: getDomainsOfAddressQueryKey(address, '.vet'),\n }),\n queryClient.invalidateQueries({\n queryKey: getDomainsOfAddressQueryKey(address, '.veworld.vet'),\n }),\n queryClient.invalidateQueries({\n queryKey: getTextRecordsQueryKey(fullDomain),\n }),\n ]);\n\n // Also ensure domains are properly refetched\n await Promise.all([\n queryClient.refetchQueries({\n queryKey: getVechainDomainQueryKey(address),\n }),\n queryClient.refetchQueries({\n queryKey: getVechainDomainQueryKey(fullDomain),\n }),\n queryClient.refetchQueries({\n queryKey: getDomainsOfAddressQueryKey(address, '.vet'),\n }),\n queryClient.refetchQueries({\n queryKey: getDomainsOfAddressQueryKey(address, '.veworld.vet'),\n }),\n queryClient.refetchQueries({\n queryKey: getAvatarQueryKey(subdomain + '.' + domain, networkType),\n }),\n queryClient.refetchQueries({\n queryKey: getTextRecordsQueryKey(fullDomain),\n }),\n queryClient.refetchQueries({\n queryKey: getEnsRecordExistsQueryKey(subdomain),\n }),\n queryClient.refetchQueries({\n queryKey: getAvatarOfAddressQueryKey(address),\n }),\n ]);\n};\n","// Direct imports to avoid circular dependency through barrel exports\nimport {\n UseSendTransactionReturnValue,\n useSendTransaction,\n} from '../../thor/transactions/useSendTransaction';\nimport { useWallet } from '../wallet/useWallet';\nimport { useCallback } from 'react';\nimport {\n VeworldSubdomainClaimer__factory,\n VetDomainsReverseRegistrar__factory,\n} from '@vechain/vechain-contract-types';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { getConfig } from '../../../config';\nimport { useVeChainKitConfig, VeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { humanAddress } from '../../../utils';\nimport { ethers } from 'ethers';\nimport { useRefreshMetadata } from '../wallet/useRefreshMetadata';\nimport { invalidateAndRefetchDomainQueries } from './utils/domainQueryUtils';\nimport type { Wallet } from '../../../types';\nimport { TransactionClause } from '@vechain/sdk-core';\n\ntype useClaimVeWorldSubdomainProps = {\n subdomain: string;\n domain: string;\n onSuccess?: () => void;\n onError?: () => void;\n onSuccessMessageTitle?: number;\n alreadyOwned?: boolean;\n};\n\ntype useClaimVeWorldSubdomainReturnValue = {\n sendTransaction: () => Promise<void>;\n clauses: () => TransactionClause[];\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nconst SubdomainClaimerInterface = VeworldSubdomainClaimer__factory.createInterface();\nconst ReverseRegistrarInterface = VetDomainsReverseRegistrar__factory.createInterface();\n\nconst buildVeWorldSubdomainClauses = (subdomain: string, domain: string, alreadyOwned: boolean, account: Wallet, network: VeChainKitConfig['network']): TransactionClause[] => {\n const clausesArray: any[] = [];\n\n if (!subdomain) throw new Error('Invalid subdomain');\n\n const fullDomain = `${subdomain}.${domain}`;\n\n // Always unset current nickname first\n clausesArray.push({\n to: getConfig(network.type).vetDomainsReverseRegistrarAddress,\n value: '0x0',\n data: ReverseRegistrarInterface.encodeFunctionData('setName', ['']),\n comment: `Unsetting your current VeChain nickname of the account ${humanAddress(\n account?.address ?? '',\n 4,\n 4,\n )}`,\n abi: ReverseRegistrarInterface.getFunction('setName'),\n });\n\n if (alreadyOwned) {\n // For already owned domains, set the name in the reverse registrar\n clausesArray.push({\n to: getConfig(network.type).vetDomainsReverseRegistrarAddress,\n value: '0x0',\n data: ReverseRegistrarInterface.encodeFunctionData('setName', [\n fullDomain,\n ]),\n comment: `Setting your VeChain nickname to ${fullDomain}`,\n abi: ReverseRegistrarInterface.getFunction('setName'),\n });\n\n // Also set the address in the public resolver\n const PublicResolverInterface = new ethers.Interface([\n 'function setAddr(bytes32 node, address addr)',\n ]);\n\n // Calculate the namehash for the domain\n const domainNode = ethers.namehash(fullDomain);\n\n clausesArray.push({\n to: getConfig(network.type).vetDomainsPublicResolverAddress,\n value: '0x0',\n data: PublicResolverInterface.encodeFunctionData('setAddr', [\n domainNode,\n account?.address || '',\n ]),\n comment: `Setting the address for ${fullDomain} to ${humanAddress(\n account?.address ?? '',\n 4,\n 4,\n )}`,\n abi: PublicResolverInterface.getFunction('setAddr'),\n });\n } else {\n if (isVeWorldDomain(domain)) {\n // For new domains, claim the subdomain\n clausesArray.push({\n to: getConfig(network.type)\n .veWorldSubdomainClaimerContractAddress,\n value: '0x0',\n data: SubdomainClaimerInterface.encodeFunctionData(\n 'claim',\n [\n subdomain,\n getConfig(network.type)\n .vetDomainsPublicResolverAddress,\n ],\n ),\n comment: `Claim VeChain subdomain: ${subdomain}.${domain}`,\n abi: SubdomainClaimerInterface.getFunction('claim'),\n });\n\n clausesArray.push({\n to: getConfig(network.type)\n .vetDomainsReverseRegistrarAddress,\n value: '0x0',\n data: ReverseRegistrarInterface.encodeFunctionData(\n 'setName',\n [subdomain + '.' + domain],\n ),\n comment: `Set ${subdomain}.${domain} as the VeChain nickname of the account ${humanAddress(\n account?.address ?? '',\n 4,\n 4,\n )}`,\n abi: ReverseRegistrarInterface.getFunction('setName'),\n });\n } else {\n throw new Error(\n 'This hook only supports .veworld.vet subdomains',\n );\n }\n }\n\n return clausesArray;\n};\n\n/**\n * Hook for claiming a .veworld.vet subdomain\n *\n * This hook specializes in handling subdomains in the .veworld.vet domain\n */\nexport const useClaimVeWorldSubdomain = ({\n subdomain,\n domain,\n onSuccess,\n onError,\n alreadyOwned = false,\n}: useClaimVeWorldSubdomainProps): useClaimVeWorldSubdomainReturnValue => {\n const queryClient = useQueryClient();\n const { account } = useWallet();\n const { network } = useVeChainKitConfig();\n const { refresh: refreshMetadata } = useRefreshMetadata(\n subdomain + '.' + domain,\n account?.address ?? '',\n );\n\n const clauses = useCallback(() => buildVeWorldSubdomainClauses(subdomain, domain, alreadyOwned, account, network), [subdomain, domain, alreadyOwned, account, network]);\n\n //Refetch queries to update ui after the tx is confirmed\n const handleOnSuccess = useCallback(async () => {\n const fullDomain = `${subdomain}.${domain}`;\n const address = account?.address ?? '';\n\n await invalidateAndRefetchDomainQueries(\n queryClient,\n address,\n fullDomain,\n subdomain,\n domain,\n network.type,\n );\n\n // Use the dedicated metadata refresh utility\n refreshMetadata();\n onSuccess?.();\n }, [\n onSuccess,\n subdomain,\n domain,\n queryClient,\n account,\n network.type,\n refreshMetadata,\n ]);\n\n const result = useSendTransaction({\n signerAccountAddress: account?.address ?? '',\n privyUIOptions: {\n title: 'Sign to claim your VeChain nickname',\n description: `Claim ${subdomain}.${domain} as your VeChain nickname`,\n buttonText: 'Sign to continue',\n },\n onTxConfirmed: handleOnSuccess,\n onTxFailedOrCancelled: () => {\n onError?.();\n },\n });\n\n return {\n ...result,\n clauses,\n sendTransaction: async () => {\n return result.sendTransaction(clauses());\n },\n };\n};\n\nconst isVeWorldDomain = (domain: string) => {\n return domain.endsWith('veworld.vet');\n};\n","// Direct imports to avoid circular dependency through barrel exports\nimport {\n UseSendTransactionReturnValue,\n useSendTransaction,\n} from '../../thor/transactions/useSendTransaction';\nimport { useWallet } from '../wallet/useWallet';\nimport { useRefreshMetadata } from '../wallet/useRefreshMetadata';\nimport { useCallback } from 'react';\nimport { VetDomainsReverseRegistrar__factory } from '@vechain/vechain-contract-types';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { getConfig } from '../../../config';\nimport { useVeChainKitConfig, VeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { ethers } from 'ethers';\nimport { invalidateAndRefetchDomainQueries } from './utils/domainQueryUtils';\nimport { humanAddress } from '../../../utils';\nimport type { Wallet } from '../../../types';\nimport { TransactionClause } from '@vechain/sdk-core';\n\ntype useClaimVetDomainProps = {\n domain: string;\n onSuccess?: () => void;\n onError?: () => void;\n onSuccessMessageTitle?: number;\n alreadyOwned?: boolean;\n};\n\ntype useClaimVetDomainReturnValue = {\n sendTransaction: () => Promise<void>;\n clauses: () => TransactionClause[];\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nconst ReverseRegistrarInterface = VetDomainsReverseRegistrar__factory.createInterface();\n\nexport const buildVetDomainClauses = (\n domain: string,\n alreadyOwned: boolean,\n account: Wallet,\n network: VeChainKitConfig['network'],\n): TransactionClause[] => {\n const clausesArray: any[] = [];\n\n if (!domain) throw new Error('Invalid domain');\n\n if (alreadyOwned) {\n // For already owned domains, set the name in the reverse registrar\n clausesArray.push({\n to: getConfig(network.type).vetDomainsReverseRegistrarAddress,\n value: '0x0',\n data: ReverseRegistrarInterface.encodeFunctionData('setName', [\n domain,\n ]),\n comment: `Setting your VeChain nickname to ${domain}`,\n abi: ReverseRegistrarInterface.getFunction('setName'),\n });\n\n // Also set the address in the public resolver\n const PublicResolverInterface = new ethers.Interface([\n 'function setAddr(bytes32 node, address addr)',\n ]);\n\n // Calculate the namehash for the domain\n const domainNode = ethers.namehash(domain);\n\n clausesArray.push({\n to: getConfig(network.type).vetDomainsPublicResolverAddress,\n value: '0x0',\n data: PublicResolverInterface.encodeFunctionData('setAddr', [\n domainNode,\n account?.address || '',\n ]),\n comment: `Setting the address for ${domain} to ${humanAddress(\n account?.address ?? '',\n 4,\n 4,\n )}`,\n abi: PublicResolverInterface.getFunction('setAddr'),\n });\n } else {\n throw new Error('Primary .vet domains are not supported yet');\n }\n\n return clausesArray;\n};\n\n/**\n * Hook for claiming a .vet domain\n *\n * This hook specializes in handling primary .vet domains\n */\nexport const useClaimVetDomain = ({\n domain,\n onSuccess,\n onError,\n alreadyOwned = false,\n}: useClaimVetDomainProps): useClaimVetDomainReturnValue => {\n const { network } = useVeChainKitConfig();\n const queryClient = useQueryClient();\n const { account } = useWallet();\n\n const { refresh: refreshMetadata } = useRefreshMetadata(\n domain,\n account?.address ?? '',\n );\n\n const clauses = useCallback(\n () => buildVetDomainClauses(domain, alreadyOwned, account, network),\n [domain, alreadyOwned, account, network],\n );\n\n // Refetch queries to update UI after the tx is confirmed\n const handleOnSuccess = useCallback(async () => {\n const address = account?.address ?? '';\n\n await invalidateAndRefetchDomainQueries(\n queryClient,\n address,\n domain,\n '', // No subdomain for primary domains\n domain.endsWith('.vet') ? domain : `${domain}.vet`,\n network.type,\n );\n\n // Use the dedicated metadata refresh utility\n refreshMetadata();\n\n onSuccess?.();\n }, [\n onSuccess,\n domain,\n queryClient,\n account,\n network.type,\n refreshMetadata,\n ]);\n\n const result = useSendTransaction({\n signerAccountAddress: account?.address ?? '',\n privyUIOptions: {\n title: 'Sign to claim your VeChain nickname',\n description: `Claim ${domain} as your VeChain nickname`,\n buttonText: 'Sign to continue',\n },\n onTxConfirmed: handleOnSuccess,\n onTxFailedOrCancelled: onError,\n });\n\n return {\n ...result,\n clauses,\n sendTransaction: async () => {\n return result.sendTransaction(clauses());\n },\n };\n};\n","import { getConfig } from '../../../config';\nimport { VeworldSubdomainClaimer__factory } from '@vechain/vechain-contract-types';\nimport { useOptionalThor } from '../dappkit/useOptionalThor';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { useQuery } from '@tanstack/react-query';\nimport { ABIContract } from '@vechain/sdk-core';\n\nexport const getIsDomainProtectedQueryKey = (domain?: string) => [\n 'VECHAIN_KIT_DOMAIN',\n domain,\n 'IS_DOMAIN_PROTECTED',\n];\n\n// Convert readonly ABI to mutable Abi type\nconst subdomainClaimerABI = ABIContract.ofAbi(VeworldSubdomainClaimer__factory.abi as any);\n\nconst getIsDomainProtected = async (\n thor: ThorClient,\n network: NETWORK_TYPE,\n domain?: string,\n) => {\n const contractAddress =\n getConfig(network).veWorldSubdomainClaimerContractAddress;\n\n const res = await thor.contracts\n .load(contractAddress, subdomainClaimerABI.abi)\n .read.isDomainProtected(domain);\n\n return res[0] as boolean;\n};\n\n/**\n * Custom hook to fetch the protection status of a VeChain domain.\n *\n * @param {string} [domain] - The domain to fetch the protection status for.\n * @param {boolean} [enabled=true] - Flag to enable or disable the hook.\n * @returns The result of the useQuery hook, with the protection status.\n */\nexport const useIsDomainProtected = (domain?: string, enabled = true) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getIsDomainProtectedQueryKey(domain),\n queryFn: () => getIsDomainProtected(thor!, network.type, domain),\n enabled: !!thor && !!domain && enabled && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (\n errorMessage.includes('cancel') ||\n errorMessage.includes('abort')\n ) {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","import { Interface, namehash } from 'ethers';\nimport { useCallback } from 'react';\n// Direct import to avoid circular dependency through barrel exports\nimport {\n UseSendTransactionReturnValue,\n useSendTransaction,\n} from '../../thor/transactions/useSendTransaction';\nimport { TransactionClause } from '@vechain/sdk-core';\n\nconst nameInterface = new Interface([\n 'function resolver(bytes32 node) returns (address resolverAddress)',\n 'function setText(bytes32 node, string key, string value) external',\n]);\n\ntype UpdateTextRecordVariables = {\n domain: string;\n key: string;\n value: string;\n};\n\ntype UseUpdateTextRecordProps = {\n onSuccess?: () => void | Promise<void>;\n onError?: (error?: Error) => void | Promise<void>;\n signerAccountAddress?: string;\n resolverAddress?: string;\n};\n\ntype UseUpdateTextRecordReturnValue = {\n sendTransaction: (params: UpdateTextRecordVariables[]) => Promise<void> | undefined;\n clauses: (params: UpdateTextRecordVariables[]) => TransactionClause[]; // Synchronous!\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nexport const buildClauses = (resolverAddress: string, params: UpdateTextRecordVariables[]): TransactionClause[] => {\n const clauses = [];\n\n for (const { domain, key, value } of params) {\n if (!domain) throw new Error('Domain is required');\n if (!resolverAddress)\n throw new Error('Resolver address is required');\n\n const node = namehash(domain);\n\n clauses.push({\n to: resolverAddress,\n data: nameInterface.encodeFunctionData('setText', [\n node,\n key,\n value,\n ]),\n value: '0',\n comment: `Update ${key} record`,\n });\n }\n return clauses;\n};\n\nexport const useUpdateTextRecord = ({\n onSuccess,\n onError,\n signerAccountAddress,\n resolverAddress,\n}: UseUpdateTextRecordProps = {}): UseUpdateTextRecordReturnValue => {\n // Always call useCallback unconditionally - keep it synchronous!\n const buildClausesCallback = useCallback(\n (params: UpdateTextRecordVariables[]) => {\n if (!resolverAddress) {\n throw new Error('Resolver address is required');\n }\n return buildClauses(resolverAddress, params);\n },\n [resolverAddress]\n );\n\n const result = useSendTransaction({\n signerAccountAddress,\n onTxConfirmed: async () => {\n await onSuccess?.();\n },\n onTxFailedOrCancelled: async () => {\n await onError?.();\n },\n privyUIOptions: {\n title: 'Update Profile Information',\n description:\n 'Update the profile information associated with your domain',\n buttonText: 'Sign to continue',\n },\n });\n\n return {\n ...result,\n clauses: buildClausesCallback, // Return the callback directly\n sendTransaction: async (params: UpdateTextRecordVariables[]) => {\n return result.sendTransaction(buildClausesCallback(params));\n },\n };\n};\n","import { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { getConfig } from '../../../config';\n// Direct import to avoid circular dependency through barrel exports\nimport { useCallClause } from '../../utils/useCallClause';\nimport { namehash } from 'viem';\nimport { VetDomainsRegistry__factory } from '@vechain/vechain-contract-types';\n\n\nexport const getResolverAddressQueryKey = (domain?: string) => [\n 'VECHAIN_KIT',\n 'RESOLVER_ADDRESS',\n domain,\n];\n\n/**\n * Hook to get resolver address for a VET domain\n * @param domain The domain to get resolver for\n * @returns The resolver address for the domain\n */\nexport const useGetResolverAddress = (domain?: string) => {\n const { network } = useVeChainKitConfig();\n\n return useCallClause({\n address: getConfig(network.type).vetDomainsContractAddress,\n abi: VetDomainsRegistry__factory.abi,\n method: 'resolver',\n args: [domain ? namehash(domain) : '0x'],\n queryOptions: {\n select: (data) => data[0],\n enabled: !!domain,\n },\n });\n};\n","/**\n * LEGACY IMPLEMENTATION\n *\n * This file contains the original implementation of the avatar fetching logic\n * which directly interacts with the VeChain blockchain to resolve avatars.\n *\n * The problem with this implementation was that some tokenURI aren't configured\n * to allow cross-origin requests from your localhost application.\n * To solve this we need a proxy server that allows us to fetch the metadata from the tokenURI\n * without having to deal with CORS issues.\n *\n * This implementation is preserved for documentation and reference purposes but is no longer\n * the active implementation. The current implementation uses the vet.domains API to fetch the avatar.\n */\n\nimport { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport {\n Interface,\n namehash,\n toUtf8String,\n zeroPadValue,\n toBeHex,\n} from 'ethers';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { getConfig } from '../../../config';\nimport { convertUriToUrl } from '../../../utils/uri';\n\nconst nameInterface = new Interface([\n 'function resolver(bytes32 node) returns (address resolverAddress)',\n 'function text(bytes32 node, string key) returns (string avatar)',\n]);\n\nconst erc721Interface = new Interface([\n 'function tokenURI(uint256 tokenId) view returns (string)',\n 'function uri(uint256 id) view returns (string)',\n]);\n\n/**\n * Fetches the avatar for a given VET domain name\n * @param networkType - The network type ('main' or 'test')\n * @param nodeUrl - The node URL\n * @param name - The VET domain name\n * @returns The avatar URL from the response\n */\n\nexport const getAvatarLegacy = async (\n networkType: NETWORK_TYPE,\n nodeUrl: string,\n name: string,\n): Promise<string | null> => {\n if (!name) throw new Error('Name is required');\n\n const node = namehash(name);\n\n try {\n // Get resolver address\n const accountsUrl = new URL('accounts/*', nodeUrl);\n const resolverResponse = await fetch(accountsUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n clauses: [\n {\n to: getConfig(networkType).vetDomainsContractAddress,\n data: nameInterface.encodeFunctionData('resolver', [\n node,\n ]),\n },\n ],\n }),\n });\n\n const [{ data: resolverData, reverted: noResolver }] =\n await resolverResponse.json();\n\n if (noResolver) {\n return null;\n }\n\n const { resolverAddress } = nameInterface.decodeFunctionResult(\n 'resolver',\n resolverData,\n );\n\n // Get avatar\n const avatarResponse = await fetch(accountsUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n clauses: [\n {\n to: resolverAddress,\n data: nameInterface.encodeFunctionData('text', [\n node,\n 'avatar',\n ]),\n },\n ],\n }),\n });\n\n const [{ data: lookupData, reverted: noLookup }] =\n await avatarResponse.json();\n\n if (noLookup || lookupData === '0x') {\n return null;\n }\n\n try {\n const { avatar } = nameInterface.decodeFunctionResult(\n 'text',\n lookupData,\n );\n const avatarRecord = avatar === '' ? null : avatar;\n\n if (!avatarRecord) return null;\n\n return parseAvatarRecord(avatarRecord, networkType, nodeUrl);\n } catch (decodeError) {\n console.error('Failed to decode avatar data:', decodeError);\n return null;\n }\n } catch (error) {\n console.error('Error fetching avatar using legacy API:', error);\n throw error;\n }\n};\n\nexport const getAvatarLegacyQueryKey = (\n name: string,\n networkType: NETWORK_TYPE,\n) => ['VECHAIN_KIT', 'VET_DOMAINS', 'AVATAR', 'LEGACY', name, networkType];\n\nasync function parseAvatarRecord(\n record: string,\n networkType: NETWORK_TYPE,\n nodeUrl: string,\n): Promise<string | null> {\n try {\n // Use the existing URI converter for direct URL handling\n if (\n record.startsWith('http') ||\n record.startsWith('ipfs://') ||\n record.startsWith('ar://')\n ) {\n return convertUriToUrl(record, networkType) || null;\n }\n\n // Handle NFT avatar (ENS-12)\n const match = record.match(\n /eip155:(\\d+)\\/(?:erc721|erc1155):([^/]+)\\/(\\d+)/,\n );\n if (match) {\n const [, chainId, contractAddress, tokenId] = match;\n const isErc1155 = record.includes('erc1155');\n\n if (!chainId || !contractAddress || tokenId === undefined) {\n return null;\n }\n\n // ... rest of NFT handling logic ...\n const clauses = [\n {\n to: contractAddress,\n data: erc721Interface.encodeFunctionData(\n isErc1155 ? 'uri' : 'tokenURI',\n [BigInt(tokenId || 0)],\n ),\n },\n ];\n\n const accountsUrl = new URL('accounts/*', nodeUrl);\n const [{ data, reverted }] = await fetch(accountsUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({ clauses }),\n }).then((res) => res.json());\n\n if (reverted) {\n console.error('Failed to fetch tokenURI');\n return null;\n }\n\n let tokenUri = '';\n try {\n tokenUri = erc721Interface.decodeFunctionResult(\n isErc1155 ? 'uri' : 'tokenURI',\n data,\n )[0];\n } catch (e) {\n console.error('Failed to decode avatar data:', e);\n tokenUri = toUtf8String(data);\n }\n\n // Use the existing URI converter\n tokenUri = convertUriToUrl(tokenUri, networkType) || tokenUri;\n\n if (isErc1155) {\n tokenUri = tokenUri.replace(\n '{id}',\n zeroPadValue(toBeHex(BigInt(tokenId || 0)), 32).slice(2),\n );\n }\n\n const metadataResponse = await fetch(tokenUri);\n if (!metadataResponse.ok) {\n console.error('Failed to fetch metadata');\n return null;\n }\n\n const metadata = await metadataResponse.json();\n const imageUrl =\n metadata.image || metadata.image_url || metadata.image_data;\n\n if (!imageUrl) {\n console.error('No image URL in metadata');\n return null;\n }\n\n // Use the existing URI converter for the final image URL\n return convertUriToUrl(imageUrl, networkType) || imageUrl;\n }\n\n return null;\n } catch (error) {\n console.error('Error parsing avatar record:', error);\n return null;\n }\n}\n\n/**\n * Hook to fetch the avatar URL for a VET domain name\n * @param name - The VET domain name\n * @returns The resolved avatar URL\n */\nexport const useGetAvatarLegacy = (name: string) => {\n const { network } = useVeChainKitConfig();\n const nodeUrl = network.nodeUrl ?? getConfig(network.type).nodeUrl;\n\n const avatarQuery = useQuery({\n queryKey: getAvatarLegacyQueryKey(name ?? '', network.type),\n queryFn: async () => {\n if (!name) return null;\n\n return getAvatarLegacy(network.type, nodeUrl, name);\n },\n enabled: !!name && !!nodeUrl && !!network.type,\n });\n\n return avatarQuery;\n};\n","// Direct imports to avoid circular dependency through barrel exports\nimport {\n UseSendTransactionReturnValue,\n useSendTransaction,\n} from '../../thor/transactions/useSendTransaction';\nimport { useWallet } from '../wallet/useWallet';\nimport { useCallback } from 'react';\nimport { VetDomainsReverseRegistrar__factory } from '@vechain/vechain-contract-types';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { getConfig } from '../../../config';\nimport { useVeChainKitConfig, VeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { humanAddress } from '../../../utils';\nimport { invalidateAndRefetchDomainQueries } from './utils/domainQueryUtils';\nimport type { Wallet } from '../../../types';\nimport { TransactionClause } from '@vechain/sdk-core';\n\ntype useUnsetDomainProps = {\n onSuccess?: () => void;\n onError?: () => void;\n};\n\ntype useUnsetDomainReturnValue = {\n sendTransaction: () => Promise<void>;\n clauses: () => TransactionClause[];\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nconst ReverseRegistrarInterface = VetDomainsReverseRegistrar__factory.createInterface();\n\nconst buildUnsetDomainClauses = (account: Wallet, network: VeChainKitConfig['network']): TransactionClause[] => {\n const clausesArray: any[] = [];\n\n // When unsetting domain, we only need to call setName with an empty string\n clausesArray.push({\n to: getConfig(network.type).vetDomainsReverseRegistrarAddress,\n value: '0x0',\n data: ReverseRegistrarInterface.encodeFunctionData('setName', ['']),\n comment: `Unsetting your current VeChain nickname of the account ${humanAddress(\n account?.address ?? '',\n 4,\n 4,\n )}`,\n abi: ReverseRegistrarInterface.getFunction('setName'),\n });\n\n return clausesArray;\n};\n\n/**\n * Hook for unsetting any domain name (both .veworld.vet and .vet domains)\n *\n * This hook is a dedicated implementation for the unset functionality\n * that was previously part of the claim hooks.\n */\nexport const useUnsetDomain = ({\n onSuccess,\n onError,\n}: useUnsetDomainProps): useUnsetDomainReturnValue => {\n const queryClient = useQueryClient();\n const { account } = useWallet();\n const { network } = useVeChainKitConfig();\n\n const clauses = useCallback(() => buildUnsetDomainClauses(account, network), [account, network]);\n\n // Refetch queries to update UI after the tx is confirmed\n const handleOnSuccess = useCallback(async () => {\n const address = account?.address ?? '';\n\n // Invalidate all domain-related queries\n await invalidateAndRefetchDomainQueries(\n queryClient,\n address,\n '', // No domain being set\n '', // No subdomain\n '', // No full domain\n network.type,\n );\n\n onSuccess?.();\n }, [onSuccess, queryClient, account, network.type]);\n\n const result = useSendTransaction({\n signerAccountAddress: account?.address ?? '',\n privyUIOptions: {\n title: 'Sign to unset your VeChain nickname',\n description: 'Unset your current VeChain nickname',\n buttonText: 'Sign to continue',\n },\n onTxConfirmed: handleOnSuccess,\n onTxFailedOrCancelled: onError,\n });\n\n return {\n ...result,\n clauses,\n sendTransaction: async () => {\n return result.sendTransaction(clauses());\n },\n };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { Address } from '@vechain/sdk-core';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { formatEther } from 'viem';\n\nexport const getAccountBalance = async (thor: ThorClient, address?: string) => {\n if (!address) throw new Error('Address is required');\n const account = await thor.accounts.getAccount(Address.of(address));\n\n return {\n balance: formatEther(BigInt(account.balance)).toString(),\n energy: formatEther(BigInt(account.energy)).toString(),\n };\n};\nexport const getAccountBalanceQueryKey = (address?: string) => [\n 'VECHAIN_KIT_BALANCE',\n address,\n];\n\n/**\n * Get the account balance for the given address\n * @param address The address of the account to get the balance for\n * @returns The account balance\n */\nexport const useAccountBalance = (address?: string) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n return useQuery({\n queryKey: getAccountBalanceQueryKey(address),\n queryFn: () => getAccountBalance(thor!, address),\n enabled: !!thor && !!address && Address.isValid(address),\n refetchInterval: 10000,\n });\n};\n","import { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { formatTokenBalance } from '../../../utils';\nimport { useQuery } from '@tanstack/react-query';\nimport { getB3trBalance } from '@vechain/contract-getters';\n\nexport const getB3trBalanceQueryKey = (address?: string) => [\n 'VEBETTERDAO_BALANCE',\n address,\n 'B3TR',\n];\n\nexport const useGetB3trBalance = (address?: string) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getB3trBalanceQueryKey(address),\n queryFn: async () => {\n if (!address) throw new Error('Address is required');\n const res = await getB3trBalance(address, {\n networkUrl: network.nodeUrl,\n });\n\n if (!res) throw new Error('Failed to get b3tr balance');\n\n const original = res[0];\n return formatTokenBalance(original);\n },\n enabled: !!address && !!network.type,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { formatTokenBalance } from '../../../utils';\nimport { getVot3Balance } from '@vechain/contract-getters';\n\nexport const getVot3BalanceQueryKey = (address?: string) => [\n 'VEBETTERDAO_BALANCE',\n address,\n 'VOT3',\n];\n\nexport const useGetVot3Balance = (address?: string) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getVot3BalanceQueryKey(address),\n queryFn: async () => {\n if (!address) throw new Error('Address is required');\n const res = await getVot3Balance(address, {\n networkUrl: network.nodeUrl,\n });\n\n if (!res) throw new Error('Failed to get vot3 balance');\n\n const original = res[0];\n return formatTokenBalance(original); \n },\n enabled: !!address && !!network.type,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n\nimport { getErc20Balance } from '@vechain/contract-getters';\nimport { formatTokenBalance } from '../../../utils';\n\nexport const getErc20BalanceQueryKey = (\n tokenAddress: string,\n address?: string,\n) => ['VECHAIN_KIT', 'BALANCE', 'ERC20', tokenAddress, address];\n\nexport const useGetErc20Balance = (tokenAddress: string, address?: string) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getErc20BalanceQueryKey(tokenAddress, address),\n queryFn: async () => {\n if (!address) throw new Error('Address is required');\n const res = await getErc20Balance(tokenAddress, address, {\n networkUrl: network.nodeUrl,\n });\n\n if (!res) throw new Error('Failed to get vot3 balance');\n\n const original = res[0];\n return formatTokenBalance(original); \n },\n enabled: !!address && !!network.type,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { getTokenInfo as getTokenInfoFromContract, type CustomTokenInfo } from '@vechain/contract-getters';\n\nexport const getTokenInfo = async (tokenAddress: string, networkUrl: string): Promise<CustomTokenInfo> => {\n return getTokenInfoFromContract(tokenAddress, {\n networkUrl,\n });\n};\n\nexport const getCustomTokenInfoQueryKey = (tokenAddress: string) => [\n 'VECHAIN_KIT_CUSTOM_TOKEN_INFO',\n tokenAddress,\n];\n\nexport const useGetCustomTokenInfo = (tokenAddress: string) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery<CustomTokenInfo>({\n queryKey: getCustomTokenInfoQueryKey(tokenAddress),\n queryFn: async () => {\n if (!tokenAddress) throw new Error('Token address is required');\n if (!network.nodeUrl) throw new Error('Network node URL is required');\n return getTokenInfo(tokenAddress, network.nodeUrl);\n },\n enabled: !!network.type && !!tokenAddress,\n retry: (failureCount, error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'token address is required' ||\n errorMessage === 'network node url is required') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","// Direct import to avoid circular dependency through barrel exports\nimport { LocalStorageKey, useLocalStorage } from '../../cache/useLocalStorage';\nimport { compareAddresses } from '../../../utils';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { getConfig } from '../../../config';\nimport { type CustomTokenInfo } from '@vechain/contract-getters';\n\nimport { getTokenInfo } from './useGetCustomTokenInfo';\n\nexport const useCustomTokens = () => {\n const [customTokens, setCustomTokens] = useLocalStorage<CustomTokenInfo[]>(\n LocalStorageKey.CUSTOM_TOKENS,\n [],\n );\n const { network } = useVeChainKitConfig();\n\n const addToken = async (address: CustomTokenInfo['address']) => {\n if (!isTokenIncluded(address) && !isDefaultToken(address)) {\n if (!network.nodeUrl) throw new Error('Network node URL is required');\n const tokenInfo = await getTokenInfo( address, network.nodeUrl);\n\n const token: CustomTokenInfo = {\n ...tokenInfo,\n address,\n };\n\n setCustomTokens([...customTokens, token]);\n }\n };\n\n const removeToken = (address: string) => {\n setCustomTokens(\n customTokens.filter((t: CustomTokenInfo) => t.address !== address),\n );\n };\n\n const isTokenIncluded = (address: string) => {\n return customTokens.some((t: CustomTokenInfo) =>\n compareAddresses(t.address, address),\n );\n };\n\n const isDefaultToken = (address: string) => {\n // Get contract addresses from config\n const contractAddresses = {\n vet: '0x', // VET has no contract address since it's the native token\n vtho: getConfig(network.type).vthoContractAddress,\n b3tr: getConfig(network.type).b3trContractAddress,\n vot3: getConfig(network.type).vot3ContractAddress,\n veDelegate: getConfig(network.type).veDelegate,\n };\n\n return Object.values(contractAddresses).includes(address);\n };\n\n return {\n customTokens,\n addToken,\n removeToken,\n isTokenIncluded,\n isDefaultToken,\n };\n};\n","import { useQueries } from '@tanstack/react-query';\n// Direct import to avoid circular dependency through barrel exports\nimport { useCustomTokens } from './useCustomTokens';\nimport { type CustomTokenInfo, getErc20Balance } from '@vechain/contract-getters';\nimport type { TokenBalance } from '../../../types';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { formatTokenBalance } from '../../../utils';\n\nexport type TokenWithBalance = CustomTokenInfo & TokenBalance;\n\n\nexport const getCustomTokenBalanceQueryKey = (\n tokenAddress?: string,\n address?: string,\n) => ['VECHAIN_KIT_BALANCE', address, 'CUSTOM_TOKEN', tokenAddress];\n\nexport const useGetCustomTokenBalances = (address?: string) => {\n const { network } = useVeChainKitConfig();\n const { customTokens } = useCustomTokens();\n\n return useQueries({\n queries: customTokens.map((token) => ({\n queryKey: getCustomTokenBalanceQueryKey(token.address, address),\n queryFn: async () => {\n if (!token.address) throw new Error('Token address is required');\n if (!address) throw new Error('Address is required');\n if (!network.nodeUrl) throw new Error('Network node URL is required');\n const tokenBalanceOriginal = await getErc20Balance(token.address, address, {\n networkUrl: network.nodeUrl,\n });\n if (!tokenBalanceOriginal) throw new Error('Failed to get token balance');\n const formattedTokenBalance = formatTokenBalance(tokenBalanceOriginal[0]);\n return {\n ...token,\n ...formattedTokenBalance,\n };\n },\n })),\n });\n};\n","import { useMemo } from 'react';\n// Import directly from specific hook files to avoid circular dependency with hooks/index.ts\nimport { useAccountBalance } from '../../thor/accounts/useAccountBalance';\nimport { useGetB3trBalance } from './useGetB3trBalance';\nimport { useGetVot3Balance } from './useGetVot3Balance';\nimport { useGetErc20Balance } from './useGetErc20Balance';\nimport { useGetCustomTokenBalances } from './useGetCustomTokenBalances';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { getConfig } from '../../../config';\n\nexport type WalletTokenBalance = {\n address: string;\n symbol: string;\n balance: string;\n};\n\nexport const useTokenBalances = (address?: string) => {\n const { network } = useVeChainKitConfig();\n const config = getConfig(network.type);\n\n // Base token balances\n const { data: vetData, isLoading: vetLoading } = useAccountBalance(address);\n const { data: b3trBalance, isLoading: b3trLoading } =\n useGetB3trBalance(address);\n const { data: vot3Balance, isLoading: vot3Loading } =\n useGetVot3Balance(address);\n const { data: veDelegateBalance, isLoading: veDelegateLoading } =\n useGetErc20Balance(config.veDelegateTokenContractAddress, address);\n const { data: gloDollarBalance, isLoading: gloDollarLoading } =\n useGetErc20Balance(config.gloDollarContractAddress, address);\n\n // Custom token balances\n const customTokenBalancesQueries = useGetCustomTokenBalances(address);\n const customTokenBalances = customTokenBalancesQueries\n .map((query) => query.data)\n .filter(Boolean);\n const customTokensLoading = customTokenBalancesQueries.some(\n (query) => query.isLoading,\n );\n\n // Get all balances\n const balances = useMemo(() => {\n if (!address) return [];\n\n // Get contract addresses from config\n const contractAddresses = {\n vet: '0x',\n vtho: config.vthoContractAddress,\n b3tr: config.b3trContractAddress,\n vot3: config.vot3ContractAddress,\n veDelegate: config.veDelegate,\n USDGLO: config.gloDollarContractAddress,\n };\n\n // Base tokens\n const baseTokens: WalletTokenBalance[] = [\n {\n address: contractAddresses.vet,\n symbol: 'VET',\n balance: vetData?.balance || '0',\n },\n {\n address: contractAddresses.vtho,\n symbol: 'VTHO',\n balance: vetData?.energy || '0',\n },\n {\n address: contractAddresses.b3tr,\n symbol: 'B3TR',\n balance: b3trBalance?.scaled ?? '0',\n },\n {\n address: contractAddresses.vot3,\n symbol: 'VOT3',\n balance: vot3Balance?.scaled ?? '0',\n },\n {\n address: contractAddresses.veDelegate,\n symbol: 'veDelegate',\n balance: veDelegateBalance?.scaled ?? '0',\n },\n {\n address: contractAddresses.USDGLO,\n symbol: 'USDGLO',\n balance: gloDollarBalance?.scaled ?? '0',\n },\n ];\n\n // Add custom tokens\n const customTokens: WalletTokenBalance[] = customTokenBalances.map(\n (token) => ({\n address: token?.address || '',\n symbol: token?.symbol || '',\n balance: token?.scaled || '0',\n }),\n );\n\n return [...baseTokens, ...customTokens];\n }, [\n address,\n vetData,\n b3trBalance,\n vot3Balance,\n veDelegateBalance,\n gloDollarBalance,\n customTokenBalances,\n network.type,\n ]);\n\n const isLoading =\n vetLoading ||\n b3trLoading ||\n vot3Loading ||\n veDelegateLoading ||\n gloDollarLoading ||\n customTokensLoading;\n\n return {\n balances,\n isLoading,\n };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useOptionalThor } from '../dappkit/useOptionalThor';\nimport { OracleVechainEnergy__factory } from '@vechain/vechain-contract-types';\nimport { BigNumber } from 'bignumber.js';\nimport { getConfig } from '../../../config';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { ThorClient } from '@vechain/sdk-network';\n\n// Create an enum or object for supported price feed IDs\nexport const PRICE_FEED_IDS = {\n B3TR: '0x623374722d757364000000000000000000000000000000000000000000000000',\n VET: '0x7665742d75736400000000000000000000000000000000000000000000000000',\n VTHO: '0x7674686f2d757364000000000000000000000000000000000000000000000000',\n GBP: '0x6762702d75736400000000000000000000000000000000000000000000000000',\n EUR: '0x657572742d757364000000000000000000000000000000000000000000000000',\n} as const;\n\nexport type SupportedToken = keyof typeof PRICE_FEED_IDS;\n\n// Rename and make the function generic\nexport const getTokenUsdPrice = async (\n thor: ThorClient,\n token: SupportedToken,\n network: NETWORK_TYPE,\n): Promise<number> => {\n const res = await thor.contracts\n .load(\n getConfig(network).oracleContractAddress,\n OracleVechainEnergy__factory.abi,\n )\n .read.getLatestValue(PRICE_FEED_IDS[token]);\n\n if (!res) throw new Error(`Failed to get price of ${token}`);\n\n return new BigNumber(res[0].toString()).div(1e12).toNumber() as number;\n};\n\nexport const getTokenUsdPriceQueryKey = (token: SupportedToken) => [\n 'VECHAIN_KIT_PRICE',\n token,\n];\n\nexport const useGetTokenUsdPrice = (token: SupportedToken) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getTokenUsdPriceQueryKey(token),\n queryFn: async () => getTokenUsdPrice(thor!, token, network.type),\n enabled: !!thor && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || errorMessage.includes('abort')) {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","import { useMemo } from 'react';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { getConfig } from '../../../config';\nimport { useGetTokenUsdPrice } from './useGetTokenUsdPrice';\n\nexport type ExchangeRates = {\n eurUsdPrice: number;\n gbpUsdPrice: number;\n};\n\nexport const useTokenPrices = () => {\n const { network } = useVeChainKitConfig();\n const config = getConfig(network.type);\n\n // Fetch base token prices\n const { data: vetUsdPrice, isLoading: vetUsdPriceLoading } =\n useGetTokenUsdPrice('VET');\n const { data: vthoUsdPrice, isLoading: vthoUsdPriceLoading } =\n useGetTokenUsdPrice('VTHO');\n const { data: b3trUsdPrice, isLoading: b3trUsdPriceLoading } =\n useGetTokenUsdPrice('B3TR');\n const { data: eurUsdPrice, isLoading: eurToUsdLoading } =\n useGetTokenUsdPrice('EUR');\n const { data: gbpUsdPrice, isLoading: gbpToUsdLoading } =\n useGetTokenUsdPrice('GBP');\n\n // Get all prices as a map\n const prices = useMemo(() => {\n const contractAddresses = {\n vet: '0x',\n vtho: config.vthoContractAddress,\n b3tr: config.b3trContractAddress,\n vot3: config.vot3ContractAddress,\n veDelegate: config.veDelegate,\n USDGLO: config.gloDollarContractAddress,\n };\n\n return {\n [contractAddresses.vet]: vetUsdPrice || 0,\n [contractAddresses.vtho]: vthoUsdPrice || 0,\n [contractAddresses.b3tr]: b3trUsdPrice || 0,\n // VOT3 and veDelegate share the same price feed as B3TR\n [contractAddresses.vot3]: b3trUsdPrice || 0,\n [contractAddresses.veDelegate]: b3trUsdPrice || 0,\n [contractAddresses.USDGLO]: 1, // GloDollar is pegged to USD\n };\n }, [\n vetUsdPrice,\n vthoUsdPrice,\n b3trUsdPrice,\n config.vthoContractAddress,\n config.b3trContractAddress,\n config.vot3ContractAddress,\n config.veDelegate,\n config.gloDollarContractAddress,\n ]);\n\n const exchangeRates: ExchangeRates = useMemo(\n () => ({\n eurUsdPrice: eurUsdPrice || 1,\n gbpUsdPrice: gbpUsdPrice || 1,\n }),\n [eurUsdPrice, gbpUsdPrice],\n );\n\n const isLoading =\n vetUsdPriceLoading ||\n vthoUsdPriceLoading ||\n b3trUsdPriceLoading ||\n eurToUsdLoading ||\n gbpToUsdLoading;\n\n return {\n prices,\n exchangeRates,\n isLoading,\n };\n};\n","import { ExchangeRates } from '../hooks/api/wallet/useTokenPrices';\nimport i18n, { bcp47LanguageCodes } from '@i18n';\n\nexport type SupportedCurrency = 'usd' | 'eur' | 'gbp';\n\nexport const convertToSelectedCurrency = (\n amountUsd: number,\n currency: SupportedCurrency,\n exchangeRates: ExchangeRates,\n): number => {\n switch (currency) {\n case 'eur':\n return amountUsd / exchangeRates.eurUsdPrice;\n case 'gbp':\n return amountUsd / exchangeRates.gbpUsdPrice;\n default:\n return amountUsd;\n }\n};\n\nexport const formatCurrencyValue = (\n value: number,\n lng = 'en',\n options?: Intl.NumberFormatOptions,\n): string => {\n const defaultOptions: Intl.NumberFormatOptions = {\n style: 'currency',\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n currency: options?.currency ?? 'usd',\n ...options,\n };\n\n return new Intl.NumberFormat(bcp47LanguageCodes[lng], defaultOptions).format(value);\n};\n\nexport const formatCompactCurrency = (\n value: number,\n options?: Intl.NumberFormatOptions,\n): string => {\n return formatCurrencyValue(\n value,\n i18n.resolvedLanguage,\n {\n notation: 'compact',\n compactDisplay: 'short',\n currency: options?.currency ?? 'usd',\n ...options,\n },\n );\n};","import { useEffect } from 'react';\n// Import directly from VeChainKitContext to avoid circular dependency with providers/index.ts\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\nimport type { CURRENCY } from '../../types';\nimport { setLocalStorageItem } from '../../utils/ssrUtils';\n\nconst STORAGE_KEY = 'vechain_kit_currency';\nconst allCurrencies: CURRENCY[] = ['usd', 'eur', 'gbp'];\n\n/**\n * Hook for managing currency preferences\n *\n * Note: This hook now uses the currency from VeChainKit context.\n * For setting currency, use the setCurrency function from useCurrentCurrency() hook instead.\n */\nexport const useCurrency = () => {\n const { currentCurrency, setCurrency } = useVeChainKitConfig();\n\n // Sync currency changes to localStorage\n useEffect(() => {\n setLocalStorageItem(STORAGE_KEY, currentCurrency);\n }, [currentCurrency]);\n\n const changeCurrency = (newCurrency: CURRENCY) => {\n if (!allCurrencies.includes(newCurrency)) {\n console.error(`Invalid currency: ${newCurrency}`);\n return;\n }\n setCurrency(newCurrency);\n };\n\n return {\n currentCurrency,\n allCurrencies,\n changeCurrency,\n };\n};\n","import { useMemo } from 'react';\nimport { useTokenBalances, WalletTokenBalance } from './useTokenBalances';\nimport { useTokenPrices } from './useTokenPrices';\nimport {\n SupportedCurrency,\n convertToSelectedCurrency,\n} from '../../../utils/currencyUtils';\nimport { useCurrency } from '../../utils/useCurrency';\n\nexport type TokenWithValue = WalletTokenBalance & {\n priceUsd: number;\n valueUsd: number;\n valueInCurrency: number;\n};\n\ntype UseTokensWithValuesProps = {\n address?: string;\n};\n\nexport const useTokensWithValues = ({\n address = '',\n}: UseTokensWithValuesProps) => {\n const { balances, isLoading: balancesLoading } = useTokenBalances(address);\n const {\n prices,\n exchangeRates,\n isLoading: pricesLoading,\n } = useTokenPrices();\n const { currentCurrency } = useCurrency();\n\n const tokensWithValues = useMemo(() => {\n return balances.map((token) => {\n const priceUsd = prices[token.address] || 0;\n const valueUsd = Number(token.balance) * priceUsd;\n const valueInCurrency = convertToSelectedCurrency(\n valueUsd,\n currentCurrency as SupportedCurrency,\n exchangeRates,\n );\n\n return {\n ...token,\n priceUsd,\n valueUsd,\n valueInCurrency,\n };\n });\n }, [balances, prices, currentCurrency, exchangeRates]);\n\n // Get sorted tokens (by value)\n const sortedTokens = useMemo(() => {\n return [...tokensWithValues].sort(\n (a, b) => b.valueInCurrency - a.valueInCurrency,\n );\n }, [tokensWithValues]);\n\n // Get tokens with positive balances\n const tokensWithBalance = useMemo(() => {\n return sortedTokens.filter((token) => Number(token.balance) > 0);\n }, [sortedTokens]);\n\n const isLoading = balancesLoading || pricesLoading;\n\n return {\n tokens: tokensWithValues,\n sortedTokens,\n tokensWithBalance,\n isLoading,\n };\n};\n","import { useMemo } from 'react';\nimport { useTokensWithValues } from './useTokensWithValues';\nimport {\n SupportedCurrency,\n formatCompactCurrency,\n} from '../../../utils/currencyUtils';\nimport { useCurrency } from '../../utils/useCurrency';\n\ntype UseTotalBalanceProps = {\n address?: string;\n};\n\nexport const useTotalBalance = ({ address = '' }: UseTotalBalanceProps) => {\n const { tokensWithBalance, isLoading } = useTokensWithValues({ address });\n const { currentCurrency } = useCurrency();\n const totalBalanceInCurrency = useMemo(() => {\n return tokensWithBalance.reduce(\n (total, token) => total + token.valueInCurrency,\n 0,\n );\n }, [tokensWithBalance]);\n\n const totalBalanceUsd = useMemo(() => {\n return tokensWithBalance.reduce(\n (total, token) => total + token.valueUsd,\n 0,\n );\n }, [tokensWithBalance]);\n\n const formattedBalance = useMemo(() => {\n return formatCompactCurrency(\n totalBalanceInCurrency,\n { currency: currentCurrency as SupportedCurrency },\n );\n }, [totalBalanceInCurrency, currentCurrency]);\n\n return {\n totalBalanceInCurrency,\n totalBalanceUsd,\n formattedBalance,\n isLoading,\n hasAnyBalance: tokensWithBalance.length > 0,\n };\n};\n","import { getConfig } from '../../../config';\nimport { XAllocationVoting__factory } from '@vechain/vechain-contract-types';\n// Direct import to avoid circular dependency through barrel exports\nimport { useCallClause, getCallClauseQueryKey } from '../../utils/useCallClause';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n\nconst abi = XAllocationVoting__factory.abi;\nconst method = 'currentRoundId' as const;\n\n/**\n * Returns the query key for fetching the current allocations round ID.\n * @returns The query key for fetching the current allocations round ID.\n */\nexport const getCurrentAllocationsRoundIdQueryKey = (address: string) =>\n getCallClauseQueryKey({ abi, address, method });\n\n/**\n * Hook to get the current roundId of allocations voting\n * @returns the current roundId of allocations voting\n */\nexport const useCurrentAllocationsRoundId = () => {\n const { network } = useVeChainKitConfig();\n\n const address = getConfig(network.type)\n .xAllocationVotingContractAddress as `0x${string}`;\n\n return useCallClause({\n abi,\n address,\n method,\n args: [],\n queryOptions: {\n select: (data) => data[0].toString(),\n },\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { getIsPerson } from '@vechain/contract-getters';\n\n/**\n * Returns the query key for fetching the isPerson status.\n * @param user - The user address.\n * @param networkType - The network type.\n * @returns The query key for fetching the isPerson status.\n */\nexport const getIsPersonQueryKey = (user: string, networkType: NETWORK_TYPE) => [\n 'VECHAIN_KIT',\n 'IS_PERSON',\n user,\n networkType,\n];\n\n/**\n * Hook to get the isPerson status from the VeBetterPassport contract.\n * @param user - The user address.\n * @returns The isPerson status.\n */\nexport const useIsPerson = (user?: string | null) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery<boolean>({\n queryKey: getIsPersonQueryKey(user ?? '', network.type),\n queryFn: async () => {\n if (!user) throw new Error('User address is required');\n\n return getIsPerson(user, {\n networkUrl: network.nodeUrl,\n });\n },\n enabled: !!user && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'user address is required') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n gcTime: 1000 * 60 * 5, // 5 minutes\n staleTime: 1000 * 60, // 1 minute\n });\n};\n","import { getConfig } from '../../../config';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { XAllocationVoting__factory } from '@vechain/vechain-contract-types';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n// Direct import to avoid circular dependency through barrel exports\nimport { getCallClauseQueryKeyWithArgs, useCallClause } from '../../utils/useCallClause';\n\nconst abi = XAllocationVoting__factory.abi;\nconst method = 'getAppsOfRound' as const;\n\nexport const getRoundXAppsQueryKey = (\n roundId: string,\n networkType: NETWORK_TYPE,\n) =>\n getCallClauseQueryKeyWithArgs({\n abi,\n address: getConfig(networkType)\n .xAllocationVotingContractAddress as `0x${string}`,\n method,\n args: [BigInt(roundId ?? 0)],\n });\n\nexport const useRoundXApps = (roundId?: string) => {\n const { network } = useVeChainKitConfig();\n\n const address = getConfig(network.type)\n .xAllocationVotingContractAddress as `0x${string}`;\n\n return useCallClause({\n abi,\n address,\n method,\n args: [BigInt(roundId ?? 0)],\n queryOptions: {\n enabled: !!roundId,\n select: (data) =>\n data[0].map((app) => ({\n id: app.id.toString(),\n teamWalletAddress: app.teamWalletAddress,\n name: app.name,\n metadataURI: app.metadataURI,\n createdAtTimestamp: app.createdAtTimestamp.toString(),\n })),\n },\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { XAllocationPool__factory } from '@vechain/vechain-contract-types';\nimport { getConfig } from '../../../config';\nimport { useOptionalThor } from '../dappkit/useOptionalThor';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { executeMultipleClausesCall } from '../../../utils';\n\nconst abi = XAllocationPool__factory.abi;\nconst method = 'getAppShares' as const;\n\n/**\n * Returns the query key for the shares of multiple xApps in an allocation round.\n * @param roundId the roundId the get the shares for\n */\nexport const getXAppsSharesQueryKey = (roundId?: number | string) => [\n 'VECHAIN_KIT',\n 'XApps',\n 'Shares',\n roundId,\n];\n\n/**\n * Fetch shares of multiple xApps in an allocation round\n * @param apps the xApps to get the shares for\n * @param roundId the round id to get the shares for\n * @returns the shares (% of allocation pool) for the xApps in the round { allocated: number, unallocated: number }\n *\n */\nexport const useXAppsShares = (apps: string[], roundId?: string) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n const address = getConfig(network.type)\n .xAllocationPoolContractAddress as `0x${string}`;\n\n return useQuery({\n queryKey: getXAppsSharesQueryKey(roundId),\n queryFn: async () => {\n if (!thor) throw new Error('Thor client not available');\n const shares = await executeMultipleClausesCall({\n thor,\n calls: apps.map(\n (app) =>\n ({\n abi,\n functionName: method,\n address,\n args: [roundId, app],\n } as const),\n ),\n });\n\n return shares.map((share, index) => {\n return {\n app: apps[index] as string,\n share: Number(share[0] || 0) / 100,\n unallocatedShare: Number(share[1] || 0) / 100,\n };\n });\n },\n enabled: !!thor && !!roundId && !!apps.length,\n });\n};\n","import { useMemo } from 'react';\nimport { useRoundXApps } from './useRoundXApps';\nimport { useXAppsShares } from './useXAppShares';\n\nexport type XApp = {\n id: string;\n teamWalletAddress: string;\n name: string;\n metadataURI: string;\n createdAtTimestamp: string;\n};\n\nexport type MostVotedAppsInRoundReturnType = {\n percentage: number;\n id: string;\n app: XApp;\n};\n\n/**\n * Get the most voted apps in a round\n *\n * @param roundId the id of the round to get the most voted apps\n * @returns a sorted array of the most voted apps in the round\n */\nexport const useMostVotedAppsInRound = (\n roundId?: string,\n): { data: MostVotedAppsInRoundReturnType[]; isLoading: boolean } => {\n const { data: apps } = useRoundXApps(roundId);\n\n // get shares of apps\n const xAppsShares = useXAppsShares(\n apps?.map((app) => app.id) ?? [],\n roundId,\n );\n\n const mostVotedApps = useMemo(\n () =>\n xAppsShares.data\n ?.map((appShares) => ({\n percentage: appShares.share + appShares.unallocatedShare,\n id: apps?.find((xa) => xa.id === appShares.app)?.id ?? '',\n app:\n apps?.find((xa) => xa.id === appShares.app) ??\n ({} as XApp),\n }))\n .sort((a, b) => Number(b.percentage) - Number(a.percentage)) ??\n [],\n [xAppsShares.data, apps],\n );\n\n return {\n data: mostVotedApps,\n isLoading: xAppsShares.isLoading,\n };\n};\n","import { useQueryClient } from '@tanstack/react-query';\nimport { useWallet } from './useWallet';\n\nexport const useRefreshBalances = () => {\n const queryClient = useQueryClient();\n const { account } = useWallet();\n\n const refresh = async () => {\n const address = account?.address ?? '';\n\n await Promise.all([\n // getAccountBalanceQueryKey\n // getB3trBalanceQueryKey\n // getVot3BalanceQueryKey\n // getVeDelegateBalanceQueryKey\n // getCustomTokenBalanceQueryKey\n queryClient.invalidateQueries({\n queryKey: ['VECHAIN_KIT_BALANCE', address],\n }),\n // getTokenUsdPriceQueryKey\n queryClient.invalidateQueries({\n queryKey: ['VECHAIN_KIT_PRICE'],\n }),\n ]);\n };\n\n return { refresh };\n};\n","import { useState, useCallback } from 'react';\n// Use optional hook to handle missing DAppKitProvider gracefully\nimport { useOptionalDAppKitWallet } from '../dappkit/useOptionalDAppKitWallet';\nimport { useWallet } from './useWallet';\nimport { useWalletStorage, StoredWallet } from './useWalletStorage';\nimport { isBrowser } from '../../../utils/ssrUtils';\n\nexport type UseSwitchWalletReturnType = {\n switchWallet: () => Promise<void>;\n isSwitching: boolean;\n getStoredWallets: () => StoredWallet[];\n setActiveWallet: (address: string) => void;\n removeWallet: (address: string) => void;\n isInAppBrowser: boolean;\n};\n\n/**\n * Hook for switching wallets\n * - In VeWorld in-app browser: Uses dapp-kit's switchWallet function\n * - On desktop: Provides wallet storage functions for UI-based switching\n */\nexport const useSwitchWallet = (): UseSwitchWalletReturnType => {\n const { switchWallet: dappKitSwitchWallet } = useOptionalDAppKitWallet();\n const { connection } = useWallet();\n const [isSwitching, setIsSwitching] = useState(false);\n const {\n getStoredWallets: getStoredWalletsStorage,\n setActiveWallet: setActiveWalletStorage,\n removeWallet: removeWalletStorage,\n } = useWalletStorage();\n\n const isInAppBrowser = connection.isInAppBrowser;\n\n const switchWallet = useCallback(async () => {\n if (isInAppBrowser) {\n // In-app browser: use dapp-kit's switchWallet\n if (!dappKitSwitchWallet) {\n return;\n }\n\n setIsSwitching(true);\n try {\n await dappKitSwitchWallet();\n } catch {\n // Silently handle errors - wallet state will update automatically on success\n } finally {\n setIsSwitching(false);\n }\n } else {\n // Desktop: wallet switching is handled via UI (SelectWalletContent)\n // This function is called but navigation is handled by components\n return Promise.resolve();\n }\n }, [dappKitSwitchWallet, isInAppBrowser]);\n\n const setActiveWallet = useCallback(\n (address: string) => {\n setActiveWalletStorage(address);\n // Dispatch event to trigger wallet change\n if (isBrowser()) {\n window.dispatchEvent(\n new CustomEvent('wallet_switched', { detail: { address } }),\n );\n }\n },\n [setActiveWalletStorage],\n );\n\n return {\n switchWallet,\n isSwitching,\n getStoredWallets: getStoredWalletsStorage,\n setActiveWallet,\n removeWallet: removeWalletStorage,\n isInAppBrowser,\n };\n};\n","import { getConfig } from '../../../config';\nimport { X2EarnApps__factory } from '@vechain/vechain-contract-types';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { useOptionalThor } from '../dappkit/useOptionalThor';\nimport { convertUriToUrl } from '../../../utils';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { useQuery } from '@tanstack/react-query';\n\n/**\n * The metadata of an xApp from the xApps metadata base uri\n * @property name - The name of the xApp\n * @property description - The description of the xApp\n * @property distribution_strategy - The B3TR distribution strategy of the xApp\n * @property external_url - The external url of the xApp\n * @property logo - The logo of the xApp (ipfs uri)\n * @property banner - The banner of the xApp (ipfs uri)\n * @property screenshots - The screenshots of the xApp (ipfs uri)\n * @property social_urls - The social urls of the xApp\n * @property app_urls - The app urls of the xApp\n * @property categories - The categories of the xApp\n */\nexport type XAppMetadata = {\n name: string;\n description: string;\n distribution_strategy?: string;\n external_url: string;\n logo: string;\n banner: string;\n screenshots: string[];\n social_urls: {\n name: string;\n url: string;\n }[];\n app_urls: {\n code: string;\n url: string;\n }[];\n tweets: string[];\n ve_world: {\n banner: string;\n };\n categories: string[];\n};\n/**\n dapp-kit broke the pre-fetching\n * @param uri - The uri of the xApps metadata\n * @returns The metadata of the xApp see {@link XAppMetadata}\n */\nexport const getXAppMetadata = async (\n uri: string,\n networkType: NETWORK_TYPE,\n): Promise<XAppMetadata | undefined> => {\n const url = convertUriToUrl(uri, networkType) || '';\n const response = await fetch(url, {\n signal: AbortSignal.timeout(20000),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const metadata = await response.json();\n return metadata;\n};\n\nconst abi = X2EarnApps__factory.abi;\n\nexport const useXAppMetadata = (xAppId: string) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: ['xAppMetaData', xAppId],\n queryFn: async () => {\n if (!thor) throw new Error('Thor client not available');\n const address = getConfig(network.type).x2EarnAppsContractAddress;\n const contract = thor.contracts.load(address, abi);\n\n const appDetailsResult = await contract.read.app(\n xAppId as `0x${string}`,\n );\n\n const appDetails = appDetailsResult[0] as unknown as unknown[];\n const metadataURI = appDetails[3]?.toString() || '';\n\n const [baseUri] = await contract.read.baseURI();\n const metadata = await getXAppMetadata(\n `${baseUri}${metadataURI}`,\n network.type,\n );\n\n return metadata;\n },\n enabled: !!thor && !!xAppId,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { convertUriToUrl } from '../../../utils';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\n\n/**\n * Fetches metadata from IPFS for a given URI\n *\n * @param networkType - The network type\n * @param uri - The IPFS URI\n * @param parseJson - Whether to parse the JSON\n * @returns The metadata\n */\nexport const getIpfsMetadata = async <T>(\n networkType: NETWORK_TYPE,\n uri?: string,\n parseJson = false,\n): Promise<T> => {\n if (!uri) throw new Error('No URI provided');\n const newUri = convertUriToUrl(uri, networkType);\n if (!newUri) throw new Error('Invalid URI');\n\n const response = await fetch(newUri, {\n headers: {\n 'X-Project-Id': 'vechain-kit',\n },\n });\n const data = await response.text();\n\n if (parseJson) return JSON.parse(data);\n\n return data as unknown as T;\n};\n\nexport const getIpfsMetadataQueryKey = (\n networkType: NETWORK_TYPE,\n ipfsUri?: string,\n) => ['VECHAIN_KIT', 'IPFS_METADATA', networkType, ipfsUri];\n\n/**\n * Fetches metadata from IPFS for a given URI\n * @param ipfsUri - The IPFS URI\n * @returns The metadata from IPFS\n */\nexport const useIpfsMetadata = <T>(ipfsUri?: string, parseJson = false) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getIpfsMetadataQueryKey(network.type, ipfsUri),\n queryFn: () => getIpfsMetadata<T>(network.type, ipfsUri, parseJson),\n enabled: !!ipfsUri && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'no uri provided' ||\n errorMessage === 'invalid uri') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n staleTime: Infinity,\n });\n};\n","import { convertUriToUrl, resolveMediaTypeFromMimeType } from '../../../utils';\nimport { useQueries, useQuery } from '@tanstack/react-query';\nimport type { NFTMediaType } from '../../../types';\n// Import directly from VeChainKitContext to avoid circular dependency with providers/index.ts\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\n\nexport interface IpfsImage {\n image: string;\n mime: string;\n mediaType: NFTMediaType;\n}\nexport const MAX_IMAGE_SIZE = 1024 * 1024 * 10; // 10MB\n\n/**\n * Fetches NFT media from IPFS\n * @param networkType - The network type\n * @param uri - The IPFS URI of the NFT media\n * @returns The NFT media\n */\nexport const getIpfsImage = async (\n networkType: NETWORK_TYPE,\n uri?: string,\n): Promise<IpfsImage> => {\n if (!uri) throw new Error('IPFS URI is required');\n\n const response = await fetch(convertUriToUrl(uri, networkType) ?? '', {\n headers: {\n 'X-Project-Id': 'vechain-kit',\n },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const blob = await response.blob();\n\n // Check if the MIME type is allowed\n const allowedMimeTypes = [\n 'image/jpeg',\n 'image/jpg',\n 'image/png',\n 'image/gif',\n 'image/bmp',\n 'image/tiff',\n 'image/webp',\n 'image/svg+xml',\n ];\n if (!allowedMimeTypes.includes(blob.type)) {\n throw new Error(`Unsupported MIME type: ${blob.type}`);\n }\n\n if (blob.size > MAX_IMAGE_SIZE) {\n throw new Error('Image size exceeds maximum allowed size');\n }\n\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.readAsDataURL(blob);\n reader.onloadend = () => {\n resolve({\n image: reader.result as string,\n mime: blob.type,\n mediaType: resolveMediaTypeFromMimeType(blob.type),\n });\n };\n reader.onerror = () => {\n reject(Error('Error occurred while reading blob.'));\n };\n });\n};\n\n/**\n * @param networkType - The network type\n * @param imageIpfsUri - The IPFS URI of the NFT media\n * @returns The NFT media\n */\nexport const getIpfsImageQueryKey = (\n networkType: NETWORK_TYPE,\n imageIpfsUri?: null | string,\n) => ['VECHAIN_KIT', 'IPFS_IMAGE', networkType, imageIpfsUri];\n\n/**\n * Hook to fetch NFT media from IPFS\n * @param imageIpfsUri - The IPFS URI of the NFT media\n * @returns The NFT media\n */\nexport const useIpfsImage = (imageIpfsUri?: null | string) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getIpfsImageQueryKey(network.type, imageIpfsUri),\n queryFn: () => getIpfsImage(network.type, imageIpfsUri!),\n enabled: !!imageIpfsUri && !!network.type,\n retry: (failureCount, error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'ipfs uri is required') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n staleTime: Infinity,\n });\n};\n\n/**\n * Custom hook to fetch a list of IPFS images.\n *\n * @param imageIpfsUriList - An array of IPFS URIs for the images.\n * @returns An array of queries for each IPFS image URI.\n */\nexport const useIpfsImageList = (imageIpfsUriList: string[]) => {\n const { network } = useVeChainKitConfig();\n\n return useQueries({\n queries: imageIpfsUriList.map((imageIpfsUri) => ({\n queryKey: getIpfsImageQueryKey(network.type, imageIpfsUri),\n queryFn: () => getIpfsImage(network.type, imageIpfsUri),\n enabled: !!imageIpfsUri && !!network.type,\n retry: (failureCount: number, error: Error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'ipfs uri is required') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n staleTime: Infinity,\n })),\n });\n};\n","import { useQueries } from '@tanstack/react-query';\nimport { getIpfsMetadata, getIpfsMetadataQueryKey } from './useIpfsMetadata';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n\n/**\n * Fetches metadatas from IPFS for given URIs\n * @param ipfsUris - The IPFS URIs\n * @returns The metadata from IPFS for each URI\n */\nexport const useIpfsMetadatas = <T>(ipfsUris: string[], parseJson = false) => {\n const { network } = useVeChainKitConfig();\n\n return useQueries({\n queries: ipfsUris.map((uri) => ({\n queryKey: getIpfsMetadataQueryKey(network.type, uri),\n queryFn: async () => {\n return getIpfsMetadata<T>(network.type, uri, parseJson);\n },\n enabled: !!uri && !!network.type,\n retry: (failureCount: number, error: Error) => {\n // Don't retry on cancellation or validation errors\n if (error instanceof Error) {\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.includes('cancel') || \n errorMessage.includes('abort') ||\n errorMessage === 'no uri provided' ||\n errorMessage === 'invalid uri') {\n return false;\n }\n }\n // Retry network errors up to 2 times\n return failureCount < 2;\n },\n staleTime: Infinity,\n })),\n });\n};\n","'use client';\nimport { useState, useCallback, useEffect } from 'react';\nimport imageCompression, {\n Options as CompressOptions,\n} from 'browser-image-compression';\n\nexport const imageCompressionOptions: CompressOptions = {\n maxSizeMB: 0.4,\n maxWidthOrHeight: 1920,\n useWebWorker: true,\n};\n\nexport const compressImages = async (images: UploadedImage[]) => {\n const compressedImages: File[] = [];\n try {\n for (const image of images) {\n const parsedFile = await imageCompression(\n image.file,\n imageCompressionOptions,\n );\n\n compressedImages.push(parsedFile);\n }\n return compressedImages;\n } catch (e) {\n console.error('compress error', e);\n throw e;\n }\n};\n\ntype Props = {\n compressImages?: boolean;\n defaultImages?: UploadedImage[];\n};\n/**\n * Hook to handle image uploads and compressions in a dropzone\n * @param param0 compressImages: boolean to indicate if the images should be compressed (default: true)\n * @returns uploadedImages: array of uploaded images, setUploadedImages: function to set the uploaded images, onDrop: function to handle the drop event\n */\n\nexport type UploadedImage = {\n file: File;\n image: string;\n};\nexport const useUploadImages = ({ compressImages, defaultImages }: Props) => {\n const [uploadedImages, setUploadedImages] = useState<UploadedImage[]>(\n defaultImages ?? [],\n );\n\n useEffect(() => {\n if (defaultImages) {\n setUploadedImages(defaultImages);\n }\n }, [defaultImages]);\n\n const [invalidDateError, setInvalidDateError] = useState<number[]>([]);\n\n const onRemove = useCallback(\n (index: number) =>\n setUploadedImages((s) => s.filter((_, i) => i !== index)),\n [],\n );\n\n const onUpload = useCallback(\n async (acceptedFiles: File[], keepCurrent = true) => {\n setInvalidDateError([]);\n\n const parsedUploads: UploadedImage[] = [];\n for (const file of acceptedFiles) {\n let parsedFile = file;\n if (compressImages) {\n parsedFile = await imageCompression(\n file,\n imageCompressionOptions,\n );\n }\n\n const image: UploadedImage = {\n file: parsedFile,\n image: URL.createObjectURL(file),\n };\n parsedUploads.push(image);\n }\n\n setUploadedImages((s) => [\n ...parsedUploads,\n ...(!keepCurrent\n ? []\n : s.filter(\n (f) =>\n !parsedUploads.some(\n (p) => p.file.name === f.file.name,\n ),\n )),\n ]);\n },\n [compressImages],\n );\n\n return {\n uploadedImages,\n setUploadedImages,\n onUpload,\n onRemove,\n invalidDateError,\n };\n};\n","import { useState, useCallback, useEffect } from 'react';\nimport imageCompression from 'browser-image-compression';\nimport { imageCompressionOptions, UploadedImage } from './useUploadImages';\n\ntype Props = {\n compressImage?: boolean;\n defaultImage?: UploadedImage;\n};\n/**\n * Hook to handle image uploads and compressions in a dropzone\n * @param param0 compressImags: boolean to indicate if the image should be compressed (default: true)\n * @param param1 defaultImage: default image to be displayed\n * @returns uploaded image, setUploadedImage: function to set the uploaded image, onDrop: function to handle the drop event\n */\n\nexport const useSingleImageUpload = ({\n compressImage,\n defaultImage,\n}: Props) => {\n const [uploadedImage, setUploadedImage] = useState<\n UploadedImage | undefined\n >(defaultImage);\n\n useEffect(() => {\n if (defaultImage) {\n setUploadedImage(defaultImage);\n }\n }, [defaultImage]);\n\n const onRemove = useCallback(() => setUploadedImage(undefined), []);\n\n const onUpload = useCallback(\n async (acceptedFile: File) => {\n let parsedFile = acceptedFile;\n if (compressImage) {\n parsedFile = await imageCompression(\n parsedFile,\n imageCompressionOptions,\n );\n }\n\n const image: UploadedImage = {\n file: parsedFile,\n image: URL.createObjectURL(parsedFile),\n };\n\n setUploadedImage(image);\n return image;\n },\n [compressImage],\n );\n\n return {\n uploadedImage,\n setUploadedImage,\n onUpload,\n onRemove,\n };\n};\n","import { useCallback } from 'react';\nimport { useSendTransaction } from '../../thor/transactions/useSendTransaction';\n// Direct import to avoid circular dependency through barrel exports\nimport { useWallet } from '../wallet/useWallet';\nimport type { SwapParams, SwapQuote } from '../../../types/swap';\nimport { useTranslation } from 'react-i18next';\n\n/**\n * Hook to execute a swap transaction\n */\nexport const useSwapTransaction = (\n params: SwapParams | null,\n quote: SwapQuote | null,\n) => {\n const { account } = useWallet();\n const { t } = useTranslation();\n\n const {\n sendTransaction,\n isTransactionPending,\n isWaitingForWalletConfirmation,\n txReceipt,\n status,\n resetStatus,\n error,\n } = useSendTransaction({\n signerAccountAddress: account?.address ?? '',\n privyUIOptions: {\n title: t('ConfirmSwapTitle', { defaultValue: 'Confirm Swap' }),\n description: t('ConfirmSwapDescription', { defaultValue: 'Please confirm the swap transaction in your wallet' }),\n buttonText: t('Confirm', { defaultValue: 'Confirm' }),\n },\n });\n\n const executeSwap = useCallback(async () => {\n if (!params || !quote) {\n throw new Error('Missing swap parameters or quote');\n }\n\n // Use the aggregator reference from the quote\n if (!quote.aggregator) {\n throw new Error(`Aggregator not found for quote from ${quote.aggregatorName}`);\n }\n\n // Build transaction clauses\n const clauses = await quote.aggregator.buildSwapTransaction(params, quote);\n\n if (clauses.length === 0) {\n throw new Error('Failed to build swap transaction');\n }\n\n // Send the transaction\n await sendTransaction(clauses);\n }, [params, quote, sendTransaction]);\n\n return {\n executeSwap,\n isTransactionPending,\n isWaitingForWalletConfirmation,\n txReceipt,\n status,\n resetStatus,\n error,\n };\n};\n\n","import { ERC20_ABI, TransactionClause } from '@vechain/sdk-core';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { decodeEventLog, zeroAddress, type Hex } from 'viem';\nimport type { SwapParams, SwapQuote, SwapSimulation } from '../../types/swap';\n\n/**\n * Helper to detect VeChain native token (VET) placeholder addresses.\n */\nconst isVETAddress = (address: string): boolean => {\n return address === '0x' || address === zeroAddress;\n};\n\n/**\n * Calculate asset inflow and outflow per token (including native VET) for a given user address.\n * - ERC20 flows are derived from Transfer events.\n * - VET flows are derived from clause value (outflow) and transfers array (inflow).\n * The result is a map: tokenAddress -> { inflow, outflow }.\n * For VET, the tokenAddress key is the zeroAddress.\n */\nconst calculateTokenFlowsFromEvents = (\n events: {\n address: string;\n topics: string[];\n data: string;\n }[],\n transfers: {\n sender: string;\n recipient: string;\n amount: string;\n }[],\n clauseValue: string | number | bigint | undefined,\n userAddress: string,\n): Record<string, { inflow: bigint; outflow: bigint }> => {\n const flowsByToken: Record<string, { inflow: bigint; outflow: bigint }> =\n {};\n const user = userAddress.toLowerCase();\n\n // ERC20 token flows from Transfer events\n for (const event of events) {\n try {\n const decoded = decodeEventLog({\n abi: ERC20_ABI,\n eventName: 'Transfer',\n topics: event.topics as unknown as [Hex, ...Hex[]],\n data: event.data as Hex,\n }) as {\n args: {\n from: string;\n to: string;\n value: bigint | string;\n };\n };\n\n const from = decoded.args.from.toLowerCase();\n const to = decoded.args.to.toLowerCase();\n const rawValue = decoded.args.value;\n const value =\n typeof rawValue === 'bigint' ? rawValue : BigInt(rawValue);\n\n // Only consider flows where the user is directly involved\n if (from !== user && to !== user) {\n continue;\n }\n\n const tokenAddress = event.address.toLowerCase();\n const current = flowsByToken[tokenAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n\n if (from === user) {\n current.outflow += value;\n }\n\n if (to === user) {\n current.inflow += value;\n }\n\n flowsByToken[tokenAddress] = current;\n } catch {\n // Not an ERC20 Transfer event, ignore\n continue;\n }\n }\n\n // VET outflow: value (VET) sent by the user in the clause\n if (clauseValue !== undefined) {\n const valueBigInt = BigInt(clauseValue);\n if (valueBigInt > 0n) {\n const current = flowsByToken[zeroAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n current.outflow += valueBigInt;\n flowsByToken[zeroAddress] = current;\n }\n }\n\n // VET inflow: transfers where the recipient is the user\n for (const transfer of transfers) {\n const recipient = transfer.recipient.toLowerCase();\n\n if (recipient !== user) {\n continue;\n }\n\n const amount = BigInt(transfer.amount);\n if (amount <= 0n) {\n continue;\n }\n\n const current = flowsByToken[zeroAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n current.inflow += amount;\n flowsByToken[zeroAddress] = current;\n }\n\n return flowsByToken;\n};\n\n/**\n * Shared swap simulation logic used by all aggregators.\n * It:\n * - simulates the provided clauses\n * - computes gas cost\n * - accumulates ERC20 inflow/outflow for the user\n * - verifies that flows match amountIn and minimumOutputAmount when applicable\n * - verifies that no unexpected token outflows occur (only fromToken should have outflow)\n */\nexport const simulateSwapWithClauses = async (\n params: SwapParams,\n quote: SwapQuote,\n clauses: TransactionClause[],\n thor: ThorClient,\n): Promise<SwapSimulation> => {\n try {\n if (clauses.length === 0) {\n return {\n gasCostVTHO: 0,\n success: false,\n error: 'No clauses found for simulation',\n };\n }\n\n const simulatedTx = await thor.transactions.simulateTransaction(\n clauses,\n {\n caller: params.userAddress,\n },\n );\n\n let reverted = false;\n let revertReason: string | undefined;\n // Base gas cost for transaction overhead (VeChain transaction base cost)\n let totalGas = 200_000;\n\n const aggregatedFlows: Record<\n string,\n { inflow: bigint; outflow: bigint }\n > = {};\n\n for (let i = 0; i < simulatedTx.length; i++) {\n const result = simulatedTx[i];\n if (result.reverted) {\n reverted = true;\n revertReason = result.vmError || 'Transaction reverted';\n }\n\n totalGas += result.gasUsed;\n\n const clause = clauses[i];\n const flowsByToken = calculateTokenFlowsFromEvents(\n result.events,\n result.transfers,\n clause?.value,\n params.userAddress,\n );\n\n // Merge per-clause flows into the aggregated map\n for (const [token, flows] of Object.entries(flowsByToken)) {\n const current = aggregatedFlows[token] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n aggregatedFlows[token] = {\n inflow: current.inflow + flows.inflow,\n outflow: current.outflow + flows.outflow,\n };\n }\n }\n\n // If any clause reverted, keep behaviour consistent with previous implementation\n if (reverted) {\n return {\n gasCostVTHO: 0,\n success: false,\n error: revertReason || 'Transaction reverted',\n };\n }\n\n // Convert gas units to VTHO\n const gasCostVTHO = totalGas / 1e5;\n\n // Verify inflow/outflow for both ERC20 tokens and native VET.\n const fromIsVET = isVETAddress(params.fromTokenAddress);\n const toIsVET = isVETAddress(params.toTokenAddress);\n\n const expectedOutflow = BigInt(params.amountIn);\n\n // Outflow check: verify expected token outflow and ensure no other tokens have outflow\n if (fromIsVET) {\n const vetFlows = aggregatedFlows[zeroAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n\n if (vetFlows.outflow > expectedOutflow) {\n return {\n gasCostVTHO,\n success: false,\n error: `VET outflow mismatch: expected ${expectedOutflow.toString()}, got ${vetFlows.outflow.toString()}`,\n };\n }\n\n // Verify no other tokens have outflow, in case an approval was granted in a different transaction\n for (const [tokenAddress, flows] of Object.entries(\n aggregatedFlows,\n )) {\n if (tokenAddress !== zeroAddress && flows.outflow > 0n) {\n return {\n gasCostVTHO,\n success: false,\n error: `Unexpected token outflow: token ${tokenAddress} has outflow ${flows.outflow.toString()}, expected 0`,\n };\n }\n }\n } else {\n const fromTokenAddress = params.fromTokenAddress.toLowerCase();\n const tokenFlows = aggregatedFlows[fromTokenAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n\n if (tokenFlows.outflow > expectedOutflow) {\n return {\n gasCostVTHO,\n success: false,\n error: `Token outflow mismatch: expected ${expectedOutflow.toString()}, got ${tokenFlows.outflow.toString()}`,\n };\n }\n\n // Verify no other tokens (including VET) have outflow\n for (const [tokenAddress, flows] of Object.entries(\n aggregatedFlows,\n )) {\n if (tokenAddress !== fromTokenAddress && flows.outflow > 0n) {\n const tokenName =\n tokenAddress === zeroAddress ? 'VET' : tokenAddress;\n return {\n gasCostVTHO,\n success: false,\n error: `Unexpected token outflow: ${tokenName} has outflow ${flows.outflow.toString()}, expected 0`,\n };\n }\n }\n }\n\n // Inflow check (only when minimumOutputAmount is present)\n if (quote.minimumOutputAmount && quote.minimumOutputAmount > 0n) {\n if (toIsVET) {\n const vetFlows = aggregatedFlows[zeroAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n\n if (vetFlows.inflow < quote.minimumOutputAmount) {\n return {\n gasCostVTHO,\n success: false,\n error: `VET inflow mismatch: expected ${quote.minimumOutputAmount.toString()}, got ${vetFlows.inflow.toString()}`,\n };\n }\n } else {\n const toTokenAddress = params.toTokenAddress.toLowerCase();\n const tokenFlows = aggregatedFlows[toTokenAddress] ?? {\n inflow: 0n,\n outflow: 0n,\n };\n\n if (tokenFlows.inflow < quote.minimumOutputAmount) {\n return {\n gasCostVTHO,\n success: false,\n error: `Token inflow mismatch: expected ${quote.minimumOutputAmount.toString()}, got ${tokenFlows.inflow.toString()}`,\n };\n }\n }\n }\n\n return {\n gasCostVTHO,\n success: true,\n };\n } catch (error) {\n return {\n gasCostVTHO: 0,\n success: false,\n error: error instanceof Error ? error.message : 'Simulation failed',\n };\n }\n};\n","import { TransactionClause } from '@vechain/sdk-core';\nimport type { SwapAggregator, SwapQuote, SwapSimulation, SwapParams } from '../../types/swap';\nimport { NETWORK_TYPE } from '../../config/network';\nimport { ThorClient } from '@vechain/sdk-network';\nimport React from 'react';\nimport { encodeFunctionData } from 'viem';\nimport type { Abi, AbiFunction } from 'viem';\nimport { simulateSwapWithClauses } from './simulateSwap';\n\n/**\n * API response structure from VeTrade API\n */\ninterface APIQuoteResponse {\n amountOut: string;\n amountOutMin: string;\n clauses: Array<{\n to: string;\n value: string;\n comment?: string;\n functionCall: {\n functionName?: string; // API may use functionName\n name?: string; // Or name\n abi: Abi | Array<{\n name: string;\n type: string;\n internalType?: string;\n components?: Array<{\n name: string;\n type: string;\n internalType?: string;\n }>;\n }>; // ABI may be just inputs array or full ABI\n args: unknown[];\n };\n }>;\n path: string[];\n}\n\n/**\n * Configuration for an API-based aggregator\n */\nexport interface ApiAggregatorConfig {\n /**\n * Name of the aggregator (e.g., \"VeTrade\")\n */\n name: string;\n /**\n * Base URL for the API endpoint\n */\n apiBaseUrl: string;\n /**\n * Network type (main, test, or solo)\n */\n network: NETWORK_TYPE;\n /**\n * Icon component factory function\n * @param boxSize Size of the icon (e.g., \"20px\", \"24px\")\n * @returns React element representing the aggregator icon\n */\n getIcon: (boxSize?: string) => React.ReactElement;\n /**\n * List of supported contract addresses for interaction\n * Clauses will be filtered to only include those targeting these addresses\n */\n supportedAddresses?: string[];\n}\n\n/**\n * Convert hex value to decimal string for TransactionClause\n * TransactionClause expects value as a string representation of the number\n */\nconst hexToDecimalString = (hexValue: string): string => {\n if (!hexValue.startsWith('0x')) {\n return hexValue;\n }\n return BigInt(hexValue).toString();\n};\n\n/**\n * Convert inputs array to full function ABI format expected by viem\n */\nconst buildFunctionABI = (\n functionName: string,\n inputs: Array<{\n name: string;\n type: string;\n internalType?: string;\n components?: Array<{\n name: string;\n type: string;\n internalType?: string;\n }>;\n }>\n): AbiFunction => {\n return {\n name: functionName,\n type: 'function',\n inputs: inputs.map(input => ({\n name: input.name,\n type: input.type,\n internalType: input.internalType,\n components: input.components,\n })),\n outputs: [], // Empty outputs array for encoding (not needed for encoding)\n stateMutability: 'nonpayable',\n };\n};\n\n/**\n * Normalize ABI to full function format if needed\n */\nconst normalizeABI = (\n abi: APIQuoteResponse['clauses'][0]['functionCall']['abi'],\n functionName: string\n): Abi => {\n // Check if ABI is already in full format (has function definitions)\n if (Array.isArray(abi) && abi.length > 0) {\n const firstItem = abi[0];\n\n // If it's already a function definition with name and type, return as is\n if (typeof firstItem === 'object' && 'name' in firstItem && 'type' in firstItem && firstItem.type === 'function') {\n return abi as unknown as Abi;\n }\n\n // Check if this is an inputs array (has name/type but not function structure)\n // An inputs array item will have name/type but won't have stateMutability or outputs\n if (typeof firstItem === 'object' && 'name' in firstItem && 'type' in firstItem) {\n const hasFunctionStructure = 'stateMutability' in firstItem || 'outputs' in firstItem;\n if (!hasFunctionStructure) {\n // This is likely just the inputs array, convert to full function ABI\n const inputsArray = abi as unknown as Array<{\n name: string;\n type: string;\n internalType?: string;\n components?: Array<{\n name: string;\n type: string;\n internalType?: string;\n }>;\n }>;\n const functionABI = buildFunctionABI(functionName, inputsArray);\n return [functionABI] as Abi;\n }\n }\n }\n\n // Return as is if already in correct format\n return abi as unknown as Abi;\n};\n\n/**\n * Encode function call data using ABI, function name, and arguments\n */\nconst encodeFunctionCallData = (functionCall: APIQuoteResponse['clauses'][0]['functionCall']): string => {\n try {\n // Get function name from either functionName or name field\n const functionName = functionCall.functionName || functionCall.name;\n\n if (!functionName) {\n throw new Error('Function name is required (either functionName or name must be provided)');\n }\n\n // Normalize ABI to full function format\n const normalizedABI = normalizeABI(functionCall.abi, functionName);\n\n // Use viem's encodeFunctionData to encode the function call\n return encodeFunctionData({\n abi: normalizedABI,\n functionName: functionName,\n args: functionCall.args,\n });\n } catch (error) {\n console.error('Failed to encode function call:', error);\n const functionName = functionCall.functionName || functionCall.name || 'unknown';\n throw new Error(`Failed to encode function call ${functionName}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n};\n\n/**\n * Convert API clause format to TransactionClause format\n * Encodes function call data locally using the provided ABI, function name, and arguments\n */\nconst convertApiClauseToTransactionClause = (apiClause: APIQuoteResponse['clauses'][0]): TransactionClause => {\n // Encode the function call data locally\n const encodedData = encodeFunctionCallData(apiClause.functionCall);\n\n return {\n to: apiClause.to,\n value: hexToDecimalString(apiClause.value),\n data: encodedData,\n comment: apiClause.comment || `Swap on aggregator`,\n };\n};\n\n/**\n * Create a SwapAggregator instance that fetches quotes from an API\n */\nexport const createApiAggregator = (config: ApiAggregatorConfig): SwapAggregator => {\n const aggregator: SwapAggregator = {\n name: config.name,\n getIcon: config.getIcon,\n\n async getQuote(params: SwapParams, _thor: ThorClient): Promise<SwapQuote> {\n try {\n // Build query parameters\n const queryParams = new URLSearchParams({\n fromAddress: params.fromTokenAddress,\n toAddress: params.toTokenAddress,\n amountIn: params.amountIn,\n recipient: params.userAddress,\n slippageBps: String((params.slippageTolerance || 1) * 100), // Convert percentage to basis points\n network: config.network,\n });\n\n // Fetch quote from API\n const quoteUrl = new URL(config.apiBaseUrl);\n quoteUrl.search = queryParams.toString();\n const response = await fetch(quoteUrl);\n\n if (!response.ok) {\n throw new Error(`API request failed: ${response.status} ${response.statusText}`);\n }\n\n const quoteData: APIQuoteResponse = await response.json();\n\n // Convert API clauses to TransactionClause format\n const clauses = quoteData.clauses.map(convertApiClauseToTransactionClause);\n\n // Convert amounts to bigint\n const outputAmount = BigInt(quoteData.amountOut);\n const minimumOutputAmount = BigInt(quoteData.amountOutMin);\n\n return {\n aggregatorName: config.name,\n aggregator,\n outputAmount,\n minimumOutputAmount,\n priceImpact: 0,\n data: {\n clauses,\n path: quoteData.path,\n },\n };\n } catch (error) {\n console.error(`${config.name} getQuote failed:`, error);\n // Return empty quote on error\n return {\n aggregatorName: config.name,\n aggregator,\n outputAmount: 0n,\n priceImpact: 0,\n minimumOutputAmount: 0n,\n data: {\n clauses: [],\n path: [],\n },\n };\n }\n },\n\n async simulateSwap(params: SwapParams, quote: SwapQuote, thor: ThorClient): Promise<SwapSimulation> {\n try {\n // Build transaction clauses using the same logic as buildSwapTransaction\n // This ensures simulation uses the same filtered clauses that will be executed\n const clauses = await this.buildSwapTransaction(params, quote);\n\n // Delegate to shared simulation helper that also verifies ERC20 inflow/outflow\n return simulateSwapWithClauses(params, quote, clauses, thor);\n } catch (error) {\n return {\n gasCostVTHO: 0,\n success: false,\n error: error instanceof Error ? error.message : 'Failed to build swap transaction for simulation',\n };\n }\n },\n\n async buildSwapTransaction(params: SwapParams, quote: SwapQuote): Promise<TransactionClause[]> {\n\n // Extract clauses from quote data\n if (!quote.data || typeof quote.data !== 'object' || !('clauses' in quote.data)) {\n throw new Error('Invalid quote data: clauses not found');\n }\n\n let clauses = quote.data.clauses as TransactionClause[];\n\n if (clauses.length === 0) {\n throw new Error('No clauses found in quote');\n }\n\n // Filter clauses to only include those targeting supported addresses\n if (config.supportedAddresses && config.supportedAddresses.length > 0) {\n const supportedAddressesLower = config.supportedAddresses.map(addr => addr.toLowerCase());\n clauses = clauses.filter(clause => {\n if (!clause.to) return false;\n return supportedAddressesLower.includes(clause.to.toLowerCase());\n });\n\n if (clauses.length === 0) {\n throw new Error('No clauses found matching supported addresses');\n }\n }\n\n // Validate minimum output amount\n if (!quote.minimumOutputAmount || quote.minimumOutputAmount === 0n) {\n throw new Error('Invalid quote: minimumOutputAmount is missing or zero');\n }\n\n // Return the filtered clauses from the API response\n // These clauses are already in the correct format for execution\n return clauses;\n },\n };\n\n return aggregator;\n};\n","import type { SwapAggregator, SwapParams, SwapQuote, SwapSimulation } from '../../types/swap';\nimport { NETWORK_TYPE } from '../../config/network';\nimport { type Address } from 'viem';\nimport { createApiAggregator } from './apiAggregator';\nimport { VeTradeLogo } from '../../assets/icons';\nimport React from 'react';\nimport { TransactionClause, ABIContract, Clause, Address as VeChainAddress, VET, Units } from '@vechain/sdk-core';\nimport { IERC20__factory } from '@vechain/vechain-contract-types';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { simulateSwapWithClauses } from './simulateSwap';\nimport { VETRADE_BASE_URL } from '../../constants';\n\n/**\n * VeTrade supported addresses for different networks\n * These addresses are used to filter clauses from the API response\n */\nconst VETRADE_ADDRESSES: Record<NETWORK_TYPE, { supportedAddresses: Address[] }> = {\n main: {\n supportedAddresses: [\n '0xE5fA980a6EfE5B79C2150a529da06AeF455963b6' as Address, // Uniswap compatible Router\n '0x7C755EC0165fCD926cC6faB10E7BB16a72E9f34A' as Address // Custom Router\n ],\n },\n test: {\n supportedAddresses: [],\n },\n solo: {\n supportedAddresses: [],\n },\n};\n\n/**\n * Helper to check if token is VET (native token)\n */\nconst isVET = (address: string): boolean => {\n return address === '0x' || address === '0x0000000000000000000000000000000000000000';\n};\n\n/**\n * Get VeTrade API base URL for a specific network\n */\nconst getVeTradeApiUrl = (_networkType: NETWORK_TYPE): string => {\n // Currently same endpoint across environments; keep signature for future overrides.\n return new URL('api/quote/vck', VETRADE_BASE_URL).toString();\n};\n\n/**\n * Create VeTrade aggregator instance for a specific network\n *\n * VeTrade uses an API-based aggregator that returns clauses with function calls\n * that are encoded locally. Only clauses targeting supported addresses are used.\n *\n * @param networkType - The network type (main, test, or solo)\n * @returns SwapAggregator instance configured for the specified network\n */\nexport const createVeTradeAggregator = (networkType: NETWORK_TYPE): SwapAggregator => {\n const addresses = VETRADE_ADDRESSES[networkType] ?? VETRADE_ADDRESSES['main'];\n\n // Create base API aggregator with supported addresses\n const baseAggregator = createApiAggregator({\n name: 'VeTrade.vet',\n apiBaseUrl: getVeTradeApiUrl(networkType),\n network: networkType,\n getIcon: (boxSize = '20px') => React.createElement(VeTradeLogo, { boxSize }),\n supportedAddresses: addresses.supportedAddresses,\n });\n\n // Wrap the aggregator to add approve clause when needed\n const aggregator: SwapAggregator = {\n ...baseAggregator,\n\n async simulateSwap(params: SwapParams, quote: SwapQuote, thor: ThorClient): Promise<SwapSimulation> {\n try {\n // Build transaction clauses for simulation (includes approve clause if needed)\n // This ensures simulation uses the same clauses that will be executed\n const clauses = await this.buildSwapTransaction(params, quote);\n\n // Delegate to shared simulation helper that also verifies ERC20 inflow/outflow\n return simulateSwapWithClauses(params, quote, clauses, thor);\n } catch (error) {\n return {\n gasCostVTHO: 0,\n success: false,\n error: error instanceof Error ? error.message : 'Simulation failed',\n };\n }\n },\n\n async buildSwapTransaction(params: SwapParams, quote: SwapQuote): Promise<TransactionClause[]> {\n const clauses: TransactionClause[] = [];\n\n // Get clauses from base aggregator (already filtered by supported addresses)\n const baseClauses = await baseAggregator.buildSwapTransaction(params, quote);\n\n if(!baseClauses || baseClauses.length === 0) {\n throw new Error('Failed to build swap transaction');\n }\n\n // Check if fromToken is VET (native token)\n const isFromVET = isVET(params.fromTokenAddress);\n\n // If fromToken is not VET, add approve clause as first clause\n if (!isFromVET) {\n // Get the router address from supported addresses (first address is typically the router)\n if (addresses.supportedAddresses.length === 0) {\n throw new Error('No supported addresses configured for VeTrade on this network');\n }\n const tokenABI = ABIContract.ofAbi(IERC20__factory.abi);\n const fromTokenAddress = VeChainAddress.of(params.fromTokenAddress);\n const amountIn = BigInt(params.amountIn);\n\n // Add approval clause: approve router to spend amountIn\n clauses.push(\n Clause.callFunction(\n fromTokenAddress,\n tokenABI.getFunction('approve'),\n [\n baseClauses[0].to,\n amountIn.toString(),\n ],\n VET.of(0n, Units.wei),\n {\n comment: `Approve ${quote.aggregatorName} to access ${params.fromTokenAddress}`,\n }\n ),\n );\n }\n else {\n baseClauses[0].value = params.amountIn\n }\n\n // Add base clauses after approve clause\n clauses.push(...baseClauses);\n\n return clauses;\n },\n };\n\n return aggregator;\n};\n","import type {\n SwapAggregator,\n SwapParams,\n SwapQuote,\n SwapSimulation,\n} from '../../types/swap';\nimport {\n IERC20__factory,\n UniswapV2Router02__factory as UniswapV2Router__factory,\n} from '@vechain/vechain-contract-types';\nimport {\n ABIContract,\n Clause,\n TransactionClause,\n Units,\n Address as VeChainAddress,\n VET,\n} from '@vechain/sdk-core';\nimport { ThorClient } from '@vechain/sdk-network';\nimport React from 'react';\nimport { Address } from 'viem';\nimport { simulateSwapWithClauses } from './simulateSwap';\n\n/**\n * Helper to check if token is VET (native token)\n */\nconst isVET = (address: string): boolean => {\n return (\n address === '0x' ||\n address === '0x0000000000000000000000000000000000000000'\n );\n};\n\n/**\n * Helper to get deadline (20 minutes from now)\n */\nconst getDeadline = (): bigint => {\n return BigInt(Math.floor(Date.now() / 1000) + 20 * 60);\n};\n\n/**\n * Configuration for a Uniswap V2 compatible aggregator\n */\nexport interface UniswapV2AggregatorConfig {\n /**\n * Name of the aggregator (e.g., \"BetterSwap\", \"VeTrade\")\n */\n name: string;\n /**\n * Router contract address\n */\n routerAddress: Address;\n /**\n * Wrapped VET (WVET) contract address\n * Used in swap paths instead of native VET address\n */\n wrappedVET: Address;\n /**\n * Icon component factory function\n * @param boxSize Size of the icon (e.g., \"20px\", \"24px\")\n * @returns React element representing the aggregator icon\n */\n getIcon: (boxSize?: string) => React.ReactElement;\n}\n\n/**\n * Create a SwapAggregator instance for a Uniswap V2 compatible router\n */\nexport const createUniswapV2Aggregator = (\n config: UniswapV2AggregatorConfig,\n): SwapAggregator => {\n const aggregator: SwapAggregator = {\n name: config.name,\n getIcon: config.getIcon,\n\n async getQuote(\n params: SwapParams,\n thor: ThorClient,\n ): Promise<SwapQuote> {\n // Use wrapped VET in paths instead of native VET address\n const path: Address[] = [\n isVET(params.fromTokenAddress)\n ? config.wrappedVET\n : (params.fromTokenAddress as Address),\n isVET(params.toTokenAddress)\n ? config.wrappedVET\n : (params.toTokenAddress as Address),\n ];\n\n const amountInBigInt = BigInt(params.amountIn);\n\n try {\n // Call getAmountsOut on the router contract\n const contract = thor.contracts.load(\n config.routerAddress,\n UniswapV2Router__factory.abi,\n );\n const [amounts] = await contract.read.getAmountsOut(\n amountInBigInt,\n path,\n );\n\n // Handle both array and single value responses\n const amountsArray = Array.isArray(amounts)\n ? amounts\n : [amounts];\n const outputAmount = amountsArray[amountsArray.length - 1];\n\n // Ensure we have a valid output amount\n if (!outputAmount || outputAmount === 0n) {\n throw new Error('Output amount is zero or invalid');\n }\n\n // Validate that outputAmount is a bigint\n if (typeof outputAmount !== 'bigint') {\n throw new Error('Output amount is not a valid bigint');\n }\n\n // Calculate minimum output with slippage\n // slippageTolerance is in percentage (e.g., 1 = 1%)\n // For 1% slippage: multiplier = 10000 - 100 = 9900 (99% of output)\n const slippageTolerancePercent = params.slippageTolerance || 1;\n const slippageMultiplier = BigInt(\n 10000 - slippageTolerancePercent * 100,\n );\n const minimumOutputAmount =\n (outputAmount * slippageMultiplier) / BigInt(10000);\n\n return {\n aggregatorName: config.name,\n aggregator,\n outputAmount,\n priceImpact: 0,\n minimumOutputAmount,\n data: {\n path,\n routerAddress: config.routerAddress,\n },\n };\n } catch (error) {\n console.error(`${config.name} getQuote failed:`, error);\n // Return empty quote on error\n return {\n aggregatorName: config.name,\n aggregator,\n outputAmount: 0n,\n priceImpact: 0,\n minimumOutputAmount: 0n,\n data: {\n path,\n routerAddress: config.routerAddress,\n },\n };\n }\n },\n\n async simulateSwap(\n params: SwapParams,\n quote: SwapQuote,\n thor: ThorClient,\n ): Promise<SwapSimulation> {\n // Build transaction clauses using existing logic\n const clauses = await this.buildSwapTransaction(params, quote);\n\n // Delegate to shared simulation helper that also verifies ERC20 inflow/outflow\n return simulateSwapWithClauses(params, quote, clauses, thor);\n },\n\n async buildSwapTransaction(\n params: SwapParams,\n quote: SwapQuote,\n ): Promise<TransactionClause[]> {\n if (\n !quote.data ||\n typeof quote.data !== 'object' ||\n !('path' in quote.data)\n ) {\n throw new Error('Invalid quote data');\n }\n\n const deadline = getDeadline();\n\n // Ensure minimumOutputAmount is set and not zero\n if (\n !quote.minimumOutputAmount ||\n quote.minimumOutputAmount === 0n\n ) {\n throw new Error(\n 'Invalid quote: minimumOutputAmount is missing or zero',\n );\n }\n\n const amountOutMin = quote.minimumOutputAmount;\n const amountIn = BigInt(params.amountIn);\n\n // Additional validation: amountOutMin should be positive\n if (amountOutMin === 0n) {\n throw new Error('Invalid quote: minimumOutputAmount is zero');\n }\n\n const isFromVET = isVET(params.fromTokenAddress);\n const isToVET = isVET(params.toTokenAddress);\n\n const routerABI = ABIContract.ofAbi(UniswapV2Router__factory.abi);\n const clauses: TransactionClause[] = [];\n\n if (isFromVET) {\n // Swap VET (native) for tokens using swapExactETHForTokens\n // Note: amountIn is sent as value (VET), amountOutMin is first parameter\n clauses.push(\n Clause.callFunction(\n VeChainAddress.of(config.routerAddress),\n routerABI.getFunction('swapExactETHForTokens'),\n [\n amountOutMin.toString(),\n quote.data.path,\n params.userAddress,\n deadline.toString(),\n ],\n VET.of(amountIn, Units.wei),\n {\n comment: `Swap on ${quote.aggregatorName}`,\n },\n ),\n );\n } else {\n // From token is an ERC20 token, need to approve the router first\n const tokenABI = ABIContract.ofAbi(IERC20__factory.abi);\n const fromTokenAddress = VeChainAddress.of(\n params.fromTokenAddress,\n );\n const routerAddress = VeChainAddress.of(config.routerAddress);\n\n // Add approval clause: approve router to spend amountIn\n clauses.push(\n Clause.callFunction(\n fromTokenAddress,\n tokenABI.getFunction('approve'),\n [routerAddress.toString(), amountIn.toString()],\n VET.of(0n, Units.wei),\n {\n comment: `Swap on ${quote.aggregatorName}`,\n },\n ),\n );\n\n // Swap tokens: either for other tokens or for VET\n if (isToVET) {\n // Swap tokens for VET using swapExactTokensForETH\n clauses.push(\n Clause.callFunction(\n routerAddress,\n routerABI.getFunction('swapExactTokensForETH'),\n [\n amountIn.toString(),\n amountOutMin.toString(),\n quote.data.path,\n params.userAddress,\n deadline.toString(),\n ],\n VET.of(0n, Units.wei),\n {\n comment: `Swap on ${quote.aggregatorName}`,\n },\n ),\n );\n } else {\n // Swap tokens for tokens using swapExactTokensForTokens\n clauses.push(\n Clause.callFunction(\n routerAddress,\n routerABI.getFunction('swapExactTokensForTokens'),\n [\n amountIn.toString(),\n amountOutMin.toString(),\n quote.data.path,\n params.userAddress,\n deadline.toString(),\n ],\n VET.of(0n, Units.wei),\n {\n comment: `Swap on ${quote.aggregatorName}`,\n },\n ),\n );\n }\n }\n\n return clauses;\n },\n };\n\n return aggregator;\n};\n","import type { SwapAggregator } from '../../types/swap';\nimport { NETWORK_TYPE } from '../../config/network';\nimport { zeroAddress, type Address } from 'viem';\nimport { createUniswapV2Aggregator } from './uniswapV2Aggregator';\nimport { BetterSwapLogo } from '../../assets/icons';\nimport React from 'react';\n\n/**\n * BetterSwap router and wrapped VET addresses for different networks\n */\nconst BETTERSWAP_ADDRESSES: Record<NETWORK_TYPE, { routerAddress: Address; wrappedVET: Address }> = {\n main: {\n routerAddress: '0xf21Dd7108D93af56FaB07423EfB90F4a3604DA89' as Address,\n wrappedVET: '0xf9b02b47694fd635A413F16dC7B38aF06Cc16fe5' as Address,\n },\n test: {\n routerAddress: zeroAddress,\n wrappedVET: zeroAddress,\n },\n solo: {\n routerAddress: zeroAddress,\n wrappedVET: zeroAddress,\n },\n};\n\n/**\n * Create BetterSwap aggregator instance for a specific network\n * \n * BetterSwap Router Contract addresses vary by network\n * Uses Uniswap V2 compatible interface\n * \n * @param networkType - The network type (main, test, or solo)\n * @returns SwapAggregator instance configured for the specified network\n */\nexport const createBetterSwapAggregator = (networkType: NETWORK_TYPE): SwapAggregator => {\n const addresses = BETTERSWAP_ADDRESSES[networkType] ?? BETTERSWAP_ADDRESSES['main'];\n \n return createUniswapV2Aggregator({\n name: 'BetterSwap.io',\n routerAddress: addresses.routerAddress,\n wrappedVET: addresses.wrappedVET,\n getIcon: (boxSize = '20px') => React.createElement(BetterSwapLogo, { boxSize }),\n });\n};\n","import type { SwapAggregator } from '../types/swap';\nimport { NETWORK_TYPE } from './network';\nimport { createVeTradeAggregator } from '../utils/swap/veTrade';\nimport { createBetterSwapAggregator } from '../utils/swap/betterSwap';\n\n/**\n * Get swap aggregators for a specific network\n * \n * Add or remove aggregators by importing their modules and adding them to this array.\n * Each aggregator module must export a function or object implementing the SwapAggregator interface.\n * \n * @param networkType - The network type (main, test, or solo)\n * @returns Array of SwapAggregator instances configured for the specified network\n */\nexport const getSwapAggregators = (networkType: NETWORK_TYPE): SwapAggregator[] => [\n createVeTradeAggregator(networkType),\n createBetterSwapAggregator(networkType),\n];\n\n","import { useQuery } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { getSwapAggregators } from '../../../config/swapAggregators';\nimport type { SwapParams, SwapQuote } from '../../../types/swap';\nimport { parseUnits, zeroAddress } from 'viem';\nimport { useOptionalThor } from '../dappkit/useOptionalThor';\nimport { useGetCustomTokenInfo } from '../wallet/useGetCustomTokenInfo';\n// Direct import to avoid circular dependency through barrel exports\nimport { TokenWithValue } from '../wallet/useTokensWithValues';\nimport { useWallet } from '../wallet/useWallet';\n\nexport type UnifiedSwapQuotesResult = {\n bestQuote: SwapQuote | null;\n quotes: SwapQuote[];\n isLoading: boolean;\n error: unknown;\n from: TokenWithValue & {\n address: string;\n decimals: number;\n } | null;\n to: TokenWithValue & {\n address: string;\n decimals: number;\n } | null;\n};\n\n/**\n * Unified hook: fetches quotes from all aggregators, simulates each, returns\n * - bestQuote (filtered against reverts when at least one succeeds)\n * - quotes: full list with revert flags and gas\n */\nexport const useSwapQuotes = (\n fromToken: TokenWithValue | null,\n toToken: TokenWithValue | null,\n amountIn: string,\n userAddress: string,\n slippageTolerance: number = 1,\n enabled: boolean = true,\n): UnifiedSwapQuotesResult => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { connection } = useWallet();\n\n // Use on-chain token decimals for correct parsing of amountIn, pass empty string to not let it fetch details for VET\n const fromTokenAddress = fromToken?.address ?? null;\n const toTokenAddress = toToken?.address ?? null;\n const { data: fromTokenInfo } = useGetCustomTokenInfo(fromTokenAddress === '0x' || fromTokenAddress === zeroAddress || !fromTokenAddress ? '' : fromTokenAddress);\n const { data: toTokenInfo } = useGetCustomTokenInfo(toTokenAddress === '0x' || toTokenAddress === zeroAddress || !toTokenAddress ? '' : toTokenAddress);\n\n const fromTokenDecimals = useMemo(() => {\n if (!fromTokenAddress || fromTokenAddress === '0x' || fromTokenAddress === zeroAddress || !fromTokenInfo) return 18;\n return Number(fromTokenInfo?.decimals ?? 18);\n }, [fromTokenAddress, fromTokenInfo?.decimals]);\n\n const toTokenDecimals = useMemo(() => {\n if (!toTokenAddress || toTokenAddress === '0x' || toTokenAddress === zeroAddress || !toTokenInfo) return 18;\n return Number(toTokenInfo?.decimals ?? 18);\n }, [toTokenAddress, toTokenInfo?.decimals]);\n\n const params: SwapParams | null = useMemo(() => {\n if (!fromTokenAddress || !toTokenAddress || !amountIn || !userAddress) return null;\n\n\n let amountInRaw: bigint;\n try {\n amountInRaw = parseUnits(amountIn, fromTokenDecimals)\n } catch (error) {\n console.error('Failed to parse amount:', amountIn, error);\n return null;\n }\n\n if (amountInRaw <= 0n) return null;\n\n return {\n fromTokenAddress,\n toTokenAddress,\n amountIn: amountInRaw.toString(),\n userAddress,\n slippageTolerance,\n };\n }, [fromTokenAddress, toTokenAddress, amountIn, userAddress, slippageTolerance, fromTokenDecimals]);\n\n const { data, isLoading, error } = useQuery<{ quotes: SwapQuote[]; best: SwapQuote | null }>({\n queryKey: ['unified-swap-quotes', params, connection.network],\n queryFn: async () => {\n if (!params || !thor || !connection.network) return { quotes: [], best: null };\n\n const aggregators = getSwapAggregators(connection.network);\n const quotePromises = aggregators.map(async (aggregator) => {\n try {\n const quote = await aggregator.getQuote(params, thor);\n try {\n const simulation = await aggregator.simulateSwap(params, quote, thor);\n const enrichedQuote: SwapQuote = {\n ...quote,\n aggregator,\n reverted: !simulation.success,\n revertReason: simulation.error,\n gasCostVTHO: simulation.gasCostVTHO,\n };\n return enrichedQuote;\n } catch (simError) {\n console.error(`Failed to simulate swap for ${aggregator.name}:`, simError);\n const enrichedQuote: SwapQuote = {\n ...quote,\n aggregator,\n reverted: true,\n revertReason: simError instanceof Error ? simError.message : 'Simulation failed',\n gasCostVTHO: 0,\n };\n return enrichedQuote;\n }\n } catch (error) {\n console.error(`Failed to get quote from ${aggregator.name}:`, error);\n return null;\n }\n });\n\n const quotes = (await Promise.all(quotePromises)).filter(\n (q): q is SwapQuote => q !== null && q.outputAmount !== 0n,\n );\n\n // Decide best quote with revert-aware filtering\n let best: SwapQuote | null = null;\n if (quotes.length > 0) {\n const nonReverted = quotes.filter((q) => !(q.reverted ?? false));\n const candidates = nonReverted.length > 0 ? nonReverted : quotes;\n best = candidates.reduce((acc, cur) => {\n const a = BigInt(acc.outputAmount || '0');\n const b = BigInt(cur.outputAmount || '0');\n return b > a ? cur : acc;\n });\n }\n\n return { quotes, best };\n },\n enabled: enabled && params !== null && thor !== null && thor !== undefined,\n refetchInterval: 10000,\n });\n\n return {\n bestQuote: data?.best ?? null,\n quotes: data?.quotes ?? [],\n isLoading,\n error,\n from: fromToken ? {\n ...fromToken,\n address: fromTokenAddress ?? '',\n decimals: fromTokenDecimals,\n } : null,\n to: toToken ? {\n ...toToken,\n address: toTokenAddress ?? '',\n decimals: toTokenDecimals,\n } : null,\n };\n};\n\n\n","'use client';\n\n// Use static import to ensure we use the same module instance as LazyDAppKitProvider\n// This avoids ESM/CJS interop issues that can occur with require() in bundled contexts\nimport { useWalletModal } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n\n/**\n * Type for the optional DAppKitWalletModal hook return value.\n */\nexport type UseOptionalDAppKitWalletModalReturnType = {\n open: () => void;\n close: () => void;\n onConnectionStatusChange: (\n callback: (address: string | null, error?: Error) => void,\n ) => void;\n};\n\n// Default return value when DAppKit is not available\nconst DEFAULT_DAPPKIT_WALLET_MODAL_STATE: UseOptionalDAppKitWalletModalReturnType =\n {\n open: () => {\n console.warn(\n 'DAppKit is not configured. Add dappKit prop to VeChainKitContext to enable wallet modal.',\n );\n },\n close: () => {},\n onConnectionStatusChange: () => {},\n };\n\n/**\n * Optional hook to access DAppKit wallet modal context.\n * Returns default values when DAppKit is not configured, avoiding the need\n * to wrap every usage in a try-catch or conditional check.\n *\n * Uses static import to ensure the same module instance as LazyDAppKitProvider,\n * avoiding ESM/CJS interop issues that can occur with require().\n *\n * @returns DAppKit wallet modal functions, or default values if DAppKit is not configured\n */\nexport const useOptionalDAppKitWalletModal =\n (): UseOptionalDAppKitWalletModalReturnType => {\n const config = useVeChainKitConfig();\n const isDAppKitConfigured = !!config.dappKit;\n\n // Always call hooks unconditionally to satisfy React's rules of hooks\n let dappKitModalResult: ReturnType<typeof useWalletModal> | null = null;\n try {\n dappKitModalResult = useWalletModal();\n } catch {\n // Hook threw (no DAppKitProvider in tree), will use defaults\n }\n\n // If DAppKit is not configured, return defaults immediately\n if (!isDAppKitConfigured) {\n return DEFAULT_DAPPKIT_WALLET_MODAL_STATE;\n }\n\n // DAppKit is configured, return actual values (or defaults if hook threw)\n if (!dappKitModalResult) {\n return DEFAULT_DAPPKIT_WALLET_MODAL_STATE;\n }\n\n return dappKitModalResult;\n };\n","// Import from specific files to avoid circular dependencies\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\n// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\nimport { useOptionalDAppKitWalletModal } from '../api/dappkit/useOptionalDAppKitWalletModal';\nimport type { ConnectModalContentsTypes } from '../../types/modal';\n\nexport const useConnectModal = () => {\n const { loginMethods } = useVeChainKitConfig();\n const hasOnlyDappKit =\n loginMethods?.length === 1 && loginMethods[0].method === 'dappkit';\n\n const { openConnectModal, closeConnectModal, isConnectModalOpen } =\n useModal();\n\n // Use optional DAppKit wallet modal hook that handles missing provider gracefully\n const { open: openDappKit, close: closeDappKit } = useOptionalDAppKitWalletModal();\n\n return {\n open: hasOnlyDappKit\n ? openDappKit\n : (initialContent?: ConnectModalContentsTypes) =>\n openConnectModal(initialContent),\n close: hasOnlyDappKit ? closeDappKit : closeConnectModal,\n isOpen: hasOnlyDappKit ? false : isConnectModalOpen,\n };\n};\n\nexport const ConnectModalProvider = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useAccountModal = () => {\n const {\n openAccountModal: open,\n closeAccountModal: close,\n isAccountModalOpen: isOpen,\n } = useModal();\n return { open: () => open(), close, isOpen };\n};\n\nexport const AccountModalProvider = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useTransactionModal = () => {\n const {\n openTransactionModal: open,\n closeTransactionModal: close,\n isTransactionModalOpen: isOpen,\n } = useModal();\n return { open, close, isOpen };\n};\n\nexport const TransactionModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useTransactionToast = () => {\n const {\n openTransactionToast: open,\n closeTransactionToast: close,\n isTransactionToastOpen: isOpen,\n } = useModal();\n return { open, close, isOpen };\n};\n\nexport const TransactionToastProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Direct import to avoid circular dependency through hooks barrel\nimport { useWallet } from '../api/wallet/useWallet';\n// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useWalletModal = () => {\n const { connection } = useWallet();\n const {\n openConnectModal,\n closeConnectModal,\n isConnectModalOpen,\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n } = useModal();\n\n const open = (options?: AccountModalOptions) => {\n if (connection.isConnected) {\n openAccountModal(undefined, options);\n } else {\n openConnectModal();\n }\n };\n\n const close = () => {\n if (isAccountModalOpen) {\n closeAccountModal();\n }\n if (isConnectModalOpen) {\n closeConnectModal();\n }\n };\n\n const isOpen = isConnectModalOpen || isAccountModalOpen;\n\n return { open, close, isOpen };\n};\n\nexport const WalletModalProvider = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useChooseNameModal = () => {\n const {\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n setAccountModalContent,\n } = useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal(\n {\n type: 'choose-name',\n props: {\n setCurrentContent: setAccountModalContent,\n onBack: () => setAccountModalContent('main'),\n initialContentSource: 'main',\n },\n },\n options,\n );\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const ChooseNameModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useSendTokenModal = () => {\n const {\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n setAccountModalContent,\n } = useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal(\n {\n type: 'send-token',\n props: {\n setCurrentContent: setAccountModalContent,\n },\n },\n options,\n );\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const SendTokenModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\n// Local type alias to avoid circular dependency with components\n// The full type is defined in components/AccountModal/Types/Types.ts\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AccountModalContentTypes = any;\n\ntype SwapTokenModalOptions = {\n fromTokenAddress?: string;\n toTokenAddress?: string;\n isolatedView?: boolean;\n};\n\nexport const useSwapTokenModal = () => {\n const {\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n setAccountModalContent,\n } = useModal();\n\n const open = (options?: SwapTokenModalOptions) => {\n const props: any = {\n setCurrentContent: setAccountModalContent,\n fromTokenAddress: options?.fromTokenAddress,\n toTokenAddress: options?.toTokenAddress,\n };\n const content: AccountModalContentTypes = {\n type: 'swap-token',\n props,\n };\n const accountOptions: AccountModalOptions = {\n isolatedView: options?.isolatedView,\n };\n openAccountModal(content, accountOptions);\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const SwapTokenModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n\n\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useExploreEcosystemModal = () => {\n const { openAccountModal, closeAccountModal, isAccountModalOpen } =\n useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal('ecosystem', options);\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const ExploreEcosystemModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useNotificationsModal = () => {\n const { openAccountModal, closeAccountModal, isAccountModalOpen } =\n useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal('notifications', options);\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const NotificationsModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useFAQModal = () => {\n const {\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n setAccountModalContent,\n } = useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal(\n {\n type: 'faq',\n props: {\n onGoBack: () => setAccountModalContent('main'),\n showLanguageSelector: false,\n },\n },\n options,\n );\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const FAQModalProvider = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useAccountCustomizationModal = () => {\n const {\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n setAccountModalContent,\n } = useModal();\n\n const open = () => {\n openAccountModal({\n type: 'account-customization',\n props: {\n setCurrentContent: setAccountModalContent,\n },\n });\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const AccountCustomizationModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useReceiveModal = () => {\n const { openAccountModal, closeAccountModal, isAccountModalOpen } =\n useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal('receive-token', options);\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const ReceiveModalProvider = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\n","// Direct import to avoid circular dependency (providers barrel re-exports hooks)\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\nimport { VECHAIN_PRIVY_APP_ID } from '../../utils';\nimport { useMemo } from 'react';\n\ntype LoginModalContentConfig = {\n showGoogleLogin: boolean;\n showEmailLogin: boolean;\n showPasskey: boolean;\n showVeChainLogin: boolean;\n showDappKit: boolean;\n showEcosystem: boolean;\n showMoreLogin: boolean;\n showGithubLogin: boolean;\n isOfficialVeChainApp: boolean;\n};\n\nexport const useLoginModalContent = (): LoginModalContentConfig => {\n const { privy, loginMethods } = useVeChainKitConfig();\n const isVeChainApp = privy?.appId === VECHAIN_PRIVY_APP_ID;\n\n // Helper function to check if a login method is enabled\n const isLoginMethodEnabled = (method: string | string[]) => {\n if (!loginMethods) return true;\n\n if (Array.isArray(method)) {\n return method.some((m) =>\n loginMethods.some((lm) => lm.method === m),\n );\n }\n return loginMethods.some((lm) => lm.method === method);\n };\n\n // Memoized login method states\n const showEcosystemLogin = useMemo(() => {\n if (!loginMethods) return true;\n return loginMethods.length === 0 || isLoginMethodEnabled('ecosystem');\n }, [loginMethods]);\n\n const showLoginWithVeChain = useMemo(\n () => isLoginMethodEnabled('vechain'),\n [loginMethods],\n );\n const showLoginWithDappKit = useMemo(\n () => isLoginMethodEnabled('dappkit'),\n [loginMethods],\n );\n const showLoginWithPasskey = useMemo(\n () => isLoginMethodEnabled('passkey'),\n [loginMethods],\n );\n const showLoginWithEmail = useMemo(\n () => isLoginMethodEnabled('email'),\n [loginMethods],\n );\n const showLoginWithGoogle = useMemo(\n () => isLoginMethodEnabled('google'),\n [loginMethods],\n );\n const showMoreLogin = useMemo(\n () => isLoginMethodEnabled('more'),\n [loginMethods],\n );\n const showLoginWithGithub = useMemo(\n () => isLoginMethodEnabled('github'),\n [loginMethods],\n );\n\n // Base configuration that's common across all cases\n const baseConfig: LoginModalContentConfig = {\n showGoogleLogin: showLoginWithGoogle,\n showEmailLogin: showLoginWithEmail,\n showPasskey: showLoginWithPasskey,\n showVeChainLogin: showLoginWithVeChain,\n showDappKit: showLoginWithDappKit,\n showEcosystem: showEcosystemLogin,\n showMoreLogin: showMoreLogin,\n showGithubLogin: showLoginWithGithub,\n isOfficialVeChainApp: false,\n };\n\n if (!privy) {\n // External apps (no self hosted privy)\n return {\n ...baseConfig,\n showGoogleLogin: false,\n showEmailLogin: false,\n showPasskey: false,\n showMoreLogin: false,\n };\n }\n\n if (isVeChainApp) {\n // VeChain app (using self hosted privy)\n return {\n ...baseConfig,\n isOfficialVeChainApp: true,\n };\n }\n\n // Self hosted privy app\n return {\n ...baseConfig,\n };\n};\n","// Import from types/modal to avoid circular dependency with components\nimport type { UpgradeSmartAccountModalStyle } from '../../types/modal';\n// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useUpgradeSmartAccountModal = (\n style?: UpgradeSmartAccountModalStyle,\n) => {\n const {\n openUpgradeSmartAccountModal: open,\n closeUpgradeSmartAccountModal: close,\n isUpgradeSmartAccountModalOpen: isOpen,\n } = useModal();\n return { open: () => open(style), close, isOpen };\n};\n\nexport const UpgradeSmartAccountModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useProfileModal = () => {\n const { openAccountModal, closeAccountModal, isAccountModalOpen } =\n useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal('profile', options);\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const ProfileModalProvider = ({ children }: { children: ReactNode }) => (\n <>{children}</>\n);\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal } from '../../providers/ModalContext';\n\nexport const useAccountModalOptions = () => {\n const { isolatedView, closeAccountModal } = useModal();\n\n return {\n isolatedView,\n closeAccountModal,\n };\n};\n","// Import from ModalContext to avoid circular dependency with ModalProvider\nimport { useModal, AccountModalOptions } from '../../providers/ModalContext';\nimport { ReactNode } from 'react';\n\nexport const useSettingsModal = () => {\n const { openAccountModal, closeAccountModal, isAccountModalOpen } =\n useModal();\n\n const open = (options?: AccountModalOptions) => {\n openAccountModal('settings', options);\n };\n\n const close = () => {\n closeAccountModal();\n };\n\n return {\n open,\n close,\n isOpen: isAccountModalOpen,\n };\n};\n\nexport const SettingsModalProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => <>{children}</>;\n","// Local type alias to avoid circular dependency with components\n// The full type is defined in components/AccountModal/Types/Types.ts\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AccountModalContentTypes = any;\n\nexport type NotificationAction = {\n label: string;\n content: AccountModalContentTypes;\n};\n\nexport type Notification = {\n id: string;\n title: string;\n description: string;\n timestamp: number;\n status: 'success' | 'info' | 'warning' | 'error';\n isRead: boolean;\n action?: NotificationAction;\n};\n\n/**\n * Default notifications shown to new users.\n * Defined here to avoid circular dependency between useNotifications and useNotificationAlerts.\n */\nexport const DEFAULT_NOTIFICATIONS: Notification[] = [\n {\n id: 'welcome',\n title: 'Welcome to the VeChain',\n description:\n 'Welcome! Here you can manage your wallet, send tokens, and interact with the VeChain blockchain and its applications.',\n timestamp: Date.now(),\n status: 'success' as const,\n isRead: false,\n },\n];\n","import { useCallback, useEffect } from 'react';\n// Direct import to avoid circular dependency through hooks barrel\nimport { useWallet } from '../api/wallet/useWallet';\n// Import from types.ts to avoid circular dependency with useNotificationAlerts\nimport { Notification, DEFAULT_NOTIFICATIONS } from './types';\nimport { getLocalStorageItem, setLocalStorageItem, isBrowser } from '../../utils/ssrUtils';\n\nexport const useNotifications = () => {\n const { account } = useWallet();\n\n const getStorageKeys = useCallback((address?: string) => {\n const normalizedAddress = address?.toLowerCase();\n return {\n notifications: `vechain_kit_notifications_${normalizedAddress}`,\n archived: `vechain_kit_archived_notifications_${normalizedAddress}`,\n initialized: `vechain_kit_notifications_initialized_${normalizedAddress}`,\n };\n }, []);\n\n const initializeNotifications = useCallback(() => {\n if (!account?.address || !isBrowser()) return;\n\n const keys = getStorageKeys(account.address);\n const isInitialized = getLocalStorageItem(keys.initialized);\n\n if (!isInitialized) {\n setLocalStorageItem(\n keys.notifications,\n JSON.stringify(DEFAULT_NOTIFICATIONS),\n );\n setLocalStorageItem(keys.initialized, 'true');\n }\n }, [account?.address, getStorageKeys]);\n\n useEffect(() => {\n initializeNotifications();\n }, [initializeNotifications]);\n\n const getNotifications = useCallback((): Notification[] => {\n if (!account?.address || !isBrowser()) return [];\n\n const keys = getStorageKeys(account.address);\n const cached = getLocalStorageItem(keys.notifications);\n if (!cached) return [];\n return JSON.parse(cached) as Notification[];\n }, [account?.address, getStorageKeys]);\n\n const getArchivedNotifications = useCallback((): Notification[] => {\n if (!account?.address || !isBrowser()) return [];\n\n const keys = getStorageKeys(account.address);\n const cached = getLocalStorageItem(keys.archived);\n if (!cached) return [];\n return JSON.parse(cached) as Notification[];\n }, [account?.address, getStorageKeys]);\n\n const addNotification = useCallback(\n (notification: Omit<Notification, 'timestamp' | 'isRead'>) => {\n if (!account?.address || !isBrowser()) return;\n\n const keys = getStorageKeys(account.address);\n const notifications = getNotifications();\n const archivedCache = getLocalStorageItem(keys.archived);\n const archivedNotifications = archivedCache ? JSON.parse(archivedCache) : [];\n\n // Check if notification exists in either active or archived notifications\n const isDuplicate = [\n ...notifications,\n ...archivedNotifications,\n ].some((n) => n.title === notification.title);\n if (isDuplicate) return;\n\n const newNotification: Notification = {\n ...notification,\n id: notification.id || Math.random().toString(36).substring(7),\n timestamp: Date.now(),\n isRead: false,\n };\n setLocalStorageItem(\n keys.notifications,\n JSON.stringify([newNotification, ...notifications]),\n );\n },\n [account?.address, getNotifications, getStorageKeys],\n );\n\n const deleteNotification = useCallback(\n (notificationId: string) => {\n if (!account?.address || !isBrowser()) return;\n\n const keys = getStorageKeys(account.address);\n const notifications = getNotifications();\n const updatedNotifications = notifications.filter(\n (n) => n.id !== notificationId,\n );\n setLocalStorageItem(\n keys.notifications,\n JSON.stringify(updatedNotifications),\n );\n },\n [account?.address, getNotifications, getStorageKeys],\n );\n\n const clearAllNotifications = useCallback(() => {\n if (!account?.address || !isBrowser()) return;\n\n const keys = getStorageKeys(account.address);\n const notifications = getNotifications();\n setLocalStorageItem(\n keys.archived,\n JSON.stringify([...getArchivedNotifications(), ...notifications]),\n );\n setLocalStorageItem(keys.notifications, JSON.stringify([]));\n }, [\n account?.address,\n getNotifications,\n getArchivedNotifications,\n getStorageKeys,\n ]);\n\n const markAsRead = useCallback(\n (notificationId: string) => {\n if (!account?.address || !isBrowser()) return;\n\n const keys = getStorageKeys(account.address);\n const notifications = getNotifications();\n const archivedNotifications = getArchivedNotifications();\n\n // Find the notification to archive\n const notificationToArchive = notifications.find(\n (n) => n.id === notificationId,\n );\n\n // Update notifications list - remove the archived one\n const updatedNotifications = notifications.filter(\n (n) => n.id !== notificationId,\n );\n\n // Add to archived list if found\n if (notificationToArchive) {\n const updatedArchivedNotifications = [\n { ...notificationToArchive, isRead: true },\n ...archivedNotifications,\n ];\n\n // Update both lists in localStorage\n setLocalStorageItem(\n keys.notifications,\n JSON.stringify(updatedNotifications),\n );\n setLocalStorageItem(\n keys.archived,\n JSON.stringify(updatedArchivedNotifications),\n );\n }\n },\n [\n account?.address,\n getNotifications,\n getArchivedNotifications,\n getStorageKeys,\n ],\n );\n\n return {\n getNotifications,\n getArchivedNotifications,\n addNotification,\n clearAllNotifications,\n markAsRead,\n deleteNotification,\n };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { getConfig } from '../../../config';\nimport { ThorClient } from '@vechain/sdk-network';\n\nexport const getUpgradeRequiredForAccount = async (\n thor: ThorClient,\n contractAddress: string,\n targetVersion: number,\n networkType: NETWORK_TYPE,\n): Promise<boolean> => {\n const res = await thor.contracts\n .load(\n getConfig(networkType).accountFactoryAddress,\n SocialLoginSmartAccountFactory__factory.abi,\n )\n .read.upgradeRequiredForAccount(contractAddress, BigInt(targetVersion));\n\n if (!res)\n throw new Error(\n `Failed to get upgrade required for contract address ${contractAddress}`,\n );\n\n return res[0] as boolean;\n};\n\nexport const getUpgradeRequiredForAccountQueryKey = (\n contractAddress: string,\n targetVersion: number,\n networkType: NETWORK_TYPE,\n) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'FACTORY',\n 'NEEDS_UPGRADE_FOR_ACCOUNT',\n contractAddress,\n targetVersion,\n networkType,\n];\n\n/**\n * Check if a smart account needs an upgrade\n * @param contractAddress - The address of the smart account\n * @param targetVersion - The target version of the smart account\n * @returns True if the smart account needs an upgrade, false otherwise\n */\nexport const useUpgradeRequiredForAccount = (\n contractAddress: string,\n targetVersion: number,\n) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getUpgradeRequiredForAccountQueryKey(\n contractAddress,\n targetVersion,\n network.type,\n ),\n queryFn: async () =>\n getUpgradeRequiredForAccount(\n thor!,\n contractAddress,\n targetVersion,\n network.type,\n ),\n enabled:\n !!thor &&\n !!network &&\n !!contractAddress &&\n !!targetVersion &&\n contractAddress !== '',\n });\n};\n","import { useEffect } from 'react';\n// Direct imports to avoid circular dependency through hooks barrel\nimport { useWallet } from '../api/wallet/useWallet';\nimport { useNotifications } from './useNotifications';\nimport { useUpgradeRequiredForAccount } from '../thor/smartAccounts/useUpgradeRequiredForAccount';\nimport { useTranslation } from 'react-i18next';\n\n// Re-export for backward compatibility (moved to types.ts to avoid circular dependency)\nexport { DEFAULT_NOTIFICATIONS } from './types';\n\nexport const useNotificationAlerts = () => {\n const { t } = useTranslation();\n const { account, connection, smartAccount } = useWallet();\n const { addNotification, getNotifications } = useNotifications();\n\n // Check if smart account needs upgrade to version 3 (only for deployed smart accounts)\n const { data: upgradeRequired } = useUpgradeRequiredForAccount(\n smartAccount?.address ?? '',\n 3, // Target version\n );\n\n // Smart Account Upgrade Alert\n useEffect(() => {\n if (!connection.isConnectedWithPrivy || !account?.address) return;\n\n const notifications = getNotifications();\n const upgradeNotificationId = `smart_account_upgrade_${account.address.toLowerCase()}`;\n const hasUpgradeNotification = notifications.some(\n (n) => n.id === upgradeNotificationId,\n );\n\n // Show notification if upgrade is required and not already shown\n if (!hasUpgradeNotification && upgradeRequired) {\n addNotification({\n id: upgradeNotificationId,\n title: t('Account Upgrade Required'),\n description: t(\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\",\n ),\n status: 'warning',\n });\n }\n }, [connection.isConnectedWithPrivy, account?.address, upgradeRequired]);\n\n // Smart Account Alert\n useEffect(() => {\n if (!connection.isConnectedWithPrivy || !account?.address) return;\n\n const notifications = getNotifications();\n const hasSmartAccountNotification = notifications.some(\n (n) => n.id === `smart_account_${account.address.toLowerCase()}`,\n );\n\n if (!hasSmartAccountNotification) {\n addNotification({\n id: `smart_account_${account.address.toLowerCase()}`,\n title: t('Smart Account detected'),\n description: t(\n 'You have an active smart account associated to this wallet. It has been set as your main identity.',\n ),\n status: 'info',\n });\n }\n }, [connection.isConnectedWithPrivy, account?.address]);\n\n // Multiclause Support Alert\n useEffect(() => {\n if (!connection.isConnectedWithPrivy || !account?.address) return;\n\n const notifications = getNotifications();\n // Only shows the new \"now supported\" notification to users who have seen the warning\n const hasMulticlauseWarning = notifications.some(\n (n) =>\n n.id === `multiclause_warning_${account.address.toLowerCase()}`,\n );\n const hasMulticlauseSupport = notifications.some(\n (n) =>\n n.id === `multiclause_support_${account.address.toLowerCase()}`,\n );\n\n // Only show the support notification if they had the warning before\n // and don't already have the support notification\n if (hasMulticlauseWarning && !hasMulticlauseSupport) {\n addNotification({\n id: `multiclause_support_${account.address.toLowerCase()}`,\n title: t('Multiclause Transactions Are Now Supported'),\n description: t(\n 'Good news! Multiclause transactions are now fully supported for smart accounts. You can now enjoy a better user experience, lower gas costs, and enchanced security.',\n ),\n status: 'info',\n });\n }\n }, [connection.isConnectedWithPrivy, account?.address]);\n\n // Add more notification alerts here\n // Example:\n // useEffect(() => {\n // if (!someCondition) return;\n // const notifications = getNotifications();\n // if (!notifications.some(n => n.id === 'some_notification_id')) {\n // addNotification({\n // id: 'some_notification_id',\n // title: t('Some Title'),\n // description: t('Some Description'),\n // status: 'info'\n // });\n // }\n // }, [someCondition]);\n};\n","'use client';\n\nimport { useCallback, useState } from 'react';\n// Import from specific provider file to avoid circular dependencies\nimport { useOptionalPrivyWalletProvider } from '../../providers/PrivyWalletProvider';\n// Direct import to avoid circular dependency through hooks barrel\nimport { useWallet } from '../api/wallet/useWallet';\nimport { useOptionalDAppKitWallet } from '../api/dappkit/useOptionalDAppKitWallet';\n\ntype UseSignMessageReturnValue = {\n signMessage: (message: string) => Promise<string>;\n isSigningPending: boolean;\n signature: string | null;\n error: Error | null;\n reset: () => void;\n};\n\n/**\n * Hook to sign messages using the connected wallet.\n * Supports both Privy and VeChain wallets.\n *\n * @returns {UseSignMessageReturnValue} Object containing the signing function and status\n */\nexport const useSignMessage = (): UseSignMessageReturnValue => {\n const [isSigningPending, setIsSigningPending] = useState(false);\n const [signature, setSignature] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n const { connection, account } = useWallet();\n // Use optional DAppKit wallet hook that handles missing provider gracefully\n const { requestCertificate } = useOptionalDAppKitWallet();\n // Use optional provider - returns null when Privy is not configured\n const privyWalletProvider = useOptionalPrivyWalletProvider();\n\n const signMessage = useCallback(\n async (message: string): Promise<string> => {\n if (!account) throw new Error('Account not found');\n\n setIsSigningPending(true);\n setError(null);\n setSignature(null);\n\n try {\n let sig: string | null = null;\n\n if (connection.isConnectedWithDappKit) {\n const certResponse = await requestCertificate(\n {\n purpose: 'agreement',\n payload: {\n type: 'text',\n content: message,\n },\n },\n {\n signer: account.address,\n },\n );\n\n sig = certResponse.signature;\n } else {\n if (!privyWalletProvider) {\n throw new Error(\n 'Privy is not configured. Please configure the privy prop in VeChainKitContext to use this feature.',\n );\n }\n sig = await privyWalletProvider.signMessage(message);\n }\n\n setSignature(sig);\n return sig;\n } catch (err) {\n const error =\n err instanceof Error ? err : new Error(String(err));\n setError(error);\n throw error;\n } finally {\n setIsSigningPending(false);\n }\n },\n [connection, privyWalletProvider, account?.address],\n );\n\n const reset = useCallback(() => {\n setIsSigningPending(false);\n setSignature(null);\n setError(null);\n }, []);\n\n return {\n signMessage,\n isSigningPending,\n signature,\n error,\n reset,\n };\n};\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type { SignTypedDataParams } from '@privy-io/react-auth';\n// Import from specific provider file to avoid circular dependencies\nimport { useOptionalPrivyWalletProvider } from '../../providers/PrivyWalletProvider';\n// Direct import to avoid circular dependency through hooks barrel\nimport { useWallet } from '../api/wallet/useWallet';\nimport { useOptionalDAppKitWallet } from '../api/dappkit/useOptionalDAppKitWallet';\nimport { SignTypedDataOptions, TypedDataDomain } from '@vechain/sdk-network';\n\ntype UseSignTypedDataReturnValue = {\n signTypedData: (\n data: SignTypedDataParams,\n options?: { signer?: string },\n ) => Promise<string>;\n isSigningPending: boolean;\n signature: string | null;\n error: Error | null;\n reset: () => void;\n};\n\n/**\n * Hook to sign typed data using the connected wallet.\n * Supports both Privy and VeChain wallets.\n *\n * @returns {UseSignTypedDataReturnValue} Object containing the signing function and status\n */\nexport const useSignTypedData = (): UseSignTypedDataReturnValue => {\n const [isSigningPending, setIsSigningPending] = useState(false);\n const [signature, setSignature] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Use optional DAppKit wallet hook that handles missing provider gracefully\n const { signer } = useOptionalDAppKitWallet();\n const { connection } = useWallet();\n // Use optional provider - returns null when Privy is not configured\n const privyWalletProvider = useOptionalPrivyWalletProvider();\n\n const signTypedData = useCallback(\n async (\n data: SignTypedDataParams,\n options?: SignTypedDataOptions,\n ): Promise<string> => {\n setIsSigningPending(true);\n setError(null);\n setSignature(null);\n\n try {\n let sig: string;\n if (connection.isConnectedWithDappKit) {\n const domain = {\n ...data.domain,\n salt: data.domain?.salt\n ? Buffer.from(data.domain.salt).toString('hex')\n : undefined,\n } as TypedDataDomain;\n\n sig = await signer.signTypedData(\n domain,\n data.types,\n data.message,\n undefined,\n options,\n );\n } else {\n if (!privyWalletProvider) {\n throw new Error(\n 'Privy is not configured. Please configure the privy prop in VeChainKitContext to use this feature.',\n );\n }\n sig = await privyWalletProvider.signTypedData(data);\n }\n\n setSignature(sig);\n return sig;\n } catch (err) {\n // Handle user rejection specifically\n if (\n err &&\n typeof err === 'object' &&\n 'statusCode' in err &&\n (err as any).statusCode === 4001\n ) {\n const userRejectionError = new Error(\n 'User denied signature request',\n );\n setError(userRejectionError);\n throw userRejectionError;\n }\n\n // Handle other errors\n const error =\n err instanceof Error\n ? err\n : new Error(\n typeof err === 'object'\n ? JSON.stringify(err)\n : String(err),\n );\n console.error(error);\n setError(error);\n throw error;\n } finally {\n setIsSigningPending(false);\n }\n },\n [connection, privyWalletProvider],\n );\n\n const reset = useCallback(() => {\n setIsSigningPending(false);\n setSignature(null);\n setError(null);\n }, []);\n\n return {\n signTypedData,\n isSigningPending,\n signature,\n error,\n reset,\n };\n};\n","import { useLoginWithPasskey as usePrivyLoginWithPasskey } from '@privy-io/react-auth';\n\nexport const useLoginWithPasskey = () => {\n const { loginWithPasskey: privyLoginWithPasskey } =\n usePrivyLoginWithPasskey();\n\n const loginWithPasskey = async () => {\n try {\n await privyLoginWithPasskey();\n } catch (error) {\n throw error;\n }\n };\n\n return { loginWithPasskey };\n};\n","import {\n useLoginWithOAuth as usePrivyLoginWithOAuth,\n useCreateWallet,\n OAuthProviderType,\n} from '@privy-io/react-auth';\nimport { useCallback } from 'react';\n\ninterface OAuthOptions {\n provider: OAuthProviderType;\n}\n\n// Module-level variable shared across all hook instances\nlet hasCreatedWallet = false;\n\nexport const useLoginWithOAuth = () => {\n const { createWallet } = useCreateWallet();\n\n // Memoize the onComplete callback to prevent recreation on every render\n const handleComplete = useCallback(\n async ({ isNewUser }: { isNewUser: boolean }) => {\n // When using initOAuth Privy does not create an embedded wallet automatically.\n // So we need to create a wallet manually.\n if (isNewUser && !hasCreatedWallet) {\n // Set the flag BEFORE the async operation to prevent race conditions\n hasCreatedWallet = true;\n \n try {\n await createWallet();\n } catch (error) {\n // Reset flag on error so it can be retried\n hasCreatedWallet = false;\n console.error('Failed to create wallet:', error);\n throw error;\n }\n }\n },\n [createWallet],\n );\n\n const { initOAuth: privyInitOAuth } = usePrivyLoginWithOAuth({\n onComplete: handleComplete,\n });\n\n const initOAuth = async ({ provider }: OAuthOptions) => {\n try {\n await privyInitOAuth({ provider });\n } catch (error) {\n throw error;\n }\n };\n\n return { initOAuth };\n};\n","import { useOptionalPrivyCrossAppSdk } from '../api/privy/useOptionalPrivyCrossAppSdk';\nimport { useCrossAppConnectionCache } from '../cache/useCrossAppConnectionCache';\n// Direct import to avoid circular dependency through hooks barrel\nimport { useFetchAppInfo } from '../api/privy/useFetchAppInfo';\nimport { VECHAIN_PRIVY_APP_ID } from '../../utils';\nimport { handlePopupError } from '../../utils/handlePopupError';\nimport { VEBETTERDAO_GOVERNANCE_BASE_URL } from '../../constants';\n\nexport const useLoginWithVeChain = () => {\n // Use optional hook that handles missing provider gracefully\n const { login: loginWithVeChain } = useOptionalPrivyCrossAppSdk();\n const { setConnectionCache } = useCrossAppConnectionCache();\n const { data: appsInfo } = useFetchAppInfo([VECHAIN_PRIVY_APP_ID]);\n\n const login = async () => {\n try {\n await loginWithVeChain(VECHAIN_PRIVY_APP_ID);\n\n setConnectionCache({\n name: 'VeChain',\n logoUrl: appsInfo?.[VECHAIN_PRIVY_APP_ID]?.logo_url,\n appId: VECHAIN_PRIVY_APP_ID,\n website: VEBETTERDAO_GOVERNANCE_BASE_URL,\n });\n\n } catch (error) {\n throw handlePopupError({\n error,\n mobileBrowserPopupMessage:\n \"Your mobile browser blocked the login window. Please click 'Try again' to open the login window or change your browser settings.\",\n rejectedMessage: 'Login request was cancelled.',\n defaultMessage:\n 'There was an unexpected issue logging in with VeChain. Please try again or contact support.',\n });\n }\n };\n\n return { login };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport type { AllowedCategories } from '../../types';\nimport { getLocalStorageItem, setLocalStorageItem } from '../../utils/ssrUtils';\nimport {\n APP_HUB_GITHUB_API_BASE_URL,\n APP_HUB_GITHUB_RAW_REPO_BASE_URL,\n} from '../../constants';\nexport type AppHubApp = {\n id: string;\n name: string;\n description: string;\n url: string;\n logo: string;\n category: AllowedCategories;\n tags: string[];\n isVeWorldSupported: boolean;\n repo?: string;\n contracts?: string[];\n veBetterDaoId?: string;\n};\n\n// Cache key for local storage\nconst CACHE_KEY = 'vechain-kit-app-hub-apps';\nconst CACHE_EXPIRY_KEY = 'vechain-kit-app-hub-apps-expiry';\nconst CACHE_EXPIRY_TIME = 24 * 60 * 60 * 1000; // 24 hours\n\n/**\n * Query key for AppHub apps\n */\nexport const getAppHubAppsQueryKey = () => ['VECHAIN_KIT', 'appHub', 'apps'];\n\n/**\n * Fetches apps from the VeChain App Hub repository\n * @returns A list of apps from the VeChain App Hub\n */\nexport const fetchAppHubApps = async (): Promise<AppHubApp[]> => {\n // Check for cached data first (skip during SSR)\n if (typeof window !== 'undefined') {\n try {\n const cachedData = getLocalStorageItem(CACHE_KEY);\n const cacheExpiry = getLocalStorageItem(CACHE_EXPIRY_KEY);\n\n // If we have valid cached data, use it\n if (cachedData && cacheExpiry) {\n const expiryTime = parseInt(cacheExpiry, 10);\n if (Date.now() < expiryTime) {\n return JSON.parse(cachedData);\n }\n }\n } catch {\n // Invalid cache, continue with fetch\n console.warn('Invalid app-hub cache, fetching fresh data');\n }\n }\n\n // Fetch fresh data from GitHub\n const appsDirUrl = new URL('contents/apps', APP_HUB_GITHUB_API_BASE_URL);\n const dirResponse = await fetch(appsDirUrl);\n if (!dirResponse.ok) {\n throw new Error('Failed to fetch app directories');\n }\n\n const directories = await dirResponse.json();\n\n // Fetch each app's manifest.json\n const appPromises = directories.map(async (dir: any) => {\n if (dir.type !== 'dir') return null;\n\n const manifestUrl = new URL(\n `master/apps/${dir.name}/manifest.json`,\n APP_HUB_GITHUB_RAW_REPO_BASE_URL,\n );\n const manifestResponse = await fetch(manifestUrl);\n\n if (!manifestResponse.ok) {\n console.warn(`Failed to fetch manifest for ${dir.name}`);\n return null;\n }\n\n try {\n const manifest = await manifestResponse.json();\n const logoUrl = new URL(\n `master/apps/${dir.name}/logo.png`,\n APP_HUB_GITHUB_RAW_REPO_BASE_URL,\n );\n return {\n id: dir.name,\n name: manifest.name,\n description: manifest.desc,\n url: manifest.href,\n logo: logoUrl.toString(),\n category: manifest.category,\n tags: manifest.tags || [],\n isVeWorldSupported: manifest.isVeWorldSupported || false,\n repo: manifest.repo,\n contracts: manifest.contracts,\n veBetterDaoId: manifest.veBetterDaoId,\n };\n } catch (e) {\n console.warn(`Error parsing manifest for ${dir.name}:`, e);\n return null;\n }\n });\n\n const appsData = await Promise.all(appPromises);\n const validApps = appsData.filter((app) => app !== null) as AppHubApp[];\n\n // Cache the valid apps data (skip during SSR)\n if (typeof window !== 'undefined') {\n try {\n setLocalStorageItem(CACHE_KEY, JSON.stringify(validApps));\n setLocalStorageItem(\n CACHE_EXPIRY_KEY,\n (Date.now() + CACHE_EXPIRY_TIME).toString(),\n );\n } catch (e) {\n console.warn('Failed to cache app-hub data:', e);\n }\n }\n\n return validApps;\n};\n\n/**\n * Hook to fetch apps from the VeChain App Hub repository\n * @returns The query result containing apps from the VeChain App Hub\n *\n * @example\n * ```tsx\n * const { data: apps, isLoading, error } = useAppHubApps();\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error loading apps</div>;\n *\n * return (\n * <div>\n * {apps?.map(app => (\n * <AppCard key={app.id} app={app} />\n * ))}\n * </div>\n * );\n * ```\n */\nexport const useAppHubApps = () => {\n return useQuery<AppHubApp[]>({\n queryKey: getAppHubAppsQueryKey(),\n queryFn: async () => {\n try {\n return await fetchAppHubApps();\n } catch (error) {\n // If fetch fails, try to use cached data as fallback\n const cachedData = localStorage.getItem(CACHE_KEY);\n if (cachedData) {\n return JSON.parse(cachedData);\n }\n // If no cached data, throw the original error\n throw error;\n }\n },\n staleTime: 1000 * 60 * 60, // Cache for 1 hour\n retry: 2,\n });\n};\n","// Direct import to avoid circular dependency (providers barrel re-exports hooks)\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\n\n/**\n * Hook to get and set the current language in VeChainKit\n *\n * This hook provides the current runtime language value and a function to change it.\n * Changes made via this hook will sync to VeChainKit settings and trigger callbacks.\n *\n * @returns Object with:\n * - `currentLanguage`: Current language code (e.g., 'en', 'fr', 'de')\n * - `setLanguage`: Function to change the language\n *\n * @example\n * ```tsx\n * const { currentLanguage, setLanguage } = useCurrentLanguage();\n *\n * return (\n * <select value={currentLanguage} onChange={(e) => setLanguage(e.target.value)}>\n * <option value=\"en\">English</option>\n * <option value=\"fr\">Français</option>\n * </select>\n * );\n * ```\n */\nexport const useCurrentLanguage = () => {\n const { currentLanguage, setLanguage } = useVeChainKitConfig();\n return {\n currentLanguage,\n setLanguage,\n };\n};\n\n","// Direct import to avoid circular dependency (providers barrel re-exports hooks)\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\n\n/**\n * Hook to get and set the current currency in VeChainKit\n *\n * This hook provides the current runtime currency value and a function to change it.\n * Changes made via this hook will sync to VeChainKit settings and trigger callbacks.\n *\n * @returns Object with:\n * - `currentCurrency`: Current currency code ('usd', 'eur', or 'gbp')\n * - `setCurrency`: Function to change the currency\n *\n * @example\n * ```tsx\n * const { currentCurrency, setCurrency } = useCurrentCurrency();\n *\n * return (\n * <select value={currentCurrency} onChange={(e) => setCurrency(e.target.value as CURRENCY)}>\n * <option value=\"usd\">USD ($)</option>\n * <option value=\"eur\">EUR (€)</option>\n * <option value=\"gbp\">GBP (£)</option>\n * </select>\n * );\n * ```\n */\nexport const useCurrentCurrency = () => {\n const { currentCurrency, setCurrency } = useVeChainKitConfig();\n return {\n currentCurrency,\n setCurrency,\n };\n};\n\n","import { useState, useEffect } from 'react';\nimport { getLocalStorageItem, setLocalStorageItem } from '../../utils/ssrUtils';\n\nexport const useFeatureAnnouncement = () => {\n const [isVisible, setIsVisible] = useState(true);\n const CACHE_KEY = 'vechain_kit_feature_announcement_closed';\n\n useEffect(() => {\n const isClosed = getLocalStorageItem(CACHE_KEY);\n if (isClosed) {\n setIsVisible(false);\n }\n }, []);\n\n const closeAnnouncement = () => {\n setLocalStorageItem(CACHE_KEY, 'true');\n setIsVisible(false);\n };\n\n return {\n isVisible,\n closeAnnouncement,\n };\n};\n","import { useEffect, useState } from 'react';\nimport { isBrowser } from '../../utils/ssrUtils';\n\nexport const useIsPWA = () => {\n // set to true by default to avoid flickering\n const [isPWA, setIsPWA] = useState(true);\n\n useEffect(() => {\n // Skip PWA check during SSR\n if (!isBrowser()) {\n setIsPWA(false);\n return;\n }\n\n const checkIsPWA = () => {\n const isStandalone =\n window.matchMedia('(display-mode: standalone)').matches ||\n (window as any).standalone ||\n document.referrer.includes('android-app://');\n setIsPWA(isStandalone);\n };\n\n checkIsPWA();\n\n window.addEventListener('resize', checkIsPWA);\n\n return () => {\n window.removeEventListener('resize', checkIsPWA);\n };\n }, []);\n\n return isPWA;\n};\n","import { useEffect } from 'react';\n\nexport const useScrollToTop = () => {\n useEffect(() => {\n // Target the modal content directly\n const modalContent = document.querySelector('.chakra-modal__content');\n if (modalContent) {\n modalContent.scrollTop = 0;\n }\n }, []);\n};\n","import { getConfig } from '../../../config';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useQuery } from '@tanstack/react-query';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { ThorClient } from '@vechain/sdk-network';\n\nexport const getAccountImplementationAddress = async (\n thor: ThorClient,\n version?: number,\n networkType?: NETWORK_TYPE,\n): Promise<string> => {\n if (!networkType) throw new Error('Network type is required');\n if (!version) throw new Error('Version is required');\n\n const contract = thor.contracts.load(\n getConfig(networkType).accountFactoryAddress,\n SocialLoginSmartAccountFactory__factory.abi,\n );\n\n let implementationAddressPromise:\n | ReturnType<typeof contract.read.accountImplementationV1>\n | ReturnType<typeof contract.read.accountImplementationV3>;\n\n switch (version) {\n case 1:\n case 2:\n implementationAddressPromise =\n contract.read.accountImplementationV1();\n break;\n\n case 3:\n implementationAddressPromise =\n contract.read.accountImplementationV3();\n break;\n default:\n throw new Error('Invalid version, must be between 1 and 3');\n }\n\n const res = await implementationAddressPromise;\n\n if (!res) throw new Error('Failed to get account implementation address');\n\n return res[0].toString();\n};\n\nexport const getAccountImplementationAddressQueryKey = (\n version?: number,\n networkType?: NETWORK_TYPE,\n) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'FACTORY',\n 'IMPLEMENTATION_ADDRESS',\n version,\n networkType,\n];\n\n/**\n * Get the address of a smart account implementation for a given version\n * @param version - The version of the smart account implementation\n * @returns The address of the smart account implementation\n */\nexport const useAccountImplementationAddress = (version?: number) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getAccountImplementationAddressQueryKey(\n version,\n network.type,\n ),\n queryFn: async () =>\n getAccountImplementationAddress(thor!, version, network.type),\n enabled: !!thor && !!version && !!network,\n });\n};\n","import { getConfig } from '../../../config';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useQuery } from '@tanstack/react-query';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { ThorClient } from '@vechain/sdk-network';\n\nexport const getCurrentAccountImplementationVersion = async (\n thor: ThorClient,\n networkType?: NETWORK_TYPE,\n): Promise<number> => {\n if (!networkType) throw new Error('Network type is required');\n\n const res = await thor.contracts\n .load(\n getConfig(networkType).accountFactoryAddress,\n SocialLoginSmartAccountFactory__factory.abi,\n )\n .read.currentAccountImplementationVersion();\n\n if (!res)\n throw new Error('Failed to get current account implementation version');\n\n return parseInt(res[0].toString());\n};\n\nexport const getCurrentAccountImplementationVersionQueryKey = (\n networkType?: NETWORK_TYPE,\n) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'FACTORY',\n 'CURRENT_ACCOUNT_IMPLEMENTATION_VERSION',\n networkType,\n];\n\n/**\n * Get the current account implementation version used by the smart account factory\n * @returns The current account implementation version\n */\nexport const useCurrentAccountImplementationVersion = () => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getCurrentAccountImplementationVersionQueryKey(network.type),\n queryFn: async () =>\n getCurrentAccountImplementationVersion(thor!, network.type),\n enabled: !!thor && !!network,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { getConfig } from '../../../config';\nimport { ThorClient } from '@vechain/sdk-network';\n\nexport const getAccountAddress = async (\n thor: ThorClient,\n ownerAddress?: string,\n networkType?: NETWORK_TYPE,\n): Promise<string> => {\n if (!ownerAddress) throw new Error('Owner address is required');\n if (!networkType) throw new Error('Network type is required');\n\n const res = await thor.contracts\n .load(\n getConfig(networkType).accountFactoryAddress,\n SocialLoginSmartAccountFactory__factory.abi,\n )\n .read.getAccountAddress(ownerAddress);\n\n if (!res)\n throw new Error(`Failed to get account address of ${ownerAddress}`);\n\n return res[0].toString();\n};\n\nexport const getAccountAddressQueryKey = (\n ownerAddress?: string,\n networkType?: NETWORK_TYPE,\n) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'FACTORY',\n 'ADDRESS',\n ownerAddress,\n networkType,\n];\n\n/**\n * Get the address of a smart account\n * @param ownerAddress - The address of the owner of the smart account\n * @returns The address of the smart account\n */\nexport const useGetAccountAddress = (ownerAddress?: string) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getAccountAddressQueryKey(ownerAddress, network.type),\n queryFn: async () =>\n getAccountAddress(thor!, ownerAddress, network.type),\n enabled: !!thor && !!ownerAddress && !!network,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\n// Direct import to avoid circular dependency\nimport { useGetNodeUrl } from '../../utils/useGetNodeUrl';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { Address } from '@vechain/sdk-core';\n\nexport const getIsDeployed = async (\n thor: ThorClient,\n accountAddress?: string,\n): Promise<boolean> => {\n if (!accountAddress) throw new Error('Account address is required');\n\n const res = await thor.accounts.getAccount(\n Address.of(String(accountAddress)),\n );\n\n if (!res) throw new Error('Account not found');\n\n return res.hasCode;\n};\n\nexport const getIsDeployedQueryKey = (contractAddress?: string) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'IS_DEPLOYED',\n contractAddress,\n];\n\n/**\n * Check if a smart account is deployed\n * @returns True if the smart account is deployed, false otherwise\n */\nexport const useIsSmartAccountDeployed = (accountAddress?: string) => {\n const nodeUrl = useGetNodeUrl();\n const thor = ThorClient.at(nodeUrl);\n\n return useQuery({\n queryKey: getIsDeployedQueryKey(accountAddress),\n queryFn: async () => getIsDeployed(thor, accountAddress),\n enabled: !!thor && !!accountAddress,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\nimport { NETWORK_TYPE } from '../../../config/network';\nimport { getConfig } from '../../../config';\nimport { ThorClient } from '@vechain/sdk-network';\n\nexport const getUpgradeRequired = async (\n thor: ThorClient,\n accountAddress: string,\n ownerAddress: string,\n targetVersion: number,\n networkType: NETWORK_TYPE,\n): Promise<boolean> => {\n const res = await thor.contracts\n .load(\n getConfig(networkType).accountFactoryAddress,\n SocialLoginSmartAccountFactory__factory.abi,\n )\n .read.upgradeRequired(\n accountAddress as `0x${string}`,\n ownerAddress as `0x${string}`,\n BigInt(targetVersion),\n );\n\n if (!res)\n throw new Error(\n `Failed to get upgrade required of contract address ${\n getConfig(networkType).accountFactoryAddress\n }`,\n );\n\n return res[0] as boolean;\n};\n\nexport const getUpgradeRequiredQueryKey = (\n accountAddress: string,\n ownerAddress: string,\n targetVersion: number,\n networkType: NETWORK_TYPE,\n) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'FACTORY',\n 'UPGRADE_REQUIRED',\n accountAddress,\n ownerAddress,\n targetVersion,\n networkType,\n];\n\n/**\n * Check if a smart account needs an upgrade (even if it's not yet deployed)\n * @param accountAddress - The address of the smart account\n * @param ownerAddress - The address of the owner of the smart account\n * @param targetVersion - The version of the smart account to check for\n * @returns True if the smart account needs an upgrade, false otherwise\n */\nexport const useUpgradeRequired = (\n accountAddress: string,\n ownerAddress: string,\n targetVersion: number,\n) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getUpgradeRequiredQueryKey(\n accountAddress,\n ownerAddress,\n targetVersion,\n network.type,\n ),\n queryFn: async () =>\n getUpgradeRequired(\n thor!,\n accountAddress,\n ownerAddress,\n targetVersion,\n network.type,\n ),\n enabled: !!thor && !!accountAddress && !!ownerAddress && !!network.type,\n });\n};\n","import { useQueryClient } from '@tanstack/react-query';\nimport { useWallet } from '../../api/wallet/useWallet';\n// Direct imports to avoid circular dependencies\nimport { getAccountVersionQueryKey } from './useGetAccountVersion';\nimport { getUpgradeRequiredQueryKey } from './useUpgradeRequired';\nimport { getUpgradeRequiredForAccountQueryKey } from './useUpgradeRequiredForAccount';\nimport { getCurrentAccountImplementationVersionQueryKey } from './useCurrentAccountImplementationVersion';\nimport { getAccountImplementationAddressQueryKey } from './useAccountImplementationAddress';\nimport { getHasV1SmartAccountQueryKey } from './useHasV1SmartAccount';\nimport { getAccountAddressQueryKey } from './useGetAccountAddress';\nimport { useVeChainKitConfig } from '../../../providers/VeChainKitContext';\n\n/**\n * Hook to refresh smart account factory-related queries\n * @returns Object with refresh function\n */\nexport const useRefreshFactoryQueries = () => {\n const queryClient = useQueryClient();\n const { connectedWallet, smartAccount } = useWallet();\n const { network } = useVeChainKitConfig();\n\n const refresh = async () => {\n const ownerAddress = connectedWallet?.address ?? '';\n const smartAccountAddress = smartAccount?.address ?? '';\n\n // First cancel all queries\n await Promise.all([\n // Factory related queries\n queryClient.cancelQueries({\n queryKey: getAccountAddressQueryKey(ownerAddress, network.type),\n }),\n queryClient.cancelQueries({\n queryKey: getAccountVersionQueryKey(\n smartAccountAddress,\n ownerAddress,\n network.type,\n ),\n }),\n queryClient.cancelQueries({\n queryKey: getHasV1SmartAccountQueryKey(\n ownerAddress,\n network.type,\n ),\n }),\n queryClient.cancelQueries({\n queryKey: getCurrentAccountImplementationVersionQueryKey(\n network.type,\n ),\n }),\n\n // Upgrade related queries - using current version 3 as default\n queryClient.cancelQueries({\n queryKey: getUpgradeRequiredQueryKey(\n smartAccountAddress,\n ownerAddress,\n 3,\n network.type,\n ),\n }),\n queryClient.cancelQueries({\n queryKey: getUpgradeRequiredForAccountQueryKey(\n smartAccountAddress,\n 3,\n network.type,\n ),\n }),\n queryClient.cancelQueries({\n queryKey: getAccountImplementationAddressQueryKey(\n 3,\n network.type,\n ),\n }),\n ]);\n\n // Then refetch all queries\n await Promise.all([\n // Factory related queries\n queryClient.refetchQueries({\n queryKey: getAccountAddressQueryKey(ownerAddress, network.type),\n }),\n queryClient.refetchQueries({\n queryKey: getAccountVersionQueryKey(\n smartAccountAddress,\n ownerAddress,\n network.type,\n ),\n }),\n queryClient.refetchQueries({\n queryKey: getHasV1SmartAccountQueryKey(\n ownerAddress,\n network.type,\n ),\n }),\n queryClient.refetchQueries({\n queryKey: getCurrentAccountImplementationVersionQueryKey(\n network.type,\n ),\n }),\n\n // Upgrade related queries - using current version 3 as default\n queryClient.refetchQueries({\n queryKey: getUpgradeRequiredQueryKey(\n smartAccountAddress,\n ownerAddress,\n 3,\n network.type,\n ),\n }),\n queryClient.refetchQueries({\n queryKey: getUpgradeRequiredForAccountQueryKey(\n smartAccountAddress,\n 3,\n network.type,\n ),\n }),\n queryClient.refetchQueries({\n queryKey: getAccountImplementationAddressQueryKey(\n 3,\n network.type,\n ),\n }),\n ]);\n };\n\n return { refresh };\n};\n","import { useQueryClient } from '@tanstack/react-query';\nimport { useWallet } from '../../api/wallet/useWallet';\n// Direct imports to avoid circular dependencies\nimport { getSmartAccountQueryKey } from './useSmartAccount';\nimport { getIsDeployedQueryKey } from './useIsSmartAccountDeployed';\n\n/**\n * Hook to refresh smart account-related queries\n * @returns Object with refresh function\n */\nexport const useRefreshSmartAccountQueries = () => {\n const queryClient = useQueryClient();\n const { smartAccount } = useWallet();\n\n const refresh = async () => {\n const smartAccountAddress = smartAccount?.address ?? '';\n\n // First cancel all queries\n await Promise.all([\n // Smart account basic info\n queryClient.cancelQueries({\n queryKey: getSmartAccountQueryKey(smartAccountAddress),\n }),\n queryClient.cancelQueries({\n queryKey: getIsDeployedQueryKey(smartAccountAddress),\n }),\n ]);\n\n // Then refetch all queries\n await Promise.all([\n // Smart account basic info\n queryClient.refetchQueries({\n queryKey: getSmartAccountQueryKey(smartAccountAddress),\n }),\n queryClient.refetchQueries({\n queryKey: getIsDeployedQueryKey(smartAccountAddress),\n }),\n ]);\n };\n\n return { refresh };\n};\n","// Direct imports to avoid circular dependencies\nimport { useAccountImplementationAddress } from './useAccountImplementationAddress';\nimport { useRefreshFactoryQueries } from './useRefreshFactoryQueries';\nimport { useRefreshSmartAccountQueries } from './useRefreshSmartAccountQueries';\nimport { useSendTransaction, UseSendTransactionReturnValue } from '../transactions/useSendTransaction';\nimport { humanAddress, isValidAddress } from '../../../utils';\nimport { SocialLoginSmartAccount__factory } from '@vechain/vechain-contract-types';\nimport { TransactionClause } from '@vechain/sdk-core';\nimport { useCallback } from 'react';\n\ntype UseUpgradeSmartAccountVersionProps = {\n smartAccountAddress: string;\n targetVersion: number;\n onSuccess?: () => void;\n onError?: () => void;\n};\n\ntype UseUpgradeSmartAccountVersionReturnValue = {\n sendTransaction: () => Promise<void>;\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nconst socialLoginSmartAccountInterface = SocialLoginSmartAccount__factory.createInterface();\n\nexport const useUpgradeSmartAccount = ({\n smartAccountAddress,\n targetVersion,\n onSuccess,\n onError,\n}: UseUpgradeSmartAccountVersionProps): UseUpgradeSmartAccountVersionReturnValue => {\n const { refresh: refreshFactoryQueries } = useRefreshFactoryQueries();\n const { refresh: refreshSmartAccountQueries } =\n useRefreshSmartAccountQueries();\n\n // Fetch the new implementation address for the requested version\n const { data: newImplementationAddress } =\n useAccountImplementationAddress(targetVersion);\n\n const buildClauses = useCallback(async () => {\n if (!smartAccountAddress || !isValidAddress(smartAccountAddress)) {\n throw new Error('Invalid smart account address');\n }\n\n if (!newImplementationAddress) {\n throw new Error(\n `Unable to fetch implementation address for version ${targetVersion}`,\n );\n }\n\n return [\n {\n to: smartAccountAddress,\n value: '0x0',\n data: socialLoginSmartAccountInterface.encodeFunctionData(\n 'upgradeToAndCall',\n [newImplementationAddress, '0x'],\n ),\n comment: `Upgrade account to version ${targetVersion}`,\n abi: socialLoginSmartAccountInterface\n .getFunction('upgradeToAndCall')\n .format('json'),\n },\n ] as TransactionClause[];\n }, [smartAccountAddress, newImplementationAddress, targetVersion]);\n\n const handleOnSuccess = async () => {\n // Refresh all relevant queries\n await Promise.all([\n refreshFactoryQueries(),\n refreshSmartAccountQueries(),\n ]);\n onSuccess?.();\n };\n\n const result = useSendTransaction({\n privyUIOptions: {\n title: 'Upgrade Smart Account',\n description: `Upgrading your account at ${humanAddress(\n smartAccountAddress,\n )} to version ${targetVersion}`,\n buttonText: 'Sign to continue',\n },\n onTxConfirmed: handleOnSuccess,\n onTxFailedOrCancelled: async () => {\n onError?.();\n },\n });\n\n return {\n ...result,\n sendTransaction: async () => {\n return result.sendTransaction(await buildClauses());\n },\n };\n};\n","import { TIME } from '../../../utils';\nimport { useQuery } from '@tanstack/react-query';\nimport { useOptionalThor } from '../../api/dappkit/useOptionalThor';\n\nexport const currentBlockQueryKey = () => ['VECHAIN_KIT', 'CURRENT_BLOCK'];\n\nconst REFETCH_INTERVAL = 10 * TIME.SECOND;\n\n/**\n * Fetches the current block from the blockchain. The block is refetched every 10 seconds.\n * @returns the current block\n */\nexport const useCurrentBlock = () => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n\n return useQuery({\n queryKey: currentBlockQueryKey(),\n queryFn: async () => {\n if (!thor) throw new Error('Thor client not available');\n const response = await thor.blocks.getBestBlockExpanded();\n if (!response) throw new Error('Failed to fetch current block');\n return response;\n },\n staleTime: 1000 * 60,\n refetchInterval: REFETCH_INTERVAL,\n enabled: !!thor,\n });\n};\n","import {\n EventLogs,\n FilterEventLogsOptions,\n ThorClient,\n} from '@vechain/sdk-network';\n\nconst MAX_EVENTS_PER_QUERY = 1000;\n/**\n * Params for getEvents function\n * @param nodeUrl the node url\n * @param thor the thor client\n * @param auctionId the auction id to get the events\n * @param order the order of the events (asc or desc)\n * @param offset the offset of the events\n * @param limit the limit of the events (max 256)\n * @param from the block number to start from\n * @param filterCriteria the filter criteria for the events\n * @returns the encoded events\n */\nexport type GetEventsProps = {\n nodeUrl: string;\n thor: ThorClient;\n order?: 'asc' | 'desc';\n offset?: number;\n limit?: number;\n from?: number;\n to?: number;\n filterCriteria: FilterEventLogsOptions['criteriaSet'];\n};\n/**\n * Get events from blockchain (auction created, auction successful, auction cancelled)\n * @param order\n * @param offset\n * @param limit\n * @param from block parse start from\n */\nexport const getEventLogs = async ({\n thor,\n order = 'asc',\n offset = 0,\n limit = MAX_EVENTS_PER_QUERY,\n from = 0,\n to = thor.blocks.getHeadBlock()?.number,\n filterCriteria,\n}: GetEventsProps) => {\n const response = await thor.logs.filterEventLogs({\n range: {\n from,\n to,\n unit: 'block',\n },\n options: {\n offset,\n limit,\n },\n order,\n criteriaSet: filterCriteria,\n });\n\n if (!response) throw new Error('Failed to fetch events');\n\n return response;\n};\n\n/**\n * call getEvents iteratively to get all the events\n * @param nodeUrl the node url\n * @param thor the thor client\n * @param order the order of the events (asc or desc)\n * @param from the block number to start from\n * @param filterCriteria the filter criteria for the events\n * @returns all the events from the blockchain\n */\nexport const getAllEventLogs = async ({\n nodeUrl,\n thor,\n order = 'asc',\n from = 0,\n to,\n filterCriteria,\n}: Omit<GetEventsProps, 'offset' | 'limit'>) => {\n const allEvents: EventLogs[] = [];\n let offset = 0;\n //return from the function only when we get all the events\n // TODO: check this can be improved, possible infinite loop here\n while (true) {\n const events = await getEventLogs({\n nodeUrl,\n thor,\n filterCriteria,\n from,\n to: to ?? Number.MAX_SAFE_INTEGER,\n limit: MAX_EVENTS_PER_QUERY,\n order,\n offset,\n });\n allEvents.push(...events);\n if (events.length < MAX_EVENTS_PER_QUERY) {\n return allEvents;\n }\n offset += MAX_EVENTS_PER_QUERY;\n }\n};\n","// Direct imports to avoid circular dependencies\nimport { useSendTransaction, UseSendTransactionReturnValue } from './useSendTransaction';\nimport { useRefreshBalances } from '../../api/wallet/useRefreshBalances';\nimport { IERC20__factory } from '@vechain/vechain-contract-types';\nimport { useMemo } from 'react';\nimport { humanAddress, isValidAddress } from '../../../utils';\nimport { parseEther } from 'viem';\nimport type { EnhancedClause } from '../../../types';\n\ntype useTransferERC20Props = {\n fromAddress: string;\n receiverAddress: string;\n amount: string;\n tokenAddress: string;\n tokenName: string;\n onSuccess?: () => void;\n onSuccessMessageTitle?: number;\n onError?: (error?: string) => void;\n};\n\ntype useTransferERC20ReturnValue = {\n sendTransaction: () => Promise<void>;\n clauses: EnhancedClause[];\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nconst ERC20Interface = IERC20__factory.createInterface();\n\nexport const buildERC20Clauses = (receiverAddress: string, amount: string, tokenAddress: string, tokenName: string): EnhancedClause[] => {\n if (!receiverAddress || !amount || !isValidAddress(receiverAddress))\n throw new Error('Invalid receiver address or amount');\n\n const clausesArray: any[] = [];\n\n clausesArray.push({\n to: tokenAddress,\n value: '0x0',\n data: ERC20Interface.encodeFunctionData('transfer', [\n receiverAddress,\n parseEther(amount),\n ]),\n comment: `Transfer ${amount} ${tokenName} to ${receiverAddress}`,\n abi: ERC20Interface.getFunction('transfer'),\n });\n return clausesArray;\n};\n\nexport const useTransferERC20 = ({\n fromAddress,\n receiverAddress,\n amount,\n tokenAddress,\n tokenName,\n onSuccess,\n onError,\n}: useTransferERC20Props): useTransferERC20ReturnValue => {\n const { refresh } = useRefreshBalances();\n\n // Memoize the clauses\n const clauses = useMemo(() => buildERC20Clauses(receiverAddress, amount, tokenAddress, tokenName), [receiverAddress, amount, tokenAddress, tokenName]);\n\n const result = useSendTransaction({\n signerAccountAddress: fromAddress,\n privyUIOptions: {\n title: 'Confirm Transfer',\n description: `Transfer ${amount} ${tokenName} to ${humanAddress(\n receiverAddress,\n )}`,\n buttonText: 'Sign to continue',\n },\n onTxConfirmed: async () => {\n refresh();\n onSuccess?.();\n },\n onTxFailedOrCancelled: async (error) => {\n onError?.(error instanceof Error ? error.message : String(error));\n },\n });\n\n return {\n ...result,\n clauses,\n sendTransaction: async () => {\n return result.sendTransaction(clauses);\n },\n };\n};\n","// Direct imports to avoid circular dependencies\nimport { useSendTransaction, UseSendTransactionReturnValue } from './useSendTransaction';\nimport { useRefreshBalances } from '../../api/wallet/useRefreshBalances';\nimport { humanAddress, isValidAddress } from '../../../utils';\nimport { useMemo } from 'react';\nimport { parseEther } from 'viem';\nimport type { EnhancedClause } from '../../../types';\n\ntype useTransferVETProps = {\n fromAddress: string;\n receiverAddress: string;\n amount: string;\n onSuccess?: () => void;\n onError?: (error?: string) => void;\n};\n\ntype useTransferVETReturnValue = {\n sendTransaction: () => Promise<void>;\n clauses: EnhancedClause[];\n} & Omit<UseSendTransactionReturnValue, 'sendTransaction'>;\n\nexport const buildVETClauses = (receiverAddress: string, amount: string): EnhancedClause[] => {\n if (!receiverAddress || !amount || !isValidAddress(receiverAddress))\n throw new Error('Invalid receiver address or amount');\n\n // Validate amount is a valid number\n if (isNaN(Number(amount))) {\n throw new Error('Invalid amount');\n }\n\n const clausesArray: EnhancedClause[] = [];\n\n try {\n clausesArray.push({\n to: receiverAddress,\n value: parseEther(amount).toString(), // Convert to string\n data: '0x',\n comment: `Transfer ${amount} VET to ${receiverAddress}`,\n });\n } catch (error) {\n console.error('Error building clauses:', error);\n throw new Error('Invalid amount format');\n }\n\n return clausesArray;\n};\n\nexport const useTransferVET = ({\n fromAddress,\n receiverAddress,\n amount,\n onSuccess,\n onError,\n}: useTransferVETProps): useTransferVETReturnValue => {\n const { refresh } = useRefreshBalances();\n \n // Memoize the clauses\n const clauses = useMemo(() => buildVETClauses(receiverAddress, amount), [receiverAddress, amount]);\n\n const result = useSendTransaction({\n signerAccountAddress: fromAddress,\n privyUIOptions: {\n title: 'Confirm Transfer',\n description: `Transfer ${amount} VET to ${humanAddress(\n receiverAddress,\n )}`,\n buttonText: 'Sign to continue',\n },\n onTxConfirmed: async () => {\n refresh();\n onSuccess?.();\n },\n onTxFailedOrCancelled: async (error) => {\n onError?.(error instanceof Error ? error.message : String(error));\n },\n });\n\n return {\n ...result,\n clauses,\n sendTransaction: async () => {\n return result.sendTransaction(clauses);\n },\n };\n};\n","import { useCallback } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\n// Direct import to avoid circular dependency\nimport { useWallet } from '../../api/wallet/useWallet';\nimport { useSendTransaction } from './useSendTransaction';\nimport { TransactionClause } from '@vechain/sdk-core';\n\nexport type BuildTransactionProps<ClausesParams> = {\n clauseBuilder: (props: ClausesParams) => TransactionClause[];\n refetchQueryKeys?: (string | undefined)[][];\n onSuccess?: () => void;\n invalidateCache?: boolean;\n suggestedMaxGas?: number;\n gasPadding?: number;\n onFailure?: () => void;\n delegationUrl?: string;\n};\n\n/**\n * Custom hook for building and sending transactions.\n * @param clauseBuilder - A function that builds an array of enhanced clauses based on the provided parameters.\n * @param refetchQueryKeys - An optional array of query keys to refetch after the transaction is sent.\n * @param invalidateCache - A flag indicating whether to invalidate the cache and refetch queries after the transaction is sent.\n * @param onSuccess - An optional callback function to be called after the transaction is successfully sent.\n * @param onFailure - An optional callback function to be called after the transaction is failed or cancelled.\n * @param suggestedMaxGas - The suggested maximum gas for the transaction.\n * @param gasPadding - The padding to add to the suggested maximum gas.\n * @param delegationUrl - The dApp sponsored delegator url.\n * @returns An object containing the result of the `useSendTransaction` hook and a `sendTransaction` function.\n */\nexport const useBuildTransaction = <ClausesParams>({\n clauseBuilder,\n refetchQueryKeys,\n invalidateCache = true,\n onSuccess,\n onFailure,\n suggestedMaxGas,\n gasPadding,\n delegationUrl,\n}: BuildTransactionProps<ClausesParams>) => {\n const { account } = useWallet();\n const queryClient = useQueryClient();\n\n /**\n * Callback function to be called when the transaction is successfully confirmed.\n * It cancels and refetches the specified queries if `invalidateCache` is `true`.\n */\n const handleOnSuccess = useCallback(async () => {\n if (invalidateCache) {\n refetchQueryKeys?.forEach(async (queryKey) => {\n await queryClient.cancelQueries({\n queryKey,\n });\n await queryClient.refetchQueries({\n queryKey,\n });\n });\n }\n\n onSuccess?.();\n }, [invalidateCache, onSuccess, queryClient, refetchQueryKeys]);\n\n const result = useSendTransaction({\n signerAccountAddress: account?.address,\n onTxConfirmed: handleOnSuccess,\n suggestedMaxGas,\n onTxFailedOrCancelled: onFailure,\n gasPadding,\n delegationUrl,\n });\n\n /**\n * Function to send a transaction based on the provided parameters.\n * @param props - The parameters to be passed to the `clauseBuilder` function.\n */\n const sendTransaction = useCallback(\n async (props: ClausesParams) => {\n result.sendTransaction(clauseBuilder(props), delegationUrl);\n },\n [clauseBuilder, result, delegationUrl],\n );\n\n return { ...result, sendTransaction };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { EventLogs, FilterCriteria } from '@vechain/sdk-network';\nimport { useCallback, useMemo } from 'react';\nimport {\n Abi,\n ContractEventName,\n decodeEventLog as viemDecodeEventLog,\n Hex as ViemHex,\n} from 'viem';\nimport { useOptionalThor } from '../api/dappkit/useOptionalThor';\nimport { getAllEventLogs } from '../thor';\n\ntype Topics = [] | [signature: ViemHex, ...args: ViemHex[]];\n\nexport const decodeEventLog = <TAbi extends Abi>(\n event: EventLogs,\n abi: TAbi,\n): {\n meta: EventLogs['meta'];\n decodedData: ReturnType<typeof viemDecodeEventLog<TAbi>>;\n} => {\n const decodedData = viemDecodeEventLog({\n abi,\n data: event.data.toString() as ViemHex,\n topics: event.topics.map((topic) => topic.toString()) as Topics,\n });\n\n return {\n meta: event.meta,\n decodedData,\n };\n};\n\nexport type UseEventsParams<\n T extends Abi,\n K extends ContractEventName<T>,\n R,\n> = {\n abi: T;\n contractAddress: string;\n eventName: K;\n filterParams?: Record<string, unknown> | unknown[] | undefined;\n mapResponse: ({\n meta,\n decodedData,\n }: {\n meta: EventLogs['meta'];\n decodedData: ReturnType<typeof viemDecodeEventLog<T, K>>;\n }) => R;\n nodeUrl: string;\n};\n\nexport type GetEventsKeyParams = {\n eventName: string;\n filterParams?: object;\n};\n\nexport const getEventsKey = ({\n eventName,\n filterParams,\n}: GetEventsKeyParams) => {\n return [eventName, filterParams ? JSON.stringify(filterParams) : 'all'];\n};\n\n/**\n * Custom hook for fetching contract events.\n */\nexport const useEvents = <T extends Abi, K extends ContractEventName<T>, R>({\n abi,\n contractAddress,\n eventName,\n filterParams,\n mapResponse,\n nodeUrl,\n}: UseEventsParams<T, K, R>) => {\n // Use optional Thor hook that handles missing provider gracefully\n const thor = useOptionalThor();\n\n const queryFn = useCallback(async () => {\n if (!thor) return [];\n\n const eventAbi = thor.contracts\n .load(contractAddress, abi)\n .getEventAbi(eventName);\n const topics = eventAbi.encodeFilterTopicsNoNull(filterParams ?? {});\n\n // Construct filter criteria\n const filterCriteria: FilterCriteria[] = [\n {\n criteria: {\n address: contractAddress,\n topic0: topics[0] ?? undefined,\n topic1: topics[1] ?? undefined,\n topic2: topics[2] ?? undefined,\n topic3: topics[3] ?? undefined,\n topic4: topics[4] ?? undefined,\n },\n eventAbi,\n },\n ];\n\n const events = (\n await getAllEventLogs({ thor, nodeUrl, filterCriteria })\n ).map((event) => decodeEventLog(event, abi));\n\n if (\n events.some(\n ({ decodedData }) => decodedData.eventName !== eventName,\n )\n )\n throw new Error(`Unknown event`);\n\n return events.map((event) =>\n mapResponse({\n meta: event.meta,\n decodedData: event.decodedData as ReturnType<\n typeof viemDecodeEventLog<T, K>\n >,\n }),\n );\n }, [\n thor,\n contractAddress,\n abi,\n eventName,\n filterParams,\n mapResponse,\n nodeUrl,\n ]);\n\n const queryKey = useMemo(\n () => getEventsKey({ eventName, filterParams }),\n [eventName, filterParams],\n );\n\n return useQuery({\n queryFn,\n queryKey,\n enabled: !!thor,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport type { EstimationResponse } from '../../types/gasEstimation';\nimport type { EnhancedClause, GasTokenType } from '../../types';\n// Direct imports to avoid circular dependency with hooks barrel\nimport { useSmartAccount } from '../thor/smartAccounts/useSmartAccount';\nimport { useWallet } from '../api/wallet/useWallet';\nimport { useTokenBalances } from '../api/wallet/useTokenBalances';\nimport { estimateGas } from './useGenericDelegator';\nimport { useGasTokenSelection } from './useGasTokenSelection';\n// Direct import to avoid circular dependency (providers barrel re-exports hooks)\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\nimport { TransactionClause } from '@vechain/sdk-core';\n\nexport interface useGenericDelegatorFeeEstimationParams {\n clauses: EnhancedClause[];\n enabled?: boolean;\n tokens: string[]; // Array of tokens to try in order\n sendingAmount?: string; // Amount being sent\n sendingTokenSymbol?: string; // Symbol of token being sent\n}\n\nexport const useGenericDelegatorFeeEstimation = ({\n clauses,\n enabled = true,\n tokens,\n sendingAmount,\n sendingTokenSymbol,\n}: useGenericDelegatorFeeEstimationParams) => {\n const { connectedWallet, account } = useWallet();\n const { data: smartAccount } = useSmartAccount(\n connectedWallet?.address ?? '',\n );\n const { feeDelegation } = useVeChainKitConfig();\n const { balances } = useTokenBalances(account?.address ?? '');\n const { updatePreferences } = useGasTokenSelection();\n // Only include essential data in query key to prevent unnecessary refetches\n const queryKey = ['gas-estimation', JSON.stringify(clauses), JSON.stringify(tokens), sendingAmount, sendingTokenSymbol];\n \n return useQuery<EstimationResponse & { usedToken: string }, Error>({\n queryKey,\n queryFn: async () => {\n let lastError: Error | null = null;\n // Try each token in sequence until one succeeds AND has sufficient balance\n for (const token of tokens) {\n try {\n const estimation = await estimateGas(\n smartAccount?.address ?? '',\n feeDelegation?.genericDelegatorUrl ?? '',\n clauses as TransactionClause[],\n token as GasTokenType,\n 'medium',\n );\n // Check if user has enough balance for this token\n const gasCost = estimation.transactionCost;\n const tokenBalance = Number(balances.find(t => t.symbol === token)?.balance || 0);\n // If sending the same token as gas token, need balance for both\n // If no sendingAmount is provided, we're only checking for gas fees\n const additionalAmount = (sendingAmount && sendingTokenSymbol && token === sendingTokenSymbol) \n ? Number(sendingAmount)\n : 0;\n const requiredBalance = gasCost + additionalAmount;\n \n if (tokenBalance >= requiredBalance) {\n // Has enough balance, return this token\n updatePreferences({ gasTokenToUse: token as GasTokenType });\n return { ...estimation, usedToken: token };\n }\n // Not enough balance, try next token\n lastError = new Error(`Insufficient ${token} balance: has ${tokenBalance}, needs ${requiredBalance}`);\n } catch (error) {\n lastError = error as Error;\n }\n }\n throw lastError || new Error('All gas tokens failed estimation or have insufficient balance');\n },\n enabled: enabled && clauses.length > 0 && !!smartAccount?.address && !!feeDelegation?.genericDelegatorUrl && tokens.length > 0 && balances.length > 0,\n staleTime: 30 * 1000,\n gcTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n refetchOnMount: false,\n retry: false,\n retryDelay: 1000,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport type { GasTokenType } from '../../types';\n// Direct imports to avoid circular dependency with hooks barrel\nimport { useSmartAccount } from '../thor/smartAccounts/useSmartAccount';\nimport { useWallet } from '../api/wallet/useWallet';\nimport { estimateGas } from './useGenericDelegator';\n// Direct import to avoid circular dependency (providers barrel re-exports hooks)\nimport { useVeChainKitConfig } from '../../providers/VeChainKitContext';\nimport { TransactionClause } from '@vechain/sdk-core';\n\nexport interface UseEstimateAllTokensParams {\n clauses: TransactionClause[];\n tokens: GasTokenType[];\n enabled?: boolean;\n}\n\nexport const useEstimateAllTokens = ({\n clauses,\n tokens,\n enabled = true,\n}: UseEstimateAllTokensParams) => {\n const { connectedWallet } = useWallet();\n const { data: smartAccount } = useSmartAccount(\n connectedWallet?.address ?? '',\n );\n const { feeDelegation } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: [\n 'gas-estimation-all-tokens',\n JSON.stringify(clauses),\n JSON.stringify(tokens),\n ],\n queryFn: async () => {\n const estimates: Record<\n GasTokenType,\n { cost: number; loading: boolean; error?: string }\n > = {} as any;\n\n await Promise.all(\n tokens.map(async (token) => {\n try {\n const estimation = await estimateGas(\n smartAccount?.address ?? '',\n feeDelegation?.genericDelegatorUrl ?? '',\n clauses,\n token,\n 'medium',\n );\n estimates[token] = {\n cost: estimation.transactionCost || 0,\n loading: false,\n };\n } catch (error) {\n estimates[token] = {\n cost: 0,\n loading: false,\n error:\n error instanceof Error\n ? error.message\n : 'Unknown error',\n };\n }\n }),\n );\n\n return estimates;\n },\n enabled:\n enabled &&\n clauses.length > 0 &&\n !!smartAccount?.address &&\n !!feeDelegation?.genericDelegatorUrl &&\n tokens.length > 0,\n staleTime: 30 * 1000,\n gcTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n refetchOnMount: false,\n });\n};\n"],"mappings":"swBASA,MAAa,MAA8B,CACvC,GAAM,CAAC,EAAW,GAAgBA,EAAAA,EAC9BC,EAAAA,EAAgB,oBAChB,EAAE,CACL,CAgBD,MAAO,CACH,YACA,YAhBiB,GAAgC,CAC5C,EAAU,KAAM,GAAyB,EAAE,MAAQ,EAAS,IAAI,EACjE,EAAa,CAAC,GAAG,EAAW,EAAS,CAAC,EAe1C,eAXoB,GAAgB,CACpC,EAAa,EAAU,OAAQ,GAAyB,EAAE,MAAQ,EAAI,CAAC,EAWvE,WARgB,GACT,EAAU,KAAM,GAAyB,EAAE,MAAQ,EAAI,CAQjE,EC7BQ,EAAoB,KAC7B,IACwB,CACxB,IAAM,EAAa,IAAI,IAAI,gBAAgB,IAASC,EAAAA,EAAoB,CAClE,EAAW,MAAM,MAAM,EAAY,CACrC,QAAS,CACL,eAAgB,EACnB,CACJ,CAAC,CAEF,GAAI,CAAC,EAAS,GACV,MAAU,MAAM,iCAAiC,CAGrD,OAAO,EAAS,MAAM,EAGb,EAA2B,GAA8B,CAClE,6BACA,GAAI,MAAM,QAAQ,EAAO,CAAG,EAAS,CAAC,EAAO,CAChD,CAEY,EAAmB,GAA8B,CAC1D,IAAM,EAAgB,MAAM,QAAQ,EAAO,CAAG,EAAS,CAAC,EAAO,CAE/D,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAAwB,EAAO,CACzC,QAAS,SAAY,CACjB,IAAM,EAAU,MAAM,QAAQ,IAC1B,EAAc,IAAK,GAAO,EAAkB,EAAG,CAAC,CACnD,CAED,OAAO,OAAO,YACV,EAAQ,KAAK,EAAQ,IAAU,CAC3B,IAAM,EAAK,EAAc,GACnB,EAAaC,EAAAA,EAA6B,KAC3C,GAAQ,EAAI,KAAO,EACvB,CACD,MAAO,CACH,EACA,CACI,GAAG,EACH,QAAS,GAAY,QACxB,CACJ,EACH,CACL,EAEL,QAAS,EAAc,OAAS,EAChC,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAAI,EAAa,SAAS,QAAQ,CACjE,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,EChEO,EAAmB,SAA6B,CACzD,GAAI,CACA,IAAM,EAAY,IAAI,IAAI,eAAgBC,EAAAA,EAAsB,CAC1D,EAAW,MAAM,MAAM,EAAU,CAEvC,GAAI,CAAC,EAAS,GACV,MAAU,MAAM,+BAA+B,CAInD,OADa,MAAM,EAAS,MAAM,EACtB,KAAK,QAAU,gBACtB,EAAO,CAEZ,OADA,QAAQ,MAAM,uBAAwB,EAAM,CACrC,wBAIF,OACT,EAAA,EAAA,UAAgB,CACZ,SAAU,CAAC,eAAe,CAC1B,QAAS,EACT,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAAI,EAAa,SAAS,QAAQ,CACjE,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,CC5BA,EAAqB,MACvB,EACA,EACA,IACmB,CAUnB,IAAM,GAAA,EAAA,EAAA,YAAA,EAAA,EAAA,QAA2B,CAP7B,sEAAA,EAAA,EAAA,YAAA,EAAA,EAAA,SAGgC,EAAK,CAAC,CAIc,CAAC,CAAC,CAEpD,EAAM,MAAM,EAAK,UAClB,KACGC,EAAAA,GAAU,EAAQ,CAAC,0BACnBC,EAAAA,4BAA4B,IAC/B,CACA,KAAK,aAAa,EAAQ,CAE/B,GAAI,CAAC,EAAK,MAAU,MAAM,uCAAuC,IAAO,CAExE,OAAO,EAAI,IAGF,EAA8B,GAAiB,CACxD,yCACA,EACH,CAEY,EAAsB,GAAiB,CAEhD,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAA2B,EAAK,CAC1C,YAAe,EAAmB,EAAO,EAAQ,KAAM,EAAK,CAC5D,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EACrB,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAAI,EAAa,SAAS,QAAQ,CACjE,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,EC1DA,EAA4B,GAAKC,EAAAA,EAAK,OAE/B,EAAqB,GAAiB,CAC/C,cACA,aACA,EACH,CASY,IAAgB,EAAc,EAAe,IAAM,CAE5D,IAAM,EAAOC,EAAAA,GAAiB,CAE9B,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAAkB,EAAK,CACjC,QAAS,SAAY,CACjB,GAAI,CAAC,EAAM,MAAU,MAAM,4BAA4B,CACvD,IAAM,EAAW,MAAM,EAAK,aAAa,mBAAmB,EAAM,CAC9D,UAAW,EAAe,EAC1B,WAAY,IACf,CAAC,CAEF,GAAI,CAAC,EAAU,MAAU,MAAM,gCAAgC,CAE/D,OAAO,GAEX,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EACxB,CAAC,ECpCO,GAAiB,MAC1B,EACA,EACA,EACA,IAIC,CACD,IAAM,EAAW,MAAM,EAAK,aAAa,YACrC,EACA,EACA,EACH,CAED,GAAI,EAAS,SAAU,MAAU,MAAM,yBAAyB,CAEhE,IAAI,EAAW,GAAU,UAAY,EAMrC,OAJI,CAAC,GAAY,OAAO,MAAM,EAAS,IACnC,EAAW,GAGR,KAAK,KAAK,EAAS,ECiFjB,GAAsB,CAC/B,uBACA,UACA,gBACA,wBACA,kBACA,iBACA,aACA,mBAC0D,CAE1D,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,SAAQ,sBAAuBC,EAAAA,GAA0B,CAC3D,CAAE,cAAeC,EAAAA,GAAW,CAC5B,CAAE,iBAAkBC,EAAAA,GAAqB,CACzC,EAAUC,EAAAA,GAAe,CAEzB,EAAsBC,EAAAA,GAAgC,CAOtD,GAAA,EAAA,EAAA,aACF,MACI,EAIA,EACA,IAKC,CACD,IAAM,EACF,OAAOC,GAAY,WAAa,MAAMA,GAAS,CAAGA,GAAW,EAAE,CACnE,GAAI,EAAW,qBAAsB,CACjC,GAAI,CAAC,EACD,MAAU,MACN,qGACH,CAEL,OAAO,MAAM,EAAoB,gBAAgB,CAC7C,UAAW,EACX,GAAGC,EACH,cAAA,EACH,CAAC,CAGN,GAAI,CAAC,EACD,MAAU,MAAM,mCAAmC,CAGvD,IAAI,EAAe,EACnB,GAAI,CACI,IACA,EAAe,MAAM,GACjB,EACA,CAAC,GAAG,EAAS,CACb,EACA,CACI,SAAUC,EAAAA,SAAS,KACnB,GAAI,EAAa,CAAE,aAAY,CAAG,EAAE,CACvC,CACJ,QAEA,EAAG,CACR,QAAQ,MAAM,wBAAyB,EAAE,CAsB7C,OAbiB,MAAM,EACnB,EACA,CACI,OAPc,EAAW,wBAA0B,CAAC,EAAW,gBAAkB,EACnF,EACA,EAAO,QAML,IAAK,GAAmB,EACxB,GAAI,GAAe,yBAA2BC,EAAgB,CAC1D,UAAW,CACP,IAAKA,GAAiB,GAAe,cAAgB,GACrD,OAAQ,EACX,CACJ,CAAG,EAAE,CACT,CACJ,EACe,MAEpB,CACI,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EAAW,uBACX,EAAW,eACd,CACJ,CAMK,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAqC,KAAK,CACnD,CAAC,EAAwB,IAAA,EAAA,EAAA,UAAsC,GAAM,CACrE,CAAC,EAAsB,IAAA,EAAA,EAAA,UAE3B,KAAK,CAED,GAAA,EAAA,EAAA,aACF,MAAO,EAAgC,IAA2C,CAC9E,GAAI,CAAC,GAAY,CAAC,EAAS,MAAU,MAAM,uBAAuB,CAClE,GAAI,CACA,EAAU,KAAK,CACf,EAA0B,GAAK,CAC/B,EAAwB,KAAK,CAC7B,EAAS,IAAA,GAAU,CAKnB,EAJiB,MAAM,EAAgB,GAAY,EAAE,CAAE,EAAgB,CACnE,GAAG,EACN,CAAC,CAEiB,OACdC,EAAO,CACZ,EACIA,GAAS,OAAOA,GAAU,UAAY,YAAaA,EAC5CA,EAAM,QACP,OAAOA,EAAM,CACtB,CACD,IACIA,aAAiB,MAAQA,EAAY,MAAM,OAAOA,EAAM,CAAC,CAC5D,QACK,CACN,EAA0B,GAAM,GAGxC,CAAC,EAAiB,EAAS,EAAgB,EAAc,CAC5D,CAKK,CACF,KAAM,EACN,UAAW,EACX,MAAO,GACP,GAAa,GAAU,GAAG,CAOxB,GAAA,EAAA,EAAA,aACF,KAAO,IAAkC,CACjC,MAACC,EAAU,UAAY,CAACA,EAAU,KAAK,MAAQ,CAAC,GAEpD,OAAO,MAAM,EAAK,aAAa,gBAAgBA,EAAU,KAAK,KAAK,EAEvE,CAAC,EAAK,CACT,CAQK,CAAC,EAAO,IAAA,EAAA,EAAA,WAAkD,CAK1D,GAAA,EAAA,EAAA,aAAuB,CACzB,GAAI,EAAwB,MAAO,UAEnC,GAAI,EACA,MAAO,QAGX,GAAI,EAAQ,CACR,GAAI,EAAoB,MAAO,sBAC/B,GAAI,EACA,MAAO,QAEX,GAAI,EAIA,OAHI,EAAU,SACH,QAEJ,UAIf,MAAO,SACR,CACC,EACA,EACA,EACA,EACA,EACA,EACH,CAAC,EAKF,EAAA,EAAA,eAAgB,CACZ,GAAI,IAAW,WAAa,IAAW,QAAS,CAC5C,GAAI,GAAwB,CAAC,EAAO,CAChC,EAAS,CACL,KAAM,oBACN,OAAQ,EACX,CAAC,CACF,OAGJ,GAAI,GAAW,UAAY,CAAC,GAAO,KAAM,EACpC,SAAY,CACT,IAAM,EAAe,MAAM,EAAsB,EAAU,CAE3D,EAAS,CACL,KAAM,oBACN,OAAQ,EACF,8BAAgC,EAChC,uBACT,CAAC,IACF,CACJ,OAGA,GAAa,CAAC,EAAU,UACxB,KAAiB,GAG1B,CACC,EACA,EACA,EACA,EACA,EACH,CAAC,CAKF,IAAM,GAAA,EAAA,EAAA,iBAAgC,CAClC,EAAU,KAAK,CACf,EAA0B,GAAM,CAChC,EAAwB,KAAK,CAC7B,EAAS,IAAA,GAAU,EACpB,EAAE,CAAC,CAkBN,MAAO,CACH,gBAAiB,EACjB,sBAAA,EAAA,EAAA,aAbI,GACA,GACA,IAAW,WACX,IAAW,sBAEhB,CAAC,EAAwB,EAAoB,EAAO,CAAC,CASpD,gCAAA,EAAA,EAAA,aANO,IAAW,UACnB,CAAC,EAAwB,EAAO,CAAC,CAMhC,UAAW,GAAa,KACxB,SACA,cACA,QACH,ECrYQ,GAAqB,EAAc,IAA8B,CAC1E,cACA,cACA,SACA,EACA,EACH,CAOY,GAAgB,GAAiB,CAC1C,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CA2BzC,OAAA,EAAA,EAAA,UAzB6B,CACzB,SAAU,EAAkB,GAAQ,GAAI,EAAQ,KAAK,CACrD,QAAS,SACA,GAEL,EAAA,EAAA,WAAiB,EAAM,CACnB,WAAY,EAAQ,QACvB,CAAC,CAJgB,KAMtB,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EAAQ,KAC7B,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAAI,EAAa,SAAS,QAAQ,CACjE,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,ECrCO,IAAsB,EAAgB,IAAoB,CACnE,IAAM,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,WAAYC,EAAAA,GAAqB,CAgBzC,MAAO,CAAE,QAdO,SAAY,CACxB,MAAM,QAAQ,IAAI,CACd,EAAY,kBAAkB,CAC1B,SAAU,EAAkB,GAAU,GAAI,EAAQ,KAAK,CAC1D,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAUC,EAAAA,EAAuB,EAAQ,EAAQ,KAAK,CACzD,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAUC,EAAAA,EAA2B,EAAQ,CAChD,CAAC,CACL,CAAC,EAGY,EClBhB,GAAeC,EAAAA,EAAE,OAAO,CAC1B,KAAMA,EAAAA,EAAE,QAAQ,CACnB,CAAC,CAEI,GAAwBA,EAAAA,EAAE,OAAO,CACnC,QAASA,EAAAA,EAAE,MAAM,GAAa,CACjC,CAAC,CAYW,GAAsB,MAC/B,EACA,EACA,IAC2B,CAC3B,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CAEpD,IAAM,EAAoBC,EAAAA,GAAU,EAAY,CAAC,kBAM3C,EAAQ;;qBAJS,EACjB,YAAY,EAAQ,aAAa,CAAC,sBAAsB,EAAa,KACrE,YAAY,EAAQ,aAAa,CAAC,IAIR;;;;OAM1B,EAAW,MAAM,MAAM,EAAmB,CAC5C,OAAQ,OACR,QAAS,CACL,eAAgB,mBAChB,OAAQ,mBACX,CACD,KAAM,KAAK,UAAU,CACjB,cAAe,gBACf,QACA,WAAY,EAAE,CACjB,CAAC,CACL,CAAC,CAEF,GAAI,CAAC,EAAS,GACV,MAAU,MAAM,0BAA0B,CAG9C,IAAM,EAAO,MAAM,EAAS,MAAM,CASlC,OANI,EAAK,MAAQ,EAAK,KAAK,UACvB,EAAK,KAAK,QAAU,EAAK,KAAK,QAAQ,OACjC,GAAgB,CAAC,EAAO,KAAK,SAAS,eAAe,CACzD,EAGE,GAAsB,MAAM,EAAK,KAAK,EAGpC,GACT,EACA,IACC,CAAC,cAAe,cAAe,EAAS,EAAa,CAQ7C,IACT,EACA,IACC,CACD,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAA4B,EAAS,EAAa,CAC5D,YAAe,GAAoB,EAAQ,KAAM,EAAS,EAAa,CACvE,QAAS,CAAC,CAAC,GAAW,CAAC,CAAC,EAAQ,KAChC,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,sBACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,EC3FO,EAAoC,MAC7C,EACA,EACA,EACA,EACA,EACA,IACgB,CAEhB,MAAM,QAAQ,IAAI,CACd,EAAY,kBAAkB,CAC1B,SAAUC,EAAAA,EAAyB,EAAQ,CAC9C,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAUA,EAAAA,EAAyB,EAAW,CACjD,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAU,EAA2B,EAAU,CAClD,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAU,EAA4B,EAAS,OAAO,CACzD,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAU,EAA4B,EAAS,eAAe,CACjE,CAAC,CACF,EAAY,kBAAkB,CAC1B,SAAUC,EAAAA,EAAuB,EAAW,CAC/C,CAAC,CACL,CAAC,CAGF,MAAM,QAAQ,IAAI,CACd,EAAY,eAAe,CACvB,SAAUD,EAAAA,EAAyB,EAAQ,CAC9C,CAAC,CACF,EAAY,eAAe,CACvB,SAAUA,EAAAA,EAAyB,EAAW,CACjD,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EAA4B,EAAS,OAAO,CACzD,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EAA4B,EAAS,eAAe,CACjE,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EAAkB,EAAY,IAAM,EAAQ,EAAY,CACrE,CAAC,CACF,EAAY,eAAe,CACvB,SAAUC,EAAAA,EAAuB,EAAW,CAC/C,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EAA2B,EAAU,CAClD,CAAC,CACF,EAAY,eAAe,CACvB,SAAUC,EAAAA,EAA2B,EAAQ,CAChD,CAAC,CACL,CAAC,ECzCA,GAA4BC,EAAAA,iCAAiC,iBAAiB,CAC9EC,EAA4BC,EAAAA,oCAAoC,iBAAiB,CAEjF,IAAgC,EAAmB,EAAgB,EAAuB,EAAiB,IAA8D,CAC3K,IAAMC,EAAsB,EAAE,CAE9B,GAAI,CAAC,EAAW,MAAU,MAAM,oBAAoB,CAEpD,IAAM,EAAa,GAAG,EAAU,GAAG,IAenC,GAZA,EAAa,KAAK,CACd,GAAIC,EAAAA,GAAU,EAAQ,KAAK,CAAC,kCAC5B,MAAO,MACP,KAAMH,EAA0B,mBAAmB,UAAW,CAAC,GAAG,CAAC,CACnE,QAAS,0DAA0DI,EAAAA,EAC/D,GAAS,SAAW,GACpB,EACA,EACH,GACD,IAAKJ,EAA0B,YAAY,UAAU,CACxD,CAAC,CAEE,EAAc,CAEd,EAAa,KAAK,CACd,GAAIG,EAAAA,GAAU,EAAQ,KAAK,CAAC,kCAC5B,MAAO,MACP,KAAMH,EAA0B,mBAAmB,UAAW,CAC1D,EACH,CAAC,CACF,QAAS,oCAAoC,IAC7C,IAAKA,EAA0B,YAAY,UAAU,CACxD,CAAC,CAGF,IAAM,EAA0B,IAAI,EAAA,OAAO,UAAU,CACjD,+CACH,CAAC,CAGI,EAAa,EAAA,OAAO,SAAS,EAAW,CAE9C,EAAa,KAAK,CACd,GAAIG,EAAAA,GAAU,EAAQ,KAAK,CAAC,gCAC5B,MAAO,MACP,KAAM,EAAwB,mBAAmB,UAAW,CACxD,EACA,GAAS,SAAW,GACvB,CAAC,CACF,QAAS,2BAA2B,EAAW,MAAMC,EAAAA,EACjD,GAAS,SAAW,GACpB,EACA,EACH,GACD,IAAK,EAAwB,YAAY,UAAU,CACtD,CAAC,SAEE,GAAgB,EAAO,CAEvB,EAAa,KAAK,CACd,GAAID,EAAAA,GAAU,EAAQ,KAAK,CACtB,uCACL,MAAO,MACP,KAAM,GAA0B,mBAC5B,QACA,CACI,EACAA,EAAAA,GAAU,EAAQ,KAAK,CAClB,gCACR,CACJ,CACD,QAAS,4BAA4B,EAAU,GAAG,IAClD,IAAK,GAA0B,YAAY,QAAQ,CACtD,CAAC,CAEF,EAAa,KAAK,CACd,GAAIA,EAAAA,GAAU,EAAQ,KAAK,CACtB,kCACL,MAAO,MACP,KAAMH,EAA0B,mBAC5B,UACA,CAAC,EAAY,IAAM,EAAO,CAC7B,CACD,QAAS,OAAO,EAAU,GAAG,EAAO,0CAA0CI,EAAAA,EAC1E,GAAS,SAAW,GACpB,EACA,EACH,GACD,IAAKJ,EAA0B,YAAY,UAAU,CACxD,CAAC,MAEF,MAAU,MACN,kDACH,CAIT,OAAO,GAQE,IAA4B,CACrC,YACA,SACA,YACA,UACA,eAAe,MACuD,CACtE,IAAM,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,WAAYK,EAAAA,GAAW,CACzB,CAAE,WAAYC,EAAAA,GAAqB,CACnC,CAAE,QAAS,GAAoB,GACjC,EAAY,IAAM,EAClB,GAAS,SAAW,GACvB,CAEK,GAAA,EAAA,EAAA,iBAA4B,GAA6B,EAAW,EAAQ,EAAc,EAAS,EAAQ,CAAE,CAAC,EAAW,EAAQ,EAAc,EAAS,EAAQ,CAAC,CAGjK,GAAA,EAAA,EAAA,aAA8B,SAAY,CAC5C,IAAM,EAAa,GAAG,EAAU,GAAG,IAGnC,MAAM,EACF,EAHY,GAAS,SAAW,GAKhC,EACA,EACA,EACA,EAAQ,KACX,CAGD,GAAiB,CACjB,KAAa,EACd,CACC,EACA,EACA,EACA,EACA,EACA,EAAQ,KACR,EACH,CAAC,CAEI,EAAS,EAAmB,CAC9B,qBAAsB,GAAS,SAAW,GAC1C,eAAgB,CACZ,MAAO,sCACP,YAAa,SAAS,EAAU,GAAG,EAAO,2BAC1C,WAAY,mBACf,CACD,cAAe,EACf,0BAA6B,CACzB,KAAW,EAElB,CAAC,CAEF,MAAO,CACH,GAAG,EACH,UACA,gBAAiB,SACN,EAAO,gBAAgB,GAAS,CAAC,CAE/C,EAGC,GAAmB,GACd,EAAO,SAAS,cAAc,CCjLnCC,GAA4BC,EAAAA,oCAAoC,iBAAiB,CAE1E,IACT,EACA,EACA,EACA,IACsB,CACtB,IAAMC,EAAsB,EAAE,CAE9B,GAAI,CAAC,EAAQ,MAAU,MAAM,iBAAiB,CAE9C,GAAI,EAAc,CAEd,EAAa,KAAK,CACd,GAAIC,EAAAA,GAAU,EAAQ,KAAK,CAAC,kCAC5B,MAAO,MACP,KAAMH,GAA0B,mBAAmB,UAAW,CAC1D,EACH,CAAC,CACF,QAAS,oCAAoC,IAC7C,IAAKA,GAA0B,YAAY,UAAU,CACxD,CAAC,CAGF,IAAM,EAA0B,IAAI,EAAA,OAAO,UAAU,CACjD,+CACH,CAAC,CAGI,EAAa,EAAA,OAAO,SAAS,EAAO,CAE1C,EAAa,KAAK,CACd,GAAIG,EAAAA,GAAU,EAAQ,KAAK,CAAC,gCAC5B,MAAO,MACP,KAAM,EAAwB,mBAAmB,UAAW,CACxD,EACA,GAAS,SAAW,GACvB,CAAC,CACF,QAAS,2BAA2B,EAAO,MAAMC,EAAAA,EAC7C,GAAS,SAAW,GACpB,EACA,EACH,GACD,IAAK,EAAwB,YAAY,UAAU,CACtD,CAAC,MAEF,MAAU,MAAM,6CAA6C,CAGjE,OAAO,GAQE,IAAqB,CAC9B,SACA,YACA,UACA,eAAe,MACyC,CACxD,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CACnC,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,WAAYC,EAAAA,GAAW,CAEzB,CAAE,QAAS,GAAoB,GACjC,EACA,GAAS,SAAW,GACvB,CAEK,GAAA,EAAA,EAAA,iBACI,GAAsB,EAAQ,EAAc,EAAS,EAAQ,CACnE,CAAC,EAAQ,EAAc,EAAS,EAAQ,CAC3C,CAGK,GAAA,EAAA,EAAA,aAA8B,SAAY,CAG5C,MAAM,EACF,EAHY,GAAS,SAAW,GAKhC,EACA,GACA,EAAO,SAAS,OAAO,CAAG,EAAS,GAAG,EAAO,MAC7C,EAAQ,KACX,CAGD,GAAiB,CAEjB,KAAa,EACd,CACC,EACA,EACA,EACA,EACA,EAAQ,KACR,EACH,CAAC,CAEI,EAAS,EAAmB,CAC9B,qBAAsB,GAAS,SAAW,GAC1C,eAAgB,CACZ,MAAO,sCACP,YAAa,SAAS,EAAO,2BAC7B,WAAY,mBACf,CACD,cAAe,EACf,sBAAuB,EAC1B,CAAC,CAEF,MAAO,CACH,GAAG,EACH,UACA,gBAAiB,SACN,EAAO,gBAAgB,GAAS,CAAC,CAE/C,EC/IQ,GAAgC,GAAoB,CAC7D,qBACA,EACA,sBACH,CAGK,GAAsBC,EAAAA,YAAY,MAAMC,EAAAA,iCAAiC,IAAW,CAEpF,GAAuB,MACzB,EACA,EACA,IACC,CACD,IAAM,EACFC,EAAAA,GAAU,EAAQ,CAAC,uCAMvB,OAJY,MAAM,EAAK,UAClB,KAAK,EAAiB,GAAoB,IAAI,CAC9C,KAAK,kBAAkB,EAAO,EAExB,IAUF,IAAwB,EAAiB,EAAU,KAAS,CAErE,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAA6B,EAAO,CAC9C,YAAe,GAAqB,EAAO,EAAQ,KAAM,EAAO,CAChE,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAU,GAAW,CAAC,CAAC,EAAQ,KACpD,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GACI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,CAE9B,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,ECxDAC,GAAgB,IAAIC,EAAAA,UAAU,CAChC,oEACA,oEACH,CAAC,CAoBW,IAAgB,EAAyB,IAA6D,CAC/G,IAAM,EAAU,EAAE,CAElB,IAAK,GAAM,CAAE,SAAQ,MAAK,WAAW,EAAQ,CACzC,GAAI,CAAC,EAAQ,MAAU,MAAM,qBAAqB,CAClD,GAAI,CAAC,EACD,MAAU,MAAM,+BAA+B,CAEnD,IAAM,GAAA,EAAA,EAAA,UAAgB,EAAO,CAE7B,EAAQ,KAAK,CACT,GAAI,EACJ,KAAMD,GAAc,mBAAmB,UAAW,CAC9C,EACA,EACA,EACH,CAAC,CACF,MAAO,IACP,QAAS,UAAU,EAAI,SAC1B,CAAC,CAEN,OAAO,GAGE,IAAuB,CAChC,YACA,UACA,uBACA,mBAC0B,EAAE,GAAqC,CAEjE,IAAM,GAAA,EAAA,EAAA,aACD,GAAwC,CACrC,GAAI,CAAC,EACD,MAAU,MAAM,+BAA+B,CAEnD,OAAO,GAAa,EAAiB,EAAO,EAEhD,CAAC,EAAgB,CACpB,CAEK,EAAS,EAAmB,CAC9B,uBACA,cAAe,SAAY,CACvB,MAAM,KAAa,EAEvB,sBAAuB,SAAY,CAC/B,MAAM,KAAW,EAErB,eAAgB,CACZ,MAAO,6BACP,YACI,6DACJ,WAAY,mBACf,CACJ,CAAC,CAEF,MAAO,CACH,GAAG,EACH,QAAS,EACT,gBAAiB,KAAO,IACb,EAAO,gBAAgB,EAAqB,EAAO,CAAC,CAElE,ECvFQ,GAA8B,GAAoB,CAC3D,cACA,mBACA,EACH,CAOY,GAAyB,GAAoB,CACtD,GAAM,CAAE,WAAYE,EAAAA,GAAqB,CAEzC,OAAOC,EAAAA,EAAc,CACjB,QAASC,EAAAA,GAAU,EAAQ,KAAK,CAAC,0BACjC,IAAKC,EAAAA,4BAA4B,IACjC,OAAQ,WACR,KAAM,CAAC,GAAA,EAAA,EAAA,UAAkB,EAAO,CAAG,KAAK,CACxC,aAAc,CACV,OAAS,GAAS,EAAK,GACvB,QAAS,CAAC,CAAC,EACd,CACJ,CAAC,ECHA,EAAgB,IAAIC,EAAAA,UAAU,CAChC,oEACA,kEACH,CAAC,CAEI,GAAkB,IAAIA,EAAAA,UAAU,CAClC,2DACA,iDACH,CAAC,CAUW,GAAkB,MAC3B,EACA,EACA,IACyB,CACzB,GAAI,CAAC,EAAM,MAAU,MAAM,mBAAmB,CAE9C,IAAM,GAAA,EAAA,EAAA,UAAgB,EAAK,CAE3B,GAAI,CAEA,IAAM,EAAc,IAAI,IAAI,aAAc,EAAQ,CAkB5C,CAAC,CAAE,KAAM,EAAc,SAAU,IACnC,MAlBqB,MAAM,MAAM,EAAa,CAC9C,OAAQ,OACR,QAAS,CACL,eAAgB,mBACnB,CACD,KAAM,KAAK,UAAU,CACjB,QAAS,CACL,CACI,GAAIC,EAAAA,GAAU,EAAY,CAAC,0BAC3B,KAAM,EAAc,mBAAmB,WAAY,CAC/C,EACH,CAAC,CACL,CACJ,CACJ,CAAC,CACL,CAAC,EAGyB,MAAM,CAEjC,GAAI,EACA,OAAO,KAGX,GAAM,CAAE,mBAAoB,EAAc,qBACtC,WACA,EACH,CAqBK,CAAC,CAAE,KAAM,EAAY,SAAU,IACjC,MAnBmB,MAAM,MAAM,EAAa,CAC5C,OAAQ,OACR,QAAS,CACL,eAAgB,mBACnB,CACD,KAAM,KAAK,UAAU,CACjB,QAAS,CACL,CACI,GAAI,EACJ,KAAM,EAAc,mBAAmB,OAAQ,CAC3C,EACA,SACH,CAAC,CACL,CACJ,CACJ,CAAC,CACL,CAAC,EAGuB,MAAM,CAE/B,GAAI,GAAY,IAAe,KAC3B,OAAO,KAGX,GAAI,CACA,GAAM,CAAE,UAAW,EAAc,qBAC7B,OACA,EACH,CACK,EAAe,IAAW,GAAK,KAAO,EAI5C,OAFK,EAEE,GAAkB,EAAc,EAAa,EAAQ,CAFlC,WAGrB,EAAa,CAElB,OADA,QAAQ,MAAM,gCAAiC,EAAY,CACpD,YAEN,EAAO,CAEZ,MADA,QAAQ,MAAM,0CAA2C,EAAM,CACzD,IAID,IACT,EACA,IACC,CAAC,cAAe,cAAe,SAAU,SAAU,EAAM,EAAY,CAE1E,eAAe,GACX,EACA,EACA,EACsB,CACtB,GAAI,CAEA,GACI,EAAO,WAAW,OAAO,EACzB,EAAO,WAAW,UAAU,EAC5B,EAAO,WAAW,QAAQ,CAE1B,OAAOC,EAAAA,EAAgB,EAAQ,EAAY,EAAI,KAInD,IAAM,EAAQ,EAAO,MACjB,kDACH,CACD,GAAI,EAAO,CACP,GAAM,EAAG,EAAS,EAAiB,GAAW,EACxC,EAAY,EAAO,SAAS,UAAU,CAE5C,GAAI,CAAC,GAAW,CAAC,GAAmB,IAAY,IAAA,GAC5C,OAAO,KAIX,IAAM,EAAU,CACZ,CACI,GAAI,EACJ,KAAM,GAAgB,mBAClB,EAAY,MAAQ,WACpB,CAAC,OAAO,GAAW,EAAE,CAAC,CACzB,CACJ,CACJ,CAEK,EAAc,IAAI,IAAI,aAAc,EAAQ,CAC5C,CAAC,CAAE,OAAM,aAAc,MAAM,MAAM,EAAa,CAClD,OAAQ,OACR,QAAS,CACL,eAAgB,mBACnB,CACD,KAAM,KAAK,UAAU,CAAE,UAAS,CAAC,CACpC,CAAC,CAAC,KAAM,GAAQ,EAAI,MAAM,CAAC,CAE5B,GAAI,EAEA,OADA,QAAQ,MAAM,2BAA2B,CAClC,KAGX,IAAI,EAAW,GACf,GAAI,CACA,EAAW,GAAgB,qBACvB,EAAY,MAAQ,WACpB,EACH,CAAC,SACG,EAAG,CACR,QAAQ,MAAM,gCAAiC,EAAE,CACjD,GAAA,EAAA,EAAA,cAAwB,EAAK,CAIjC,EAAWA,EAAAA,EAAgB,EAAU,EAAY,EAAI,EAEjD,IACA,EAAW,EAAS,QAChB,QAAA,EAAA,EAAA,eAAA,EAAA,EAAA,SACqB,OAAO,GAAW,EAAE,CAAC,CAAE,GAAG,CAAC,MAAM,EAAE,CAC3D,EAGL,IAAM,EAAmB,MAAM,MAAM,EAAS,CAC9C,GAAI,CAAC,EAAiB,GAElB,OADA,QAAQ,MAAM,2BAA2B,CAClC,KAGX,IAAM,EAAW,MAAM,EAAiB,MAAM,CACxC,EACF,EAAS,OAAS,EAAS,WAAa,EAAS,WAQrD,OANK,EAMEA,EAAAA,EAAgB,EAAU,EAAY,EAAI,GAL7C,QAAQ,MAAM,2BAA2B,CAClC,MAOf,OAAO,WACF,EAAO,CAEZ,OADA,QAAQ,MAAM,+BAAgC,EAAM,CAC7C,MASf,MAAa,GAAsB,GAAiB,CAChD,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CACnC,EAAU,EAAQ,SAAWF,EAAAA,GAAU,EAAQ,KAAK,CAAC,QAY3D,OAAA,EAAA,EAAA,UAV6B,CACzB,SAAU,GAAwB,GAAQ,GAAI,EAAQ,KAAK,CAC3D,QAAS,SACA,EAEE,GAAgB,EAAQ,KAAM,EAAS,EAAK,CAFjC,KAItB,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAW,CAAC,CAAC,EAAQ,KAC7C,CAAC,ECpOA,GAA4BG,EAAAA,oCAAoC,iBAAiB,CAEjF,IAA2B,EAAiB,IAA8D,CAC5G,IAAMC,EAAsB,EAAE,CAe9B,OAZA,EAAa,KAAK,CACd,GAAIC,EAAAA,GAAU,EAAQ,KAAK,CAAC,kCAC5B,MAAO,MACP,KAAM,GAA0B,mBAAmB,UAAW,CAAC,GAAG,CAAC,CACnE,QAAS,0DAA0DC,EAAAA,EAC/D,GAAS,SAAW,GACpB,EACA,EACH,GACD,IAAK,GAA0B,YAAY,UAAU,CACxD,CAAC,CAEK,GASE,IAAkB,CAC3B,YACA,aACkD,CAClD,IAAM,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,WAAYC,EAAAA,GAAW,CACzB,CAAE,WAAYC,EAAAA,GAAqB,CAEnC,GAAA,EAAA,EAAA,iBAA4B,GAAwB,EAAS,EAAQ,CAAE,CAAC,EAAS,EAAQ,CAAC,CAG1F,GAAA,EAAA,EAAA,aAA8B,SAAY,CAI5C,MAAM,EACF,EAJY,GAAS,SAAW,GAMhC,GACA,GACA,GACA,EAAQ,KACX,CAED,KAAa,EACd,CAAC,EAAW,EAAa,EAAS,EAAQ,KAAK,CAAC,CAE7C,EAAS,EAAmB,CAC9B,qBAAsB,GAAS,SAAW,GAC1C,eAAgB,CACZ,MAAO,sCACP,YAAa,sCACb,WAAY,mBACf,CACD,cAAe,EACf,sBAAuB,EAC1B,CAAC,CAEF,MAAO,CACH,GAAG,EACH,UACA,gBAAiB,SACN,EAAO,gBAAgB,GAAS,CAAC,CAE/C,EC3FQ,GAAoB,MAAO,EAAkB,IAAqB,CAC3E,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CACpD,IAAM,EAAU,MAAM,EAAK,SAAS,WAAWC,EAAAA,QAAQ,GAAG,EAAQ,CAAC,CAEnE,MAAO,CACH,SAAA,EAAA,EAAA,aAAqB,OAAO,EAAQ,QAAQ,CAAC,CAAC,UAAU,CACxD,QAAA,EAAA,EAAA,aAAoB,OAAO,EAAQ,OAAO,CAAC,CAAC,UAAU,CACzD,EAEQ,GAA6B,GAAqB,CAC3D,sBACA,EACH,CAOY,GAAqB,GAAqB,CAEnD,IAAM,EAAOC,EAAAA,GAAiB,CAC9B,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAA0B,EAAQ,CAC5C,YAAe,GAAkB,EAAO,EAAQ,CAChD,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAWD,EAAAA,QAAQ,QAAQ,EAAQ,CACxD,gBAAiB,IACpB,CAAC,EC5BO,GAA0B,GAAqB,CACxD,sBACA,EACA,OACH,CAEY,GAAqB,GAAqB,CACnD,GAAM,CAAE,WAAYE,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAuB,EAAQ,CACzC,QAAS,SAAY,CACjB,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CACpD,IAAM,EAAM,MAAA,EAAA,EAAA,gBAAqB,EAAS,CACtC,WAAY,EAAQ,QACvB,CAAC,CAEF,GAAI,CAAC,EAAK,MAAU,MAAM,6BAA6B,CAEvD,IAAM,EAAW,EAAI,GACrB,OAAOC,EAAAA,EAAmB,EAAS,EAEvC,QAAS,CAAC,CAAC,GAAW,CAAC,CAAC,EAAQ,KACnC,CAAC,ECvBO,GAA0B,GAAqB,CACxD,sBACA,EACA,OACH,CAEY,GAAqB,GAAqB,CACnD,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAuB,EAAQ,CACzC,QAAS,SAAY,CACjB,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CACpD,IAAM,EAAM,MAAA,EAAA,EAAA,gBAAqB,EAAS,CACtC,WAAY,EAAQ,QACvB,CAAC,CAEF,GAAI,CAAC,EAAK,MAAU,MAAM,6BAA6B,CAEvD,IAAM,EAAW,EAAI,GACrB,OAAOC,EAAAA,EAAmB,EAAS,EAEvC,QAAS,CAAC,CAAC,GAAW,CAAC,CAAC,EAAQ,KACnC,CAAC,ECtBO,IACT,EACA,IACC,CAAC,cAAe,UAAW,QAAS,EAAc,EAAQ,CAElD,GAAsB,EAAsB,IAAqB,CAC1E,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAwB,EAAc,EAAQ,CACxD,QAAS,SAAY,CACjB,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CACpD,IAAM,EAAM,MAAA,EAAA,EAAA,iBAAsB,EAAc,EAAS,CACrD,WAAY,EAAQ,QACvB,CAAC,CAEF,GAAI,CAAC,EAAK,MAAU,MAAM,6BAA6B,CAEvD,IAAM,EAAW,EAAI,GACrB,OAAOC,EAAAA,EAAmB,EAAS,EAEvC,QAAS,CAAC,CAAC,GAAW,CAAC,CAAC,EAAQ,KACnC,CAAC,ECxBO,EAAe,MAAO,EAAsB,KACrD,EAAA,EAAA,cAAgC,EAAc,CAC1C,aACH,CAAC,CAGO,GAA8B,GAAyB,CAChE,gCACA,EACH,CAEY,EAAyB,GAAyB,CAC3D,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAiC,CAC7B,SAAU,GAA2B,EAAa,CAClD,QAAS,SAAY,CACjB,GAAI,CAAC,EAAc,MAAU,MAAM,4BAA4B,CAC/D,GAAI,CAAC,EAAQ,QAAS,MAAU,MAAM,+BAA+B,CACrE,OAAO,EAAa,EAAc,EAAQ,QAAQ,EAEtD,QAAS,CAAC,CAAC,EAAQ,MAAQ,CAAC,CAAC,EAC7B,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,6BACjB,IAAiB,+BACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,ECjCO,OAAwB,CACjC,GAAM,CAAC,EAAc,GAAmBC,EAAAA,EACpCC,EAAAA,EAAgB,cAChB,EAAE,CACL,CACK,CAAE,WAAYC,EAAAA,GAAqB,CAEnC,EAAW,KAAO,IAAwC,CAC5D,GAAI,CAAC,EAAgB,EAAQ,EAAI,CAAC,EAAe,EAAQ,CAAE,CACvD,GAAI,CAAC,EAAQ,QAAS,MAAU,MAAM,+BAA+B,CAGrE,IAAMC,EAAyB,CAC3B,GAHc,MAAM,EAAc,EAAS,EAAQ,QAAQ,CAI3D,UACH,CAED,EAAgB,CAAC,GAAG,EAAc,EAAM,CAAC,GAI3C,EAAe,GAAoB,CACrC,EACI,EAAa,OAAQ,GAAuB,EAAE,UAAY,EAAQ,CACrE,EAGC,EAAmB,GACd,EAAa,KAAM,GACtBC,EAAAA,EAAiB,EAAE,QAAS,EAAQ,CACvC,CAGC,EAAkB,GAAoB,CAExC,IAAM,EAAoB,CACtB,IAAK,KACL,KAAMC,EAAAA,GAAU,EAAQ,KAAK,CAAC,oBAC9B,KAAMA,EAAAA,GAAU,EAAQ,KAAK,CAAC,oBAC9B,KAAMA,EAAAA,GAAU,EAAQ,KAAK,CAAC,oBAC9B,WAAYA,EAAAA,GAAU,EAAQ,KAAK,CAAC,WACvC,CAED,OAAO,OAAO,OAAO,EAAkB,CAAC,SAAS,EAAQ,EAG7D,MAAO,CACH,eACA,WACA,cACA,kBACA,iBACH,EClDQ,IACT,EACA,IACC,CAAC,sBAAuB,EAAS,eAAgB,EAAa,CAEtD,GAA6B,GAAqB,CAC3D,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CACnC,CAAE,gBAAiB,IAAiB,CAE1C,OAAA,EAAA,EAAA,YAAkB,CACd,QAAS,EAAa,IAAK,IAAW,CAClC,SAAU,GAA8B,EAAM,QAAS,EAAQ,CAC/D,QAAS,SAAY,CACjB,GAAI,CAAC,EAAM,QAAS,MAAU,MAAM,4BAA4B,CAChE,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CACpD,GAAI,CAAC,EAAQ,QAAS,MAAU,MAAM,+BAA+B,CACrE,IAAM,EAAuB,MAAA,EAAA,EAAA,iBAAsB,EAAM,QAAS,EAAS,CACvE,WAAY,EAAQ,QACvB,CAAC,CACF,GAAI,CAAC,EAAsB,MAAU,MAAM,8BAA8B,CACzE,IAAM,EAAwBC,EAAAA,EAAmB,EAAqB,GAAG,CACzE,MAAO,CACH,GAAG,EACH,GAAG,EACN,EAER,EAAE,CACN,CAAC,ECtBO,EAAoB,GAAqB,CAClD,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CACnC,EAASC,EAAAA,GAAU,EAAQ,KAAK,CAGhC,CAAE,KAAM,EAAS,UAAW,GAAe,GAAkB,EAAQ,CACrE,CAAE,KAAM,EAAa,UAAW,GAClC,GAAkB,EAAQ,CACxB,CAAE,KAAM,EAAa,UAAW,GAClC,GAAkB,EAAQ,CACxB,CAAE,KAAM,EAAmB,UAAW,GACxC,EAAmB,EAAO,+BAAgC,EAAQ,CAChE,CAAE,KAAM,EAAkB,UAAW,GACvC,EAAmB,EAAO,yBAA0B,EAAQ,CAG1D,EAA6B,GAA0B,EAAQ,CAC/D,EAAsB,EACvB,IAAK,GAAU,EAAM,KAAK,CAC1B,OAAO,QAAQ,CACd,EAAsB,EAA2B,KAClD,GAAU,EAAM,UACpB,CA+ED,MAAO,CACH,UAAA,EAAA,EAAA,aA7E2B,CAC3B,GAAI,CAAC,EAAS,MAAO,EAAE,CAGvB,IAAM,EAAoB,CACtB,IAAK,KACL,KAAM,EAAO,oBACb,KAAM,EAAO,oBACb,KAAM,EAAO,oBACb,WAAY,EAAO,WACnB,OAAQ,EAAO,yBAClB,CAGKC,EAAmC,CACrC,CACI,QAAS,EAAkB,IAC3B,OAAQ,MACR,QAAS,GAAS,SAAW,IAChC,CACD,CACI,QAAS,EAAkB,KAC3B,OAAQ,OACR,QAAS,GAAS,QAAU,IAC/B,CACD,CACI,QAAS,EAAkB,KAC3B,OAAQ,OACR,QAAS,GAAa,QAAU,IACnC,CACD,CACI,QAAS,EAAkB,KAC3B,OAAQ,OACR,QAAS,GAAa,QAAU,IACnC,CACD,CACI,QAAS,EAAkB,WAC3B,OAAQ,aACR,QAAS,GAAmB,QAAU,IACzC,CACD,CACI,QAAS,EAAkB,OAC3B,OAAQ,SACR,QAAS,GAAkB,QAAU,IACxC,CACJ,CAGKC,EAAqC,EAAoB,IAC1D,IAAW,CACR,QAAS,GAAO,SAAW,GAC3B,OAAQ,GAAO,QAAU,GACzB,QAAS,GAAO,QAAU,IAC7B,EACJ,CAED,MAAO,CAAC,GAAG,EAAY,GAAG,EAAa,EACxC,CACC,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EAAQ,KACX,CAAC,CAYE,UATA,GACA,GACA,GACA,GACA,GACA,EAKH,EC9GQ,GAAiB,CAC1B,KAAM,qEACN,IAAK,qEACL,KAAM,qEACN,IAAK,qEACL,IAAK,qEACR,CAKY,GAAmB,MAC5B,EACA,EACA,IACkB,CAClB,IAAM,EAAM,MAAM,EAAK,UAClB,KACGC,EAAAA,GAAU,EAAQ,CAAC,sBACnBC,EAAAA,6BAA6B,IAChC,CACA,KAAK,eAAe,GAAe,GAAO,CAE/C,GAAI,CAAC,EAAK,MAAU,MAAM,0BAA0B,IAAQ,CAE5D,OAAO,IAAIC,EAAAA,UAAU,EAAI,GAAG,UAAU,CAAC,CAAC,IAAI,aAAK,CAAC,UAAU,EAGnD,GAA4B,GAA0B,CAC/D,oBACA,EACH,CAEY,EAAuB,GAA0B,CAE1D,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAyB,EAAM,CACzC,QAAS,SAAY,GAAiB,EAAO,EAAO,EAAQ,KAAK,CACjE,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EAAQ,KAC7B,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAAI,EAAa,SAAS,QAAQ,CACjE,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,ECvDO,OAAuB,CAChC,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CACnC,EAASC,EAAAA,GAAU,EAAQ,KAAK,CAGhC,CAAE,KAAM,EAAa,UAAW,GAClC,EAAoB,MAAM,CACxB,CAAE,KAAM,EAAc,UAAW,GACnC,EAAoB,OAAO,CACzB,CAAE,KAAM,EAAc,UAAW,GACnC,EAAoB,OAAO,CACzB,CAAE,KAAM,EAAa,UAAW,GAClC,EAAoB,MAAM,CACxB,CAAE,KAAM,EAAa,UAAW,GAClC,EAAoB,MAAM,CAgD9B,MAAO,CACH,QAAA,EAAA,EAAA,aA9CyB,CACzB,IAAM,EAAoB,CACtB,IAAK,KACL,KAAM,EAAO,oBACb,KAAM,EAAO,oBACb,KAAM,EAAO,oBACb,WAAY,EAAO,WACnB,OAAQ,EAAO,yBAClB,CAED,MAAO,EACF,EAAkB,KAAM,GAAe,GACvC,EAAkB,MAAO,GAAgB,GACzC,EAAkB,MAAO,GAAgB,GAEzC,EAAkB,MAAO,GAAgB,GACzC,EAAkB,YAAa,GAAgB,GAC/C,EAAkB,QAAS,EAC/B,EACF,CACC,EACA,EACA,EACA,EAAO,oBACP,EAAO,oBACP,EAAO,oBACP,EAAO,WACP,EAAO,yBACV,CAAC,CAmBE,eAAA,EAAA,EAAA,cAhBO,CACH,YAAa,GAAe,EAC5B,YAAa,GAAe,EAC/B,EACD,CAAC,EAAa,EAAY,CAC7B,CAYG,UATA,GACA,GACA,GACA,GACA,EAMH,ECvEQ,IACT,EACA,EACA,IACS,CACT,OAAQ,EAAR,CACI,IAAK,MACD,OAAO,EAAY,EAAc,YACrC,IAAK,MACD,OAAO,EAAY,EAAc,YACrC,QACI,OAAO,IAIN,IACT,EACA,EAAM,KACN,IACS,CACT,IAAMC,EAA2C,CAC7C,MAAO,WACP,sBAAuB,EACvB,sBAAuB,EACvB,SAAU,GAAS,UAAY,MAC/B,GAAG,EACN,CAED,OAAO,IAAI,KAAK,aAAaC,EAAAA,GAAmB,GAAM,EAAe,CAAC,OAAO,EAAM,EAG1E,IACT,EACA,IAEO,GACH,EACAC,EAAAA,GAAK,iBACL,CACI,SAAU,UACV,eAAgB,QAChB,SAAU,GAAS,UAAY,MAC/B,GAAG,EACN,CACJ,CC3CC,GAAc,uBACdC,GAA4B,CAAC,MAAO,MAAO,MAAM,CAQ1C,OAAoB,CAC7B,GAAM,CAAE,kBAAiB,eAAgBC,EAAAA,GAAqB,CAe9D,OAZA,EAAA,EAAA,eAAgB,CACZ,EAAA,EAAoB,uBAAa,EAAgB,EAClD,CAAC,EAAgB,CAAC,CAUd,CACH,kBACA,iBACA,eAXoB,GAA0B,CAC9C,GAAI,CAAC,GAAc,SAAS,EAAY,CAAE,CACtC,QAAQ,MAAM,qBAAqB,IAAc,CACjD,OAEJ,EAAY,EAAY,EAO3B,EChBQ,IAAuB,CAChC,UAAU,MACkB,CAC5B,GAAM,CAAE,WAAU,UAAW,GAAoB,EAAiB,EAAQ,CACpE,CACF,SACA,gBACA,UAAW,GACX,IAAgB,CACd,CAAE,mBAAoB,IAAa,CAEnC,GAAA,EAAA,EAAA,aACK,EAAS,IAAK,GAAU,CAC3B,IAAM,EAAW,EAAO,EAAM,UAAY,EACpC,EAAW,OAAO,EAAM,QAAQ,CAAG,EACnC,EAAkB,GACpB,EACA,EACA,EACH,CAED,MAAO,CACH,GAAG,EACH,WACA,WACA,kBACH,EACH,CACH,CAAC,EAAU,EAAQ,EAAiB,EAAc,CAAC,CAGhD,GAAA,EAAA,EAAA,aACK,CAAC,GAAG,EAAiB,CAAC,MACxB,EAAG,IAAM,EAAE,gBAAkB,EAAE,gBACnC,CACF,CAAC,EAAiB,CAAC,CAStB,MAAO,CACH,OAAQ,EACR,eACA,mBAAA,EAAA,EAAA,aARO,EAAa,OAAQ,GAAU,OAAO,EAAM,QAAQ,CAAG,EAAE,CACjE,CAAC,EAAa,CAAC,CAQd,UANc,GAAmB,EAOpC,ECxDQ,IAAmB,CAAE,UAAU,MAA+B,CACvE,GAAM,CAAE,oBAAmB,aAAc,GAAoB,CAAE,UAAS,CAAC,CACnE,CAAE,mBAAoB,IAAa,CACnC,GAAA,EAAA,EAAA,aACK,EAAkB,QACpB,EAAO,IAAU,EAAQ,EAAM,gBAChC,EACH,CACF,CAAC,EAAkB,CAAC,CAgBvB,MAAO,CACH,yBACA,iBAAA,EAAA,EAAA,aAfO,EAAkB,QACpB,EAAO,IAAU,EAAQ,EAAM,SAChC,EACH,CACF,CAAC,EAAkB,CAAC,CAYnB,kBAAA,EAAA,EAAA,aATO,GACH,EACA,CAAE,SAAU,EAAsC,CACrD,CACF,CAAC,EAAwB,EAAgB,CAAC,CAMzC,YACA,cAAe,EAAkB,OAAS,EAC7C,ECpCCC,GAAMC,EAAAA,2BAA2B,IACjCC,GAAS,iBAMF,GAAwC,GACjDC,EAAAA,EAAsB,CAAE,IAAA,GAAK,UAAS,OAAA,GAAQ,CAAC,CAMtC,OAAqC,CAC9C,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEnC,EAAUC,EAAAA,GAAU,EAAQ,KAAK,CAClC,iCAEL,OAAOC,EAAAA,EAAc,CACjB,IAAA,GACA,UACA,OAAA,GACA,KAAM,EAAE,CACR,aAAc,CACV,OAAS,GAAS,EAAK,GAAG,UAAU,CACvC,CACJ,CAAC,ECvBO,IAAuB,EAAc,IAA8B,CAC5E,cACA,YACA,EACA,EACH,CAOY,GAAe,GAAyB,CACjD,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAyB,CACrB,SAAU,GAAoB,GAAQ,GAAI,EAAQ,KAAK,CACvD,QAAS,SAAY,CACjB,GAAI,CAAC,EAAM,MAAU,MAAM,2BAA2B,CAEtD,OAAA,EAAA,EAAA,aAAmB,EAAM,CACrB,WAAY,EAAQ,QACvB,CAAC,EAEN,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EAAQ,KAC7B,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,2BACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,OAAQ,IAAO,GAAK,EACpB,UAAW,IAAO,GACrB,CAAC,EC5CAC,GAAMC,EAAAA,2BAA2B,IACjCC,GAAS,iBAEF,IACT,EACA,IAEAC,EAAAA,EAA8B,CAC1B,IAAA,GACA,QAASC,EAAAA,GAAU,EAAY,CAC1B,iCACL,OAAA,GACA,KAAM,CAAC,OAAO,GAAW,EAAE,CAAC,CAC/B,CAAC,CAEO,GAAiB,GAAqB,CAC/C,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEnC,EAAUD,EAAAA,GAAU,EAAQ,KAAK,CAClC,iCAEL,OAAOE,EAAAA,EAAc,CACjB,IAAA,GACA,UACA,OAAA,GACA,KAAM,CAAC,OAAO,GAAW,EAAE,CAAC,CAC5B,aAAc,CACV,QAAS,CAAC,CAAC,EACX,OAAS,GACL,EAAK,GAAG,IAAK,IAAS,CAClB,GAAI,EAAI,GAAG,UAAU,CACrB,kBAAmB,EAAI,kBACvB,KAAM,EAAI,KACV,YAAa,EAAI,YACjB,mBAAoB,EAAI,mBAAmB,UAAU,CACxD,EAAE,CACV,CACJ,CAAC,ECrCAC,GAAMC,EAAAA,yBAAyB,IAC/B,GAAS,eAMF,GAA0B,GAA8B,CACjE,cACA,QACA,SACA,EACH,CASY,IAAkB,EAAgB,IAAqB,CAEhE,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEnC,EAAUC,EAAAA,GAAU,EAAQ,KAAK,CAClC,+BAEL,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAuB,EAAQ,CACzC,QAAS,SAAY,CACjB,GAAI,CAAC,EAAM,MAAU,MAAM,4BAA4B,CAcvD,OAbe,MAAMC,EAAAA,EAA2B,CAC5C,OACA,MAAO,EAAK,IACP,IACI,CACG,IAAA,GACA,aAAc,eACd,UACA,KAAM,CAAC,EAAS,EAAI,CACvB,EACR,CACJ,CAAC,EAEY,KAAK,EAAO,KACf,CACH,IAAK,EAAK,GACV,MAAO,OAAO,EAAM,IAAM,EAAE,CAAG,IAC/B,iBAAkB,OAAO,EAAM,IAAM,EAAE,CAAG,IAC7C,EACH,EAEN,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAW,CAAC,CAAC,EAAK,OAC1C,CAAC,ECtCO,GACT,GACiE,CACjE,GAAM,CAAE,KAAM,GAAS,GAAc,EAAQ,CAGvC,EAAc,GAChB,GAAM,IAAK,GAAQ,EAAI,GAAG,EAAI,EAAE,CAChC,EACH,CAiBD,MAAO,CACH,MAAA,EAAA,EAAA,aAdI,EAAY,MACN,IAAK,IAAe,CAClB,WAAY,EAAU,MAAQ,EAAU,iBACxC,GAAI,GAAM,KAAM,GAAO,EAAG,KAAO,EAAU,IAAI,EAAE,IAAM,GACvD,IACI,GAAM,KAAM,GAAO,EAAG,KAAO,EAAU,IAAI,EAC1C,EAAE,CACV,EAAE,CACF,MAAM,EAAG,IAAM,OAAO,EAAE,WAAW,CAAG,OAAO,EAAE,WAAW,CAAC,EAChE,EAAE,CACN,CAAC,EAAY,KAAM,EAAK,CAC3B,CAIG,UAAW,EAAY,UAC1B,EClDQ,OAA2B,CACpC,IAAM,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,WAAYC,EAAAA,GAAW,CAqB/B,MAAO,CAAE,QAnBO,SAAY,CACxB,IAAM,EAAU,GAAS,SAAW,GAEpC,MAAM,QAAQ,IAAI,CAMd,EAAY,kBAAkB,CAC1B,SAAU,CAAC,sBAAuB,EAAQ,CAC7C,CAAC,CAEF,EAAY,kBAAkB,CAC1B,SAAU,CAAC,oBAAoB,CAClC,CAAC,CACL,CAAC,EAGY,ECLT,OAAmD,CAC5D,GAAM,CAAE,aAAc,GAAwBC,EAAAA,GAA0B,CAClE,CAAE,cAAeC,EAAAA,GAAW,CAC5B,CAAC,EAAa,IAAA,EAAA,EAAA,UAA2B,GAAM,CAC/C,CACF,iBAAkB,EAClB,gBAAiB,EACjB,aAAc,GACdC,EAAAA,GAAkB,CAEhB,EAAiB,EAAW,eAqClC,MAAO,CACH,cAAA,EAAA,EAAA,aApC6B,SAAY,CACzC,GAAI,EAAgB,CAEhB,GAAI,CAAC,EACD,OAGJ,EAAe,GAAK,CACpB,GAAI,CACA,MAAM,GAAqB,MACvB,SAEE,CACN,EAAe,GAAM,OAKzB,OAAO,QAAQ,SAAS,EAE7B,CAAC,EAAqB,EAAe,CAAC,CAiBrC,cACA,iBAAkB,EAClB,iBAAA,EAAA,EAAA,aAhBC,GAAoB,CACjB,EAAuB,EAAQ,CAE3BC,EAAAA,GAAW,EACX,OAAO,cACH,IAAI,YAAY,kBAAmB,CAAE,OAAQ,CAAE,UAAS,CAAE,CAAC,CAC9D,EAGT,CAAC,EAAuB,CAC3B,CAOG,aAAc,EACd,iBACH,EC3BQ,GAAkB,MAC3B,EACA,IACoC,CACpC,IAAM,EAAMC,EAAAA,EAAgB,EAAK,EAAY,EAAI,GAC3C,EAAW,MAAM,MAAM,EAAK,CAC9B,OAAQ,YAAY,QAAQ,IAAM,CACrC,CAAC,CAEF,GAAI,CAAC,EAAS,GACV,MAAU,MAAM,uBAAuB,EAAS,SAAS,CAI7D,OADiB,MAAM,EAAS,MAAM,EAIpC,GAAMC,EAAAA,oBAAoB,IAEnB,GAAmB,GAAmB,CAE/C,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,CAAC,eAAgB,EAAO,CAClC,QAAS,SAAY,CACjB,GAAI,CAAC,EAAM,MAAU,MAAM,4BAA4B,CACvD,IAAM,EAAUC,EAAAA,GAAU,EAAQ,KAAK,CAAC,0BAClC,EAAW,EAAK,UAAU,KAAK,EAAS,GAAI,CAO5C,GALmB,MAAM,EAAS,KAAK,IACzC,EACH,EAEmC,GACL,IAAI,UAAU,EAAI,GAE3C,CAAC,GAAW,MAAM,EAAS,KAAK,SAAS,CAM/C,OALiB,MAAM,GACnB,GAAG,IAAU,IACb,EAAQ,KACX,EAIL,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EACxB,CAAC,EClFO,GAAkB,MAC3B,EACA,EACA,EAAY,KACC,CACb,GAAI,CAAC,EAAK,MAAU,MAAM,kBAAkB,CAC5C,IAAM,EAASC,EAAAA,EAAgB,EAAK,EAAY,CAChD,GAAI,CAAC,EAAQ,MAAU,MAAM,cAAc,CAO3C,IAAM,EAAO,MALI,MAAM,MAAM,EAAQ,CACjC,QAAS,CACL,eAAgB,cACnB,CACJ,CAAC,EAC0B,MAAM,CAIlC,OAFI,EAAkB,KAAK,MAAM,EAAK,CAE/B,GAGE,IACT,EACA,IACC,CAAC,cAAe,gBAAiB,EAAa,EAAQ,CAO9C,IAAsB,EAAkB,EAAY,KAAU,CACvE,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAwB,EAAQ,KAAM,EAAQ,CACxD,YAAe,GAAmB,EAAQ,KAAM,EAAS,EAAU,CACnE,QAAS,CAAC,CAAC,GAAW,CAAC,CAAC,EAAQ,KAChC,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,mBACjB,IAAiB,cACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,UAAW,IACd,CAAC,ECtDO,GAAiB,KAAO,KAAO,GAQ/B,EAAe,MACxB,EACA,IACqB,CACrB,GAAI,CAAC,EAAK,MAAU,MAAM,uBAAuB,CAEjD,IAAM,EAAW,MAAM,MAAMC,EAAAA,EAAgB,EAAK,EAAY,EAAI,GAAI,CAClE,QAAS,CACL,eAAgB,cACnB,CACJ,CAAC,CAEF,GAAI,CAAC,EAAS,GACV,MAAU,MAAM,uBAAuB,EAAS,SAAS,CAG7D,IAAM,EAAO,MAAM,EAAS,MAAM,CAalC,GAAI,CAVqB,CACrB,aACA,YACA,YACA,YACA,YACA,aACA,aACA,gBACH,CACqB,SAAS,EAAK,KAAK,CACrC,MAAU,MAAM,0BAA0B,EAAK,OAAO,CAG1D,GAAI,EAAK,KAAO,GACZ,MAAU,MAAM,0CAA0C,CAG9D,OAAO,IAAI,SAAS,EAAS,IAAW,CACpC,IAAM,EAAS,IAAI,WACnB,EAAO,cAAc,EAAK,CAC1B,EAAO,cAAkB,CACrB,EAAQ,CACJ,MAAO,EAAO,OACd,KAAM,EAAK,KACX,UAAWC,EAAAA,EAA6B,EAAK,KAAK,CACrD,CAAC,EAEN,EAAO,YAAgB,CACnB,EAAO,MAAM,qCAAqC,CAAC,GAEzD,EAQO,IACT,EACA,IACC,CAAC,cAAe,aAAc,EAAa,EAAa,CAOhD,GAAgB,GAAiC,CAC1D,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,GAAqB,EAAQ,KAAM,EAAa,CAC1D,YAAe,EAAa,EAAQ,KAAM,EAAc,CACxD,QAAS,CAAC,CAAC,GAAgB,CAAC,CAAC,EAAQ,KACrC,OAAQ,EAAc,IAAU,CAE5B,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,uBACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,UAAW,IACd,CAAC,EASO,GAAoB,GAA+B,CAC5D,GAAM,CAAE,WAAYA,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,YAAkB,CACd,QAAS,EAAiB,IAAK,IAAkB,CAC7C,SAAU,GAAqB,EAAQ,KAAM,EAAa,CAC1D,YAAe,EAAa,EAAQ,KAAM,EAAa,CACvD,QAAS,CAAC,CAAC,GAAgB,CAAC,CAAC,EAAQ,KACrC,OAAQ,EAAsB,IAAiB,CAE3C,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,uBACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,UAAW,IACd,EAAE,CACN,CAAC,ECpIO,IAAuB,EAAoB,EAAY,KAAU,CAC1E,GAAM,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,YAAkB,CACd,QAAS,EAAS,IAAK,IAAS,CAC5B,SAAU,GAAwB,EAAQ,KAAM,EAAI,CACpD,QAAS,SACE,GAAmB,EAAQ,KAAM,EAAK,EAAU,CAE3D,QAAS,CAAC,CAAC,GAAO,CAAC,CAAC,EAAQ,KAC5B,OAAQ,EAAsB,IAAiB,CAE3C,GAAI,aAAiB,MAAO,CACxB,IAAM,EAAe,EAAM,QAAQ,aAAa,CAChD,GAAI,EAAa,SAAS,SAAS,EAC/B,EAAa,SAAS,QAAQ,EAC9B,IAAiB,mBACjB,IAAiB,cACjB,MAAO,GAIf,OAAO,EAAe,GAE1B,UAAW,IACd,EAAE,CACN,CAAC,EC7BOC,EAA2C,CACpD,UAAW,GACX,iBAAkB,KAClB,aAAc,GACjB,CAEY,GAAiB,KAAO,IAA4B,CAC7D,IAAMC,EAA2B,EAAE,CACnC,GAAI,CACA,IAAK,IAAM,KAAS,EAAQ,CACxB,IAAM,EAAa,MAAA,EAAA,EAAA,SACf,EAAM,KACN,EACH,CAED,EAAiB,KAAK,EAAW,CAErC,OAAO,QACF,EAAG,CAER,MADA,QAAQ,MAAM,iBAAkB,EAAE,CAC5B,IAkBD,IAAmB,CAAE,eAAA,EAAgB,mBAA2B,CACzE,GAAM,CAAC,EAAgB,IAAA,EAAA,EAAA,UACnB,GAAiB,EAAE,CACtB,EAED,EAAA,EAAA,eAAgB,CACR,GACA,EAAkB,EAAc,EAErC,CAAC,EAAc,CAAC,CAEnB,GAAM,CAAC,EAAkB,IAAA,EAAA,EAAA,UAA0C,EAAE,CAAC,CAEhE,GAAA,EAAA,EAAA,aACD,GACG,EAAmB,GAAM,EAAE,QAAQ,EAAG,IAAM,IAAM,EAAM,CAAC,CAC7D,EAAE,CACL,CAsCD,MAAO,CACH,iBACA,oBACA,UAAA,EAAA,EAAA,aAtCA,MAAO,EAAuB,EAAc,KAAS,CACjD,EAAoB,EAAE,CAAC,CAEvB,IAAMC,EAAiC,EAAE,CACzC,IAAK,IAAM,KAAQ,EAAe,CAC9B,IAAI,EAAa,EACbC,IACA,EAAa,MAAA,EAAA,EAAA,SACT,EACA,EACH,EAGL,IAAMC,EAAuB,CACzB,KAAM,EACN,MAAO,IAAI,gBAAgB,EAAK,CACnC,CACD,EAAc,KAAK,EAAM,CAG7B,EAAmB,GAAM,CACrB,GAAG,EACH,GAAK,EAEC,EAAE,OACG,GACG,CAAC,EAAc,KACV,GAAM,EAAE,KAAK,OAAS,EAAE,KAAK,KACjC,CACR,CAND,EAAE,CAOX,CAAC,EAEN,CAACD,EAAe,CACnB,CAMG,WACA,mBACH,EC1FQ,IAAwB,CACjC,gBACA,kBACS,CACT,GAAM,CAAC,EAAe,IAAA,EAAA,EAAA,UAEpB,EAAa,EAEf,EAAA,EAAA,eAAgB,CACR,GACA,EAAiB,EAAa,EAEnC,CAAC,EAAa,CAAC,CAElB,IAAM,GAAA,EAAA,EAAA,iBAA6B,EAAiB,IAAA,GAAU,CAAE,EAAE,CAAC,CAuBnE,MAAO,CACH,gBACA,mBACA,UAAA,EAAA,EAAA,aAvBA,KAAO,IAAuB,CAC1B,IAAI,EAAa,EACb,IACA,EAAa,MAAA,EAAA,EAAA,SACT,EACA,EACH,EAGL,IAAME,EAAuB,CACzB,KAAM,EACN,MAAO,IAAI,gBAAgB,EAAW,CACzC,CAGD,OADA,EAAiB,EAAM,CAChB,GAEX,CAAC,EAAc,CAClB,CAMG,WACH,EC/CQ,IACT,EACA,IACC,CACD,GAAM,CAAE,WAAYC,EAAAA,GAAW,CACzB,CAAE,MAAA,EAAA,EAAA,iBAAsB,CAExB,CACF,kBACA,uBACA,iCACA,YACA,SACA,cACA,SACA,EAAmB,CACnB,qBAAsB,GAAS,SAAW,GAC1C,eAAgB,CACZ,MAAO,EAAE,mBAAoB,CAAE,aAAc,eAAgB,CAAC,CAC9D,YAAa,EAAE,yBAA0B,CAAE,aAAc,qDAAsD,CAAC,CAChH,WAAY,EAAE,UAAW,CAAE,aAAc,UAAW,CAAC,CACxD,CACJ,CAAC,CAuBF,MAAO,CACH,aAAA,EAAA,EAAA,aAtB4B,SAAY,CACxC,GAAI,CAAC,GAAU,CAAC,EACZ,MAAU,MAAM,mCAAmC,CAIvD,GAAI,CAAC,EAAM,WACP,MAAU,MAAM,uCAAuC,EAAM,iBAAiB,CAIlF,IAAM,EAAU,MAAM,EAAM,WAAW,qBAAqB,EAAQ,EAAM,CAE1E,GAAI,EAAQ,SAAW,EACnB,MAAU,MAAM,mCAAmC,CAIvD,MAAM,EAAgB,EAAQ,EAC/B,CAAC,EAAQ,EAAO,EAAgB,CAAC,CAIhC,uBACA,iCACA,YACA,SACA,cACA,QACH,ECvDC,GAAgB,GACX,IAAY,MAAQ,IAAYC,EAAAA,YAUrC,IACF,EAKA,EAKA,EACA,IACsD,CACtD,IAAMC,EACF,EAAE,CACA,EAAO,EAAY,aAAa,CAGtC,IAAK,IAAM,KAAS,EAChB,GAAI,CACA,IAAM,GAAA,EAAA,EAAA,gBAAyB,CAC3B,IAAKC,EAAAA,UACL,UAAW,WACX,OAAQ,EAAM,OACd,KAAM,EAAM,KACf,CAAC,CAQI,EAAO,EAAQ,KAAK,KAAK,aAAa,CACtC,EAAK,EAAQ,KAAK,GAAG,aAAa,CAClC,EAAW,EAAQ,KAAK,MACxB,EACF,OAAO,GAAa,SAAW,EAAW,OAAO,EAAS,CAG9D,GAAI,IAAS,GAAQ,IAAO,EACxB,SAGJ,IAAM,EAAe,EAAM,QAAQ,aAAa,CAC1C,EAAU,EAAa,IAAiB,CAC1C,OAAQ,GACR,QAAS,GACZ,CAEG,IAAS,IACT,EAAQ,SAAW,GAGnB,IAAO,IACP,EAAQ,QAAU,GAGtB,EAAa,GAAgB,OACzB,CAEJ,SAKR,GAAI,IAAgB,IAAA,GAAW,CAC3B,IAAM,EAAc,OAAO,EAAY,CACvC,GAAI,EAAc,GAAI,CAClB,IAAM,EAAU,EAAaF,EAAAA,cAAgB,CACzC,OAAQ,GACR,QAAS,GACZ,CACD,EAAQ,SAAW,EACnB,EAAaA,EAAAA,aAAe,GAKpC,IAAK,IAAM,KAAY,EAAW,CAG9B,GAFkB,EAAS,UAAU,aAAa,GAEhC,EACd,SAGJ,IAAM,EAAS,OAAO,EAAS,OAAO,CACtC,GAAI,GAAU,GACV,SAGJ,IAAM,EAAU,EAAaA,EAAAA,cAAgB,CACzC,OAAQ,GACR,QAAS,GACZ,CACD,EAAQ,QAAU,EAClB,EAAaA,EAAAA,aAAe,EAGhC,OAAO,GAYE,GAA0B,MACnC,EACA,EACA,EACA,IAC0B,CAC1B,GAAI,CACA,GAAI,EAAQ,SAAW,EACnB,MAAO,CACH,YAAa,EACb,QAAS,GACT,MAAO,kCACV,CAGL,IAAM,EAAc,MAAM,EAAK,aAAa,oBACxC,EACA,CACI,OAAQ,EAAO,YAClB,CACJ,CAEG,EAAW,GACXG,EAEA,EAAW,IAETC,EAGF,EAAE,CAEN,IAAK,IAAI,EAAI,EAAG,EAAI,EAAY,OAAQ,IAAK,CACzC,IAAM,EAAS,EAAY,GACvB,EAAO,WACP,EAAW,GACX,EAAe,EAAO,SAAW,wBAGrC,GAAY,EAAO,QAEnB,IAAM,EAAS,EAAQ,GACjB,EAAe,GACjB,EAAO,OACP,EAAO,UACP,GAAQ,MACR,EAAO,YACV,CAGD,IAAK,GAAM,CAAC,EAAO,KAAU,OAAO,QAAQ,EAAa,CAAE,CACvD,IAAM,EAAU,EAAgB,IAAU,CACtC,OAAQ,GACR,QAAS,GACZ,CACD,EAAgB,GAAS,CACrB,OAAQ,EAAQ,OAAS,EAAM,OAC/B,QAAS,EAAQ,QAAU,EAAM,QACpC,EAKT,GAAI,EACA,MAAO,CACH,YAAa,EACb,QAAS,GACT,MAAO,GAAgB,uBAC1B,CAIL,IAAM,EAAc,EAAW,IAGzB,EAAY,GAAa,EAAO,iBAAiB,CACjD,EAAU,GAAa,EAAO,eAAe,CAE7C,EAAkB,OAAO,EAAO,SAAS,CAG/C,GAAI,EAAW,CACX,IAAM,EAAW,EAAgBJ,EAAAA,cAAgB,CAC7C,OAAQ,GACR,QAAS,GACZ,CAED,GAAI,EAAS,QAAU,EACnB,MAAO,CACH,cACA,QAAS,GACT,MAAO,kCAAkC,EAAgB,UAAU,CAAC,QAAQ,EAAS,QAAQ,UAAU,GAC1G,CAIL,IAAK,GAAM,CAAC,EAAc,KAAU,OAAO,QACvC,EACH,CACG,GAAI,IAAiBA,EAAAA,aAAe,EAAM,QAAU,GAChD,MAAO,CACH,cACA,QAAS,GACT,MAAO,mCAAmC,EAAa,eAAe,EAAM,QAAQ,UAAU,CAAC,cAClG,KAGN,CACH,IAAM,EAAmB,EAAO,iBAAiB,aAAa,CACxD,EAAa,EAAgB,IAAqB,CACpD,OAAQ,GACR,QAAS,GACZ,CAED,GAAI,EAAW,QAAU,EACrB,MAAO,CACH,cACA,QAAS,GACT,MAAO,oCAAoC,EAAgB,UAAU,CAAC,QAAQ,EAAW,QAAQ,UAAU,GAC9G,CAIL,IAAK,GAAM,CAAC,EAAc,KAAU,OAAO,QACvC,EACH,CACG,GAAI,IAAiB,GAAoB,EAAM,QAAU,GAGrD,MAAO,CACH,cACA,QAAS,GACT,MAAO,6BAJP,IAAiBA,EAAAA,YAAc,MAAQ,EAIO,eAAe,EAAM,QAAQ,UAAU,CAAC,cACzF,CAMb,GAAI,EAAM,qBAAuB,EAAM,oBAAsB,GACzD,GAAI,EAAS,CACT,IAAM,EAAW,EAAgBA,EAAAA,cAAgB,CAC7C,OAAQ,GACR,QAAS,GACZ,CAED,GAAI,EAAS,OAAS,EAAM,oBACxB,MAAO,CACH,cACA,QAAS,GACT,MAAO,iCAAiC,EAAM,oBAAoB,UAAU,CAAC,QAAQ,EAAS,OAAO,UAAU,GAClH,KAEF,CAEH,IAAM,EAAa,EADI,EAAO,eAAe,aAAa,GACJ,CAClD,OAAQ,GACR,QAAS,GACZ,CAED,GAAI,EAAW,OAAS,EAAM,oBAC1B,MAAO,CACH,cACA,QAAS,GACT,MAAO,mCAAmC,EAAM,oBAAoB,UAAU,CAAC,QAAQ,EAAW,OAAO,UAAU,GACtH,CAKb,MAAO,CACH,cACA,QAAS,GACZ,OACI,EAAO,CACZ,MAAO,CACH,YAAa,EACb,QAAS,GACT,MAAO,aAAiB,MAAQ,EAAM,QAAU,oBACnD,GC/OH,GAAsB,GACnB,EAAS,WAAW,KAAK,CAGvB,OAAO,EAAS,CAAC,UAAU,CAFvB,EAQT,IACF,EACA,KAWO,CACH,KAAM,EACN,KAAM,WACN,OAAQ,EAAO,IAAI,IAAU,CACzB,KAAM,EAAM,KACZ,KAAM,EAAM,KACZ,aAAc,EAAM,aACpB,WAAY,EAAM,WACrB,EAAE,CACH,QAAS,EAAE,CACX,gBAAiB,aACpB,EAMC,IACF,EACA,IACM,CAEN,GAAI,MAAM,QAAQK,EAAI,EAAIA,EAAI,OAAS,EAAG,CACtC,IAAM,EAAYA,EAAI,GAGtB,GAAI,OAAO,GAAc,UAAY,SAAU,GAAa,SAAU,GAAa,EAAU,OAAS,WAClG,OAAOA,EAKX,GAAI,OAAO,GAAc,UAAY,SAAU,GAAa,SAAU,GAE9D,EADyB,oBAAqB,GAAa,YAAa,GAcxE,MAAO,CADa,GAAiB,EAVjBA,EAU2C,CAC3C,CAMhC,OAAOA,GAML,GAA0B,GAAyE,CACrG,GAAI,CAEA,IAAM,EAAe,EAAa,cAAgB,EAAa,KAE/D,GAAI,CAAC,EACD,MAAU,MAAM,2EAA2E,CAO/F,OAAA,EAAA,EAAA,oBAA0B,CACtB,IAJkB,GAAa,EAAa,IAAK,EAAa,CAKhD,eACd,KAAM,EAAa,KACtB,CAAC,OACG,EAAO,CACZ,QAAQ,MAAM,kCAAmC,EAAM,CACvD,IAAM,EAAe,EAAa,cAAgB,EAAa,MAAQ,UACvE,MAAU,MAAM,kCAAkC,EAAa,IAAI,aAAiB,MAAQ,EAAM,QAAU,kBAAkB,GAQhI,GAAuC,GAAiE,CAE1G,IAAM,EAAc,GAAuB,EAAU,aAAa,CAElE,MAAO,CACH,GAAI,EAAU,GACd,MAAO,GAAmB,EAAU,MAAM,CAC1C,KAAM,EACN,QAAS,EAAU,SAAW,qBACjC,EAMQ,GAAuB,GAAgD,CAChF,IAAMC,EAA6B,CAC/B,KAAM,EAAO,KACb,QAAS,EAAO,QAEhB,MAAM,SAAS,EAAoB,EAAuC,CACtE,GAAI,CAEA,IAAM,EAAc,IAAI,gBAAgB,CACpC,YAAa,EAAO,iBACpB,UAAW,EAAO,eAClB,SAAU,EAAO,SACjB,UAAW,EAAO,YAClB,YAAa,QAAQ,EAAO,mBAAqB,GAAK,IAAI,CAC1D,QAAS,EAAO,QACnB,CAAC,CAGI,EAAW,IAAI,IAAI,EAAO,WAAW,CAC3C,EAAS,OAAS,EAAY,UAAU,CACxC,IAAM,EAAW,MAAM,MAAM,EAAS,CAEtC,GAAI,CAAC,EAAS,GACV,MAAU,MAAM,uBAAuB,EAAS,OAAO,GAAG,EAAS,aAAa,CAGpF,IAAMC,EAA8B,MAAM,EAAS,MAAM,CAGnD,EAAU,EAAU,QAAQ,IAAI,GAAoC,CAGpE,EAAe,OAAO,EAAU,UAAU,CAC1C,EAAsB,OAAO,EAAU,aAAa,CAE1D,MAAO,CACH,eAAgB,EAAO,KACvB,aACA,eACA,sBACA,YAAa,EACb,KAAM,CACF,UACA,KAAM,EAAU,KACnB,CACJ,OACI,EAAO,CAGZ,OAFA,QAAQ,MAAM,GAAG,EAAO,KAAK,mBAAoB,EAAM,CAEhD,CACH,eAAgB,EAAO,KACvB,aACA,aAAc,GACd,YAAa,EACb,oBAAqB,GACrB,KAAM,CACF,QAAS,EAAE,CACX,KAAM,EAAE,CACX,CACJ,GAIT,MAAM,aAAa,EAAoB,EAAkB,EAA2C,CAChG,GAAI,CAMA,OAAO,GAAwB,EAAQ,EAHvB,MAAM,KAAK,qBAAqB,EAAQ,EAAM,CAGP,EAAK,OACvD,EAAO,CACZ,MAAO,CACH,YAAa,EACb,QAAS,GACT,MAAO,aAAiB,MAAQ,EAAM,QAAU,kDACnD,GAIT,MAAM,qBAAqB,EAAoB,EAAgD,CAG3F,GAAI,CAAC,EAAM,MAAQ,OAAO,EAAM,MAAS,UAAY,EAAE,YAAa,EAAM,MACtE,MAAU,MAAM,wCAAwC,CAG5D,IAAI,EAAU,EAAM,KAAK,QAEzB,GAAI,EAAQ,SAAW,EACnB,MAAU,MAAM,4BAA4B,CAIhD,GAAI,EAAO,oBAAsB,EAAO,mBAAmB,OAAS,EAAG,CACnE,IAAM,EAA0B,EAAO,mBAAmB,IAAI,GAAQ,EAAK,aAAa,CAAC,CAMzF,GALA,EAAU,EAAQ,OAAO,GAChB,EAAO,GACL,EAAwB,SAAS,EAAO,GAAG,aAAa,CAAC,CADzC,GAEzB,CAEE,EAAQ,SAAW,EACnB,MAAU,MAAM,gDAAgD,CAKxE,GAAI,CAAC,EAAM,qBAAuB,EAAM,sBAAwB,GAC5D,MAAU,MAAM,wDAAwD,CAK5E,OAAO,GAEd,CAED,OAAO,GC1SLC,GAA6E,CAC/E,KAAM,CACF,mBAAoB,CAChB,6CACA,6CACH,CACJ,CACD,KAAM,CACF,mBAAoB,EAAE,CACzB,CACD,KAAM,CACF,mBAAoB,EAAE,CACzB,CACJ,CAKKC,GAAS,GACJ,IAAY,MAAQ,IAAY,6CAMrC,GAAoB,GAEf,IAAI,IAAI,gBAAiBC,EAAAA,EAAiB,CAAC,UAAU,CAYnD,GAA2B,GAA8C,CAClF,IAAM,EAAY,GAAkB,IAAgB,GAAkB,KAGhE,EAAiB,GAAoB,CACvC,KAAM,cACN,WAAY,GAAiB,EAAY,CACzC,QAAS,EACT,SAAU,EAAU,SAAWC,EAAAA,QAAM,cAAcC,EAAAA,EAAa,CAAE,UAAS,CAAC,CAC5E,mBAAoB,EAAU,mBACjC,CAAC,CAyEF,MAtEmC,CAC/B,GAAG,EAEH,MAAM,aAAa,EAAoB,EAAkB,EAA2C,CAChG,GAAI,CAMA,OAAO,GAAwB,EAAQ,EAHvB,MAAM,KAAK,qBAAqB,EAAQ,EAAM,CAGP,EAAK,OACvD,EAAO,CACZ,MAAO,CACH,YAAa,EACb,QAAS,GACT,MAAO,aAAiB,MAAQ,EAAM,QAAU,oBACnD,GAIT,MAAM,qBAAqB,EAAoB,EAAgD,CAC3F,IAAMC,EAA+B,EAAE,CAGjC,EAAc,MAAM,EAAe,qBAAqB,EAAQ,EAAM,CAE5E,GAAG,CAAC,GAAe,EAAY,SAAW,EACtC,MAAU,MAAM,mCAAmC,CAOvD,GAHkBJ,GAAM,EAAO,iBAAiB,CA6B5C,EAAY,GAAG,MAAQ,EAAO,aA1BlB,CAEZ,GAAI,EAAU,mBAAmB,SAAW,EACxC,MAAU,MAAM,gEAAgE,CAEpF,IAAM,EAAWK,EAAAA,YAAY,MAAMC,EAAAA,gBAAgB,IAAI,CACjD,EAAmBC,EAAAA,QAAe,GAAG,EAAO,iBAAiB,CAC7D,EAAW,OAAO,EAAO,SAAS,CAGxC,EAAQ,KACJC,EAAAA,OAAO,aACH,EACA,EAAS,YAAY,UAAU,CAC/B,CACI,EAAY,GAAG,GACf,EAAS,UAAU,CACtB,CACDC,EAAAA,IAAI,GAAG,GAAIC,EAAAA,MAAM,IAAI,CACrB,CACI,QAAS,WAAW,EAAM,eAAe,aAAa,EAAO,mBAChE,CACJ,CACJ,CASL,OAFA,EAAQ,KAAK,GAAG,EAAY,CAErB,GAEd,EC9GC,EAAS,GAEP,IAAY,MACZ,IAAY,6CAOd,OACK,OAAO,KAAK,MAAM,KAAK,KAAK,CAAG,IAAK,CAAG,KAAQ,CA+B7C,GACT,GACiB,CACjB,IAAMC,EAA6B,CAC/B,KAAM,EAAO,KACb,QAAS,EAAO,QAEhB,MAAM,SACF,EACA,EACkB,CAElB,IAAMC,EAAkB,CACpB,EAAM,EAAO,iBAAiB,CACxB,EAAO,WACN,EAAO,iBACd,EAAM,EAAO,eAAe,CACtB,EAAO,WACN,EAAO,eACjB,CAEK,EAAiB,OAAO,EAAO,SAAS,CAE9C,GAAI,CAMA,GAAM,CAAC,GAAW,MAJD,EAAK,UAAU,KAC5B,EAAO,cACPC,EAAAA,2BAAyB,IAC5B,CACgC,KAAK,cAClC,EACA,EACH,CAGK,EAAe,MAAM,QAAQ,EAAQ,CACrC,EACA,CAAC,EAAQ,CACT,EAAe,EAAa,EAAa,OAAS,GAGxD,GAAI,CAAC,GAAgB,IAAiB,GAClC,MAAU,MAAM,mCAAmC,CAIvD,GAAI,OAAO,GAAiB,SACxB,MAAU,MAAM,sCAAsC,CAM1D,IAAM,EAA2B,EAAO,mBAAqB,EAIvD,EACD,EAJsB,OACvB,IAAQ,EAA2B,IACtC,CAEyC,OAAO,IAAM,CAEvD,MAAO,CACH,eAAgB,EAAO,KACvB,aACA,eACA,YAAa,EACb,sBACA,KAAM,CACF,OACA,cAAe,EAAO,cACzB,CACJ,OACI,EAAO,CAGZ,OAFA,QAAQ,MAAM,GAAG,EAAO,KAAK,mBAAoB,EAAM,CAEhD,CACH,eAAgB,EAAO,KACvB,aACA,aAAc,GACd,YAAa,EACb,oBAAqB,GACrB,KAAM,CACF,OACA,cAAe,EAAO,cACzB,CACJ,GAIT,MAAM,aACF,EACA,EACA,EACuB,CAKvB,OAAO,GAAwB,EAAQ,EAHvB,MAAM,KAAK,qBAAqB,EAAQ,EAAM,CAGP,EAAK,EAGhE,MAAM,qBACF,EACA,EAC4B,CAC5B,GACI,CAAC,EAAM,MACP,OAAO,EAAM,MAAS,UACtB,EAAE,SAAU,EAAM,MAElB,MAAU,MAAM,qBAAqB,CAGzC,IAAM,EAAW,IAAa,CAG9B,GACI,CAAC,EAAM,qBACP,EAAM,sBAAwB,GAE9B,MAAU,MACN,wDACH,CAGL,IAAM,EAAe,EAAM,oBACrB,EAAW,OAAO,EAAO,SAAS,CAGxC,GAAI,IAAiB,GACjB,MAAU,MAAM,6CAA6C,CAGjE,IAAM,EAAY,EAAM,EAAO,iBAAiB,CAC1C,EAAU,EAAM,EAAO,eAAe,CAEtC,EAAYC,EAAAA,YAAY,MAAMD,EAAAA,2BAAyB,IAAI,CAC3DE,EAA+B,EAAE,CAEvC,GAAI,EAGA,EAAQ,KACJC,EAAAA,OAAO,aACHC,EAAAA,QAAe,GAAG,EAAO,cAAc,CACvC,EAAU,YAAY,wBAAwB,CAC9C,CACI,EAAa,UAAU,CACvB,EAAM,KAAK,KACX,EAAO,YACP,EAAS,UAAU,CACtB,CACDC,EAAAA,IAAI,GAAG,EAAUC,EAAAA,MAAM,IAAI,CAC3B,CACI,QAAS,WAAW,EAAM,iBAC7B,CACJ,CACJ,KACE,CAEH,IAAM,EAAWL,EAAAA,YAAY,MAAMM,EAAAA,gBAAgB,IAAI,CACjD,EAAmBH,EAAAA,QAAe,GACpC,EAAO,iBACV,CACK,EAAgBA,EAAAA,QAAe,GAAG,EAAO,cAAc,CAG7D,EAAQ,KACJD,EAAAA,OAAO,aACH,EACA,EAAS,YAAY,UAAU,CAC/B,CAAC,EAAc,UAAU,CAAE,EAAS,UAAU,CAAC,CAC/CE,EAAAA,IAAI,GAAG,GAAIC,EAAAA,MAAM,IAAI,CACrB,CACI,QAAS,WAAW,EAAM,iBAC7B,CACJ,CACJ,CAGG,EAEA,EAAQ,KACJH,EAAAA,OAAO,aACH,EACA,EAAU,YAAY,wBAAwB,CAC9C,CACI,EAAS,UAAU,CACnB,EAAa,UAAU,CACvB,EAAM,KAAK,KACX,EAAO,YACP,EAAS,UAAU,CACtB,CACDE,EAAAA,IAAI,GAAG,GAAIC,EAAAA,MAAM,IAAI,CACrB,CACI,QAAS,WAAW,EAAM,iBAC7B,CACJ,CACJ,CAGD,EAAQ,KACJH,EAAAA,OAAO,aACH,EACA,EAAU,YAAY,2BAA2B,CACjD,CACI,EAAS,UAAU,CACnB,EAAa,UAAU,CACvB,EAAM,KAAK,KACX,EAAO,YACP,EAAS,UAAU,CACtB,CACDE,EAAAA,IAAI,GAAG,GAAIC,EAAAA,MAAM,IAAI,CACrB,CACI,QAAS,WAAW,EAAM,iBAC7B,CACJ,CACJ,CAIT,OAAO,GAEd,CAED,OAAO,GC1RLE,GAA8F,CAChG,KAAM,CACF,cAAe,6CACf,WAAY,6CACf,CACD,KAAM,CACF,cAAeC,EAAAA,YACf,WAAYA,EAAAA,YACf,CACD,KAAM,CACF,cAAeA,EAAAA,YACf,WAAYA,EAAAA,YACf,CACJ,CAWY,GAA8B,GAA8C,CACrF,IAAM,EAAY,GAAqB,IAAgB,GAAqB,KAE5E,OAAO,GAA0B,CAC7B,KAAM,gBACN,cAAe,EAAU,cACzB,WAAY,EAAU,WACtB,SAAU,EAAU,SAAWC,EAAAA,QAAM,cAAcC,EAAAA,EAAgB,CAAE,UAAS,CAAC,CAClF,CAAC,EC5BO,GAAsB,GAAgD,CAC/E,GAAwB,EAAY,CACpC,GAA2B,EAAY,CAC1C,CCcY,IACT,EACA,EACA,EACA,EACA,EAA4B,EAC5B,EAAmB,KACO,CAE1B,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,cAAeC,EAAAA,GAAW,CAG5B,EAAmB,GAAW,SAAW,KACzC,EAAiB,GAAS,SAAW,KACrC,CAAE,KAAM,GAAkB,EAAsB,IAAqB,MAAQ,IAAqBC,EAAAA,aAAe,CAAC,EAAmB,GAAK,EAAiB,CAC3J,CAAE,KAAM,GAAgB,EAAsB,IAAmB,MAAQ,IAAmBA,EAAAA,aAAe,CAAC,EAAiB,GAAK,EAAe,CAEjJ,GAAA,EAAA,EAAA,aACE,CAAC,GAAoB,IAAqB,MAAQ,IAAqBA,EAAAA,aAAe,CAAC,EAAsB,GAC1G,OAAO,GAAe,UAAY,GAAG,CAC7C,CAAC,EAAkB,GAAe,SAAS,CAAC,CAEzC,GAAA,EAAA,EAAA,aACE,CAAC,GAAkB,IAAmB,MAAQ,IAAmBA,EAAAA,aAAe,CAAC,EAAoB,GAClG,OAAO,GAAa,UAAY,GAAG,CAC3C,CAAC,EAAgB,GAAa,SAAS,CAAC,CAErCC,GAAAA,EAAAA,EAAAA,aAA0C,CAC5C,GAAI,CAAC,GAAoB,CAAC,GAAkB,CAAC,GAAY,CAAC,EAAa,OAAO,KAG9E,IAAIC,EACJ,GAAI,CACA,GAAA,EAAA,EAAA,YAAyB,EAAU,EAAkB,OAChDC,EAAO,CAEZ,OADA,QAAQ,MAAM,0BAA2B,EAAUA,EAAM,CAClD,KAKX,OAFI,GAAe,GAAW,KAEvB,CACH,mBACA,iBACA,SAAU,EAAY,UAAU,CAChC,cACA,oBACH,EACF,CAAC,EAAkB,EAAgB,EAAU,EAAa,EAAmB,EAAkB,CAAC,CAE7F,CAAE,OAAM,YAAW,UAAA,EAAA,EAAA,UAAoE,CACzF,SAAU,CAAC,sBAAuB,EAAQ,EAAW,QAAQ,CAC7D,QAAS,SAAY,CACjB,GAAI,CAAC,GAAU,CAAC,GAAQ,CAAC,EAAW,QAAS,MAAO,CAAE,OAAQ,EAAE,CAAE,KAAM,KAAM,CAG9E,IAAM,EADc,GAAmB,EAAW,QAAQ,CACxB,IAAI,KAAO,IAAe,CACxD,GAAI,CACA,IAAM,EAAQ,MAAM,EAAW,SAAS,EAAQ,EAAK,CACrD,GAAI,CACA,IAAM,EAAa,MAAM,EAAW,aAAa,EAAQ,EAAO,EAAK,CAQrE,MAPiC,CAC7B,GAAG,EACH,aACA,SAAU,CAAC,EAAW,QACtB,aAAc,EAAW,MACzB,YAAa,EAAW,YAC3B,OAEI,EAAU,CASf,OARA,QAAQ,MAAM,+BAA+B,EAAW,KAAK,GAAI,EAAS,CACzC,CAC7B,GAAG,EACH,aACA,SAAU,GACV,aAAc,aAAoB,MAAQ,EAAS,QAAU,oBAC7D,YAAa,EAChB,QAGAA,EAAO,CAEZ,OADA,QAAQ,MAAM,4BAA4B,EAAW,KAAK,GAAIA,EAAM,CAC7D,OAEb,CAEI,GAAU,MAAM,QAAQ,IAAI,EAAc,EAAE,OAC7C,GAAsB,IAAM,MAAQ,EAAE,eAAiB,GAC3D,CAGGC,EAAyB,KAC7B,GAAI,EAAO,OAAS,EAAG,CACnB,IAAM,EAAc,EAAO,OAAQ,GAAM,EAAE,EAAE,UAAY,IAAO,CAEhE,GADmB,EAAY,OAAS,EAAI,EAAc,GACxC,QAAQ,EAAK,IAAQ,CACnC,IAAM,EAAI,OAAO,EAAI,cAAgB,IAAI,CAEzC,OADU,OAAO,EAAI,cAAgB,IAAI,CAC9B,EAAI,EAAM,GACvB,CAGN,MAAO,CAAE,SAAQ,OAAM,EAE3B,QAAS,GAAW,IAAW,MAAQ,GAAS,KAChD,gBAAiB,IACpB,CAAC,CAEF,MAAO,CACH,UAAW,GAAM,MAAQ,KACzB,OAAQ,GAAM,QAAU,EAAE,CAC1B,YACA,QACA,KAAM,EAAY,CACd,GAAG,EACH,QAAS,GAAoB,GAC7B,SAAU,EACb,CAAG,KACJ,GAAI,EAAU,CACV,GAAG,EACH,QAAS,GAAkB,GAC3B,SAAU,EACb,CAAG,KACP,ECxICC,GACF,CACI,SAAY,CACR,QAAQ,KACJ,2FACH,EAEL,UAAa,GACb,6BAAgC,GACnC,CAYQ,OACsC,CAE3C,IAAM,EAAsB,CAAC,CADdC,EAAAA,GAAqB,CACC,QAGjCC,EAA+D,KACnE,GAAI,CACA,GAAA,EAAA,EAAA,iBAAqC,MACjC,EAcR,MATI,CAAC,GAKD,CAAC,EACM,GAGJ,GCvDF,OAAwB,CACjC,GAAM,CAAE,gBAAiBC,EAAAA,GAAqB,CACxC,EACF,GAAc,SAAW,GAAK,EAAa,GAAG,SAAW,UAEvD,CAAE,mBAAkB,oBAAmB,sBACzCC,EAAAA,GAAU,CAGR,CAAE,KAAM,EAAa,MAAO,GAAiB,IAA+B,CAElF,MAAO,CACH,KAAM,EACA,EACC,GACG,EAAiB,EAAe,CAC1C,MAAO,EAAiB,EAAe,EACvC,OAAQ,EAAiB,GAAQ,EACpC,EAGQ,IAAwB,CAAE,eACnC,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CC1BN,OAAwB,CACjC,GAAM,CACF,iBAAkB,EAClB,kBAAmB,EACnB,mBAAoB,GACpBC,EAAAA,GAAU,CACd,MAAO,CAAE,SAAY,GAAM,CAAE,QAAO,SAAQ,EAGnC,IAAwB,CAAE,eACnC,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCVN,OAA4B,CACrC,GAAM,CACF,qBAAsB,EACtB,sBAAuB,EACvB,uBAAwB,GACxBC,EAAAA,GAAU,CACd,MAAO,CAAE,OAAM,QAAO,SAAQ,EAGrB,IAA4B,CACrC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCbR,OAA4B,CACrC,GAAM,CACF,qBAAsB,EACtB,sBAAuB,EACvB,uBAAwB,GACxBC,EAAAA,GAAU,CACd,MAAO,CAAE,OAAM,QAAO,SAAQ,EAGrB,IAA4B,CACrC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCXR,OAAuB,CAChC,GAAM,CAAE,cAAeC,EAAAA,GAAW,CAC5B,CACF,mBACA,oBACA,qBACA,mBACA,oBACA,sBACAC,EAAAA,GAAU,CAqBd,MAAO,CAAE,KAnBK,GAAkC,CACxC,EAAW,YACX,EAAiB,IAAA,GAAW,EAAQ,CAEpC,GAAkB,EAeX,UAXK,CACZ,GACA,GAAmB,CAEnB,GACA,GAAmB,EAML,OAFP,GAAsB,EAEP,EAGrB,IAAuB,CAAE,eAClC,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCpCN,OAA2B,CACpC,GAAM,CACF,mBACA,oBACA,qBACA,0BACAC,EAAAA,GAAU,CAoBd,MAAO,CACH,KAnBU,GAAkC,CAC5C,EACI,CACI,KAAM,cACN,MAAO,CACH,kBAAmB,EACnB,WAAc,EAAuB,OAAO,CAC5C,qBAAsB,OACzB,CACJ,CACD,EACH,EASD,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAA2B,CACpC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCrCR,OAA0B,CACnC,GAAM,CACF,mBACA,oBACA,qBACA,0BACAC,EAAAA,GAAU,CAkBd,MAAO,CACH,KAjBU,GAAkC,CAC5C,EACI,CACI,KAAM,aACN,MAAO,CACH,kBAAmB,EACtB,CACJ,CACD,EACH,EASD,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAA0B,CACnC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCxBR,OAA0B,CACnC,GAAM,CACF,mBACA,oBACA,qBACA,0BACAC,EAAAA,GAAU,CAsBd,MAAO,CACH,KArBU,GAAoC,CAa9C,EAP0C,CACtC,KAAM,aACN,MAPe,CACf,kBAAmB,EACnB,iBAAkB,GAAS,iBAC3B,eAAgB,GAAS,eAC5B,CAIA,CAC2C,CACxC,aAAc,GAAS,aAC1B,CACwC,EASzC,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAA0B,CACnC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CClDR,OAAiC,CAC1C,GAAM,CAAE,mBAAkB,oBAAmB,sBACzCC,EAAAA,GAAU,CAUd,MAAO,CACH,KATU,GAAkC,CAC5C,EAAiB,YAAa,EAAQ,EAStC,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAAiC,CAC1C,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCvBR,OAA8B,CACvC,GAAM,CAAE,mBAAkB,oBAAmB,sBACzCC,EAAAA,GAAU,CAUd,MAAO,CACH,KATU,GAAkC,CAC5C,EAAiB,gBAAiB,EAAQ,EAS1C,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAA8B,CACvC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCvBR,OAAoB,CAC7B,GAAM,CACF,mBACA,oBACA,qBACA,0BACAC,EAAAA,GAAU,CAmBd,MAAO,CACH,KAlBU,GAAkC,CAC5C,EACI,CACI,KAAM,MACN,MAAO,CACH,aAAgB,EAAuB,OAAO,CAC9C,qBAAsB,GACzB,CACJ,CACD,EACH,EASD,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAAoB,CAAE,eAC/B,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCjCN,OAAqC,CAC9C,GAAM,CACF,mBACA,oBACA,qBACA,0BACAC,EAAAA,GAAU,CAed,MAAO,CACH,SAde,CACf,EAAiB,CACb,KAAM,wBACN,MAAO,CACH,kBAAmB,EACtB,CACJ,CAAC,EASF,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAAqC,CAC9C,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CChCR,OAAwB,CACjC,GAAM,CAAE,mBAAkB,oBAAmB,sBACzCC,EAAAA,GAAU,CAUd,MAAO,CACH,KATU,GAAkC,CAC5C,EAAiB,gBAAiB,EAAQ,EAS1C,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAAwB,CAAE,eACnC,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCPN,OAAsD,CAC/D,GAAM,CAAE,QAAO,gBAAiBC,EAAAA,GAAqB,CAC/C,EAAe,GAAO,QAAUC,EAAAA,GAGhC,EAAwB,GACrB,EAED,MAAM,QAAQC,EAAO,CACdA,EAAO,KAAM,GAChB,EAAa,KAAM,GAAO,EAAG,SAAW,EAAE,CAC7C,CAEE,EAAa,KAAM,GAAO,EAAG,SAAWA,EAAO,CAP5B,GAWxB,GAAA,EAAA,EAAA,aACG,EACE,EAAa,SAAW,GAAK,EAAqB,YAAY,CAD3C,GAE3B,CAAC,EAAa,CAAC,CAEZ,GAAA,EAAA,EAAA,aACI,EAAqB,UAAU,CACrC,CAAC,EAAa,CACjB,CACK,GAAA,EAAA,EAAA,aACI,EAAqB,UAAU,CACrC,CAAC,EAAa,CACjB,CACK,GAAA,EAAA,EAAA,aACI,EAAqB,UAAU,CACrC,CAAC,EAAa,CACjB,CACK,GAAA,EAAA,EAAA,aACI,EAAqB,QAAQ,CACnC,CAAC,EAAa,CACjB,CAeKC,EAAsC,CACxC,iBAAA,EAAA,EAAA,aAdM,EAAqB,SAAS,CACpC,CAAC,EAAa,CACjB,CAaG,eAAgB,EAChB,YAAa,EACb,iBAAkB,EAClB,YAAa,EACb,cAAe,EACf,eAAA,EAAA,EAAA,aAhBM,EAAqB,OAAO,CAClC,CAAC,EAAa,CACjB,CAeG,iBAAA,EAAA,EAAA,aAbM,EAAqB,SAAS,CACpC,CAAC,EAAa,CACjB,CAYG,qBAAsB,GACzB,CAsBD,OApBK,EAWD,EAEO,CACH,GAAG,EACH,qBAAsB,GACzB,CAIE,CACH,GAAG,EACN,CApBU,CACH,GAAG,EACH,gBAAiB,GACjB,eAAgB,GAChB,YAAa,GACb,cAAe,GAClB,ECnFI,GACT,GACC,CACD,GAAM,CACF,6BAA8B,EAC9B,8BAA+B,EAC/B,+BAAgC,GAChCC,EAAAA,GAAU,CACd,MAAO,CAAE,SAAY,EAAK,EAAM,CAAE,QAAO,SAAQ,EAGxC,IAAoC,CAC7C,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCjBR,OAAwB,CACjC,GAAM,CAAE,mBAAkB,oBAAmB,sBACzCC,EAAAA,GAAU,CAUd,MAAO,CACH,KATU,GAAkC,CAC5C,EAAiB,UAAW,EAAQ,EASpC,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAAwB,CAAE,eACnC,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCrBN,OAA+B,CACxC,GAAM,CAAE,eAAc,qBAAsBC,EAAAA,GAAU,CAEtD,MAAO,CACH,eACA,oBACH,ECLQ,OAAyB,CAClC,GAAM,CAAE,mBAAkB,oBAAmB,sBACzCC,EAAAA,GAAU,CAUd,MAAO,CACH,KATU,GAAkC,CAC5C,EAAiB,WAAY,EAAQ,EASrC,UANgB,CAChB,GAAmB,EAMnB,OAAQ,EACX,EAGQ,IAAyB,CAClC,eAGE,EAAA,EAAA,KAAA,EAAA,SAAA,CAAG,WAAA,CAAY,CCHRC,GAAwC,CACjD,CACI,GAAI,UACJ,MAAO,yBACP,YACI,wHACJ,UAAW,KAAK,KAAK,CACrB,OAAQ,UACR,OAAQ,GACX,CACJ,CC3BY,OAAyB,CAClC,GAAM,CAAE,WAAYC,EAAAA,GAAW,CAEzB,GAAA,EAAA,EAAA,aAA8B,GAAqB,CACrD,IAAM,EAAoB,GAAS,aAAa,CAChD,MAAO,CACH,cAAe,6BAA6B,IAC5C,SAAU,sCAAsC,IAChD,YAAa,yCAAyC,IACzD,EACF,EAAE,CAAC,CAEA,GAAA,EAAA,EAAA,iBAA4C,CAC9C,GAAI,CAAC,GAAS,SAAW,CAACC,EAAAA,GAAW,CAAE,OAEvC,IAAM,EAAO,EAAe,EAAQ,QAAQ,CACtBC,EAAAA,EAAoB,EAAK,YAAY,GAGvD,EAAA,EACI,EAAK,cACL,KAAK,UAAU,GAAsB,CACxC,CACD,EAAA,EAAoB,EAAK,YAAa,OAAO,GAElD,CAAC,GAAS,QAAS,EAAe,CAAC,EAEtC,EAAA,EAAA,eAAgB,CACZ,GAAyB,EAC1B,CAAC,EAAwB,CAAC,CAE7B,IAAM,GAAA,EAAA,EAAA,iBAAqD,CACvD,GAAI,CAAC,GAAS,SAAW,CAACD,EAAAA,GAAW,CAAE,MAAO,EAAE,CAGhD,IAAM,EAASC,EAAAA,EADF,EAAe,EAAQ,QAAQ,CACJ,cAAc,CAEtD,OADK,EACE,KAAK,MAAM,EAAO,CADL,EAAE,EAEvB,CAAC,GAAS,QAAS,EAAe,CAAC,CAEhC,GAAA,EAAA,EAAA,iBAA6D,CAC/D,GAAI,CAAC,GAAS,SAAW,CAACD,EAAAA,GAAW,CAAE,MAAO,EAAE,CAGhD,IAAM,EAASC,EAAAA,EADF,EAAe,EAAQ,QAAQ,CACJ,SAAS,CAEjD,OADK,EACE,KAAK,MAAM,EAAO,CADL,EAAE,EAEvB,CAAC,GAAS,QAAS,EAAe,CAAC,CAEhC,GAAA,EAAA,EAAA,aACD,GAA6D,CAC1D,GAAI,CAAC,GAAS,SAAW,CAACD,EAAAA,GAAW,CAAE,OAEvC,IAAM,EAAO,EAAe,EAAQ,QAAQ,CACtC,EAAgB,GAAkB,CAClC,EAAgBC,EAAAA,EAAoB,EAAK,SAAS,CAClD,EAAwB,EAAgB,KAAK,MAAM,EAAc,CAAG,EAAE,CAO5E,GAJoB,CAChB,GAAG,EACH,GAAG,EACN,CAAC,KAAM,GAAM,EAAE,QAAU,EAAa,MAAM,CAC5B,OAEjB,IAAMC,EAAgC,CAClC,GAAG,EACH,GAAI,EAAa,IAAM,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,UAAU,EAAE,CAC9D,UAAW,KAAK,KAAK,CACrB,OAAQ,GACX,CACD,EAAA,EACI,EAAK,cACL,KAAK,UAAU,CAAC,EAAiB,GAAG,EAAc,CAAC,CACtD,EAEL,CAAC,GAAS,QAAS,EAAkB,EAAe,CACvD,CAEK,GAAA,EAAA,EAAA,aACD,GAA2B,CACxB,GAAI,CAAC,GAAS,SAAW,CAACF,EAAAA,GAAW,CAAE,OAEvC,IAAM,EAAO,EAAe,EAAQ,QAAQ,CAEtC,EADgB,GAAkB,CACG,OACtC,GAAM,EAAE,KAAO,EACnB,CACD,EAAA,EACI,EAAK,cACL,KAAK,UAAU,EAAqB,CACvC,EAEL,CAAC,GAAS,QAAS,EAAkB,EAAe,CACvD,CA+DD,MAAO,CACH,mBACA,2BACA,kBACA,uBAAA,EAAA,EAAA,iBAjE4C,CAC5C,GAAI,CAAC,GAAS,SAAW,CAACA,EAAAA,GAAW,CAAE,OAEvC,IAAM,EAAO,EAAe,EAAQ,QAAQ,CACtC,EAAgB,GAAkB,CACxC,EAAA,EACI,EAAK,SACL,KAAK,UAAU,CAAC,GAAG,GAA0B,CAAE,GAAG,EAAc,CAAC,CACpE,CACD,EAAA,EAAoB,EAAK,cAAe,KAAK,UAAU,EAAE,CAAC,CAAC,EAC5D,CACC,GAAS,QACT,EACA,EACA,EACH,CAAC,CAmDE,YAAA,EAAA,EAAA,aAhDC,GAA2B,CACxB,GAAI,CAAC,GAAS,SAAW,CAACA,EAAAA,GAAW,CAAE,OAEvC,IAAM,EAAO,EAAe,EAAQ,QAAQ,CACtC,EAAgB,GAAkB,CAClC,EAAwB,GAA0B,CAGlD,EAAwB,EAAc,KACvC,GAAM,EAAE,KAAO,EACnB,CAGK,EAAuB,EAAc,OACtC,GAAM,EAAE,KAAO,EACnB,CAGD,GAAI,EAAuB,CACvB,IAAM,EAA+B,CACjC,CAAE,GAAG,EAAuB,OAAQ,GAAM,CAC1C,GAAG,EACN,CAGD,EAAA,EACI,EAAK,cACL,KAAK,UAAU,EAAqB,CACvC,CACD,EAAA,EACI,EAAK,SACL,KAAK,UAAU,EAA6B,CAC/C,GAGT,CACI,GAAS,QACT,EACA,EACA,EACH,CACJ,CAQG,qBACH,ECnKQ,GAA+B,MACxC,EACA,EACA,EACA,IACmB,CACnB,IAAM,EAAM,MAAM,EAAK,UAClB,KACGG,EAAAA,GAAU,EAAY,CAAC,sBACvBC,EAAAA,wCAAwC,IAC3C,CACA,KAAK,0BAA0B,EAAiB,OAAO,EAAc,CAAC,CAE3E,GAAI,CAAC,EACD,MAAU,MACN,uDAAuD,IAC1D,CAEL,OAAO,EAAI,IAGF,GACT,EACA,EACA,IACC,CACD,cACA,gBACA,UACA,4BACA,EACA,EACA,EACH,CAQY,IACT,EACA,IACC,CAED,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EACN,EACA,EACA,EAAQ,KACX,CACD,QAAS,SACL,GACI,EACA,EACA,EACA,EAAQ,KACX,CACL,QACI,CAAC,CAAC,GACF,CAAC,CAAC,GACF,CAAC,CAAC,GACF,CAAC,CAAC,GACF,IAAoB,GAC3B,CAAC,EClEO,OAA8B,CACvC,GAAM,CAAE,MAAA,EAAA,EAAA,iBAAsB,CACxB,CAAE,UAAS,aAAY,gBAAiBC,EAAAA,GAAW,CACnD,CAAE,kBAAiB,oBAAqB,IAAkB,CAG1D,CAAE,KAAM,GAAoB,GAC9B,GAAc,SAAW,GACzB,EACH,EAGD,EAAA,EAAA,eAAgB,CACZ,GAAI,CAAC,EAAW,sBAAwB,CAAC,GAAS,QAAS,OAE3D,IAAM,EAAgB,GAAkB,CAClC,EAAwB,yBAAyB,EAAQ,QAAQ,aAAa,GAMhF,CAL2B,EAAc,KACxC,GAAM,EAAE,KAAO,EACnB,EAG8B,GAC3B,EAAgB,CACZ,GAAI,EACJ,MAAO,EAAE,2BAA2B,CACpC,YAAa,EACT,0HACH,CACD,OAAQ,UACX,CAAC,EAEP,CAAC,EAAW,qBAAsB,GAAS,QAAS,EAAgB,CAAC,EAGxE,EAAA,EAAA,eAAgB,CACR,CAAC,EAAW,sBAAwB,CAAC,GAAS,SAE5B,GAAkB,CACU,KAC7C,GAAM,EAAE,KAAO,iBAAiB,EAAQ,QAAQ,aAAa,GACjE,EAGG,EAAgB,CACZ,GAAI,iBAAiB,EAAQ,QAAQ,aAAa,GAClD,MAAO,EAAE,yBAAyB,CAClC,YAAa,EACT,qGACH,CACD,OAAQ,OACX,CAAC,EAEP,CAAC,EAAW,qBAAsB,GAAS,QAAQ,CAAC,EAGvD,EAAA,EAAA,eAAgB,CACZ,GAAI,CAAC,EAAW,sBAAwB,CAAC,GAAS,QAAS,OAE3D,IAAM,EAAgB,GAAkB,CAElC,EAAwB,EAAc,KACvC,GACG,EAAE,KAAO,uBAAuB,EAAQ,QAAQ,aAAa,GACpE,CACK,EAAwB,EAAc,KACvC,GACG,EAAE,KAAO,uBAAuB,EAAQ,QAAQ,aAAa,GACpE,CAIG,GAAyB,CAAC,GAC1B,EAAgB,CACZ,GAAI,uBAAuB,EAAQ,QAAQ,aAAa,GACxD,MAAO,EAAE,6CAA6C,CACtD,YAAa,EACT,uKACH,CACD,OAAQ,OACX,CAAC,EAEP,CAAC,EAAW,qBAAsB,GAAS,QAAQ,CAAC,ECrE9C,OAAkD,CAC3D,GAAM,CAAC,EAAkB,IAAA,EAAA,EAAA,UAAgC,GAAM,CACzD,CAAC,EAAW,IAAA,EAAA,EAAA,UAAwC,KAAK,CACzD,CAAC,EAAO,IAAA,EAAA,EAAA,UAAmC,KAAK,CAEhD,CAAE,aAAY,WAAYC,EAAAA,GAAW,CAErC,CAAE,sBAAuBC,EAAAA,GAA0B,CAEnD,EAAsBC,EAAAA,GAAgC,CAyD5D,MAAO,CACH,aAAA,EAAA,EAAA,aAvDA,KAAO,IAAqC,CACxC,GAAI,CAAC,EAAS,MAAU,MAAM,oBAAoB,CAElD,EAAoB,GAAK,CACzB,EAAS,KAAK,CACd,EAAa,KAAK,CAElB,GAAI,CACA,IAAIC,EAAqB,KAEzB,GAAI,EAAW,uBAcX,GAbqB,MAAM,EACvB,CACI,QAAS,YACT,QAAS,CACL,KAAM,OACN,QAAS,EACZ,CACJ,CACD,CACI,OAAQ,EAAQ,QACnB,CACJ,EAEkB,cAChB,CACH,GAAI,CAAC,EACD,MAAU,MACN,qGACH,CAEL,EAAM,MAAM,EAAoB,YAAY,EAAQ,CAIxD,OADA,EAAa,EAAI,CACV,QACF,EAAK,CACV,IAAMC,EACF,aAAe,MAAQ,EAAU,MAAM,OAAO,EAAI,CAAC,CAEvD,MADA,EAASA,EAAM,CACTA,SACA,CACN,EAAoB,GAAM,GAGlC,CAAC,EAAY,EAAqB,GAAS,QAAQ,CACtD,CAUG,mBACA,YACA,QACA,OAAA,EAAA,EAAA,iBAX4B,CAC5B,EAAoB,GAAM,CAC1B,EAAa,KAAK,CAClB,EAAS,KAAK,EACf,EAAE,CAAC,CAQL,ECnEQ,OAAsD,CAC/D,GAAM,CAAC,EAAkB,IAAA,EAAA,EAAA,UAAgC,GAAM,CACzD,CAAC,EAAW,IAAA,EAAA,EAAA,UAAwC,KAAK,CACzD,CAAC,EAAO,IAAA,EAAA,EAAA,UAAmC,KAAK,CAGhD,CAAE,UAAWC,EAAAA,GAA0B,CACvC,CAAE,cAAeC,EAAAA,GAAW,CAE5B,EAAsBC,EAAAA,GAAgC,CA+E5D,MAAO,CACH,eAAA,EAAA,EAAA,aA7EA,MACI,EACA,IACkB,CAClB,EAAoB,GAAK,CACzB,EAAS,KAAK,CACd,EAAa,KAAK,CAElB,GAAI,CACA,IAAIC,EACJ,GAAI,EAAW,uBAAwB,CACnC,IAAM,EAAS,CACX,GAAG,EAAK,OACR,KAAM,EAAK,QAAQ,KACb,OAAO,KAAK,EAAK,OAAO,KAAK,CAAC,SAAS,MAAM,CAC7C,IAAA,GACT,CAED,EAAM,MAAM,EAAO,cACf,EACA,EAAK,MACL,EAAK,QACL,IAAA,GACA,EACH,KACE,CACH,GAAI,CAAC,EACD,MAAU,MACN,qGACH,CAEL,EAAM,MAAM,EAAoB,cAAc,EAAK,CAIvD,OADA,EAAa,EAAI,CACV,QACF,EAAK,CAEV,GACI,GACA,OAAO,GAAQ,UACf,eAAgB,GACf,EAAY,aAAe,KAC9B,CACE,IAAM,EAAyB,MAC3B,gCACH,CAED,MADA,EAAS,EAAmB,CACtB,EAIV,IAAMC,EACF,aAAe,MACT,EACI,MACA,OAAO,GAAQ,SACT,KAAK,UAAU,EAAI,CACnB,OAAO,EAAI,CACpB,CAGX,MAFA,QAAQ,MAAMA,EAAM,CACpB,EAASA,EAAM,CACTA,SACA,CACN,EAAoB,GAAM,GAGlC,CAAC,EAAY,EAAoB,CACpC,CAUG,mBACA,YACA,QACA,OAAA,EAAA,EAAA,iBAX4B,CAC5B,EAAoB,GAAM,CAC1B,EAAa,KAAK,CAClB,EAAS,KAAK,EACf,EAAE,CAAC,CAQL,ECxHQ,OAA4B,CACrC,GAAM,CAAE,iBAAkB,IAAA,EAAA,EAAA,sBACI,CAU9B,MAAO,CAAE,iBARgB,SAAY,CACjC,GAAI,CACA,MAAM,GAAuB,OACxB,EAAO,CACZ,MAAM,IAIa,ECF/B,IAAI,GAAmB,GAEvB,MAAa,OAA0B,CACnC,GAAM,CAAE,iBAAA,EAAA,EAAA,kBAAkC,CAwBpC,CAAE,UAAW,IAAA,EAAA,EAAA,mBAA0C,CACzD,YAAA,EAAA,EAAA,aArBA,MAAO,CAAE,eAAwC,CAG7C,GAAI,GAAa,CAAC,GAAkB,CAEhC,GAAmB,GAEnB,GAAI,CACA,MAAM,GAAc,OACf,EAAO,CAIZ,KAFA,IAAmB,GACnB,QAAQ,MAAM,2BAA4B,EAAM,CAC1C,KAIlB,CAAC,EAAa,CACjB,CAIA,CAAC,CAUF,MAAO,CAAE,UARS,MAAO,CAAE,cAA6B,CACpD,GAAI,CACA,MAAM,EAAe,CAAE,WAAU,CAAC,OAC7B,EAAO,CACZ,MAAM,IAIM,EC3CX,OAA4B,CAErC,GAAM,CAAE,MAAO,GAAqBC,EAAAA,GAA6B,CAC3D,CAAE,sBAAuBC,EAAAA,GAA4B,CACrD,CAAE,KAAM,GAAa,EAAgB,CAACC,EAAAA,GAAqB,CAAC,CAyBlE,MAAO,CAAE,MAvBK,SAAY,CACtB,GAAI,CACA,MAAM,EAAiBA,EAAAA,GAAqB,CAE5C,EAAmB,CACf,KAAM,UACN,QAAS,IAAWA,EAAAA,KAAuB,SAC3C,MAAOA,EAAAA,GACP,QAASC,EAAAA,EACZ,CAAC,OAEG,EAAO,CACZ,MAAMC,EAAAA,EAAiB,CACnB,QACA,0BACI,mIACJ,gBAAiB,+BACjB,eACI,8FACP,CAAC,GAIM,ECfd,GAAY,2BACZ,GAAmB,kCACnB,GAAoB,KAAU,GAAK,IAK5B,OAA8B,CAAC,cAAe,SAAU,OAAO,CAM/D,GAAkB,SAAkC,CAE7D,GAAI,OAAO,OAAW,IAClB,GAAI,CACA,IAAM,EAAaC,EAAAA,EAAoB,GAAU,CAC3C,EAAcA,EAAAA,EAAoB,GAAiB,CAGzD,GAAI,GAAc,EAAa,CAC3B,IAAM,EAAa,SAAS,EAAa,GAAG,CAC5C,GAAI,KAAK,KAAK,CAAG,EACb,OAAO,KAAK,MAAM,EAAW,OAGjC,CAEJ,QAAQ,KAAK,6CAA6C,CAKlE,IAAM,EAAa,IAAI,IAAI,gBAAiBC,EAAAA,EAA4B,CAClE,EAAc,MAAM,MAAM,EAAW,CAC3C,GAAI,CAAC,EAAY,GACb,MAAU,MAAM,kCAAkC,CAMtD,IAAM,GAHc,MAAM,EAAY,MAAM,EAGZ,IAAI,KAAO,IAAa,CACpD,GAAI,EAAI,OAAS,MAAO,OAAO,KAE/B,IAAM,EAAc,IAAI,IACpB,eAAe,EAAI,KAAK,gBACxBC,EAAAA,EACH,CACK,EAAmB,MAAM,MAAM,EAAY,CAEjD,GAAI,CAAC,EAAiB,GAElB,OADA,QAAQ,KAAK,gCAAgC,EAAI,OAAO,CACjD,KAGX,GAAI,CACA,IAAM,EAAW,MAAM,EAAiB,MAAM,CACxC,EAAU,IAAI,IAChB,eAAe,EAAI,KAAK,WACxBA,EAAAA,EACH,CACD,MAAO,CACH,GAAI,EAAI,KACR,KAAM,EAAS,KACf,YAAa,EAAS,KACtB,IAAK,EAAS,KACd,KAAM,EAAQ,UAAU,CACxB,SAAU,EAAS,SACnB,KAAM,EAAS,MAAQ,EAAE,CACzB,mBAAoB,EAAS,oBAAsB,GACnD,KAAM,EAAS,KACf,UAAW,EAAS,UACpB,cAAe,EAAS,cAC3B,OACI,EAAG,CAER,OADA,QAAQ,KAAK,8BAA8B,EAAI,KAAK,GAAI,EAAE,CACnD,OAEb,CAGI,GADW,MAAM,QAAQ,IAAI,EAAY,EACpB,OAAQ,GAAQ,IAAQ,KAAK,CAGxD,GAAI,OAAO,OAAW,IAClB,GAAI,CACA,EAAA,EAAoB,GAAW,KAAK,UAAU,EAAU,CAAC,CACzD,EAAA,EACI,IACC,KAAK,KAAK,CAAG,OAAmB,UAAU,CAC9C,OACI,EAAG,CACR,QAAQ,KAAK,gCAAiC,EAAE,CAIxD,OAAO,GAuBE,QACT,EAAA,EAAA,UAA6B,CACzB,SAAU,IAAuB,CACjC,QAAS,SAAY,CACjB,GAAI,CACA,OAAO,MAAM,IAAiB,OACzB,EAAO,CAEZ,IAAM,EAAa,aAAa,QAAQ,GAAU,CAClD,GAAI,EACA,OAAO,KAAK,MAAM,EAAW,CAGjC,MAAM,IAGd,UAAW,IAAO,GAAK,GACvB,MAAO,EACV,CAAC,CCxIO,OAA2B,CACpC,GAAM,CAAE,kBAAiB,eAAgBC,EAAAA,GAAqB,CAC9D,MAAO,CACH,kBACA,cACH,ECJQ,OAA2B,CACpC,GAAM,CAAE,kBAAiB,eAAgBC,EAAAA,GAAqB,CAC9D,MAAO,CACH,kBACA,cACH,EC5BQ,OAA+B,CACxC,GAAM,CAAC,EAAW,IAAA,EAAA,EAAA,UAAyB,GAAK,CAC1CC,EAAY,0CAclB,OAZA,EAAA,EAAA,eAAgB,CACKC,EAAAA,EAAoBD,EAAU,EAE3C,EAAa,GAAM,EAExB,EAAE,CAAC,CAOC,CACH,YACA,sBAP4B,CAC5B,EAAA,EAAoBA,EAAW,OAAO,CACtC,EAAa,GAAM,EAMtB,ECnBQ,OAAiB,CAE1B,GAAM,CAAC,EAAO,IAAA,EAAA,EAAA,UAAqB,GAAK,CA0BxC,OAxBA,EAAA,EAAA,eAAgB,CAEZ,GAAI,CAACE,EAAAA,GAAW,CAAE,CACd,EAAS,GAAM,CACf,OAGJ,IAAM,MAAmB,CAKrB,EAHI,OAAO,WAAW,6BAA6B,CAAC,SAC/C,OAAe,YAChB,SAAS,SAAS,SAAS,iBAAiB,CAC1B,EAO1B,OAJA,GAAY,CAEZ,OAAO,iBAAiB,SAAU,EAAW,KAEhC,CACT,OAAO,oBAAoB,SAAU,EAAW,GAErD,EAAE,CAAC,CAEC,GC7BE,OAAuB,EAChC,EAAA,EAAA,eAAgB,CAEZ,IAAM,EAAe,SAAS,cAAc,yBAAyB,CACjE,IACA,EAAa,UAAY,IAE9B,EAAE,CAAC,ECDG,GAAkC,MAC3C,EACA,EACA,IACkB,CAClB,GAAI,CAAC,EAAa,MAAU,MAAM,2BAA2B,CAC7D,GAAI,CAAC,EAAS,MAAU,MAAM,sBAAsB,CAEpD,IAAM,EAAW,EAAK,UAAU,KAC5BC,EAAAA,GAAU,EAAY,CAAC,sBACvBC,EAAAA,wCAAwC,IAC3C,CAEGC,EAIJ,OAAQ,EAAR,CACI,IAAK,GACL,IAAK,GACD,EACI,EAAS,KAAK,yBAAyB,CAC3C,MAEJ,IAAK,GACD,EACI,EAAS,KAAK,yBAAyB,CAC3C,MACJ,QACI,MAAU,MAAM,2CAA2C,CAGnE,IAAM,EAAM,MAAM,EAElB,GAAI,CAAC,EAAK,MAAU,MAAM,+CAA+C,CAEzE,OAAO,EAAI,GAAG,UAAU,EAGf,GACT,EACA,IACC,CACD,cACA,gBACA,UACA,yBACA,EACA,EACH,CAOY,GAAmC,GAAqB,CAEjE,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EACN,EACA,EAAQ,KACX,CACD,QAAS,SACL,GAAgC,EAAO,EAAS,EAAQ,KAAK,CACjE,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAW,CAAC,CAAC,EACrC,CAAC,ECrEO,GAAyC,MAClD,EACA,IACkB,CAClB,GAAI,CAAC,EAAa,MAAU,MAAM,2BAA2B,CAE7D,IAAM,EAAM,MAAM,EAAK,UAClB,KACGC,EAAAA,GAAU,EAAY,CAAC,sBACvBC,EAAAA,wCAAwC,IAC3C,CACA,KAAK,qCAAqC,CAE/C,GAAI,CAAC,EACD,MAAU,MAAM,uDAAuD,CAE3E,OAAO,SAAS,EAAI,GAAG,UAAU,CAAC,EAGzB,EACT,GACC,CACD,cACA,gBACA,UACA,yCACA,EACH,CAMY,OAA+C,CAExD,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAA+C,EAAQ,KAAK,CACtE,QAAS,SACL,GAAuC,EAAO,EAAQ,KAAK,CAC/D,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EACxB,CAAC,EC3CO,GAAoB,MAC7B,EACA,EACA,IACkB,CAClB,GAAI,CAAC,EAAc,MAAU,MAAM,4BAA4B,CAC/D,GAAI,CAAC,EAAa,MAAU,MAAM,2BAA2B,CAE7D,IAAM,EAAM,MAAM,EAAK,UAClB,KACGC,EAAAA,GAAU,EAAY,CAAC,sBACvBC,EAAAA,wCAAwC,IAC3C,CACA,KAAK,kBAAkB,EAAa,CAEzC,GAAI,CAAC,EACD,MAAU,MAAM,oCAAoC,IAAe,CAEvE,OAAO,EAAI,GAAG,UAAU,EAGf,GACT,EACA,IACC,CACD,cACA,gBACA,UACA,UACA,EACA,EACH,CAOY,GAAwB,GAA0B,CAE3D,IAAM,EAAOC,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAA0B,EAAc,EAAQ,KAAK,CAC/D,QAAS,SACL,GAAkB,EAAO,EAAc,EAAQ,KAAK,CACxD,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAgB,CAAC,CAAC,EAC1C,CAAC,EClDO,GAAgB,MACzB,EACA,IACmB,CACnB,GAAI,CAAC,EAAgB,MAAU,MAAM,8BAA8B,CAEnE,IAAM,EAAM,MAAM,EAAK,SAAS,WAC5BC,EAAAA,QAAQ,GAAG,OAAO,EAAe,CAAC,CACrC,CAED,GAAI,CAAC,EAAK,MAAU,MAAM,oBAAoB,CAE9C,OAAO,EAAI,SAGF,EAAyB,GAA6B,CAC/D,cACA,gBACA,cACA,EACH,CAMY,GAA6B,GAA4B,CAClE,IAAM,EAAUC,EAAAA,GAAe,CACzB,EAAOC,EAAAA,WAAW,GAAG,EAAQ,CAEnC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EAAsB,EAAe,CAC/C,QAAS,SAAY,GAAc,EAAM,EAAe,CACxD,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,EACxB,CAAC,EChCO,GAAqB,MAC9B,EACA,EACA,EACA,EACA,IACmB,CACnB,IAAM,EAAM,MAAM,EAAK,UAClB,KACGC,EAAAA,GAAU,EAAY,CAAC,sBACvBC,EAAAA,wCAAwC,IAC3C,CACA,KAAK,gBACF,EACA,EACA,OAAO,EAAc,CACxB,CAEL,GAAI,CAAC,EACD,MAAU,MACN,sDACID,EAAAA,GAAU,EAAY,CAAC,wBAE9B,CAEL,OAAO,EAAI,IAGF,GACT,EACA,EACA,EACA,IACC,CACD,cACA,gBACA,UACA,mBACA,EACA,EACA,EACA,EACH,CASY,IACT,EACA,EACA,IACC,CAED,IAAM,EAAOE,EAAAA,GAAiB,CACxB,CAAE,WAAYC,EAAAA,GAAqB,CAEzC,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,EACN,EACA,EACA,EACA,EAAQ,KACX,CACD,QAAS,SACL,GACI,EACA,EACA,EACA,EACA,EAAQ,KACX,CACL,QAAS,CAAC,CAAC,GAAQ,CAAC,CAAC,GAAkB,CAAC,CAAC,GAAgB,CAAC,CAAC,EAAQ,KACtE,CAAC,ECpEO,OAAiC,CAC1C,IAAM,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,kBAAiB,gBAAiBC,EAAAA,GAAW,CAC/C,CAAE,WAAYC,EAAAA,GAAqB,CAyGzC,MAAO,CAAE,QAvGO,SAAY,CACxB,IAAM,EAAe,GAAiB,SAAW,GAC3C,EAAsB,GAAc,SAAW,GAGrD,MAAM,QAAQ,IAAI,CAEd,EAAY,cAAc,CACtB,SAAU,EAA0B,EAAc,EAAQ,KAAK,CAClE,CAAC,CACF,EAAY,cAAc,CACtB,SAAUC,EAAAA,EACN,EACA,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,cAAc,CACtB,SAAUC,EAAAA,EACN,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,cAAc,CACtB,SAAU,EACN,EAAQ,KACX,CACJ,CAAC,CAGF,EAAY,cAAc,CACtB,SAAU,EACN,EACA,EACA,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,cAAc,CACtB,SAAU,EACN,EACA,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,cAAc,CACtB,SAAU,EACN,EACA,EAAQ,KACX,CACJ,CAAC,CACL,CAAC,CAGF,MAAM,QAAQ,IAAI,CAEd,EAAY,eAAe,CACvB,SAAU,EAA0B,EAAc,EAAQ,KAAK,CAClE,CAAC,CACF,EAAY,eAAe,CACvB,SAAUD,EAAAA,EACN,EACA,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,eAAe,CACvB,SAAUC,EAAAA,EACN,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EACN,EAAQ,KACX,CACJ,CAAC,CAGF,EAAY,eAAe,CACvB,SAAU,EACN,EACA,EACA,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EACN,EACA,EACA,EAAQ,KACX,CACJ,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EACN,EACA,EAAQ,KACX,CACJ,CAAC,CACL,CAAC,EAGY,EClHT,OAAsC,CAC/C,IAAM,GAAA,EAAA,EAAA,iBAA8B,CAC9B,CAAE,gBAAiBC,EAAAA,GAAW,CA4BpC,MAAO,CAAE,QA1BO,SAAY,CACxB,IAAM,EAAsB,GAAc,SAAW,GAGrD,MAAM,QAAQ,IAAI,CAEd,EAAY,cAAc,CACtB,SAAUC,EAAAA,EAAwB,EAAoB,CACzD,CAAC,CACF,EAAY,cAAc,CACtB,SAAU,EAAsB,EAAoB,CACvD,CAAC,CACL,CAAC,CAGF,MAAM,QAAQ,IAAI,CAEd,EAAY,eAAe,CACvB,SAAUA,EAAAA,EAAwB,EAAoB,CACzD,CAAC,CACF,EAAY,eAAe,CACvB,SAAU,EAAsB,EAAoB,CACvD,CAAC,CACL,CAAC,EAGY,ECnBhB,GAAmCC,EAAAA,iCAAiC,iBAAiB,CAE9E,IAA0B,CACnC,sBACA,gBACA,YACA,aACgF,CAChF,GAAM,CAAE,QAAS,GAA0B,IAA0B,CAC/D,CAAE,QAAS,GACb,IAA+B,CAG7B,CAAE,KAAM,GACV,GAAgC,EAAc,CAE5CC,GAAAA,EAAAA,EAAAA,aAA2B,SAAY,CACzC,GAAI,CAAC,GAAuB,CAACC,EAAAA,EAAe,EAAoB,CAC5D,MAAU,MAAM,gCAAgC,CAGpD,GAAI,CAAC,EACD,MAAU,MACN,sDAAsD,IACzD,CAGL,MAAO,CACH,CACI,GAAI,EACJ,MAAO,MACP,KAAM,GAAiC,mBACnC,mBACA,CAAC,EAA0B,KAAK,CACnC,CACD,QAAS,8BAA8B,IACvC,IAAK,GACA,YAAY,mBAAmB,CAC/B,OAAO,OAAO,CACtB,CACJ,EACF,CAAC,EAAqB,EAA0B,EAAc,CAAC,CAW5D,EAAS,EAAmB,CAC9B,eAAgB,CACZ,MAAO,wBACP,YAAa,6BAA6BC,EAAAA,EACtC,EACH,CAAC,cAAc,IAChB,WAAY,mBACf,CACD,cAjBoB,SAAY,CAEhC,MAAM,QAAQ,IAAI,CACd,GAAuB,CACvB,GAA4B,CAC/B,CAAC,CACF,KAAa,EAYb,sBAAuB,SAAY,CAC/B,KAAW,EAElB,CAAC,CAEF,MAAO,CACH,GAAG,EACH,gBAAiB,SACN,EAAO,gBAAgB,MAAMF,GAAc,CAAC,CAE1D,ECxFQ,OAA6B,CAAC,cAAe,gBAAgB,CAEpE,GAAmB,GAAKG,EAAAA,EAAK,OAMtB,OAAwB,CAEjC,IAAM,EAAOC,EAAAA,GAAiB,CAE9B,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,IAAsB,CAChC,QAAS,SAAY,CACjB,GAAI,CAAC,EAAM,MAAU,MAAM,4BAA4B,CACvD,IAAM,EAAW,MAAM,EAAK,OAAO,sBAAsB,CACzD,GAAI,CAAC,EAAU,MAAU,MAAM,gCAAgC,CAC/D,OAAO,GAEX,UAAW,IAAO,GAClB,gBAAiB,GACjB,QAAS,CAAC,CAAC,EACd,CAAC,ECrBA,EAAuB,IA8BhB,GAAe,MAAO,CAC/B,OACA,QAAQ,MACR,SAAS,EACT,QAAQ,EACR,OAAO,EACP,KAAK,EAAK,OAAO,cAAc,EAAE,OACjC,oBACkB,CAClB,IAAM,EAAW,MAAM,EAAK,KAAK,gBAAgB,CAC7C,MAAO,CACH,OACA,KACA,KAAM,QACT,CACD,QAAS,CACL,SACA,QACH,CACD,QACA,YAAa,EAChB,CAAC,CAEF,GAAI,CAAC,EAAU,MAAU,MAAM,yBAAyB,CAExD,OAAO,GAYE,GAAkB,MAAO,CAClC,UACA,OACA,QAAQ,MACR,OAAO,EACP,KACA,oBAC4C,CAC5C,IAAMC,EAAyB,EAAE,CAC7B,EAAS,EAGb,OAAa,CACT,IAAM,EAAS,MAAM,GAAa,CAC9B,UACA,OACA,iBACA,OACA,GAAI,WACJ,MAAO,EACP,QACA,SACH,CAAC,CAEF,GADA,EAAU,KAAK,GAAG,EAAO,CACrB,EAAO,OAAS,EAChB,OAAO,EAEX,GAAU,IC3EZ,GAAiBC,EAAAA,gBAAgB,iBAAiB,CAE3C,IAAqB,EAAyB,EAAgB,EAAsB,IAAwC,CACrI,GAAI,CAAC,GAAmB,CAAC,GAAU,CAACC,EAAAA,EAAe,EAAgB,CAC/D,MAAU,MAAM,qCAAqC,CAEzD,IAAMC,EAAsB,EAAE,CAY9B,OAVA,EAAa,KAAK,CACd,GAAI,EACJ,MAAO,MACP,KAAM,GAAe,mBAAmB,WAAY,CAChD,GAAA,EAAA,EAAA,YACW,EAAO,CACrB,CAAC,CACF,QAAS,YAAY,EAAO,GAAG,EAAU,MAAM,IAC/C,IAAK,GAAe,YAAY,WAAW,CAC9C,CAAC,CACK,GAGE,IAAoB,CAC7B,cACA,kBACA,SACA,eACA,YACA,YACA,aACsD,CACtD,GAAM,CAAE,WAAY,IAAoB,CAGlC,GAAA,EAAA,EAAA,aAAwB,GAAkB,EAAiB,EAAQ,EAAc,EAAU,CAAE,CAAC,EAAiB,EAAQ,EAAc,EAAU,CAAC,CAEhJ,EAAS,EAAmB,CAC9B,qBAAsB,EACtB,eAAgB,CACZ,MAAO,mBACP,YAAa,YAAY,EAAO,GAAG,EAAU,MAAMC,EAAAA,EAC/C,EACH,GACD,WAAY,mBACf,CACD,cAAe,SAAY,CACvB,GAAS,CACT,KAAa,EAEjB,sBAAuB,KAAO,IAAU,CACpC,IAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,EAExE,CAAC,CAEF,MAAO,CACH,GAAG,EACH,UACA,gBAAiB,SACN,EAAO,gBAAgB,EAAQ,CAE7C,EC/DQ,IAAmB,EAAyB,IAAqC,CAC1F,GAAI,CAAC,GAAmB,CAAC,GAAU,CAACC,EAAAA,EAAe,EAAgB,CAC/D,MAAU,MAAM,qCAAqC,CAGzD,GAAI,MAAM,OAAO,EAAO,CAAC,CACrB,MAAU,MAAM,iBAAiB,CAGrC,IAAMC,EAAiC,EAAE,CAEzC,GAAI,CACA,EAAa,KAAK,CACd,GAAI,EACJ,OAAA,EAAA,EAAA,YAAkB,EAAO,CAAC,UAAU,CACpC,KAAM,KACN,QAAS,YAAY,EAAO,UAAU,IACzC,CAAC,OACG,EAAO,CAEZ,MADA,QAAQ,MAAM,0BAA2B,EAAM,CACrC,MAAM,wBAAwB,CAG5C,OAAO,GAGE,IAAkB,CAC3B,cACA,kBACA,SACA,YACA,aACkD,CAClD,GAAM,CAAE,WAAY,IAAoB,CAGlC,GAAA,EAAA,EAAA,aAAwB,GAAgB,EAAiB,EAAO,CAAE,CAAC,EAAiB,EAAO,CAAC,CAE5F,EAAS,EAAmB,CAC9B,qBAAsB,EACtB,eAAgB,CACZ,MAAO,mBACP,YAAa,YAAY,EAAO,UAAUC,EAAAA,EACtC,EACH,GACD,WAAY,mBACf,CACD,cAAe,SAAY,CACvB,GAAS,CACT,KAAa,EAEjB,sBAAuB,KAAO,IAAU,CACpC,IAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,EAExE,CAAC,CAEF,MAAO,CACH,GAAG,EACH,UACA,gBAAiB,SACN,EAAO,gBAAgB,EAAQ,CAE7C,ECrDQ,IAAsC,CAC/C,gBACA,mBACA,kBAAkB,GAClB,YACA,YACA,kBACA,aACA,mBACwC,CACxC,GAAM,CAAE,WAAYC,EAAAA,GAAW,CACzB,GAAA,EAAA,EAAA,iBAA8B,CAM9B,GAAA,EAAA,EAAA,aAA8B,SAAY,CACxC,GACA,GAAkB,QAAQ,KAAO,IAAa,CAC1C,MAAM,EAAY,cAAc,CAC5B,WACH,CAAC,CACF,MAAM,EAAY,eAAe,CAC7B,WACH,CAAC,EACJ,CAGN,KAAa,EACd,CAAC,EAAiB,EAAW,EAAa,EAAiB,CAAC,CAEzD,EAAS,EAAmB,CAC9B,qBAAsB,GAAS,QAC/B,cAAe,EACf,kBACA,sBAAuB,EACvB,aACA,gBACH,CAAC,CAMI,GAAA,EAAA,EAAA,aACF,KAAO,IAAyB,CAC5B,EAAO,gBAAgB,EAAc,EAAM,CAAE,EAAc,EAE/D,CAAC,EAAe,EAAQ,EAAc,CACzC,CAED,MAAO,CAAE,GAAG,EAAQ,kBAAiB,ECpE5B,IACT,EACA,IAIC,CACD,IAAM,GAAA,EAAA,EAAA,gBAAiC,CACnC,IAAA,EACA,KAAM,EAAM,KAAK,UAAU,CAC3B,OAAQ,EAAM,OAAO,IAAK,GAAU,EAAM,UAAU,CAAC,CACxD,CAAC,CAEF,MAAO,CACH,KAAM,EAAM,KACZ,cACH,EA2BQ,IAAgB,CACzB,YACA,kBAEO,CAAC,EAAW,EAAe,KAAK,UAAU,EAAa,CAAG,MAAM,CAM9D,IAA+D,CACxE,IAAA,EACA,kBACA,YACA,eACA,cACA,aAC4B,CAE5B,IAAM,EAAOC,EAAAA,GAAiB,CA2D9B,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAA,EAAA,EAAA,aA1DwB,SAAY,CACpC,GAAI,CAAC,EAAM,MAAO,EAAE,CAEpB,IAAM,EAAW,EAAK,UACjB,KAAK,EAAiBC,EAAI,CAC1B,YAAY,EAAU,CACrB,EAAS,EAAS,yBAAyB,GAAgB,EAAE,CAAC,CAiB9D,GACF,MAAM,GAAgB,CAAE,OAAM,UAAS,eAfF,CACrC,CACI,SAAU,CACN,QAAS,EACT,OAAQ,EAAO,IAAM,IAAA,GACrB,OAAQ,EAAO,IAAM,IAAA,GACrB,OAAQ,EAAO,IAAM,IAAA,GACrB,OAAQ,EAAO,IAAM,IAAA,GACrB,OAAQ,EAAO,IAAM,IAAA,GACxB,CACD,WACH,CACJ,CAG0D,CAAC,EAC1D,IAAK,GAAU,GAAe,EAAOA,EAAI,CAAC,CAE5C,GACI,EAAO,MACF,CAAE,iBAAkB,EAAY,YAAc,EAClD,CAED,MAAU,MAAM,gBAAgB,CAEpC,OAAO,EAAO,IAAK,GACf,EAAY,CACR,KAAM,EAAM,KACZ,YAAa,EAAM,YAGtB,CAAC,CACL,EACF,CACC,EACA,EACAA,EACA,EACA,EACA,EACA,EACH,CAAC,CASE,UAAA,EAAA,EAAA,aANM,GAAa,CAAE,YAAW,eAAc,CAAC,CAC/C,CAAC,EAAW,EAAa,CAC5B,CAKG,QAAS,CAAC,CAAC,EACd,CAAC,ECtHO,IAAoC,CAC7C,UACA,UAAU,GACV,SACA,gBACA,wBAC0C,CAC1C,GAAM,CAAE,kBAAiB,WAAYC,EAAAA,GAAW,CAC1C,CAAE,KAAM,GAAiBC,EAAAA,EAC3B,GAAiB,SAAW,GAC/B,CACK,CAAE,iBAAkBC,EAAAA,GAAqB,CACzC,CAAE,YAAa,EAAiB,GAAS,SAAW,GAAG,CACvD,CAAE,qBAAsBC,EAAAA,GAAsB,CAIpD,OAAA,EAAA,EAAA,UAAmE,CAC/D,SAHa,CAAC,iBAAkB,KAAK,UAAU,EAAQ,CAAE,KAAK,UAAU,EAAO,CAAE,EAAe,EAAmB,CAInH,QAAS,SAAY,CACjB,IAAIC,EAA0B,KAE9B,IAAK,IAAM,KAAS,EAChB,GAAI,CACA,IAAM,EAAa,MAAMC,EAAAA,EACrB,GAAc,SAAW,GACzB,GAAe,qBAAuB,GACtC,EACA,EACA,SACH,CAEK,EAAU,EAAW,gBACrB,EAAe,OAAO,EAAS,KAAK,GAAK,EAAE,SAAW,EAAM,EAAE,SAAW,EAAE,CAM3E,EAAkB,GAHE,GAAiB,GAAsB,IAAU,EACrE,OAAO,EAAc,CACrB,GAGN,GAAI,GAAgB,EAGhB,OADA,EAAkB,CAAE,cAAe,EAAuB,CAAC,CACpD,CAAE,GAAG,EAAY,UAAW,EAAO,CAG9C,EAAgB,MAAM,gBAAgB,EAAM,gBAAgB,EAAa,UAAU,IAAkB,OAChG,EAAO,CACZ,EAAY,EAGpB,MAAM,GAAiB,MAAM,gEAAgE,EAEjG,QAAS,GAAW,EAAQ,OAAS,GAAK,CAAC,CAAC,GAAc,SAAW,CAAC,CAAC,GAAe,qBAAuB,EAAO,OAAS,GAAK,EAAS,OAAS,EACpJ,UAAW,GAAK,IAChB,OAAQ,IAAS,IACjB,qBAAsB,GACtB,mBAAoB,GACpB,eAAgB,GAChB,MAAO,GACP,WAAY,IACf,CAAC,ECnEO,IAAwB,CACjC,UACA,SACA,UAAU,MACoB,CAC9B,GAAM,CAAE,mBAAoBC,EAAAA,GAAW,CACjC,CAAE,KAAM,GAAiBC,EAAAA,EAC3B,GAAiB,SAAW,GAC/B,CACK,CAAE,iBAAkBC,EAAAA,GAAqB,CAE/C,OAAA,EAAA,EAAA,UAAgB,CACZ,SAAU,CACN,4BACA,KAAK,UAAU,EAAQ,CACvB,KAAK,UAAU,EAAO,CACzB,CACD,QAAS,SAAY,CACjB,IAAMC,EAGF,EAAE,CA6BN,OA3BA,MAAM,QAAQ,IACV,EAAO,IAAI,KAAO,IAAU,CACxB,GAAI,CAQA,EAAU,GAAS,CACf,MARe,MAAMC,EAAAA,EACrB,GAAc,SAAW,GACzB,GAAe,qBAAuB,GACtC,EACA,EACA,SACH,EAEoB,iBAAmB,EACpC,QAAS,GACZ,OACI,EAAO,CACZ,EAAU,GAAS,CACf,KAAM,EACN,QAAS,GACT,MACI,aAAiB,MACX,EAAM,QACN,gBACb,GAEP,CACL,CAEM,GAEX,QACI,GACA,EAAQ,OAAS,GACjB,CAAC,CAAC,GAAc,SAChB,CAAC,CAAC,GAAe,qBACjB,EAAO,OAAS,EACpB,UAAW,GAAK,IAChB,OAAQ,IAAS,IACjB,qBAAsB,GACtB,mBAAoB,GACpB,eAAgB,GACnB,CAAC"}
|