@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
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["en","de","it","fr","es","zh","ja","bcp47LanguageCodes: Record<string, string>","defaultLightTokens: ThemeTokens","defaultDarkTokens: ThemeTokens","merged: ThemeTokens","tokens: Partial<ThemeTokens>","vars: CustomizedStyle","cssRules: string[]","internalQueryClient: QueryClient | null","copyToClipboard","safeCopyToClipboard","packageJson.version","current: HTMLElement | null","observerOptions: IntersectionObserverInit","observerOptions: IntersectionObserverInit","modalContentProps: ModalContentProps","address: string | null","domain: string | null","useThor","ReverseRegistrarInterface","clausesArray: any[]","ReverseRegistrarInterface","clausesArray: any[]","useThor","nameInterface","nameInterface","namehash","CROSSAPP_AVATAR_MAP: Record<string, string>","CACHE_KEY","clausesArray: any[]","baseTokens: WalletTokenBalance[]","customTokens: WalletTokenBalance[]","useThor","defaultOptions: Intl.NumberFormatOptions","i18n","allCurrencies: CURRENCY[]","abi","method","getTokenInfoFromContract","token: CustomTokenInfo","abi","method","abi","method","useThor","useSignTypedData","useSignMessage","walletToSave: StoredWallet","useLoginWithOAuth","usePrivy","connectionSource: ConnectionSource","account","abi","useThor","imageCompressionOptions: CompressOptions","compressedImages: File[]","parsedUploads: UploadedImage[]","compressImages","image: UploadedImage","image: UploadedImage","useThor","useDAppKitWallet","clauses","privyUIOptions","delegationUrl","error","txReceipt","flowsByToken: Record<string, { inflow: bigint; outflow: bigint }>","decodeEventLog","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","clauses: TransactionClause[]","VeChainAddress","isVET","aggregator: SwapAggregator","path: Address[]","UniswapV2Router__factory","clauses: TransactionClause[]","VeChainAddress","BETTERSWAP_ADDRESSES: Record<NETWORK_TYPE, { routerAddress: Address; wrappedVET: Address }>","useThor","params: SwapParams | null","amountInRaw: bigint","error","best: SwapQuote | null","error","useDappKitWallet","method","method","t","formatEther","allEvents: Event[]","allTransfers: Transfer[]","fromAmount: bigint | null","toAmount: bigint | null","decodeEventLog","t","buildClauses","swapDescription: string | undefined","i18n","QUICK_ACTIONS: QuickAction[]","changes: {\n avatarIpfsHash?: string;\n displayName?: string;\n description?: string;\n }","domain","allCurrencies","i18n","document","document","document","agreements","indices: number[]","useWalletDappKit","packageJson.version","usePrivy","method","FaDiscord","newNotification: Notification","DEFAULT_APPS: XAppMetadata[]","theme","SuccessfulOperationContent","SuccessfulOperationContent","method","isMobile","theme","UpgradeSmartAccountContent","UpgradeSmartAccountContent","parts","definePartsStyle","defineMultiStyleConfig","definePartsStyle","defineMultiStyleConfig","parts","baseTheme","theme","theme","theme","method","baseConfig: LoginModalContentConfig","useDappKitWallet","sig: string | null","error","sig: string","error","usePrivyLoginWithPasskey","usePrivyLoginWithOAuth","CACHE_KEY","cacheData: CrossAppConnectionCache","method","useThor","CACHE_KEY","formatEther","useThor","version","implementationAddressPromise:\n | ReturnType<typeof contract.read.accountImplementationV1>\n | ReturnType<typeof contract.read.accountImplementationV3>","useThor","useThor","useThor","abi","useThor","ThorClient","useThor","useThor","useThor","buildClauses","useThor","useThor","allEvents: EventLogs[]","clausesArray: any[]","parseEther","clausesArray: EnhancedClause[]","parseEther","useThor","viemDecodeEventLog","useThor","abi","toArray: string[]","valueArray: string[]","dataArray: string[]","usePrivy","version","dataToSign: ExecuteWithAuthorizationSignData[]","signatures: string[]","signature","randomTransactionUser","ERC20Interface","ThorClient","gasEstimationResponse: EstimationResponse","depositAccount: DepositAccount","parseEther","gasPayerResponse: {\n signature: string;\n address: string;\n raw: string;\n origin: string;\n }","lastError: Error | null","estimates: Record<\n GasTokenType,\n { cost: number; loading: boolean; error?: string }\n >","GasFeeSummary: React.FC<GasFeeSummaryProps>","initialStates: Record<\n string,\n { cost: number; loading: boolean }\n >","t","displayToken: GasTokenType | undefined","document","document","document","document","documents","theme","usePrivy","ThorClient","errors: string[]","method","privyAppId: string","privyClientId: string","i18n"],"sources":["../src/languages/en.json","../src/languages/de.json","../src/languages/it.json","../src/languages/fr.json","../src/languages/es.json","../src/languages/zh.json","../src/languages/ja.json","../i18n.ts","../src/utils/i18n.ts","../src/theme/tokens.ts","../src/utils/cssVariables.ts","../src/providers/EnsureQueryClient.tsx","../src/components/common/ModalBackButton.tsx","../src/components/common/AddressDisplay.tsx","../package.json","../src/components/common/VersionFooter.tsx","../src/components/common/StickyHeaderContainer.tsx","../src/components/common/StickyFooterContainer.tsx","../src/components/common/BaseBottomSheet.tsx","../src/components/common/BaseModal.tsx","../src/hooks/api/privy/useFetchAppInfo.ts","../src/hooks/api/privy/useFetchPrivyStatus.ts","../src/hooks/api/vetDomains/useVechainDomain.ts","../src/hooks/api/vetDomains/useEnsRecordExists.ts","../src/hooks/api/wallet/useRefreshMetadata.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/useGetDomainsOfAddress.ts","../src/hooks/api/vetDomains/useGetAvatar.ts","../src/hooks/api/vetDomains/useGetTextRecords.ts","../src/hooks/api/vetDomains/useUpdateTextRecord.ts","../src/hooks/api/vetDomains/useGetResolverAddress.ts","../src/hooks/api/vetDomains/useGetAvatarOfAddress.ts","../src/hooks/api/vetDomains/useGetAvatarLegacy.ts","../src/hooks/api/vetDomains/useUnsetDomain.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/useGetCustomTokenInfo.ts","../src/hooks/api/wallet/useCustomTokens.ts","../src/hooks/api/wallet/useGetB3trBalance.ts","../src/hooks/api/wallet/useGetCustomTokenBalances.ts","../src/hooks/api/wallet/useGetErc20Balance.ts","../src/hooks/api/wallet/useGetVot3Balance.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/utils/handlePopupError.ts","../src/providers/PrivyCrossAppProvider.tsx","../src/hooks/api/wallet/useWalletMetadata.ts","../src/hooks/api/wallet/useWalletStorage.ts","../src/hooks/api/wallet/useWallet.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/thor/transactions/useGasEstimate.ts","../src/hooks/thor/transactions/useSendTransaction.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/components/EmailCodeVerificationModal/EmailCodeVerificationModal.tsx","../src/components/ConnectModal/Components/EmailLoginButton.tsx","../src/components/ConnectModal/Components/LoginWithGoogleButton.tsx","../src/components/ConnectModal/Components/LoginWithGithubButton.tsx","../src/components/ConnectModal/Components/VeChainWithPrivyLoginButton.tsx","../src/components/ConnectModal/Components/VeChainLoginButton.tsx","../src/components/ConnectModal/Components/PasskeyLoginButton.tsx","../src/components/ConnectModal/Components/DappKitButton.tsx","../src/components/ConnectModal/Components/PrivyButton.tsx","../src/components/ConnectModal/Components/ConnectionOptionsStack.tsx","../src/components/ConnectModal/Components/EcosystemButton.tsx","../src/components/ConnectModal/Contents/MainContent.tsx","../src/components/AccountModal/Contents/Account/AccountMainContent.tsx","../src/components/AccountModal/Contents/SendToken/SelectTokenContent.tsx","../src/hooks/modals/useAccountModalOptions.tsx","../src/components/AccountModal/Contents/SendToken/SendTokenContent.tsx","../src/components/AccountModal/Contents/SendToken/SendTokenSummaryContent.tsx","../src/components/AccountModal/Contents/Receive/ReceiveTokenContent.tsx","../src/components/AccountModal/Contents/Swap/SelectQuoteContent.tsx","../src/utils/swap/extractSwapAmounts.ts","../src/components/AccountModal/Contents/Swap/SwapTokenContent.tsx","../src/components/AccountModal/Contents/ChooseName/ChooseNameContent.tsx","../src/components/AccountModal/Contents/ChooseName/Components/ExistingDomainsList.tsx","../src/components/AccountModal/Contents/ChooseName/ChooseNameSearchContent.tsx","../src/components/AccountModal/Contents/ChooseName/ChooseNameSummaryContent.tsx","../src/components/AccountModal/Contents/FAQ/FAQAccordion.tsx","../src/components/AccountModal/Contents/FAQ/FAQContent.tsx","../src/components/AccountModal/Components/AccountDetailsButton.tsx","../src/components/AccountModal/Components/ActionButton.tsx","../src/components/AccountModal/Components/AccountSelector.tsx","../src/components/WalletButton/AssetIcons.tsx","../src/components/AccountModal/Components/BalanceSection.tsx","../src/components/AccountModal/Components/QuickActionsSection.tsx","../src/components/AccountModal/Components/Alerts/FeatureAnnouncementCard.tsx","../src/components/AccountModal/Components/Alerts/ExchangeWarningAlert.tsx","../src/components/AccountModal/Components/Alerts/DomainRequiredAlert.tsx","../src/components/AccountModal/Components/CrossAppConnectionSecurityCard.tsx","../src/components/AccountModal/Contents/Profile/Customization/CustomizationContent.tsx","../src/components/AccountModal/Contents/Profile/Customization/CustomizationSummaryContent.tsx","../src/components/AccountModal/Contents/Profile/Components/ProfileCard/ProfileCard.tsx","../src/components/common/ModalSettingsButton.tsx","../src/components/AccountModal/Contents/Profile/ProfileContent.tsx","../src/components/AccountModal/Contents/UpgradeSmartAccount/UpgradeSmartAccountContent.tsx","../src/components/AccountModal/Contents/Assets/AssetsContent.tsx","../src/components/AccountModal/Contents/Assets/ManageCustomTokenContent.tsx","../src/components/AccountModal/Contents/Bridge/BridgeContent.tsx","../src/components/AccountModal/Contents/KitSettings/ChangeCurrencyContent.tsx","../src/components/AccountModal/Contents/KitSettings/LanguageSettingsContent.tsx","../src/components/AccountModal/Contents/KitSettings/GasTokenDragList.tsx","../src/components/AccountModal/Contents/KitSettings/GasTokenSettingsContent.tsx","../src/components/AccountModal/Contents/KitSettings/SettingsContent.tsx","../src/components/common/EmptyContent.tsx","../src/utils/dateUtils.ts","../src/components/AccountModal/Contents/TermsAndPrivacy/AcceptedPolicyItem.tsx","../src/components/AccountModal/Contents/TermsAndPrivacy/PolicyAccordion.tsx","../src/components/AccountModal/Contents/TermsAndPrivacy/TermsAndPrivacyAccordion.tsx","../src/components/AccountModal/Contents/TermsAndPrivacy/TermsAndPrivacyContent.tsx","../src/components/AccountModal/Contents/DisconnectConfirmation/DisconnectConfirmContent.tsx","../src/components/AccountModal/Contents/SelectWallet/Components/WalletCard.tsx","../src/components/AccountModal/Contents/SelectWallet/SelectWalletContent.tsx","../src/components/AccountModal/Contents/SelectWallet/RemoveWalletConfirmContent.tsx","../src/components/AccountModal/Contents/ConnectionDetails/Components/ConnectionCard.tsx","../src/components/AccountModal/Contents/ConnectionDetails/Components/WalletSecuredBy.tsx","../src/components/AccountModal/Contents/ConnectionDetails/ConnectionDetailsContent.tsx","../src/components/AccountModal/Contents/PrivyLinkedAccounts/PrivyLinkedAccounts.tsx","../src/hooks/notifications/useNotificationAlerts.ts","../src/hooks/notifications/useNotifications.ts","../src/components/AccountModal/Contents/Notifications/Components/EmptyNotifications.tsx","../src/components/AccountModal/Contents/Notifications/Components/NotificationItem.tsx","../src/components/AccountModal/Contents/Notifications/NotificationContent.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/CategoryLabel.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/SharedAppCard.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/AppComponent.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/CustomAppComponent.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/ShortcutsSection.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/CategoryFilterSection.tsx","../src/components/AccountModal/Contents/Ecosystem/ExploreEcosystemContent.tsx","../src/components/AccountModal/Contents/Ecosystem/Components/ShortcutButton.tsx","../src/components/AccountModal/Contents/Ecosystem/AppOverviewContent.tsx","../src/components/TransactionModal/Components/ShareButtons.tsx","../src/components/TransactionModal/TransactionModalContent.tsx","../src/components/TransactionModal/TransactionModal.tsx","../src/components/AccountModal/Contents/SuccessfulOperation/SuccessfulOperationContent.tsx","../src/components/AccountModal/Contents/FailedOperation/FailedOperationContent.tsx","../src/components/AccountModal/AccountModal.tsx","../src/components/ConnectModal/Contents/LoadingContent.tsx","../src/components/ConnectModal/Contents/ErrorContent.tsx","../src/components/ConnectModal/Contents/EcosystemContent.tsx","../src/components/ConnectModal/ConnectModal.tsx","../src/components/ConnectModal/Components/ConnectionButton.tsx","../src/components/ConnectModal/ConnectPopover.tsx","../src/components/WalletButton/WalletDisplay.tsx","../src/components/WalletButton/ConnectedWallet.tsx","../src/components/WalletButton/WalletButton.tsx","../src/components/WalletButton/SocialIcons.tsx","../src/components/TransactionToast/TransactionToastContent.tsx","../src/components/TransactionToast/TransactionToast.tsx","../src/components/UpgradeSmartAccountModal/Contents/SuccessfulOperationContent.tsx","../src/components/UpgradeSmartAccountModal/Contents/UpgradeSmartAccountContent.tsx","../src/components/UpgradeSmartAccountModal/UpgradeSmartAccountModal.tsx","../src/theme/modal.ts","../src/theme/card.ts","../src/theme/button.ts","../src/theme/popover.ts","../src/theme/theme.tsx","../src/providers/VechainKitThemeProvider.tsx","../src/providers/ModalProvider.tsx","../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/useSettingsModal.tsx","../src/hooks/signing/useSignMessage.ts","../src/hooks/signing/useSignTypedData.ts","../src/hooks/login/useLoginWithPasskey.ts","../src/hooks/login/useLoginWithOAuth.ts","../src/hooks/cache/useCrossAppConnectionCache.ts","../src/hooks/login/useLoginWithVeChain.ts","../src/hooks/utils/useAppHubApps.ts","../src/hooks/utils/useCallClause.ts","../src/hooks/utils/useCurrentLanguage.ts","../src/hooks/utils/useCurrentCurrency.ts","../src/hooks/utils/useFeatureAnnouncement.ts","../src/hooks/utils/useGetNodeUrl.ts","../src/hooks/utils/useIsPwa.ts","../src/hooks/utils/useScrollToTop.ts","../src/hooks/thor/accounts/useAccountBalance.ts","../src/hooks/thor/smartAccounts/useAccountImplementationAddress.ts","../src/hooks/thor/smartAccounts/useCurrentAccountImplementationVersion.ts","../src/hooks/thor/smartAccounts/useGetAccountAddress.ts","../src/hooks/thor/smartAccounts/useGetAccountVersion.ts","../src/hooks/thor/smartAccounts/useHasV1SmartAccount.ts","../src/hooks/thor/smartAccounts/useIsSmartAccountDeployed.ts","../src/hooks/thor/smartAccounts/useRefreshFactoryQueries.ts","../src/hooks/thor/smartAccounts/useRefreshSmartAccountQueries.ts","../src/hooks/thor/smartAccounts/useSmartAccount.ts","../src/hooks/thor/smartAccounts/useUpgradeRequired.ts","../src/hooks/thor/smartAccounts/useUpgradeRequiredForAccount.ts","../src/hooks/thor/smartAccounts/useUpgradeSmartAccount.ts","../src/hooks/thor/blocks/useCurrentBlock.ts","../src/hooks/thor/blocks/useGetChainId.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/thor/transactions/useTxReceipt.ts","../src/hooks/utils/useEvents.ts","../src/hooks/utils/useBuildClauses.ts","../src/hooks/cache/useLocalStorage.ts","../src/hooks/cache/useSyncableLocalStorage.ts","../src/hooks/cache/useEcosystemShortcuts.ts","../src/hooks/generic-delegator/useGenericDelegator.ts","../src/hooks/generic-delegator/useGasTokenSelection.ts","../src/hooks/generic-delegator/useGenericDelegatorFeeEstimation.ts","../src/hooks/generic-delegator/useEstimateAllTokens.ts","../src/components/common/AssetButton.tsx","../src/components/common/AddressDisplayCard.tsx","../src/components/common/ModalFAQButton.tsx","../src/components/common/ScrollToTopWrapper.tsx","../src/components/common/AccountAvatar.tsx","../src/components/common/TransactionButtonAndStatus.tsx","../src/components/common/ModalNotificationButton.tsx","../src/components/common/GasFeeTokenSelector.tsx","../src/components/common/GasFeeSummary.tsx","../src/components/common/InlineFeedback.tsx","../src/components/common/WalletSwitchFeedback.tsx","../src/components/StepModal/StepModal.tsx","../src/components/LegalDocumentsModal/Components/LegalDocumentItem.tsx","../src/components/LegalDocumentsModal/LegalDocumentsContent.tsx","../src/components/LegalDocumentsModal/LegalDocumentsModal.tsx","../src/utils/legalDocumentsUtils.ts","../src/providers/LegalDocumentsProvider.tsx","../src/providers/PrivyWalletProvider.tsx","../src/providers/VeChainKitProvider.tsx"],"sourcesContent":["{\n \" and \": \" and \",\n \"'{{policyName}}' on connect\": \"'{{policyName}}' on connect\",\n \"'{{policyName}}' on {{date}}\": \"'{{policyName}}' on {{date}}\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \"A .vet domain is required to customize your profile. Choose an account name to get started.\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\",\n \"A new version is available for your account\": \"A new version is available for your account\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\",\n \"AVAILABLE\": \"AVAILABLE\",\n \"Accept\": \"Accept\",\n \"Accept all\": \"Accept all\",\n \"Accept selected\": \"Accept selected\",\n \"Access and security\": \"Access and security\",\n \"Account Upgrade Required\": \"Account Upgrade Required\",\n \"Account already upgraded\": \"Account already upgraded\",\n \"Account upgrade required\": \"Account upgrade required\",\n \"Active\": \"Active\",\n \"Active Wallet\": \"Active Wallet\",\n \"Add Login Method\": \"Add Login Method\",\n \"Add New Wallet\": \"Add New Wallet\",\n \"Add Token\": \"Add Token\",\n \"Add to shortcuts\": \"Add to shortcuts\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\",\n \"Address is required\": \"Address is required\",\n \"All\": \"All\",\n \"All apps\": \"All apps\",\n \"All policies you have accepted\": \"All policies you have accepted\",\n \"All tokens\": \"All tokens\",\n \"Already have an x2earn app wallet?\": \"Already have an x2earn app wallet?\",\n \"Amount\": \"Amount\",\n \"Amount is required\": \"Amount is required\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\",\n \"An unexpected error occurred.\": \"An unexpected error occurred.\",\n \"Apple\": \"Apple\",\n \"Apply\": \"Apply\",\n \"Archived\": \"Archived\",\n \"Archived Notifications\": \"Archived Notifications\",\n \"Are you sure you want to disconnect your wallet?\": \"Are you sure you want to disconnect your wallet?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"Are you sure you want to reject the policies and disconnect?\",\n \"Are you sure you want to remove this wallet?\": \"Are you sure you want to remove this wallet?\",\n \"Are you sure you want to set your domain name to\": \"Are you sure you want to set your domain name to\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\",\n \"Are you sure you want to unset your current domain?\": \"Are you sure you want to unset your current domain?\",\n \"Assets\": \"Assets\",\n \"At\": \"At\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\",\n \"Backup\": \"Backup\",\n \"Backup your wallet\": \"Backup your wallet\",\n \"Backup your wallet, configure MFA and set recovery options\": \"Backup your wallet, configure MFA and set recovery options\",\n \"Balance\": \"Balance\",\n \"Benefits of this upgrade:\": \"Benefits of this upgrade:\",\n \"Best\": \"Best\",\n \"Better transaction handling\": \"Better transaction handling\",\n \"Bridge\": \"Bridge\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"By confirming, the following details attached to your name ({{domain}}) will be updated\",\n \"By confirming, your address will be set to {{domain}}\": \"By confirming, your address will be set to {{domain}}\",\n \"By confirming, your current domain will be unset\": \"By confirming, your current domain will be unset\",\n \"By continuing, you agree to\": \"By continuing, you agree to\",\n \"Cancel\": \"Cancel\",\n \"Checking...\": \"Checking...\",\n \"Choose Name\": \"Choose Name\",\n \"Choose a name for your account.\": \"Choose a name for your account.\",\n \"Choose a unique .vet domain name for your account.\": \"Choose a unique .vet domain name for your account.\",\n \"Choose account name\": \"Choose account name\",\n \"Choose name\": \"Choose name\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"Choose which tokens to use for transaction fees when the app is not covering them.\",\n \"Choose your account name\": \"Choose your account name\",\n \"Claim your vet domain!\": \"Claim your vet domain!\",\n \"Claiming name...\": \"Claiming name...\",\n \"Clear all\": \"Clear all\",\n \"Cleared notifications will appear here\": \"Cleared notifications will appear here\",\n \"Click\": \"Click\",\n \"Click below to access {{ name }} and explore its features.\": \"Click below to access {{ name }} and explore its features.\",\n \"Close\": \"Close\",\n \"Close and do this later\": \"Close and do this later\",\n \"Close announcement\": \"Close announcement\",\n \"Coming Soon!\": \"Coming Soon!\",\n \"Coming soon\": \"Coming soon\",\n \"Confirm\": \"Confirm\",\n \"Confirm Changes\": \"Confirm Changes\",\n \"Confirm Name\": \"Confirm Name\",\n \"Confirm Unset Domain\": \"Confirm Unset Domain\",\n \"Confirm the transaction in your wallet to complete it.\": \"Confirm the transaction in your wallet to complete it.\",\n \"Confirm transaction\": \"Confirm transaction\",\n \"Connect an external wallet for easier access\": \"Connect an external wallet for easier access\",\n \"Connect wallet\": \"Connect wallet\",\n \"Connect with VeWorld wallet\": \"Connect with VeWorld wallet\",\n \"Connect your Apple account for easier access\": \"Connect your Apple account for easier access\",\n \"Connect your Discord account for easier access\": \"Connect your Discord account for easier access\",\n \"Connect your Farcaster account for easier access\": \"Connect your Farcaster account for easier access\",\n \"Connect your Github account for easier access\": \"Connect your Github account for easier access\",\n \"Connect your Google account for easier access\": \"Connect your Google account for easier access\",\n \"Connect your Instagram account for easier access\": \"Connect your Instagram account for easier access\",\n \"Connect your LinkedIn account for easier access\": \"Connect your LinkedIn account for easier access\",\n \"Connect your Spotify account for easier access\": \"Connect your Spotify account for easier access\",\n \"Connect your Telegram account for easier access\": \"Connect your Telegram account for easier access\",\n \"Connect your Tiktok account for easier access\": \"Connect your Tiktok account for easier access\",\n \"Connect your Twitter account for easier access\": \"Connect your Twitter account for easier access\",\n \"Connect your email for easier access\": \"Connect your email for easier access\",\n \"Connect your phone number for easier access\": \"Connect your phone number for easier access\",\n \"Connecting to VeChain\": \"Connecting to VeChain\",\n \"Connecting with\": \"Connecting with\",\n \"Connecting with Passkey\": \"Connecting with Passkey\",\n \"Connecting...\": \"Connecting...\",\n \"Connection Details\": \"Connection Details\",\n \"Connection Failed\": \"Connection Failed\",\n \"Connection Type\": \"Connection Type\",\n \"Connection details\": \"Connection details\",\n \"Continue\": \"Continue\",\n \"Continue with Github\": \"Continue with Github\",\n \"Continue with Google\": \"Continue with Google\",\n \"Cookie Policy\": \"Cookie Policy\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"Cookie policy outlining the use of cookies and tracking technologies.\",\n \"Copied!\": \"Copied!\",\n \"Copy your address or scan this QR code\": \"Copy your address or scan this QR code\",\n \"Currency\": \"Currency\",\n \"Current\": \"Current\",\n \"Current domain\": \"Current domain\",\n \"Customization\": \"Customization\",\n \"Customize\": \"Customize\",\n \"Customize profile\": \"Customize profile\",\n \"Customize the appearance of your wallet.\": \"Customize the appearance of your wallet.\",\n \"Description\": \"Description\",\n \"Description must be less than 100 characters\": \"Description must be less than 100 characters\",\n \"Didn't get an email?\": \"Didn't get an email?\",\n \"Discord\": \"Discord\",\n \"Display Name\": \"Display Name\",\n \"Display name must be less than 25 characters\": \"Display name must be less than 25 characters\",\n \"Domain set\": \"Domain set\",\n \"Domain unset\": \"Domain unset\",\n \"Done\": \"Done\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\",\n \"Ecosystem\": \"Ecosystem\",\n \"Eg: DevRel @ ENS Labs\": \"Eg: DevRel @ ENS Labs\",\n \"Email\": \"Email\",\n \"Email address\": \"Email address\",\n \"Embedded wallet\": \"Embedded wallet\",\n \"Enhanced compatibility with dApps\": \"Enhanced compatibility with dApps\",\n \"Enter confirmation code\": \"Enter confirmation code\",\n \"Enter your display name\": \"Enter your display name\",\n \"Enter your name\": \"Enter your name\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\",\n \"Existing Custom Tokens\": \"Existing Custom Tokens\",\n \"Explore ecosystem\": \"Explore ecosystem\",\n \"Failed to connect with Passkey\": \"Failed to connect with Passkey\",\n \"Failed to connect with VeChain\": \"Failed to connect with VeChain\",\n \"Failed to connect with ecosystem app\": \"Failed to connect with ecosystem app\",\n \"Failed to load App Hub apps\": \"Failed to load App Hub apps\",\n \"Farcaster\": \"Farcaster\",\n \"Fee\": \"Fee\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\",\n \"Fee token\": \"Fee token\",\n \"Filter by category\": \"Filter by category\",\n \"Finally say goodbye to 0x addresses\": \"Finally say goodbye to 0x addresses\",\n \"For developers\": \"For developers\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\",\n \"Found following rates\": \"Found following rates\",\n \"Frequently asked questions\": \"Frequently asked questions\",\n \"From\": \"From\",\n \"Gas Token Preferences\": \"Gas Token Preferences\",\n \"Gas fee\": \"Gas fee\",\n \"General\": \"General\",\n \"Github\": \"Github\",\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.\": \"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 \"Google\": \"Google\",\n \"Help\": \"Help\",\n \"Hide\": \"Hide\",\n \"How do I backup my wallet?\": \"How do I backup my wallet?\",\n \"How do I send tokens?\": \"How do I send tokens?\",\n \"How is my wallet secured?\": \"How is my wallet secured?\",\n \"I have read and agree to \": \"I have read and agree to \",\n \"Ignore and continue\": \"Ignore and continue\",\n \"Improved security features\": \"Improved security features\",\n \"Instagram\": \"Instagram\",\n \"Insufficient balance\": \"Insufficient balance\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"Insufficient balance to claim this domain and cover gas fees.\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"Insufficient balance to complete this transaction and cover gas fees.\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"Insufficient balance to complete this transfer and cover gas fees.\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"Insufficient balance to update your profile and cover gas fees.\",\n \"Insufficient {{symbol}} balance\": \"Insufficient {{symbol}} balance\",\n \"Invalid address or domain\": \"Invalid address or domain\",\n \"Invalid contract address\": \"Invalid contract address\",\n \"Invalid token address\": \"Invalid token address\",\n \"Language\": \"Language\",\n \"Launch vechain.energy\": \"Launch vechain.energy\",\n \"Launch {{name}}\": \"Launch {{name}}\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\",\n \"Link Apple Account\": \"Link Apple Account\",\n \"Link Discord Account\": \"Link Discord Account\",\n \"Link Email Account\": \"Link Email Account\",\n \"Link External Wallet\": \"Link External Wallet\",\n \"Link Farcaster Account\": \"Link Farcaster Account\",\n \"Link Github Account\": \"Link Github Account\",\n \"Link Google Account\": \"Link Google Account\",\n \"Link Instagram Account\": \"Link Instagram Account\",\n \"Link LinkedIn Account\": \"Link LinkedIn Account\",\n \"Link Phone Number\": \"Link Phone Number\",\n \"Link Spotify Account\": \"Link Spotify Account\",\n \"Link Telegram Account\": \"Link Telegram Account\",\n \"Link Tiktok Account\": \"Link Tiktok Account\",\n \"Link Twitter Account\": \"Link Twitter Account\",\n \"LinkedIn\": \"LinkedIn\",\n \"Loading quote...\": \"Loading quote...\",\n \"Loading your domains...\": \"Loading your domains...\",\n \"Loading...\": \"Loading...\",\n \"Log in or sign up\": \"Log in or sign up\",\n \"Logged in with\": \"Logged in with\",\n \"Login\": \"Login\",\n \"Login failed:\": \"Login failed:\",\n \"Login methods\": \"Login methods\",\n \"Login methods and Passkeys\": \"Login methods and Passkeys\",\n \"Logout\": \"Logout\",\n \"Manage Custom Tokens\": \"Manage Custom Tokens\",\n \"Manage MFA\": \"Manage MFA\",\n \"Manage Recovery\": \"Manage Recovery\",\n \"Manage on {{appName}}\": \"Manage on {{appName}}\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\",\n \"Manage your login methods and passkeys\": \"Manage your login methods and passkeys\",\n \"Manage your preferences for currency, language, and appearance.\": \"Manage your preferences for currency, language, and appearance.\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"Minimum {{symbol}} transfer is {{min}}\",\n \"More\": \"More\",\n \"Multiclause Transactions Are Now Supported\": \"Multiclause Transactions Are Now Supported\",\n \"Name must be at least 3 characters long\": \"Name must be at least 3 characters long\",\n \"Name your account to make it easier to exchange assets\": \"Name your account to make it easier to exchange assets\",\n \"Network\": \"Network\",\n \"New\": \"New\",\n \"New image selected\": \"New image selected\",\n \"No additional accounts available to link\": \"No additional accounts available to link\",\n \"No application from VeChain ecosystem is available to login.\": \"No application from VeChain ecosystem is available to login.\",\n \"No apps found in this category\": \"No apps found in this category\",\n \"No archived notifications\": \"No archived notifications\",\n \"No assets\": \"No assets\",\n \"No notifications\": \"No notifications\",\n \"No policies accepted\": \"No policies accepted\",\n \"No questions found\": \"No questions found\",\n \"No quotes available\": \"No quotes available\",\n \"No tokens found\": \"No tokens found\",\n \"Node URL\": \"Node URL\",\n \"Notifications\": \"Notifications\",\n \"Only letters, numbers, and hyphens are allowed\": \"Only letters, numbers, and hyphens are allowed\",\n \"Optional\": \"Optional\",\n \"Other Wallets\": \"Other Wallets\",\n \"Other options\": \"Other options\",\n \"Passkey\": \"Passkey\",\n \"Phone Number\": \"Phone Number\",\n \"Please approve the request in the connection request window...\": \"Please approve the request in the connection request window...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"Please be sure to keep this wallet safe and backed up.\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"Please check {{email}} for an email from privy.io and enter your code below.\",\n \"Please complete the passkey authentication...\": \"Please complete the passkey authentication...\",\n \"Please confirm the transaction in your wallet.\": \"Please confirm the transaction in your wallet.\",\n \"Please enter a valid Twitter handle without @\": \"Please enter a valid Twitter handle without @\",\n \"Please enter a valid contract address\": \"Please enter a valid contract address\",\n \"Please enter a valid email address\": \"Please enter a valid email address\",\n \"Please enter a valid number\": \"Please enter a valid number\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\",\n \"Policy\": \"Policy\",\n \"Preparing changes...\": \"Preparing changes...\",\n \"Privacy Policy\": \"Privacy Policy\",\n \"Privacy policy outlining the data collection and processing practices.\": \"Privacy policy outlining the data collection and processing practices.\",\n \"Privy Status\": \"Privy Status\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\",\n \"Processing transaction...\": \"Processing transaction...\",\n \"Profile\": \"Profile\",\n \"Profile Image\": \"Profile Image\",\n \"Profile Picture\": \"Profile Picture\",\n \"Profile Updated\": \"Profile Updated\",\n \"Read More\": \"Read More\",\n \"Receive\": \"Receive\",\n \"Receive tokens\": \"Receive tokens\",\n \"Reduced gas costs for operations\": \"Reduced gas costs for operations\",\n \"Reject and logout\": \"Reject and logout\",\n \"Remove\": \"Remove\",\n \"Remove Login Method\": \"Remove Login Method\",\n \"Remove Wallet\": \"Remove Wallet\",\n \"Remove from shortcuts\": \"Remove from shortcuts\",\n \"Remove wallet\": \"Remove wallet\",\n \"Remove your current domain name\": \"Remove your current domain name\",\n \"Resend code\": \"Resend code\",\n \"Retry\": \"Retry\",\n \"Save Changes\": \"Save Changes\",\n \"Saving changes...\": \"Saving changes...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\",\n \"Search Apps\": \"Search Apps\",\n \"Search FAQ\": \"Search FAQ\",\n \"Security preferences\": \"Security preferences\",\n \"Security settings\": \"Security settings\",\n \"Select Additional Login Method\": \"Select Additional Login Method\",\n \"Select Token\": \"Select Token\",\n \"Select Wallet\": \"Select Wallet\",\n \"Select currency\": \"Select currency\",\n \"Select language\": \"Select language\",\n \"Select the token to pay the fee with\": \"Select the token to pay the fee with\",\n \"Select token\": \"Select token\",\n \"Send\": \"Send\",\n \"Send all\": \"Send all\",\n \"Sending Transaction...\": \"Sending Transaction...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"Sending to OceanX or other exchanges may result in loss of funds.\",\n \"Sending...\": \"Sending...\",\n \"Set a domain first\": \"Set a domain first\",\n \"Set up Passkey\": \"Set up Passkey\",\n \"Set up a passkey for easier access\": \"Set up a passkey for easier access\",\n \"Settings\": \"Settings\",\n \"Share on\": \"Share on\",\n \"Shortcuts\": \"Shortcuts\",\n \"Show Advanced Options\": \"Show Advanced Options\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"Show More\",\n \"Slippage tolerance\": \"Slippage tolerance\",\n \"Smart Account\": \"Smart Account\",\n \"Smart Account detected\": \"Smart Account detected\",\n \"Something went wrong\": \"Something went wrong\",\n \"Something went wrong. Please try again.\": \"Something went wrong. Please try again.\",\n \"Source\": \"Source\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"Stay tuned for our upcoming Activity feature\",\n \"Stay tuned for our upcoming NFT feature\": \"Stay tuned for our upcoming NFT feature\",\n \"Submit\": \"Submit\",\n \"Swap\": \"Swap\",\n \"Swap all\": \"Swap all\",\n \"Swapping...\": \"Swapping...\",\n \"Switch\": \"Switch\",\n \"Account Changed\": \"Account Changed\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"Terms and Conditions\",\n \"Terms and Policies\": \"Terms and Policies\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\",\n \"This address only supports VeChain assets.\": \"This address only supports VeChain assets.\",\n \"This domain is already taken\": \"This domain is already taken\",\n \"This domain is protected\": \"This domain is protected\",\n \"This is taking longer than expected.\": \"This is taking longer than expected.\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"This is your main wallet, created by {{element}} and secured by Privy.\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"To\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\",\n \"Token Contract Address\": \"Token Contract Address\",\n \"Token Priority Order\": \"Token Priority Order\",\n \"Token already added\": \"Token already added\",\n \"Tools\": \"Tools\",\n \"Transaction failed\": \"Transaction failed\",\n \"Transaction failed:\": \"Transaction failed:\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"Transaction is being processed, it can take up to 15 seconds.\",\n \"Transaction successful\": \"Transaction successful\",\n \"Transaction successful!\": \"Transaction successful!\",\n \"Try again\": \"Try again\",\n \"Try searching with a different term\": \"Try searching with a different term\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Twitter username\",\n \"Type the receiver address or domain\": \"Type the receiver address or domain\",\n \"UNAVAILABLE\": \"UNAVAILABLE\",\n \"Unable to fetch the price\": \"Unable to fetch the price\",\n \"Unset current domain\": \"Unset current domain\",\n \"Unsetting current domain...\": \"Unsetting current domain...\",\n \"Upgrade Smart Account to V3\": \"Upgrade Smart Account to V3\",\n \"Upgrade Successful!\": \"Upgrade Successful!\",\n \"Upgrade account\": \"Upgrade account\",\n \"Upgrading...\": \"Upgrading...\",\n \"Use social login with VeChain\": \"Use social login with VeChain\",\n \"Use this token for future transactions\": \"Use this token for future transactions\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\",\n \"VeChain Kit\": \"VeChain Kit\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\",\n \"VeWorld Wallet\": \"VeWorld Wallet\",\n \"Vechain Kit Policy\": \"Vechain Kit Policy\",\n \"View Current Policy\": \"View Current Policy\",\n \"View on explorer\": \"View on explorer\",\n \"View transaction on the explorer\": \"View transaction on the explorer\",\n \"Waiting for confirmation\": \"Waiting for confirmation\",\n \"Waiting for confirmation...\": \"Waiting for confirmation...\",\n \"Waiting wallet confirmation...\": \"Waiting wallet confirmation...\",\n \"Wallet\": \"Wallet\",\n \"Wallet secured by\": \"Wallet secured by\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\",\n \"Website\": \"Website\",\n \"Website URL\": \"Website URL\",\n \"Website URL must start with https://\": \"Website URL must start with https://\",\n \"What is B3TR?\": \"What is B3TR?\",\n \"What is Privy?\": \"What is Privy?\",\n \"What is VET?\": \"What is VET?\",\n \"What is VTHO?\": \"What is VTHO?\",\n \"What is VeBetterDAO?\": \"What is VeBetterDAO?\",\n \"What is VeChain?\": \"What is VeChain?\",\n \"What is a Smart Account?\": \"What is a Smart Account?\",\n \"What is a domain name?\": \"What is a domain name?\",\n \"What is a network?\": \"What is a network?\",\n \"What is a wallet?\": \"What is a wallet?\",\n \"What is an x2earn application?\": \"What is an x2earn application?\",\n \"What is fee delegation?\": \"What is fee delegation?\",\n \"When you have accepted a policy, it will appear here\": \"When you have accepted a policy, it will appear here\",\n \"When you have notifications, they will appear here\": \"When you have notifications, they will appear here\",\n \"YOU OWN THIS\": \"YOU OWN THIS\",\n \"You accepted current policy on {{date}}\": \"You accepted current policy on {{date}}\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"You have an active smart account associated to this wallet. It has been set as your main identity.\",\n \"You may want to try establishing the connection again.\": \"You may want to try establishing the connection again.\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\",\n \"Your address has been successfully set to {{name}}\": \"Your address has been successfully set to {{name}}\",\n \"Your changes have been saved successfully.\": \"Your changes have been saved successfully.\",\n \"Your domain has been unset successfully.\": \"Your domain has been unset successfully.\",\n \"Your embedded wallet\": \"Your embedded wallet\",\n \"Your existing domains\": \"Your existing domains\",\n \"Your smart account is already upgraded to this version.\": \"Your smart account is already upgraded to this version.\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"Your smart account needs to be upgraded to the latest version (v3).\",\n \"Your tokens\": \"Your tokens\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"here\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"rate\",\n \"to learn more about embedded wallets.\": \"to learn more about embedded wallets.\",\n \"unavailable\": \"unavailable\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"your@email.com\"\n}\n","{\n \" and \": \" und \",\n \"'{{policyName}}' on connect\": \"'{{policyName}}' bei Verbindung\",\n \"'{{policyName}}' on {{date}}\": \"'{{policyName}}' am {{date}}\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>Ihre Privatsphäre ist wichtig.</bold> Sie haben die Kontrolle. Akzeptieren Sie, um optionale Funktionen wie Cookies zu aktivieren, die uns helfen, Ihr Erlebnis zu verbessern.\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \"Eine .vet-Domain ist erforderlich, um Ihr Profil anzupassen. Wählen Sie einen Kontonamen, um zu beginnen.\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"Ein Smart Account ist eine Smart-Contract-Wallet, die erweiterte Sicherheit und Funktionalität bietet. Sie ermöglicht Funktionen wie soziale Wiederherstellung, Transaktionsbündelung und mehr.\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"Ein Domain-Name ist eine Art Spitzname für Ihre Wallet-Adresse. Er ermöglicht es Ihnen, Ihre Wallet leicht zu identifizieren und mit dApps über einen menschenlesbaren Namen zu interagieren. Zum Beispiel könnte bei einer Wallet-Adresse von 0x1234567890 Ihr Spitzname \\\"alice.vechain\\\" sein.\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"Ein Netzwerk in der Blockchain bezieht sich auf die Umgebung, in der Transaktionen stattfinden. VeChain hat zwei Hauptnetzwerke: Mainnet (das Live-Netzwerk, in dem echte Transaktionen stattfinden) und Testnet (eine Testumgebung für Entwickler). Das Netzwerk, mit dem Sie verbunden sind, wird oben in diesem Modal angezeigt.\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"Ein neues Upgrade ist für Ihr Smart-Konto verfügbar. Bitte wechseln Sie zum Abschnitt 'Zugang und Sicherheit', um es zu aktualisieren.\",\n \"A new version is available for your account\": \"Eine neue Version ist für Ihr Konto verfügbar\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"Eine Wallet ist Ihr Zugang zur VeChain-Blockchain. Sie speichert Ihre privaten Schlüssel und ermöglicht es Ihnen, Ihre digitalen Vermögenswerte sicher zu verwalten, Tokens zu senden und zu empfangen und mit dezentralen Anwendungen zu interagieren. Denken Sie daran als Ihr digitales Bankkonto für Blockchain-Transaktionen.\",\n \"AVAILABLE\": \"VERFÜGBAR\",\n \"Accept\": \"Akzeptieren\",\n \"Accept all\": \"Alle akzeptieren\",\n \"Accept selected\": \"Auswahl akzeptieren\",\n \"Access and security\": \"Zugang und Sicherheit\",\n \"Account Upgrade Required\": \"Kontoupdate erforderlich\",\n \"Account already upgraded\": \"Konto bereits aktualisiert\",\n \"Account upgrade required\": \"Kontoupgrade erforderlich\",\n \"Active\": \"Aktiv\",\n \"Active Wallet\": \"Aktive Brieftasche\",\n \"Add Login Method\": \"Anmeldemethode hinzufügen\",\n \"Add New Wallet\": \"Neue Brieftasche hinzufügen\",\n \"Add Token\": \"Token hinzufügen\",\n \"Add to shortcuts\": \"Zu den Verknüpfungen hinzufügen\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"Das Hinzufügen weiterer verknüpfter Konten erhöht die Sicherheit gegen Verlust des Zugangs, bringt aber auch zusätzliche potenzielle Angriffsvektoren mit sich. Für verbesserte Sicherheit empfehlen wir die Aktivierung von MFA.\",\n \"Address is required\": \"Adresse ist erforderlich\",\n \"All\": \"Alle\",\n \"All apps\": \"Alle Apps\",\n \"All policies you have accepted\": \"Alle akzeptierten Richtlinien\",\n \"All tokens\": \"Alle Token\",\n \"Already have an x2earn app wallet?\": \"Haben Sie bereits eine x2earn-App-Wallet?\",\n \"Amount\": \"Betrag\",\n \"Amount is required\": \"Betrag ist erforderlich\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"Eine X2Earn-Anwendung in VeBetterDAO ist eine nachhaltige App, die Benutzer für umweltfreundliche Aktionen mit B3TR-Token belohnt. Diese Apps müssen B3TR verteilen, Benutzer-Wallets verknüpfen und den Nachweis nachhaltiger Aktionen erbringen. Sie treten VeBetterDAO durch Unterstützung bei und nehmen an wöchentlichen Token-Zuweisungsrunden teil.\",\n \"An unexpected error occurred.\": \"Ein unerwarteter Fehler ist aufgetreten.\",\n \"Apple\": \"Apple\",\n \"Apply\": \"Anwenden\",\n \"Archived\": \"Archiviert\",\n \"Archived Notifications\": \"Archivierte Benachrichtigungen\",\n \"Are you sure you want to disconnect your wallet?\": \"Sind Sie sicher, dass Sie Ihr Wallet trennen möchten?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"Sind Sie sicher, dass Sie die Richtlinien ablehnen und die Verbindung trennen möchten?\",\n \"Are you sure you want to remove this wallet?\": \"Sind Sie sicher, dass Sie diese Brieftasche entfernen möchten?\",\n \"Are you sure you want to set your domain name to\": \"Sind Sie sicher, dass Sie Ihren Domainnamen auf\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"Sind Sie sicher, dass Sie {{accountType}} als Anmeldemethode, die mit {{accountDescription}} verknüpft ist, trennen möchten?\",\n \"Are you sure you want to unset your current domain?\": \"Sind Sie sicher, dass Sie Ihre aktuelle Domain aufheben möchten?\",\n \"Assets\": \"Vermögenswerte\",\n \"At\": \"Am\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TR ist der Anreiz-Token von VeBetterDAO, aufgebaut auf der VechainThor-Blockchain. Es gibt eine Obergrenze von 1 Milliarde Tokens, die wöchentlich über 12 Jahre hinweg ausgegeben werden. B3TR wird für Belohnungen, Governance und die Unterstützung von VOT3-Token im Verhältnis 1:1 verwendet. Es unterstützt Nachhaltigkeitsanwendungen und das Verwaltung der DAO-Kasse.\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"Das Sichern Ihres Wallets ist entscheidend, da Sie der Einzige mit Zugriff auf Ihre privaten Schlüssel sind. Wenn etwas schiefgeht, ist Ihr privater Schlüssel der einzige Weg, um Ihre Vermögenswerte wiederherzustellen. Die Art der Sicherung hängt davon ab, wie Sie auf Ihr Wallet zugreifen: Wenn Sie VeWorld verwenden, ist die Sicherungsoption in der App verfügbar. Für Benutzer mit sozialem Login finden Sie Sicherungsoptionen im Wallet-Bereich. Wenn Sie über VeChain oder eine andere Ecosystem-App verbunden sind, müssen Sie die ursprüngliche Website besuchen, sich anmelden und dort auf den Wallet-Bereich zugreifen.\",\n \"Backup\": \"Backup\",\n \"Backup your wallet\": \"Sichern Sie Ihr Wallet\",\n \"Backup your wallet, configure MFA and set recovery options\": \"Sichern Sie Ihre Wallet, konfigurieren Sie MFA und legen Sie Wiederherstellungsoptionen fest\",\n \"Balance\": \"Guthaben\",\n \"Benefits of this upgrade:\": \"Vorteile dieses Upgrades:\",\n \"Best\": \"Beste\",\n \"Better transaction handling\": \"Bessere Transaktionsabwicklung\",\n \"Bridge\": \"Brücke\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"Mit Bestätigung werden die folgenden Angaben, die Ihrem Namen ({{domain}}) zugeordnet sind, aktualisiert\",\n \"By confirming, your address will be set to {{domain}}\": \"Mit Bestätigung wird Ihre Adresse auf {{domain}} gesetzt\",\n \"By confirming, your current domain will be unset\": \"Mit Bestätigung wird Ihre aktuelle Domain entfernt\",\n \"By continuing, you agree to\": \"Indem Sie fortfahren, stimmen Sie zu\",\n \"Cancel\": \"Abbrechen\",\n \"Checking...\": \"Überprüfen...\",\n \"Choose Name\": \"Namen wählen\",\n \"Choose a name for your account.\": \"Wählen Sie einen Namen für Ihr Konto.\",\n \"Choose a unique .vet domain name for your account.\": \"Wählen Sie einen eindeutigen .vet-Domainnamen für Ihr Konto.\",\n \"Choose account name\": \"Kontonamen wählen\",\n \"Choose name\": \"Namen wählen\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"Wählen Sie aus, welche Token für Transaktionsgebühren verwendet werden sollen, wenn die App diese nicht übernimmt.\",\n \"Choose your account name\": \"Wählen Sie Ihren Kontonamen\",\n \"Claim your vet domain!\": \"Beanspruchen Sie Ihre Vet-Domain!\",\n \"Claiming name...\": \"Name wird beansprucht...\",\n \"Clear all\": \"Alle löschen\",\n \"Cleared notifications will appear here\": \"Gelöschte Benachrichtigungen werden hier angezeigt\",\n \"Click\": \"Klicken\",\n \"Click below to access {{ name }} and explore its features.\": \"Klicken Sie unten, um auf {{ name }} zuzugreifen und dessen Funktionen zu erkunden.\",\n \"Close\": \"Schließen\",\n \"Close and do this later\": \"Schließen und später erledigen\",\n \"Close announcement\": \"Ankündigung schließen\",\n \"Coming Soon!\": \"Kommt bald!\",\n \"Coming soon\": \"Demnächst\",\n \"Confirm\": \"Bestätigen\",\n \"Confirm Changes\": \"Änderungen bestätigen\",\n \"Confirm Name\": \"Name bestätigen\",\n \"Confirm Unset Domain\": \"Löschung der Domain bestätigen\",\n \"Confirm the transaction in your wallet to complete it.\": \"Bestätigen Sie die Transaktion in Ihrer Wallet, um sie abzuschließen.\",\n \"Confirm transaction\": \"Transaktion bestätigen\",\n \"Connect an external wallet for easier access\": \"Verbinden Sie eine externe Wallet für einfacheren Zugang\",\n \"Connect wallet\": \"Wallet verbinden\",\n \"Connect with VeWorld wallet\": \"Mit VeWorld Wallet verbinden\",\n \"Connect your Apple account for easier access\": \"Verbinden Sie Ihr Apple-Konto für einfacheren Zugriff\",\n \"Connect your Discord account for easier access\": \"Verbinden Sie Ihr Discord-Konto für einen einfacheren Zugriff\",\n \"Connect your Farcaster account for easier access\": \"Verbinden Sie Ihr Farcaster-Konto für einfacheren Zugriff\",\n \"Connect your Github account for easier access\": \"Verbinden Sie Ihr Github-Konto für einfacheren Zugriff\",\n \"Connect your Google account for easier access\": \"Verbinden Sie Ihr Google-Konto für einfacheren Zugriff\",\n \"Connect your Instagram account for easier access\": \"Verbinden Sie Ihr Instagram-Konto für einfacheren Zugriff\",\n \"Connect your LinkedIn account for easier access\": \"Verbinden Sie Ihr LinkedIn-Konto für einfacheren Zugriff\",\n \"Connect your Spotify account for easier access\": \"Verbinden Sie Ihr Spotify-Konto für einfacheren Zugriff\",\n \"Connect your Telegram account for easier access\": \"Verbinden Sie Ihr Telegram-Konto für einfacheren Zugriff\",\n \"Connect your Tiktok account for easier access\": \"Verbinden Sie Ihr Tiktok-Konto für einfacheren Zugriff\",\n \"Connect your Twitter account for easier access\": \"Verbinden Sie Ihr Twitter-Konto für einfacheren Zugriff\",\n \"Connect your email for easier access\": \"Verbinden Sie Ihre E-Mail für einfacheren Zugriff\",\n \"Connect your phone number for easier access\": \"Verbinden Sie Ihre Telefonnummer für einfacheren Zugriff\",\n \"Connecting to VeChain\": \"Verbindung zu VeChain wird hergestellt\",\n \"Connecting with\": \"Verbinden mit\",\n \"Connecting with Passkey\": \"Verbinden mit Passkey\",\n \"Connecting...\": \"Verbinden...\",\n \"Connection Details\": \"Verbindungsdetails\",\n \"Connection Failed\": \"Verbindung fehlgeschlagen\",\n \"Connection Type\": \"Verbindungstyp\",\n \"Connection details\": \"Verbindungsdetails\",\n \"Continue\": \"Fortfahren\",\n \"Continue with Github\": \"Weiter mit Github\",\n \"Continue with Google\": \"Mit Google fortfahren\",\n \"Cookie Policy\": \"Cookie-Richtlinie\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"Cookie-Richtlinie, die die Verwendung von Cookies und Tracking-Technologien beschreibt.\",\n \"Copied!\": \"Kopiert!\",\n \"Copy your address or scan this QR code\": \"Kopieren Sie Ihre Adresse oder scannen Sie diesen QR-Code\",\n \"Currency\": \"Währung\",\n \"Current\": \"Aktuell\",\n \"Current domain\": \"Aktuelle Domain\",\n \"Customization\": \"Anpassung\",\n \"Customize\": \"Anpassen\",\n \"Customize profile\": \"Profil anpassen\",\n \"Customize the appearance of your wallet.\": \"Passen Sie das Erscheinungsbild Ihrer Geldbörse an.\",\n \"Description\": \"Beschreibung\",\n \"Description must be less than 100 characters\": \"Die Beschreibung muss weniger als 100 Zeichen umfassen\",\n \"Didn't get an email?\": \"Keine E-Mail erhalten?\",\n \"Discord\": \"Discord\",\n \"Display Name\": \"Anzeigename\",\n \"Display name must be less than 25 characters\": \"Der Anzeigename muss weniger als 25 Zeichen umfassen\",\n \"Domain set\": \"Domain eingerichtet\",\n \"Domain unset\": \"Domain aufgehoben\",\n \"Done\": \"Fertig\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"Ziehen, um die Reihenfolge zu ändern. Das System verwendet automatisch das Token mit der höchsten Priorität und ausreichendem Guthaben.\",\n \"Ecosystem\": \"Ökosystem\",\n \"Eg: DevRel @ ENS Labs\": \"Z.B.: DevRel @ ENS Labs\",\n \"Email\": \"E-Mail\",\n \"Email address\": \"E-Mail-Adresse\",\n \"Embedded wallet\": \"Eingebettetes Wallet\",\n \"Enhanced compatibility with dApps\": \"Erhöhte Kompatibilität mit dApps\",\n \"Enter confirmation code\": \"Bestätigungscode eingeben\",\n \"Enter your display name\": \"Geben Sie Ihren Anzeigenamen ein\",\n \"Enter your name\": \"Geben Sie Ihren Namen ein\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"Tauschen Sie Ihre digitalen Assets einfach und sicher zwischen VeChain und anderen Blockchain-Netzwerken aus. Swaps werden über Partner durchgeführt, die sowohl dezentrale als auch zentrale Börsen nutzen, um Token zu konvertieren.\",\n \"Existing Custom Tokens\": \"Vorhandene benutzerdefinierte Tokens\",\n \"Explore ecosystem\": \"Ökosystem erkunden\",\n \"Failed to connect with Passkey\": \"Verbindung mit Passkey fehlgeschlagen\",\n \"Failed to connect with VeChain\": \"Verbindung mit VeChain fehlgeschlagen\",\n \"Failed to connect with ecosystem app\": \"Verbindung mit der Ökosystem-App fehlgeschlagen\",\n \"Failed to load App Hub apps\": \"Fehler beim Laden der App Hub-Apps\",\n \"Farcaster\": \"Farcaster\",\n \"Fee\": \"Gebühr\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"Fee Delegation ist ein einzigartiges Merkmal von VeChain, das es jemand anderem (einem Delegator) ermöglicht, Ihre Transaktionsgebühren zu bezahlen. Während viele dApps und Dienstanbieter als Delegatoren fungieren, um neuen Benutzern den Einstieg zu erleichtern, können bei einigen Transaktionen dennoch Gebühren anfallen, die Sie mit Ihrem eigenen VTHO bezahlen müssen. Gebühren sind notwendig, um Netzwerkmissbrauch zu verhindern und die Knoten zu entschädigen, die Transaktionen in der Blockchain verarbeiten und validieren. Wenn Sie die Gebühren selbst bezahlen, können Sie VTHO aus Ihren Vermögenswerten auswählen, um die Transaktionskosten zu decken.\",\n \"Fee token\": \"Gebührentoken\",\n \"Filter by category\": \"Nach Kategorie filtern\",\n \"Finally say goodbye to 0x addresses\": \"Sagen Sie endlich 0x-Adressen auf Wiedersehen\",\n \"For developers\": \"Für Entwickler\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"Aus Sicherheitsgründen können Sie die Einstellungen Ihrer eingebetteten Wallet nur auf der {{appName}} Plattform verwalten.\",\n \"Found following rates\": \"Folgende Kurse gefunden\",\n \"Frequently asked questions\": \"Häufig gestellte Fragen\",\n \"From\": \"Von\",\n \"Gas Token Preferences\": \"Gas-Token-Einstellungen\",\n \"Gas fee\": \"Gasgebühr\",\n \"General\": \"Allgemein\",\n \"Github\": \"Github\",\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.\": \"Gute Neuigkeiten! Multiclause-Transaktionen werden jetzt vollständig für Smart-Accounts unterstützt. Sie können jetzt von einer besseren Benutzererfahrung, niedrigeren Gaskosten und erhöhter Sicherheit profitieren.\",\n \"Google\": \"Google\",\n \"Help\": \"Hilfe\",\n \"Hide\": \"Ausblenden\",\n \"How do I backup my wallet?\": \"Wie sichere ich meine Brieftasche?\",\n \"How do I send tokens?\": \"Wie sende ich Tokens?\",\n \"How is my wallet secured?\": \"Wie ist meine Brieftasche gesichert?\",\n \"I have read and agree to \": \"Ich habe gelesen und stimme zu \",\n \"Ignore and continue\": \"Ignorieren und fortfahren\",\n \"Improved security features\": \"Verbesserte Sicherheitsfunktionen\",\n \"Instagram\": \"Instagram\",\n \"Insufficient balance\": \"Unzureichendes Guthaben\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"Unzureichendes Guthaben, um diese Domain zu beanspruchen und die Gasgebühren zu bezahlen.\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"Unzureichendes Guthaben, um diese Transaktion abzuschließen und die Gasgebühren zu bezahlen.\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"Unzureichendes Guthaben, um diese Überweisung abzuschließen und die Gasgebühren zu bezahlen.\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"Unzureichendes Guthaben, um Ihr Profil zu aktualisieren und die Gasgebühren zu bezahlen.\",\n \"Insufficient {{symbol}} balance\": \"Unzureichendes {{symbol}} Guthaben\",\n \"Invalid address or domain\": \"Ungültige Adresse oder Domain\",\n \"Invalid contract address\": \"Ungültige Vertragsadresse\",\n \"Invalid token address\": \"Ungültige Token-Adresse\",\n \"Language\": \"Sprache\",\n \"Launch vechain.energy\": \"Starte vechain.energy\",\n \"Launch {{name}}\": \"Starte {{name}}\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"Rechtsvereinbarung zwischen Ihnen, Vechain Kit und der aktuellen App, die die Regeln für die Nutzung von Wallet-Diensten beschreibt.\",\n \"Link Apple Account\": \"Apple-Konto verknüpfen\",\n \"Link Discord Account\": \"Discord-Konto verknüpfen\",\n \"Link Email Account\": \"E-Mail-Konto verknüpfen\",\n \"Link External Wallet\": \"Externe Brieftasche verknüpfen\",\n \"Link Farcaster Account\": \"Farcaster-Konto verknüpfen\",\n \"Link Github Account\": \"Github-Konto verknüpfen\",\n \"Link Google Account\": \"Google-Konto verknüpfen\",\n \"Link Instagram Account\": \"Instagram-Konto verknüpfen\",\n \"Link LinkedIn Account\": \"LinkedIn-Konto verknüpfen\",\n \"Link Phone Number\": \"Telefonnummer verknüpfen\",\n \"Link Spotify Account\": \"Spotify-Konto verknüpfen\",\n \"Link Telegram Account\": \"Telegram-Konto verknüpfen\",\n \"Link Tiktok Account\": \"Tiktok-Konto verknüpfen\",\n \"Link Twitter Account\": \"Twitter-Konto verknüpfen\",\n \"LinkedIn\": \"LinkedIn\",\n \"Loading quote...\": \"Angebot wird geladen...\",\n \"Loading your domains...\": \"Ihre Domains werden geladen...\",\n \"Loading...\": \"Lädt...\",\n \"Log in or sign up\": \"Einloggen oder anmelden\",\n \"Logged in with\": \"Angemeldet mit\",\n \"Login\": \"Einloggen\",\n \"Login failed:\": \"Anmeldung fehlgeschlagen:\",\n \"Login methods\": \"Anmeldemethoden\",\n \"Login methods and Passkeys\": \"Anmeldeverfahren und Zugangsschlüssel\",\n \"Logout\": \"Ausloggen\",\n \"Manage Custom Tokens\": \"Benutzerdefinierte Token verwalten\",\n \"Manage MFA\": \"MFA verwalten\",\n \"Manage Recovery\": \"Wiederherstellung verwalten\",\n \"Manage on {{appName}}\": \"Verwalten auf {{appName}}\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"Verwalten Sie die Sicherheitseinstellungen Ihrer eingebetteten Wallet: Verwalten Sie Ihre Anmeldemethoden, fügen Sie einen Zugangsschlüssel hinzu oder sichern Sie Ihre Wallet, um nie den Zugriff auf Ihre Assets zu verlieren.\",\n \"Manage your login methods and passkeys\": \"Verwalten Sie Ihre Anmeldemethoden und Zugangsschlüssel\",\n \"Manage your preferences for currency, language, and appearance.\": \"Verwalten Sie Ihre Einstellungen für Währung, Sprache und Erscheinungsbild.\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"Die Mindestübertragung von {{symbol}} beträgt {{min}}\",\n \"More\": \"Mehr\",\n \"Multiclause Transactions Are Now Supported\": \"Multiclause-Transaktionen werden jetzt unterstützt\",\n \"Name must be at least 3 characters long\": \"Der Name muss mindestens 3 Zeichen lang sein\",\n \"Name your account to make it easier to exchange assets\": \"Geben Sie Ihrem Konto einen Namen, um den Austausch von Vermögenswerten zu erleichtern\",\n \"Network\": \"Netzwerk\",\n \"New\": \"Neu\",\n \"New image selected\": \"Neues Bild ausgewählt\",\n \"No additional accounts available to link\": \"Keine zusätzlichen Konten zum Verknüpfen verfügbar\",\n \"No application from VeChain ecosystem is available to login.\": \"Keine Anwendung aus dem VeChain-Ökosystem ist zur Anmeldung verfügbar.\",\n \"No apps found in this category\": \"Keine Apps in dieser Kategorie gefunden\",\n \"No archived notifications\": \"Keine archivierten Benachrichtigungen\",\n \"No assets\": \"Keine Vermögenswerte\",\n \"No notifications\": \"Keine Benachrichtigungen\",\n \"No policies accepted\": \"Keine akzeptierten Richtlinien\",\n \"No questions found\": \"Keine Fragen gefunden\",\n \"No quotes available\": \"Keine Angebote verfügbar\",\n \"No tokens found\": \"Keine Token gefunden\",\n \"Node URL\": \"Knoten-URL\",\n \"Notifications\": \"Benachrichtigungen\",\n \"Only letters, numbers, and hyphens are allowed\": \"Es sind nur Buchstaben, Zahlen und Bindestriche erlaubt\",\n \"Optional\": \"Optional\",\n \"Other Wallets\": \"Weitere Brieftaschen\",\n \"Other options\": \"Weitere Optionen\",\n \"Passkey\": \"Passwort\",\n \"Phone Number\": \"Telefonnummer\",\n \"Please approve the request in the connection request window...\": \"Bitte genehmigen Sie die Anfrage im Verbindungsanfragefenster...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"Bitte stellen Sie sicher, dass diese Brieftasche sicher und gesichert aufbewahrt wird.\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"Bitte überprüfen Sie {{email}} auf eine E-Mail von privy.io und geben Sie Ihren Code unten ein.\",\n \"Please complete the passkey authentication...\": \"Bitte schließen Sie die Passworthauthentifizierung ab...\",\n \"Please confirm the transaction in your wallet.\": \"Bitte bestätigen Sie die Transaktion in Ihrem Wallet.\",\n \"Please enter a valid Twitter handle without @\": \"Bitte geben Sie einen gültigen Twitter-Handle ohne @ ein\",\n \"Please enter a valid contract address\": \"Bitte geben Sie eine gültige Vertragsadresse ein\",\n \"Please enter a valid email address\": \"Bitte geben Sie eine gültige E-Mail-Adresse ein\",\n \"Please enter a valid number\": \"Bitte geben Sie eine gültige Nummer ein\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"Bitte nehmen Sie sich einen Moment Zeit, um alle Richtlinien zu überprüfen. Die Annahme ist zwingend erforderlich, um fortzufahren.\",\n \"Policy\": \"Richtlinie\",\n \"Preparing changes...\": \"Änderungen werden vorbereitet...\",\n \"Privacy Policy\": \"Datenschutzrichtlinie\",\n \"Privacy policy outlining the data collection and processing practices.\": \"Datenschutzrichtlinie, die die Praktiken zur Datenerfassung und -verarbeitung umreißt.\",\n \"Privy Status\": \"Privy Status\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy entwickelt Infrastruktur für die Benutzeranmeldung und eingebettete Wallets, um bessere Produkte auf Krypto-Basis zu ermöglichen. Das bedeutet, dass die Kontrolle über Vermögenswerte direkt in die Anwendungen eingebettet wird, um es Benutzern, Unternehmen oder Maschinen zu ermöglichen, digitale Vermögenswerte durch nahtlose Produkterfahrungen zu nutzen.\",\n \"Processing transaction...\": \"Transaktion wird verarbeitet...\",\n \"Profile\": \"Profil\",\n \"Profile Image\": \"Profilbild\",\n \"Profile Picture\": \"Profilbild\",\n \"Profile Updated\": \"Profil aktualisiert\",\n \"Read More\": \"Read More\",\n \"Receive\": \"Empfangen\",\n \"Receive tokens\": \"Token empfangen\",\n \"Reduced gas costs for operations\": \"Reduzierte Gaskosten für Operationen\",\n \"Reject and logout\": \"Ablehnen und abmelden\",\n \"Remove\": \"Entfernen\",\n \"Remove Login Method\": \"Anmeldemethode entfernen\",\n \"Remove Wallet\": \"Brieftasche entfernen\",\n \"Remove from shortcuts\": \"Aus den Verknüpfungen entfernen\",\n \"Remove wallet\": \"Brieftasche entfernen\",\n \"Remove your current domain name\": \"Entfernen Sie Ihren aktuellen Domainnamen\",\n \"Resend code\": \"Code erneut senden\",\n \"Retry\": \"Erneut versuchen\",\n \"Save Changes\": \"Änderungen speichern\",\n \"Saving changes...\": \"Änderungen werden gespeichert...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"Verabschieden Sie sich von 0x-Adressen, beanspruchen Sie Ihre .veworld.vet-Subdomain jetzt kostenlos!\",\n \"Search Apps\": \"Apps durchsuchen\",\n \"Search FAQ\": \"FAQ durchsuchen\",\n \"Security preferences\": \"Sicherheitseinstellungen\",\n \"Security settings\": \"Sicherheitseinstellungen\",\n \"Select Additional Login Method\": \"Zusätzliche Anmeldemethode auswählen\",\n \"Select Token\": \"Token auswählen\",\n \"Select Wallet\": \"Brieftasche auswählen\",\n \"Select currency\": \"Währung auswählen\",\n \"Select language\": \"Sprache auswählen\",\n \"Select the token to pay the fee with\": \"Wählen Sie das Token aus, mit dem Sie die Gebühr bezahlen möchten\",\n \"Select token\": \"Token auswählen\",\n \"Send\": \"Senden\",\n \"Send all\": \"Alle senden\",\n \"Sending Transaction...\": \"Transaktion wird gesendet...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"Das Senden an OceanX oder andere Börsen kann zu einem Verlust von Geldern führen.\",\n \"Sending...\": \"Senden...\",\n \"Set a domain first\": \"Legen Sie zuerst eine Domain fest\",\n \"Set up Passkey\": \"Passkey einrichten\",\n \"Set up a passkey for easier access\": \"Richten Sie einen Passkey für einfacheren Zugriff ein\",\n \"Settings\": \"Einstellungen\",\n \"Share on\": \"Teilen auf\",\n \"Shortcuts\": \"Kurzbefehle\",\n \"Show Advanced Options\": \"Erweiterte Optionen anzeigen\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"Mehr anzeigen\",\n \"Slippage tolerance\": \"Slippage-Toleranz\",\n \"Smart Account\": \"Smartes Konto\",\n \"Smart Account detected\": \"Smart-Konto erkannt\",\n \"Something went wrong\": \"Etwas ist schiefgelaufen\",\n \"Something went wrong. Please try again.\": \"Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.\",\n \"Source\": \"Quelle\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"Bleiben Sie dran für unser kommendes Aktivitäts-Feature\",\n \"Stay tuned for our upcoming NFT feature\": \"Bleiben Sie dran für unser kommendes NFT-Feature\",\n \"Submit\": \"Absenden\",\n \"Swap\": \"Tauschen\",\n \"Swap all\": \"Alle tauschen\",\n \"Swapping...\": \"Tauschen...\",\n \"Switch\": \"Wechseln\",\n \"Account Changed\": \"Konto geändert\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"Allgemeine Geschäftsbedingungen\",\n \"Terms and Policies\": \"Bedingungen und Richtlinien\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"Diese Konten sind mit Ihrem eingebetteten Wallet verknüpft und können verwendet werden, um sich in Ihrem Wallet anzumelden und auf Ihren private Schlüssel zuzugreifen.\",\n \"This address only supports VeChain assets.\": \"Diese Adresse unterstützt nur VeChain-Vermögenswerte.\",\n \"This domain is already taken\": \"Diese Domain ist bereits vergeben\",\n \"This domain is protected\": \"Diese Domain ist geschützt\",\n \"This is taking longer than expected.\": \"Dies dauert länger als erwartet.\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"Dies ist Ihre Hauptbrieftasche, erstellt von {{element}} und gesichert durch Privy.\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"Dieses Wallet ist der Besitzer Ihres Smart-Accounts, der als Ihre Identität und als Tor für Ihre Blockchain-Interaktionen verwendet wird.\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"Zu\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"Um weiterhin mit der VeChain-Blockchain zu interagieren und Ihre Operation abzuschließen, muss Ihr Smart Account auf die neueste Version (v3) aktualisiert werden.\",\n \"Token Contract Address\": \"Token-Vertragsadresse\",\n \"Token Priority Order\": \"Token-Prioritätsreihenfolge\",\n \"Token already added\": \"Token bereits hinzugefügt\",\n \"Tools\": \"Werkzeuge\",\n \"Transaction failed\": \"Transaktion fehlgeschlagen\",\n \"Transaction failed:\": \"Transaktion fehlgeschlagen:\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"Die Transaktion wird bearbeitet, es kann bis zu 15 Sekunden dauern.\",\n \"Transaction successful\": \"Transaktion erfolgreich\",\n \"Transaction successful!\": \"Transaktion erfolgreich!\",\n \"Try again\": \"Erneut versuchen\",\n \"Try searching with a different term\": \"Versuchen Sie, mit einem anderen Begriff zu suchen\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Twitter-Benutzername\",\n \"Type the receiver address or domain\": \"Geben Sie die Empfängeradresse oder Domain ein\",\n \"UNAVAILABLE\": \"NICHT VERFÜGBAR\",\n \"Unable to fetch the price\": \"Preis konnte nicht abgerufen werden\",\n \"Unset current domain\": \"Aktuelle Domain aufheben\",\n \"Unsetting current domain...\": \"Aktuelle Domain wird aufgehoben...\",\n \"Upgrade Smart Account to V3\": \"Smart Account auf V3 upgraden\",\n \"Upgrade Successful!\": \"Upgrade erfolgreich!\",\n \"Upgrade account\": \"Account upgraden\",\n \"Upgrading...\": \"Aktualisierung...\",\n \"Use social login with VeChain\": \"Soziale Anmeldung mit VeChain verwenden\",\n \"Use this token for future transactions\": \"Dieses Token für zukünftige Transaktionen verwenden\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"VET ist die primäre Kryptowährung des VeChain-Netzwerks. Es repräsentiert Wert und Eigentum im VeChain-Ökosystem, ähnlich wie Aktien Eigentum in einem Unternehmen darstellen. Das Halten von VET generiert automatisch VTHO, das benötigt wird, um Transaktionen im Netzwerk zu bezahlen.\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"VTHO (VeThor) ist der Energie- oder 'Gas'-Token des VeChain-Netzwerks. Es wird verwendet, um Transaktionsgebühren bei der Interaktion mit der Blockchain zu zahlen. VTHO wird automatisch durch das Halten von VET-Tokens erzeugt und schafft ein Zwei-Token-System, das zur Aufrechterhaltung der Netzwerkstabilität und zur Verwaltung der Transaktionskosten beiträgt.\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAO ist eine dezentrale Organisation auf der VeChain-Blockchain, die sich auf Nachhaltigkeit konzentriert. Mitglieder beteiligen sich an der Governance des DAO, indem sie B3TR-Tokens für Belohnungen und VOT3 für Abstimmungen bei Vorschlägen und wöchentlichen Token-Zuteilungsrunden nutzen.\",\n \"VeChain Kit\": \"VeChain Kit\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"VeChain, mit Hauptsitz in San Marino, Europa, ist ein wegweisendes Blockchain-Ökosystem und Schöpfer von VeChainThor, einer erstklassigen Smart-Contract-Plattform, die die reale Akzeptanz von Blockchain vorantreibt. Gegründet im Jahr 2015 von Sunny Lu, hat sich VeChain kontinuierlich dafür eingesetzt, eine transparente, effiziente, skalierbare und anpassungsfähige Blockchain-Lösung zu liefern.\",\n \"VeWorld Wallet\": \"VeWorld Wallet\",\n \"Vechain Kit Policy\": \"Vechain Kit-Richtlinie\",\n \"View Current Policy\": \"Aktuelle Richtlinie anzeigen\",\n \"View on explorer\": \"Im Explorer ansehen\",\n \"View transaction on the explorer\": \"Transaktion im Explorer ansehen\",\n \"Waiting for confirmation\": \"Warten auf Bestätigung\",\n \"Waiting for confirmation...\": \"Warten auf Bestätigung...\",\n \"Waiting wallet confirmation...\": \"Warten auf Bestätigung der Wallet...\",\n \"Wallet\": \"Wallet\",\n \"Wallet secured by\": \"Wallet gesichert durch\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"Wir empfehlen dringend, deinen privaten Schlüssel zu exportieren, um dein Wallet zu sichern. Dies stellt sicher, dass du es bei Bedarf wiederherstellen oder in Eigenverwahrung übertragen kannst, indem du\",\n \"Website\": \"Webseite\",\n \"Website URL\": \"Webseiten-URL\",\n \"Website URL must start with https://\": \"Webseiten-URL muss mit https:// beginnen\",\n \"What is B3TR?\": \"Was ist B3TR?\",\n \"What is Privy?\": \"Was ist Privy?\",\n \"What is VET?\": \"Was ist VET?\",\n \"What is VTHO?\": \"Was ist VTHO?\",\n \"What is VeBetterDAO?\": \"Was ist VeBetterDAO?\",\n \"What is VeChain?\": \"Was ist VeChain?\",\n \"What is a Smart Account?\": \"Was ist ein Smart Account?\",\n \"What is a domain name?\": \"Was ist ein Domainname?\",\n \"What is a network?\": \"Was ist ein Netzwerk?\",\n \"What is a wallet?\": \"Was ist eine Wallet?\",\n \"What is an x2earn application?\": \"Was ist eine x2earn-Anwendung?\",\n \"What is fee delegation?\": \"Was ist Gebührendelegation?\",\n \"When you have accepted a policy, it will appear here\": \"Wenn Sie eine Richtlinie akzeptiert haben, wird sie hier angezeigt\",\n \"When you have notifications, they will appear here\": \"Wenn Sie Benachrichtigungen haben, werden sie hier angezeigt\",\n \"YOU OWN THIS\": \"DAS GEHÖRT IHNEN\",\n \"You accepted current policy on {{date}}\": \"Sie haben die aktuelle Richtlinie am {{date}} akzeptiert\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"Sie verwenden ein eingebettetes Wallet, das durch Ihre soziale Anmeldemethode gesichert ist und ein nahtloses VeChain-Erlebnis bietet.\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"Sie können Tokens senden, indem Sie das Senden-Symbol im Bereich Schnelle Aktionen anklicken. Geben Sie die Adresse oder den VeChain-Domainnamen des Empfängers ein, wählen Sie das Token aus und geben Sie den Betrag an, den Sie senden möchten.\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"Sie haben keine Gas-Token aktiviert. Bitte aktivieren Sie mindestens ein Gas-Token in den Gas-Token-Einstellungen.\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"Sie haben ein aktives Smart-Konto, das mit dieser Wallet verbunden ist. Es wurde als Ihre Hauptidentität festgelegt.\",\n \"You may want to try establishing the connection again.\": \"Sie sollten möglicherweise versuchen, die Verbindung erneut herzustellen.\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"Sie müssen mindestens ein Token aktivieren, um Transaktionen durchzuführen. Ohne aktivierte Token können Sie keine Gasgebühren bezahlen.\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"Ihr Konto wurde erfolgreich auf die neueste Version aktualisiert. Sie können nun eine bessere Benutzererfahrung, niedrigere Gaskosten und erhöhte Sicherheit genießen.\",\n \"Your address has been successfully set to {{name}}\": \"Ihre Adresse wurde erfolgreich auf {{name}} gesetzt\",\n \"Your changes have been saved successfully.\": \"Ihre Änderungen wurden erfolgreich gespeichert.\",\n \"Your domain has been unset successfully.\": \"Ihre Domain wurde erfolgreich aufgehoben.\",\n \"Your embedded wallet\": \"Ihr eingebettetes Portemonnaie\",\n \"Your existing domains\": \"Ihre vorhandenen Domains\",\n \"Your smart account is already upgraded to this version.\": \"Ihr Smart-Konto ist bereits auf diese Version aktualisiert.\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"Ihr Smart-Konto muss auf die neueste Version (v3) aktualisiert werden.\",\n \"Your tokens\": \"Ihre Token\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"Die Sicherheit Ihres Wallets hängt davon ab, wie Sie darauf zugreifen. Mit Selbstverwaltungsoptionen wie der VeWorld-Erweiterung, der mobilen App oder einer Hardware-Wallet haben Sie die vollständige Kontrolle über Ihre privaten Schlüssel. Diese Erweiterung selbst hat keinen Zugriff auf Ihre privaten Schlüssel. Beim Einloggen mit sozialen Konten oder VeChain wird Ihr Wallet von Privy erstellt und gesichert und von VeChain verwaltet, was ein einfacheres Onboarding-Erlebnis bietet und gleichzeitig die Sicherheit gewährleistet.\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"hier\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"Kurs\",\n \"to learn more about embedded wallets.\": \"um mehr über eingebettete Wallets zu erfahren.\",\n \"unavailable\": \"nicht verfügbar\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"your@email.com\"\n}","{\n \" and \": \" e \",\n \"'{{policyName}}' on connect\": \"'{{policyName}}' su connessione\",\n \"'{{policyName}}' on {{date}}\": \"'{{policyName}}' il {{date}}\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>La tua privacy è importante.</bold> Hai il controllo, accetta per abilitare funzionalità opzionali come i cookie che ci aiutano a migliorare la tua esperienza.\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \"È richiesto un dominio .vet per personalizzare il tuo profilo. Scegli un nome per l'account per iniziare.\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"Un Smart Account è un portafoglio smart contract che offre una maggiore sicurezza e funzionalità. Permette caratteristiche come il recupero sociale, il raggruppamento delle transazioni e altro ancora.\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"Un nome di dominio è una sorta di soprannome per il tuo indirizzo del portafoglio. Ti consente di identificare facilmente il tuo portafoglio e interagire con le dApp utilizzando un nome leggibile dall'uomo. Ad esempio, se il tuo indirizzo del portafoglio è 0x1234567890, il tuo soprannome potrebbe essere \\\"alice.vechain\\\".\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"Una rete nella blockchain si riferisce all'ambiente in cui avvengono le transazioni. VeChain ha due reti principali: Mainnet (la rete live dove avvengono le transazioni reali) e Testnet (un ambiente di test per gli sviluppatori). La rete a cui sei connesso è visualizzata nella parte superiore di questo modulo.\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"Un nuovo aggiornamento è disponibile per il tuo account intelligente. Vai alla sezione 'Accesso e Sicurezza' per aggiornarlo.\",\n \"A new version is available for your account\": \"Una nuova versione è disponibile per il tuo account\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"Un portafoglio è il tuo gateway alla blockchain di VeChain. Conserva le tue chiavi private e ti permette di gestire in modo sicuro i tuoi asset digitali, inviare e ricevere token, e interagire con applicazioni decentralizzate. Pensalo come il tuo conto bancario digitale per le transazioni blockchain.\",\n \"AVAILABLE\": \"DISPONIBILE\",\n \"Accept\": \"Accetta\",\n \"Accept all\": \"Accetta tutto\",\n \"Accept selected\": \"Accetta selezionati\",\n \"Access and security\": \"Accesso e sicurezza\",\n \"Account Upgrade Required\": \"Aggiornamento dell'account richiesto\",\n \"Account already upgraded\": \"Account già aggiornato\",\n \"Account upgrade required\": \"Aggiornamento dell'account richiesto\",\n \"Active\": \"Attivo\",\n \"Active Wallet\": \"Portafoglio Attivo\",\n \"Add Login Method\": \"Aggiungi metodo di accesso\",\n \"Add New Wallet\": \"Aggiungi Nuovo Portafoglio\",\n \"Add Token\": \"Aggiungi Token\",\n \"Add to shortcuts\": \"Aggiungi ai collegamenti\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"Aggiungere più account collegati aumenta la sicurezza contro la perdita di accesso, ma introduce anche ulteriori potenziali vettori di attacco. Per una maggiore sicurezza, raccomandiamo di abilitare l'MFA.\",\n \"Address is required\": \"L'indirizzo è richiesto\",\n \"All\": \"Tutti\",\n \"All apps\": \"Tutte le app\",\n \"All policies you have accepted\": \"Tutte le politiche che hai accettato\",\n \"All tokens\": \"Tutti i token\",\n \"Already have an x2earn app wallet?\": \"Hai già un portafoglio x2earn app?\",\n \"Amount\": \"Importo\",\n \"Amount is required\": \"È richiesto l'importo\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"Un'applicazione X2Earn in VeBetterDAO è un'app sostenibile che premia gli utenti con token B3TR per azioni ecologiche. Queste app devono distribuire B3TR, collegare i portafogli degli utenti e fornire la prova delle azioni sostenibili. Si uniscono a VeBetterDAO tramite sponsorizzazione e partecipano a turni settimanali di allocazione dei token.\",\n \"An unexpected error occurred.\": \"Si è verificato un errore inaspettato.\",\n \"Apple\": \"Apple\",\n \"Apply\": \"Applica\",\n \"Archived\": \"Archiviato\",\n \"Archived Notifications\": \"Notifiche archiviate\",\n \"Are you sure you want to disconnect your wallet?\": \"Sei sicuro di voler disconnettere il tuo portafoglio?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"Sei sicuro di voler rifiutare le politiche e disconnetterti?\",\n \"Are you sure you want to remove this wallet?\": \"Sei sicuro di voler rimuovere questo portafoglio?\",\n \"Are you sure you want to set your domain name to\": \"Sei sicuro di voler impostare il tuo nome di dominio su\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"Sei sicuro di voler scollegare {{accountType}} come metodo di accesso collegato a {{accountDescription}}?\",\n \"Are you sure you want to unset your current domain?\": \"Sei sicuro di voler rimuovere il tuo attuale dominio?\",\n \"Assets\": \"Risorse\",\n \"At\": \"Alle\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TR è il token incentivo di VeBetterDAO, creato sulla blockchain VechainThor. Ha una fornitura massima di 1 miliardo di token, emessi settimanalmente per 12 anni. B3TR viene utilizzato per ricompense, governance e supporto dei token VOT3 1:1. Supporta applicazioni di sostenibilità e gestione del tesoro del DAO.\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"Fare il backup del tuo portafoglio è fondamentale poiché sei l'unico ad avere accesso alle tue chiavi private. Se qualcosa va storto, avere la tua chiave privata è l'unico modo per recuperare i tuoi beni. Come fare il backup dipende da come accedi al tuo portafoglio: se usi VeWorld, l'opzione di backup è disponibile all'interno dell'app. Per gli utenti con accesso tramite login sociale, puoi trovare opzioni di backup nella sezione Portafoglio. Se sei connesso tramite VeChain o un'altra app dell'ecosistema, dovrai visitare il sito originale, accedere e raggiungere la sezione Portafoglio da lì.\",\n \"Backup\": \"Backup\",\n \"Backup your wallet\": \"Esegui il backup del tuo portafoglio\",\n \"Backup your wallet, configure MFA and set recovery options\": \"Esegui il backup del tuo portafoglio, configura MFA e imposta le opzioni di recupero\",\n \"Balance\": \"Saldo\",\n \"Benefits of this upgrade:\": \"Vantaggi di questo aggiornamento:\",\n \"Best\": \"Migliore\",\n \"Better transaction handling\": \"Gestione migliore delle transazioni\",\n \"Bridge\": \"Ponte\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"Confermando, i seguenti dettagli collegati al tuo nome ({{domain}}) saranno aggiornati\",\n \"By confirming, your address will be set to {{domain}}\": \"Confermando, il tuo indirizzo sarà impostato su {{domain}}\",\n \"By confirming, your current domain will be unset\": \"Confermando, il tuo dominio attuale sarà rimosso\",\n \"By continuing, you agree to\": \"Continuando, accetti di\",\n \"Cancel\": \"Annulla\",\n \"Checking...\": \"Verifica in corso...\",\n \"Choose Name\": \"Scegli Nome\",\n \"Choose a name for your account.\": \"Scegli un nome per il tuo account.\",\n \"Choose a unique .vet domain name for your account.\": \"Scegli un nome di dominio .vet unico per il tuo account.\",\n \"Choose account name\": \"Scegli nome account\",\n \"Choose name\": \"Scegli nome\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"Scegli quali token usare per le commissioni di transazione quando l'app non le copre.\",\n \"Choose your account name\": \"Scegli il nome del tuo account\",\n \"Claim your vet domain!\": \"Richiedi il tuo dominio vet!\",\n \"Claiming name...\": \"Reclamo del nome in corso...\",\n \"Clear all\": \"Cancella tutto\",\n \"Cleared notifications will appear here\": \"Le notifiche cancellate appariranno qui\",\n \"Click\": \"Clicca\",\n \"Click below to access {{ name }} and explore its features.\": \"Clicca qui sotto per accedere a {{ name }} ed esplorarne le funzionalità.\",\n \"Close\": \"Chiudi\",\n \"Close and do this later\": \"Chiudi e fallo più tardi\",\n \"Close announcement\": \"Chiudi annuncio\",\n \"Coming Soon!\": \"Prossimamente!\",\n \"Coming soon\": \"Prossimamente\",\n \"Confirm\": \"Conferma\",\n \"Confirm Changes\": \"Conferma Modifiche\",\n \"Confirm Name\": \"Conferma Nome\",\n \"Confirm Unset Domain\": \"Conferma Rimozione Dominio\",\n \"Confirm the transaction in your wallet to complete it.\": \"Conferma la transazione nel tuo portafoglio per completarla.\",\n \"Confirm transaction\": \"Conferma transazione\",\n \"Connect an external wallet for easier access\": \"Collega un portafoglio esterno per un accesso più semplice\",\n \"Connect wallet\": \"Connetti portafoglio\",\n \"Connect with VeWorld wallet\": \"Connettiti con il portafoglio VeWorld\",\n \"Connect your Apple account for easier access\": \"Collega il tuo account Apple per un accesso più facile\",\n \"Connect your Discord account for easier access\": \"Collega il tuo account Discord per accedere più facilmente\",\n \"Connect your Farcaster account for easier access\": \"Collega il tuo account Farcaster per un accesso più facile\",\n \"Connect your Github account for easier access\": \"Collega il tuo account Github per un accesso più facile\",\n \"Connect your Google account for easier access\": \"Collega il tuo account Google per un accesso più facile\",\n \"Connect your Instagram account for easier access\": \"Collega il tuo account Instagram per un accesso più facile\",\n \"Connect your LinkedIn account for easier access\": \"Collega il tuo account LinkedIn per un accesso più facile\",\n \"Connect your Spotify account for easier access\": \"Collega il tuo account Spotify per un accesso più facile\",\n \"Connect your Telegram account for easier access\": \"Collega il tuo account Telegram per un accesso più facile\",\n \"Connect your Tiktok account for easier access\": \"Collega il tuo account Tiktok per un accesso più facile\",\n \"Connect your Twitter account for easier access\": \"Collega il tuo account Twitter per un accesso più facile\",\n \"Connect your email for easier access\": \"Collega la tua email per un accesso più facile\",\n \"Connect your phone number for easier access\": \"Collega il tuo numero di telefono per un accesso più facile\",\n \"Connecting to VeChain\": \"Connessione a VeChain\",\n \"Connecting with\": \"Collegamento con\",\n \"Connecting with Passkey\": \"Collegamento con Passkey\",\n \"Connecting...\": \"Collegamento...\",\n \"Connection Details\": \"Dettagli di Connessione\",\n \"Connection Failed\": \"Connessione Fallita\",\n \"Connection Type\": \"Tipo di connessione\",\n \"Connection details\": \"Dettagli della connessione\",\n \"Continue\": \"Continua\",\n \"Continue with Github\": \"Continua con Github\",\n \"Continue with Google\": \"Continua con Google\",\n \"Cookie Policy\": \"Politica sui cookie\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"Politica sui cookie che descrive l'uso di cookie e tecnologie di tracciamento.\",\n \"Copied!\": \"Copiato!\",\n \"Copy your address or scan this QR code\": \"Copia il tuo indirizzo o scansiona questo codice QR\",\n \"Currency\": \"Valuta\",\n \"Current\": \"Attuale\",\n \"Current domain\": \"Dominio attuale\",\n \"Customization\": \"Personalizzazione\",\n \"Customize\": \"Personalizza\",\n \"Customize profile\": \"Personalizza profilo\",\n \"Customize the appearance of your wallet.\": \"Personalizza l'aspetto del tuo portafoglio.\",\n \"Description\": \"Descrizione\",\n \"Description must be less than 100 characters\": \"La descrizione deve contenere meno di 100 caratteri\",\n \"Didn't get an email?\": \"Non hai ricevuto un'email?\",\n \"Discord\": \"Discord\",\n \"Display Name\": \"Nome da visualizzare\",\n \"Display name must be less than 25 characters\": \"Il nome da visualizzare deve contenere meno di 25 caratteri\",\n \"Domain set\": \"Dominio impostato\",\n \"Domain unset\": \"Dominio rimosso\",\n \"Done\": \"Fatto\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"Trascina per riordinare. Il sistema userà automaticamente il token con priorità più alta e saldo sufficiente.\",\n \"Ecosystem\": \"Ecosistema\",\n \"Eg: DevRel @ ENS Labs\": \"Es: DevRel @ ENS Labs\",\n \"Email\": \"Email\",\n \"Email address\": \"Indirizzo email\",\n \"Embedded wallet\": \"Portafoglio incorporato\",\n \"Enhanced compatibility with dApps\": \"Compatibilità migliorata con dApps\",\n \"Enter confirmation code\": \"Inserisci il codice di conferma\",\n \"Enter your display name\": \"Inserisci il tuo nome da visualizzare\",\n \"Enter your name\": \"Inserisci il tuo nome\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"Scambia i tuoi beni digitali tra VeChain e altre reti blockchain in modo facile e sicuro. Gli scambi sono eseguiti tramite partner che utilizzano sia exchange decentralizzati che centralizzati per convertire i token.\",\n \"Existing Custom Tokens\": \"Token personalizzati esistenti\",\n \"Explore ecosystem\": \"Esplora l'ecosistema\",\n \"Failed to connect with Passkey\": \"Connessione fallita con Passkey\",\n \"Failed to connect with VeChain\": \"Connessione fallita con VeChain\",\n \"Failed to connect with ecosystem app\": \"Connessione fallita con l'app dell'ecosistema\",\n \"Failed to load App Hub apps\": \"Caricamento delle app di App Hub non riuscito\",\n \"Farcaster\": \"Farcaster\",\n \"Fee\": \"Commissione\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"La delega delle commissioni è una funzione unica di VeChain che consente a qualcun altro (un delegante) di pagare le tue commissioni di transazione. Mentre molte dApp e fornitori di servizi agiscono come deleganti per facilitare l'inizio per i nuovi utenti, alcune transazioni potrebbero comunque richiedere che tu paghi le commissioni usando il tuo VTHO. Le commissioni sono necessarie per prevenire lo spam di rete e compensare i nodi che elaborano e convalidano le transazioni sulla blockchain. Quando paghi le commissioni di persona, potrai selezionare VTHO dai tuoi asset per coprire il costo della transazione.\",\n \"Fee token\": \"Token di commissione\",\n \"Filter by category\": \"Filtra per categoria\",\n \"Finally say goodbye to 0x addresses\": \"Finalmente dì addio agli indirizzi 0x\",\n \"For developers\": \"Per sviluppatori\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"Per motivi di sicurezza, puoi gestire le impostazioni del tuo portafoglio integrato solo sulla piattaforma {{appName}}.\",\n \"Found following rates\": \"Trovate le seguenti tariffe\",\n \"Frequently asked questions\": \"Domande frequenti\",\n \"From\": \"Da\",\n \"Gas Token Preferences\": \"Preferenze token gas\",\n \"Gas fee\": \"Commissione gas\",\n \"General\": \"Generale\",\n \"Github\": \"Github\",\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.\": \"Buone notizie! Le transazioni multi-clausola sono ora completamente supportate per gli account intelligenti. Ora puoi godere di una migliore esperienza utente, costi di gas ridotti e maggiore sicurezza.\",\n \"Google\": \"Google\",\n \"Help\": \"Aiuto\",\n \"Hide\": \"Nascondi\",\n \"How do I backup my wallet?\": \"Come faccio a fare il backup del mio portafoglio?\",\n \"How do I send tokens?\": \"Come posso inviare token?\",\n \"How is my wallet secured?\": \"Come è protetto il mio portafoglio?\",\n \"I have read and agree to \": \"Ho letto e accetto \",\n \"Ignore and continue\": \"Ignora e continua\",\n \"Improved security features\": \"Funzionalità di sicurezza migliorate\",\n \"Instagram\": \"Instagram\",\n \"Insufficient balance\": \"Saldo insufficiente\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"Saldo insufficiente per rivendicare questo dominio e coprire le commissioni di gas.\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"Saldo insufficiente per completare questa transazione e coprire le commissioni di gas.\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"Saldo insufficiente per completare questo trasferimento e coprire le commissioni di gas.\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"Saldo insufficiente per aggiornare il tuo profilo e coprire le commissioni di gas.\",\n \"Insufficient {{symbol}} balance\": \"Saldo insufficiente di {{symbol}}\",\n \"Invalid address or domain\": \"Indirizzo o dominio non valido\",\n \"Invalid contract address\": \"Indirizzo del contratto non valido\",\n \"Invalid token address\": \"Indirizzo del token non valido\",\n \"Language\": \"Lingua\",\n \"Launch vechain.energy\": \"Avvia vechain.energy\",\n \"Launch {{name}}\": \"Avvia {{name}}\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"Accordo legale tra te, Vechain Kit e l'app corrente, che descrive le regole per l'utilizzo dei servizi del wallet.\",\n \"Link Apple Account\": \"Collega account Apple\",\n \"Link Discord Account\": \"Collega account Discord\",\n \"Link Email Account\": \"Collega account Email\",\n \"Link External Wallet\": \"Collega Portafoglio Esterno\",\n \"Link Farcaster Account\": \"Collega account Farcaster\",\n \"Link Github Account\": \"Collega account Github\",\n \"Link Google Account\": \"Collega account Google\",\n \"Link Instagram Account\": \"Collega account Instagram\",\n \"Link LinkedIn Account\": \"Collega account LinkedIn\",\n \"Link Phone Number\": \"Collega numero di telefono\",\n \"Link Spotify Account\": \"Collega account Spotify\",\n \"Link Telegram Account\": \"Collega account Telegram\",\n \"Link Tiktok Account\": \"Collega account Tiktok\",\n \"Link Twitter Account\": \"Collega account Twitter\",\n \"LinkedIn\": \"LinkedIn\",\n \"Loading quote...\": \"Caricamento preventivo...\",\n \"Loading your domains...\": \"Caricamento dei tuoi domini...\",\n \"Loading...\": \"Caricamento...\",\n \"Log in or sign up\": \"Accedi o registrati\",\n \"Logged in with\": \"Accesso effettuato con\",\n \"Login\": \"Accedi\",\n \"Login failed:\": \"Accesso fallito:\",\n \"Login methods\": \"Metodi di accesso\",\n \"Login methods and Passkeys\": \"Metodi di accesso e Chiavi di accesso\",\n \"Logout\": \"Esci\",\n \"Manage Custom Tokens\": \"Gestisci Token Personalizzati\",\n \"Manage MFA\": \"Gestisci MFA\",\n \"Manage Recovery\": \"Gestisci Recupero\",\n \"Manage on {{appName}}\": \"Gestisci su {{appName}}\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"Gestisci le impostazioni di sicurezza del tuo portafoglio integrato: gestisci i tuoi metodi di accesso, aggiungi una chiave di accesso o esegui il backup del portafoglio per non perdere mai l'accesso ai tuoi beni.\",\n \"Manage your login methods and passkeys\": \"Gestisci i tuoi metodi di accesso e chiavi di accesso\",\n \"Manage your preferences for currency, language, and appearance.\": \"Gestisci le tue preferenze per valuta, lingua e aspetto.\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"Il trasferimento minimo di {{symbol}} è {{min}}\",\n \"More\": \"Altro\",\n \"Multiclause Transactions Are Now Supported\": \"Le transazioni multi-clausola sono ora supportate\",\n \"Name must be at least 3 characters long\": \"Il nome deve essere lungo almeno 3 caratteri\",\n \"Name your account to make it easier to exchange assets\": \"Dai un nome al tuo account per semplificare lo scambio di beni\",\n \"Network\": \"Rete\",\n \"New\": \"Nuovo\",\n \"New image selected\": \"Nuova immagine selezionata\",\n \"No additional accounts available to link\": \"Nessun account aggiuntivo disponibile da collegare\",\n \"No application from VeChain ecosystem is available to login.\": \"Nessuna applicazione dell'ecosistema VeChain è disponibile per l'accesso.\",\n \"No apps found in this category\": \"Nessuna app trovata in questa categoria\",\n \"No archived notifications\": \"Nessuna notifica archiviata\",\n \"No assets\": \"Nessun bene\",\n \"No notifications\": \"Nessuna notifica\",\n \"No policies accepted\": \"Nessuna politica accettata\",\n \"No questions found\": \"Nessuna domanda trovata\",\n \"No quotes available\": \"Nessuna quotazione disponibile\",\n \"No tokens found\": \"Nessun token trovato\",\n \"Node URL\": \"URL del nodo\",\n \"Notifications\": \"Notifiche\",\n \"Only letters, numbers, and hyphens are allowed\": \"Sono ammessi solo lettere, numeri e trattini\",\n \"Optional\": \"Opzionale\",\n \"Other Wallets\": \"Altri Portafogli\",\n \"Other options\": \"Altre opzioni\",\n \"Passkey\": \"Chiave di accesso\",\n \"Phone Number\": \"Numero di telefono\",\n \"Please approve the request in the connection request window...\": \"Si prega di approvare la richiesta nella finestra della richiesta di connessione...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"Si prega di assicurarsi che questo portafoglio sia al sicuro e con un backup.\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"Controlla {{email}} per un'email da privy.io e inserisci il tuo codice qui sotto.\",\n \"Please complete the passkey authentication...\": \"Si prega di completare l'autenticazione con chiave di accesso...\",\n \"Please confirm the transaction in your wallet.\": \"Si prega di confermare la transazione nel proprio wallet.\",\n \"Please enter a valid Twitter handle without @\": \"Inserisci un handle Twitter valido senza @\",\n \"Please enter a valid contract address\": \"Inserisci un indirizzo di contratto valido\",\n \"Please enter a valid email address\": \"Inserisci un indirizzo email valido\",\n \"Please enter a valid number\": \"Per favore inserisci un numero valido\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"Per favore, prenditi un momento per esaminare tutte le politiche, la cui accettazione è obbligatoria per continuare.\",\n \"Policy\": \"Politica\",\n \"Preparing changes...\": \"Preparazione delle modifiche...\",\n \"Privacy Policy\": \"Informativa sulla privacy\",\n \"Privacy policy outlining the data collection and processing practices.\": \"Informativa sulla privacy che delinea le pratiche di raccolta e trattamento dei dati.\",\n \"Privy Status\": \"Privy Status\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy costruisce infrastrutture per l'onboarding degli utenti e per wallet integrati, per abilitare prodotti migliori basati su crypto. Questo significa incorporare il controllo degli asset all'interno delle applicazioni stesse per permettere a utenti, imprese o macchine di utilizzare asset digitali attraverso esperienze di prodotto fluide.\",\n \"Processing transaction...\": \"Elaborazione della transazione...\",\n \"Profile\": \"Profilo\",\n \"Profile Image\": \"Immagine del profilo\",\n \"Profile Picture\": \"Immagine del Profilo\",\n \"Profile Updated\": \"Profilo aggiornato\",\n \"Read More\": \"Read More\",\n \"Receive\": \"Ricevi\",\n \"Receive tokens\": \"Ricevi token\",\n \"Reduced gas costs for operations\": \"Costi del gas ridotti per le operazioni\",\n \"Reject and logout\": \"Rifiuta e disconnetti\",\n \"Remove\": \"Rimuovi\",\n \"Remove Login Method\": \"Rimuovi metodo di accesso\",\n \"Remove Wallet\": \"Rimuovi Portafoglio\",\n \"Remove from shortcuts\": \"Rimuovi dai collegamenti\",\n \"Remove wallet\": \"Rimuovi portafoglio\",\n \"Remove your current domain name\": \"Rimuovi il tuo attuale nome di dominio\",\n \"Resend code\": \"Reinvia codice\",\n \"Retry\": \"Riprova\",\n \"Save Changes\": \"Salva modifiche\",\n \"Saving changes...\": \"Salvataggio delle modifiche...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"Dì addio agli indirizzi 0x, richiedi il tuo sottodominio .veworld.vet ora gratuitamente!\",\n \"Search Apps\": \"Cerca App\",\n \"Search FAQ\": \"Cerca FAQ\",\n \"Security preferences\": \"Preferenze di sicurezza\",\n \"Security settings\": \"Impostazioni di sicurezza\",\n \"Select Additional Login Method\": \"Seleziona metodo di accesso aggiuntivo\",\n \"Select Token\": \"Seleziona Token\",\n \"Select Wallet\": \"Seleziona Portafoglio\",\n \"Select currency\": \"Seleziona valuta\",\n \"Select language\": \"Seleziona lingua\",\n \"Select the token to pay the fee with\": \"Seleziona il token con cui pagare la commissione\",\n \"Select token\": \"Seleziona\",\n \"Send\": \"Invia\",\n \"Send all\": \"Invia tutto\",\n \"Sending Transaction...\": \"Invio Transazione...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"Inviare a OceanX o ad altri exchange potrebbe comportare la perdita di fondi.\",\n \"Sending...\": \"Invio...\",\n \"Set a domain first\": \"Imposta prima un dominio\",\n \"Set up Passkey\": \"Configura Chiave di Accesso\",\n \"Set up a passkey for easier access\": \"Configura una chiave di accesso per un accesso più semplice\",\n \"Settings\": \"Impostazioni\",\n \"Share on\": \"Condividi su\",\n \"Shortcuts\": \"Scorciatoie\",\n \"Show Advanced Options\": \"Mostra opzioni avanzate\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"Mostra di più\",\n \"Slippage tolerance\": \"Tolleranza allo slippage\",\n \"Smart Account\": \"Account Smart\",\n \"Smart Account detected\": \"Account smart rilevato\",\n \"Something went wrong\": \"Qualcosa è andato storto\",\n \"Something went wrong. Please try again.\": \"Qualcosa è andato storto. Per favore riprova.\",\n \"Source\": \"Fonte\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"Resta sintonizzato per la nostra prossima funzionalità Attività\",\n \"Stay tuned for our upcoming NFT feature\": \"Resta sintonizzato per la nostra prossima funzionalità NFT\",\n \"Submit\": \"Invia\",\n \"Swap\": \"Scambia\",\n \"Swap all\": \"Scambia tutto\",\n \"Swapping...\": \"Scambio in corso...\",\n \"Switch\": \"Cambia\",\n \"Account Changed\": \"Account cambiato\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"Termini e condizioni\",\n \"Terms and Policies\": \"Termini e politiche\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"Questi account sono collegati al tuo portafoglio integrato e possono essere utilizzati per accedere al tuo portafoglio e alla tua chiave privata.\",\n \"This address only supports VeChain assets.\": \"Questo indirizzo supporta solo i beni VeChain.\",\n \"This domain is already taken\": \"Questo dominio è già stato preso\",\n \"This domain is protected\": \"Questo dominio è protetto\",\n \"This is taking longer than expected.\": \"Sta richiedendo più tempo del previsto.\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"Questo è il tuo portafoglio principale, creato da {{element}} e protetto da Privy.\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"Questo portafoglio è il proprietario del tuo account smart, che è utilizzato come la tua identità e come un gateway per le tue interazioni con la blockchain.\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"A\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"Per continuare a interagire con la blockchain VeChain e completare la tua operazione, il tuo conto smart deve essere aggiornato all'ultima versione (v3).\",\n \"Token Contract Address\": \"Indirizzo del Contratto del Token\",\n \"Token Priority Order\": \"Ordine di priorità dei token\",\n \"Token already added\": \"Token già aggiunto\",\n \"Tools\": \"Strumenti\",\n \"Transaction failed\": \"Transazione fallita\",\n \"Transaction failed:\": \"Transazione fallita:\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"La transazione è in fase di elaborazione, può richiedere fino a 15 secondi.\",\n \"Transaction successful\": \"Transazione avvenuta con successo\",\n \"Transaction successful!\": \"Transazione avvenuta con successo!\",\n \"Try again\": \"Riprovare\",\n \"Try searching with a different term\": \"Prova a cercare con un termine diverso\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Nome utente Twitter\",\n \"Type the receiver address or domain\": \"Inserisci l'indirizzo o il dominio del destinatario\",\n \"UNAVAILABLE\": \"NON DISPONIBILE\",\n \"Unable to fetch the price\": \"Impossibile recuperare il prezzo\",\n \"Unset current domain\": \"Rimuovi dominio attuale\",\n \"Unsetting current domain...\": \"Rimozione del dominio attuale in corso...\",\n \"Upgrade Smart Account to V3\": \"Aggiorna Conto Smart a V3\",\n \"Upgrade Successful!\": \"Aggiornamento Riuscito!\",\n \"Upgrade account\": \"Aggiorna conto\",\n \"Upgrading...\": \"Aggiornamento in corso...\",\n \"Use social login with VeChain\": \"Usa il login social con VeChain\",\n \"Use this token for future transactions\": \"Usa questo token per le transazioni future\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"VET è la criptovaluta principale della rete VeChain. Rappresenta valore e proprietà nell'ecosistema VeChain, simile a come le azioni rappresentano la proprietà in un'azienda. Possedere VET genera automaticamente VTHO, che è necessario per pagare le transazioni sulla rete.\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"VTHO (VeThor) è il token energetico o 'gas' della rete VeChain. Viene utilizzato per pagare le commissioni di transazione quando si interagisce con la blockchain. VTHO viene generato automaticamente detenendo token VET, creando un sistema a due token che aiuta a mantenere la stabilità della rete e gestire i costi di transazione.\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAO è un'organizzazione decentralizzata sulla blockchain VeChain focalizzata sulla sostenibilità. I membri partecipano alla governance del DAO utilizzando token B3TR per le ricompense e VOT3 per votare nelle proposte e nei turni di allocazione settimanale dei token.\",\n \"VeChain Kit\": \"Kit VeChain\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"VeChain, con sede a San Marino, Europa, è un ecosistema blockchain pionieristico e creatore di VeChainThor, una piattaforma di smart contract di classe mondiale che promuove l'adozione della blockchain nel mondo reale. Fondata nel 2015 da Sunny Lu, VeChain ha costantemente lavorato per offrire una soluzione blockchain trasparente, efficiente, scalabile e adattabile.\",\n \"VeWorld Wallet\": \"Portafoglio VeWorld\",\n \"Vechain Kit Policy\": \"Politica del Vechain Kit\",\n \"View Current Policy\": \"Visualizza politica corrente\",\n \"View on explorer\": \"Visualizza sull'explorer\",\n \"View transaction on the explorer\": \"Visualizza la transazione sull'explorer\",\n \"Waiting for confirmation\": \"In attesa di conferma\",\n \"Waiting for confirmation...\": \"In attesa di conferma...\",\n \"Waiting wallet confirmation...\": \"In attesa di conferma del portafoglio...\",\n \"Wallet\": \"Portafoglio\",\n \"Wallet secured by\": \"Portafoglio protetto da\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"Consigliamo vivamente di esportare la tua chiave privata per eseguire il backup del tuo portafoglio. Questo garantisce che tu possa ripristinarlo se necessario o trasferirlo in self-custody utilizzando\",\n \"Website\": \"Sito web\",\n \"Website URL\": \"URL del sito web\",\n \"Website URL must start with https://\": \"L'URL del sito web deve iniziare con https://\",\n \"What is B3TR?\": \"Cos'è B3TR?\",\n \"What is Privy?\": \"Cos'è Privy?\",\n \"What is VET?\": \"Che cos'è VET?\",\n \"What is VTHO?\": \"Che cos'è VTHO?\",\n \"What is VeBetterDAO?\": \"Che cos'è VeBetterDAO?\",\n \"What is VeChain?\": \"Che cos'è VeChain?\",\n \"What is a Smart Account?\": \"Cos'è un Account Smart?\",\n \"What is a domain name?\": \"Cos'è un nome di dominio?\",\n \"What is a network?\": \"Che cos'è una rete?\",\n \"What is a wallet?\": \"Che cos'è un portafoglio?\",\n \"What is an x2earn application?\": \"Cos'è un'applicazione x2earn?\",\n \"What is fee delegation?\": \"Che cos'è la delega delle commissioni?\",\n \"When you have accepted a policy, it will appear here\": \"Quando avrai accettato una politica, apparirà qui\",\n \"When you have notifications, they will appear here\": \"Quando hai notifiche, appariranno qui\",\n \"YOU OWN THIS\": \"QUESTO È TUO\",\n \"You accepted current policy on {{date}}\": \"Hai accettato la politica corrente il {{date}}\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"Stai usando un Portafoglio Integrato protetto dal tuo metodo di accesso sociale, garantendo un'esperienza VeChain senza interruzioni.\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"Puoi inviare token cliccando sull'icona di invio nella sezione Azioni Rapide. Inserisci l'indirizzo del destinatario o il nome di dominio VeChain, seleziona il token e specifica l'importo che desideri inviare.\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"Non hai nessun token gas abilitato. Abilita almeno un token gas nelle Preferenze Token Gas.\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"Hai un account smart attivo associato a questo wallet. È stato impostato come la tua identità principale.\",\n \"You may want to try establishing the connection again.\": \"Potresti voler provare a stabilire nuovamente la connessione.\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"Devi abilitare almeno un token per eseguire transazioni. Senza alcun token abilitato, non potrai pagare le commissioni di gas.\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"Il tuo account è stato aggiornato con successo all'ultima versione. Ora puoi godere di un'esperienza utente migliorata, costi del gas ridotti e maggiore sicurezza.\",\n \"Your address has been successfully set to {{name}}\": \"Il tuo indirizzo è stato impostato correttamente su {{name}}\",\n \"Your changes have been saved successfully.\": \"Le tue modifiche sono state salvate con successo.\",\n \"Your domain has been unset successfully.\": \"Il tuo dominio è stato rimosso con successo.\",\n \"Your embedded wallet\": \"Il tuo portafoglio integrato\",\n \"Your existing domains\": \"I tuoi domini esistenti\",\n \"Your smart account is already upgraded to this version.\": \"Il tuo account smart è già stato aggiornato a questa versione.\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"Il tuo account smart deve essere aggiornato all'ultima versione (v3).\",\n \"Your tokens\": \"I tuoi token\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"La sicurezza del tuo portafoglio dipende da come vi accedi. Con opzioni di autocustodia come l'estensione VeWorld, l'app mobile o il portafoglio hardware, hai il controllo completo sulle tue chiavi private. Questa estensione stessa non ha accesso alle tue chiavi private. Quando accedi con i social account o VeChain, il tuo portafoglio viene creato e protetto da Privy e gestito da VeChain, offrendo un'esperienza di onboarding più semplice mantenendo la sicurezza.\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"qui\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"tariffa\",\n \"to learn more about embedded wallets.\": \"per saperne di più sui portafogli integrati.\",\n \"unavailable\": \"non disponibile\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"your@email.com\"\n}","{\n \" and \": \" et \",\n \"'{{policyName}}' on connect\": \"'{{policyName}}' lors de la connexion\",\n \"'{{policyName}}' on {{date}}\": \"'{{policyName}}' le {{date}}\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>Votre vie privée compte.</bold> Vous gardez le contrôle, acceptez d’activer des fonctionnalités optionnelles comme les cookies qui nous aident à améliorer votre expérience.\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \"Un domaine .vet est requis pour personnaliser votre profil. Choisissez un nom de compte pour commencer.\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"Un compte intelligent est un portefeuille de contrat intelligent offrant une sécurité et des fonctionnalités améliorées. Il permet des fonctionnalités telles que la récupération sociale, le regroupement de transactions, et plus encore.\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"Un nom de domaine est une sorte de surnom pour votre adresse de portefeuille. Il vous permet d'identifier facilement votre portefeuille et d'interagir avec des dApps en utilisant un nom lisible par l'homme. Par exemple, si votre adresse de portefeuille est 0x1234567890, votre surnom pourrait être \\\"alice.vechain\\\".\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"Un réseau dans la blockchain se réfère à l'environnement où les transactions ont lieu. VeChain dispose de deux réseaux principaux : Mainnet (le réseau actif où les transactions réelles se produisent) et Testnet (un environnement de test pour les développeurs). Le réseau auquel vous êtes connecté est affiché en haut de cette fenêtre modale.\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"Une nouvelle mise à niveau est disponible pour votre compte intelligent. Veuillez vous rendre dans la section 'Accès et Sécurité' pour le mettre à niveau.\",\n \"A new version is available for your account\": \"Une nouvelle version est disponible pour votre compte\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"Un portefeuille est votre passerelle vers la blockchain VeChain. Il stocke vos clés privées et vous permet de gérer en toute sécurité vos actifs numériques, d'envoyer et de recevoir des tokens, et d'interagir avec des applications décentralisées. Considérez-le comme votre compte bancaire numérique pour les transactions blockchain.\",\n \"AVAILABLE\": \"DISPONIBLE\",\n \"Accept\": \"Accepter\",\n \"Accept all\": \"Tout accepter\",\n \"Accept selected\": \"Accepter la sélection\",\n \"Access and security\": \"Accès et sécurité\",\n \"Account Upgrade Required\": \"Mise à niveau du compte requise\",\n \"Account already upgraded\": \"Compte déjà mis à niveau\",\n \"Account upgrade required\": \"Mise à niveau du compte requise\",\n \"Active\": \"Actif\",\n \"Active Wallet\": \"Portefeuille actif\",\n \"Add Login Method\": \"Ajouter une méthode de connexion\",\n \"Add New Wallet\": \"Ajouter un nouveau portefeuille\",\n \"Add Token\": \"Ajouter un jeton\",\n \"Add to shortcuts\": \"Ajouter aux raccourcis\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"Ajouter plus de comptes liés augmente la sécurité contre la perte d'accès, mais introduit également des vecteurs d'attaque potentiels supplémentaires. Pour une sécurité accrue, nous vous recommandons d'activer l'authentification multifacteur (MFA).\",\n \"Address is required\": \"L'adresse est requise\",\n \"All\": \"Tout\",\n \"All apps\": \"Toutes les applications\",\n \"All policies you have accepted\": \"Toutes les politiques que vous avez acceptées\",\n \"All tokens\": \"Tous les jetons\",\n \"Already have an x2earn app wallet?\": \"Vous avez déjà un portefeuille d'application x2earn ?\",\n \"Amount\": \"Montant\",\n \"Amount is required\": \"Le montant est requis\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"Une application X2Earn dans VeBetterDAO est une application durable qui récompense les utilisateurs avec des tokens B3TR pour des actions écologiques. Ces applications doivent distribuer B3TR, lier les portefeuilles utilisateurs et fournir une preuve des actions durables. Elles rejoignent VeBetterDAO par recommandation et participent à des rondes d’allocation de tokens hebdomadaires.\",\n \"An unexpected error occurred.\": \"Une erreur inattendue est survenue.\",\n \"Apple\": \"Apple\",\n \"Apply\": \"Appliquer\",\n \"Archived\": \"Archivé\",\n \"Archived Notifications\": \"Notifications archivées\",\n \"Are you sure you want to disconnect your wallet?\": \"Êtes-vous sûr de vouloir déconnecter votre portefeuille ?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"Êtes-vous sûr de vouloir rejeter les politiques et vous déconnecter ?\",\n \"Are you sure you want to remove this wallet?\": \"Êtes-vous sûr de vouloir supprimer ce portefeuille ?\",\n \"Are you sure you want to set your domain name to\": \"Êtes-vous sûr de vouloir définir votre nom de domaine sur\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"Êtes-vous sûr de vouloir dissocier {{accountType}} en tant que méthode de connexion liée à {{accountDescription}} ?\",\n \"Are you sure you want to unset your current domain?\": \"Êtes-vous sûr de vouloir désélectionner votre domaine actuel ?\",\n \"Assets\": \"Actifs\",\n \"At\": \"À\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TR est le token incitatif de VeBetterDAO, construit sur la blockchain VechainThor. Il a un approvisionnement limité à 1 milliard de tokens, émis de façon hebdomadaire sur 12 ans. B3TR est utilisé pour les récompenses, la gouvernance et pour soutenir les tokens VOT3 à un taux de 1:1. Il soutient les applications de durabilité et la gestion de la trésorerie DAO.\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"Sauvegarder votre portefeuille est crucial puisque vous êtes le seul à avoir accès à vos clés privées. Si quelque chose ne va pas, avoir votre clé privée est le seul moyen de récupérer vos actifs. La façon de sauvegarder dépend de la manière dont vous accédez à votre portefeuille : si vous utilisez VeWorld, l'option de sauvegarde est disponible dans l'application. Pour les utilisateurs de connexion sociale, vous trouverez les options de sauvegarde dans la section Portefeuille. Si vous êtes connecté via VeChain ou une autre application de l'écosystème, vous devrez visiter le site web d'origine, vous connecter et accéder à la section Portefeuille à partir de là.\",\n \"Backup\": \"Sauvegarder\",\n \"Backup your wallet\": \"Sauvegardez votre portefeuille\",\n \"Backup your wallet, configure MFA and set recovery options\": \"Sauvegardez votre portefeuille, configurez l'authentification multi-facteurs et définissez les options de récupération\",\n \"Balance\": \"Solde\",\n \"Benefits of this upgrade:\": \"Avantages de cette mise à niveau :\",\n \"Best\": \"Meilleur\",\n \"Better transaction handling\": \"Meilleure gestion des transactions\",\n \"Bridge\": \"Pont\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"En confirmant, les informations suivantes associées à votre nom ({{domain}}) seront mises à jour\",\n \"By confirming, your address will be set to {{domain}}\": \"En confirmant, votre adresse sera définie sur {{domain}}\",\n \"By confirming, your current domain will be unset\": \"En confirmant, votre domaine actuel sera désactivé\",\n \"By continuing, you agree to\": \"En continuant, vous acceptez\",\n \"Cancel\": \"Annuler\",\n \"Checking...\": \"Vérification...\",\n \"Choose Name\": \"Choisir le nom\",\n \"Choose a name for your account.\": \"Choisissez un nom pour votre compte.\",\n \"Choose a unique .vet domain name for your account.\": \"Choisissez un nom de domaine .vet unique pour votre compte.\",\n \"Choose account name\": \"Choisir le nom du compte\",\n \"Choose name\": \"Choisir un nom\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"Choisissez quels jetons utiliser pour les frais de transaction lorsque l’application ne les prend pas en charge.\",\n \"Choose your account name\": \"Choisissez le nom de votre compte\",\n \"Claim your vet domain!\": \"Réclamez votre domaine vet !\",\n \"Claiming name...\": \"Réclamation du nom...\",\n \"Clear all\": \"Tout effacer\",\n \"Cleared notifications will appear here\": \"Les notifications effacées apparaîtront ici\",\n \"Click\": \"Cliquez\",\n \"Click below to access {{ name }} and explore its features.\": \"Cliquez ci-dessous pour accéder à {{ name }} et explorer ses fonctionnalités.\",\n \"Close\": \"Fermer\",\n \"Close and do this later\": \"Fermer et faire ceci plus tard\",\n \"Close announcement\": \"Fermer l'annonce\",\n \"Coming Soon!\": \"Bientôt disponible !\",\n \"Coming soon\": \"Bientôt disponible\",\n \"Confirm\": \"Confirmer\",\n \"Confirm Changes\": \"Confirmer les modifications\",\n \"Confirm Name\": \"Confirmer le nom\",\n \"Confirm Unset Domain\": \"Confirmer la désélection du domaine\",\n \"Confirm the transaction in your wallet to complete it.\": \"Confirmez la transaction dans votre portefeuille pour la terminer.\",\n \"Confirm transaction\": \"Confirmer la transaction\",\n \"Connect an external wallet for easier access\": \"Connectez un portefeuille externe pour un accès plus facile\",\n \"Connect wallet\": \"Connecter le portefeuille\",\n \"Connect with VeWorld wallet\": \"Connectez-vous avec le portefeuille VeWorld\",\n \"Connect your Apple account for easier access\": \"Connectez votre compte Apple pour un accès plus facile\",\n \"Connect your Discord account for easier access\": \"Connectez votre compte Discord pour un accès plus facile\",\n \"Connect your Farcaster account for easier access\": \"Connectez votre compte Farcaster pour un accès plus facile\",\n \"Connect your Github account for easier access\": \"Connectez votre compte Github pour un accès plus facile\",\n \"Connect your Google account for easier access\": \"Connectez votre compte Google pour un accès plus facile\",\n \"Connect your Instagram account for easier access\": \"Connectez votre compte Instagram pour un accès plus facile\",\n \"Connect your LinkedIn account for easier access\": \"Connectez votre compte LinkedIn pour un accès plus facile\",\n \"Connect your Spotify account for easier access\": \"Connectez votre compte Spotify pour un accès plus facile\",\n \"Connect your Telegram account for easier access\": \"Connectez votre compte Telegram pour un accès plus facile\",\n \"Connect your Tiktok account for easier access\": \"Connectez votre compte Tiktok pour un accès plus facile\",\n \"Connect your Twitter account for easier access\": \"Connectez votre compte Twitter pour un accès plus facile\",\n \"Connect your email for easier access\": \"Connectez votre email pour un accès facilité\",\n \"Connect your phone number for easier access\": \"Connectez votre numéro de téléphone pour un accès facilité\",\n \"Connecting to VeChain\": \"Connexion à VeChain\",\n \"Connecting with\": \"Connexion avec\",\n \"Connecting with Passkey\": \"Connexion avec Passkey\",\n \"Connecting...\": \"Connexion...\",\n \"Connection Details\": \"Détails de la connexion\",\n \"Connection Failed\": \"Échec de la connexion\",\n \"Connection Type\": \"Type de connexion\",\n \"Connection details\": \"Détails de la connexion\",\n \"Continue\": \"Continuer\",\n \"Continue with Github\": \"Continuer avec Github\",\n \"Continue with Google\": \"Continuer avec Google\",\n \"Cookie Policy\": \"Politique de cookies\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"Politique de cookies décrivant l'utilisation des cookies et des technologies de suivi.\",\n \"Copied!\": \"Copié !\",\n \"Copy your address or scan this QR code\": \"Copiez votre adresse ou scannez ce code QR\",\n \"Currency\": \"Devise\",\n \"Current\": \"Actuel\",\n \"Current domain\": \"Domaine actuel\",\n \"Customization\": \"Personnalisation\",\n \"Customize\": \"Personnaliser\",\n \"Customize profile\": \"Personnaliser le profil\",\n \"Customize the appearance of your wallet.\": \"Personnalisez l'apparence de votre portefeuille.\",\n \"Description\": \"Description\",\n \"Description must be less than 100 characters\": \"La description doit comporter moins de 100 caractères\",\n \"Didn't get an email?\": \"Vous n'avez pas reçu d'e-mail ?\",\n \"Discord\": \"Discord\",\n \"Display Name\": \"Nom affiché\",\n \"Display name must be less than 25 characters\": \"Le nom affiché doit comporter moins de 25 caractères\",\n \"Domain set\": \"Domaine défini\",\n \"Domain unset\": \"Domaine désélectionné\",\n \"Done\": \"Fait\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"Faites glisser pour réorganiser. Le système utilisera automatiquement le jeton de priorité la plus élevée avec un solde suffisant.\",\n \"Ecosystem\": \"Écosystème\",\n \"Eg: DevRel @ ENS Labs\": \"Ex : DevRel @ ENS Labs\",\n \"Email\": \"Email\",\n \"Email address\": \"Adresse électronique\",\n \"Embedded wallet\": \"Portefeuille intégré\",\n \"Enhanced compatibility with dApps\": \"Compatibilité améliorée avec les dApps\",\n \"Enter confirmation code\": \"Entrez le code de confirmation\",\n \"Enter your display name\": \"Entrez votre nom affiché\",\n \"Enter your name\": \"Entrez votre nom\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"Échangez vos actifs numériques entre VeChain et d'autres réseaux blockchain facilement et en toute sécurité. Les échanges sont effectués par des partenaires qui utilisent à la fois des échanges décentralisés et centralisés pour convertir les jetons.\",\n \"Existing Custom Tokens\": \"Jetons personnalisés existants\",\n \"Explore ecosystem\": \"Explorer l’écosystème\",\n \"Failed to connect with Passkey\": \"Échec de la connexion avec Passkey\",\n \"Failed to connect with VeChain\": \"Échec de la connexion avec VeChain\",\n \"Failed to connect with ecosystem app\": \"Échec de la connexion avec l'application écosystème\",\n \"Failed to load App Hub apps\": \"Échec du chargement des applications App Hub\",\n \"Farcaster\": \"Farcaster\",\n \"Fee\": \"Frais\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"La délégation de frais est une fonctionnalité unique de VeChain qui permet à quelqu'un d'autre (un délégataire) de payer vos frais de transaction. Bien que de nombreuses dApps et prestataires de services agissent en tant que délégataires pour faciliter le démarrage des nouveaux utilisateurs, certaines transactions peuvent encore nécessiter que vous payiez des frais en utilisant votre propre VTHO. Les frais sont nécessaires pour prévenir le spam sur le réseau et pour rémunérer les nœuds qui traitent et valident les transactions sur la blockchain. Lorsque vous payez vous-même les frais, vous pourrez sélectionner VTHO parmi vos actifs pour couvrir le coût de la transaction.\",\n \"Fee token\": \"Jeton de frais\",\n \"Filter by category\": \"Filtrer par catégorie\",\n \"Finally say goodbye to 0x addresses\": \"Enfin, dites adieu aux adresses 0x\",\n \"For developers\": \"Pour les développeurs\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"Pour des raisons de sécurité, vous pouvez gérer les paramètres de votre portefeuille intégré uniquement sur la plateforme {{appName}}.\",\n \"Found following rates\": \"Taux suivants trouvés\",\n \"Frequently asked questions\": \"Foire aux questions\",\n \"From\": \"De\",\n \"Gas Token Preferences\": \"Préférences de jetons de gaz\",\n \"Gas fee\": \"Frais de gaz\",\n \"General\": \"Général\",\n \"Github\": \"Github\",\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.\": \"Bonne nouvelle ! Les transactions multiclause sont désormais entièrement prises en charge pour les comptes intelligents. Vous pouvez désormais profiter d'une meilleure expérience utilisateur, de frais de gaz réduits et d'une sécurité renforcée.\",\n \"Google\": \"Google\",\n \"Help\": \"Aide\",\n \"Hide\": \"Masquer\",\n \"How do I backup my wallet?\": \"Comment sauvegarder mon portefeuille ?\",\n \"How do I send tokens?\": \"Comment envoyer des jetons ?\",\n \"How is my wallet secured?\": \"Comment mon portefeuille est-il sécurisé ?\",\n \"I have read and agree to \": \"J'ai lu et j'accepte \",\n \"Ignore and continue\": \"Ignorer et continuer\",\n \"Improved security features\": \"Fonctionnalités de sécurité améliorées\",\n \"Instagram\": \"Instagram\",\n \"Insufficient balance\": \"Solde insuffisant\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"Solde insuffisant pour réclamer ce domaine et couvrir les frais de gaz.\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"Solde insuffisant pour finaliser cette transaction et couvrir les frais de gaz.\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"Solde insuffisant pour effectuer ce transfert et couvrir les frais de gaz.\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"Solde insuffisant pour mettre à jour votre profil et couvrir les frais de gaz.\",\n \"Insufficient {{symbol}} balance\": \"Solde {{symbol}} insuffisant\",\n \"Invalid address or domain\": \"Adresse ou domaine invalide\",\n \"Invalid contract address\": \"Adresse de contrat invalide\",\n \"Invalid token address\": \"Adresse de jeton invalide\",\n \"Language\": \"Langue\",\n \"Launch vechain.energy\": \"Lancer vechain.energy\",\n \"Launch {{name}}\": \"Lancer {{name}}\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"Accord juridique entre vous, Vechain Kit et l'application actuelle, décrivant les règles d'utilisation des services de portefeuille.\",\n \"Link Apple Account\": \"Lier le compte Apple\",\n \"Link Discord Account\": \"Lier le compte Discord\",\n \"Link Email Account\": \"Lier le compte Email\",\n \"Link External Wallet\": \"Lier un portefeuille externe\",\n \"Link Farcaster Account\": \"Lier le compte Farcaster\",\n \"Link Github Account\": \"Lier le compte Github\",\n \"Link Google Account\": \"Lier le compte Google\",\n \"Link Instagram Account\": \"Lier le compte Instagram\",\n \"Link LinkedIn Account\": \"Lier le compte LinkedIn\",\n \"Link Phone Number\": \"Lier le numéro de téléphone\",\n \"Link Spotify Account\": \"Lier le compte Spotify\",\n \"Link Telegram Account\": \"Lier le compte Telegram\",\n \"Link Tiktok Account\": \"Lier le compte Tiktok\",\n \"Link Twitter Account\": \"Lier le compte Twitter\",\n \"LinkedIn\": \"LinkedIn\",\n \"Loading quote...\": \"Chargement du devis...\",\n \"Loading your domains...\": \"Chargement de vos domaines...\",\n \"Loading...\": \"Chargement...\",\n \"Log in or sign up\": \"Connexion ou inscription\",\n \"Logged in with\": \"Connecté avec\",\n \"Login\": \"Connexion\",\n \"Login failed:\": \"Échec de la connexion :\",\n \"Login methods\": \"Méthodes de connexion\",\n \"Login methods and Passkeys\": \"Méthodes de connexion et clés d'accès\",\n \"Logout\": \"Déconnexion\",\n \"Manage Custom Tokens\": \"Gérer les jetons personnalisés\",\n \"Manage MFA\": \"Gérer la MFA\",\n \"Manage Recovery\": \"Gérer la récupération\",\n \"Manage on {{appName}}\": \"Gérer sur {{appName}}\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"Gérez les paramètres de sécurité de votre portefeuille intégré : gérez vos méthodes de connexion, ajoutez une clé d'accès ou sauvegardez votre portefeuille pour ne jamais perdre l'accès à vos actifs.\",\n \"Manage your login methods and passkeys\": \"Gérez vos méthodes de connexion et clés d'accès\",\n \"Manage your preferences for currency, language, and appearance.\": \"Gérez vos préférences de devise, de langue et d'apparence.\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"Le transfert minimum {{symbol}} est {{min}}\",\n \"More\": \"Plus\",\n \"Multiclause Transactions Are Now Supported\": \"Les transactions multiclause sont désormais prises en charge\",\n \"Name must be at least 3 characters long\": \"Le nom doit comporter au moins 3 caractères\",\n \"Name your account to make it easier to exchange assets\": \"Nommez votre compte pour faciliter l'échange d'actifs\",\n \"Network\": \"Réseau\",\n \"New\": \"Nouveau\",\n \"New image selected\": \"Nouvelle image sélectionnée\",\n \"No additional accounts available to link\": \"Aucun compte supplémentaire disponible à lier\",\n \"No application from VeChain ecosystem is available to login.\": \"Aucune application de l'écosystème VeChain n'est disponible pour se connecter.\",\n \"No apps found in this category\": \"Aucune application trouvée dans cette catégorie\",\n \"No archived notifications\": \"Aucune notification archivée\",\n \"No assets\": \"Aucun actif\",\n \"No notifications\": \"Aucune notification\",\n \"No policies accepted\": \"Aucune politique acceptée\",\n \"No questions found\": \"Aucune question trouvée\",\n \"No quotes available\": \"Aucun prix disponible\",\n \"No tokens found\": \"Aucun jeton trouvé\",\n \"Node URL\": \"URL du nœud\",\n \"Notifications\": \"Notifications\",\n \"Only letters, numbers, and hyphens are allowed\": \"Seules les lettres, les chiffres et les tirets sont autorisés\",\n \"Optional\": \"Facultatif\",\n \"Other Wallets\": \"Autres portefeuilles\",\n \"Other options\": \"Autres options\",\n \"Passkey\": \"Clé de passe\",\n \"Phone Number\": \"Numéro de téléphone\",\n \"Please approve the request in the connection request window...\": \"Veuillez approuver la demande dans la fenêtre de demande de connexion...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"Veuillez vous assurer que ce portefeuille est en sécurité et sauvegardé.\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"Veuillez vérifier {{email}} pour un email de privy.io et entrez votre code ci-dessous.\",\n \"Please complete the passkey authentication...\": \"Veuillez compléter l'authentification par clé de passe...\",\n \"Please confirm the transaction in your wallet.\": \"Veuillez confirmer la transaction dans votre portefeuille.\",\n \"Please enter a valid Twitter handle without @\": \"Veuillez entrer un identifiant Twitter valide sans @\",\n \"Please enter a valid contract address\": \"Veuillez entrer une adresse de contrat valide\",\n \"Please enter a valid email address\": \"Veuillez entrer une adresse e-mail valide\",\n \"Please enter a valid number\": \"Veuillez entrer un numéro valide\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"Veuillez prendre un moment pour examiner toutes les politiques, l'acceptation étant obligatoire pour continuer.\",\n \"Policy\": \"Politique\",\n \"Preparing changes...\": \"Préparation des modifications...\",\n \"Privacy Policy\": \"Politique de confidentialité\",\n \"Privacy policy outlining the data collection and processing practices.\": \"Politique de confidentialité décrivant les pratiques de collecte et de traitement des données.\",\n \"Privy Status\": \"Statut Privy\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy construit l'infrastructure d'intégration des utilisateurs et de portefeuilles intégrés pour permettre de meilleurs produits construits sur les rails crypto. Cela signifie intégrer le contrôle des actifs au sein même des applications pour permettre aux utilisateurs, entreprises ou machines de gérer des actifs numériques via des expériences produits fluides.\",\n \"Processing transaction...\": \"Traitement de la transaction...\",\n \"Profile\": \"Profil\",\n \"Profile Image\": \"Image de profil\",\n \"Profile Picture\": \"Image de profil\",\n \"Profile Updated\": \"Profil mis à jour\",\n \"Read More\": \"Read More\",\n \"Receive\": \"Recevoir\",\n \"Receive tokens\": \"Recevoir des jetons\",\n \"Reduced gas costs for operations\": \"Réduction des coûts de gaz pour les opérations\",\n \"Reject and logout\": \"Rejeter et se déconnecter\",\n \"Remove\": \"Supprimer\",\n \"Remove Login Method\": \"Supprimer la méthode de connexion\",\n \"Remove Wallet\": \"Supprimer le portefeuille\",\n \"Remove from shortcuts\": \"Retirer des raccourcis\",\n \"Remove wallet\": \"Supprimer le portefeuille\",\n \"Remove your current domain name\": \"Supprimer votre nom de domaine actuel\",\n \"Resend code\": \"Renvoyer le code\",\n \"Retry\": \"Réessayer\",\n \"Save Changes\": \"Enregistrer les modifications\",\n \"Saving changes...\": \"Enregistrement des modifications...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"Dites adieu aux adresses 0x, réclamez dès maintenant votre sous-domaine .veworld.vet gratuitement!\",\n \"Search Apps\": \"Rechercher des applications\",\n \"Search FAQ\": \"Rechercher dans la FAQ\",\n \"Security preferences\": \"Préférences de sécurité\",\n \"Security settings\": \"Paramètres de sécurité\",\n \"Select Additional Login Method\": \"Sélectionner une méthode de connexion supplémentaire\",\n \"Select Token\": \"Sélectionner un jeton\",\n \"Select Wallet\": \"Sélectionner un portefeuille\",\n \"Select currency\": \"Sélectionner la devise\",\n \"Select language\": \"Sélectionner la langue\",\n \"Select the token to pay the fee with\": \"Sélectionnez le jeton pour payer les frais\",\n \"Select token\": \"Sélectionner un jeton\",\n \"Send\": \"Envoyer\",\n \"Send all\": \"Tout envoyer\",\n \"Sending Transaction...\": \"Envoi de la transaction...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"Envoyer à OceanX ou à d'autres échanges peut entraîner une perte de fonds.\",\n \"Sending...\": \"Envoi...\",\n \"Set a domain first\": \"Définissez d'abord un domaine\",\n \"Set up Passkey\": \"Configurer une clé d'accès\",\n \"Set up a passkey for easier access\": \"Configurer une clé d'accès pour un accès plus facile\",\n \"Settings\": \"Paramètres\",\n \"Share on\": \"Partager sur\",\n \"Shortcuts\": \"Raccourcis\",\n \"Show Advanced Options\": \"Afficher les options avancées\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"Afficher plus\",\n \"Slippage tolerance\": \"Tolérance au slippage\",\n \"Smart Account\": \"Compte intelligent\",\n \"Smart Account detected\": \"Compte intelligent détecté\",\n \"Something went wrong\": \"Quelque chose a mal tourné\",\n \"Something went wrong. Please try again.\": \"Un problème est survenu. Veuillez réessayer.\",\n \"Source\": \"Source\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"Restez à l'écoute pour notre prochaine fonctionnalité Activité\",\n \"Stay tuned for our upcoming NFT feature\": \"Restez à l'écoute pour notre prochaine fonctionnalité NFT\",\n \"Submit\": \"Soumettre\",\n \"Swap\": \"Échanger\",\n \"Swap all\": \"Tout échanger\",\n \"Swapping...\": \"Échange en cours...\",\n \"Switch\": \"Changer\",\n \"Account Changed\": \"Compte modifié\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"Conditions générales\",\n \"Terms and Policies\": \"Conditions et politiques\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"Ces comptes sont liés à votre portefeuille intégré et peuvent être utilisés pour se connecter à votre portefeuille et accéder à votre clé privée.\",\n \"This address only supports VeChain assets.\": \"Cette adresse ne prend en charge que les actifs VeChain.\",\n \"This domain is already taken\": \"Ce domaine est déjà pris\",\n \"This domain is protected\": \"Ce domaine est protégé\",\n \"This is taking longer than expected.\": \"Cela prend plus de temps que prévu.\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"Ceci est votre portefeuille principal, créé par {{element}} et sécurisé par Privy.\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"Ce portefeuille est le propriétaire de votre compte intelligent, qui est utilisé comme votre identité et comme une passerelle pour vos interactions blockchain.\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"À\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"Pour continuer à interagir avec la blockchain VeChain et terminer votre opération, votre compte intelligent doit être mis à niveau vers la dernière version (v3).\",\n \"Token Contract Address\": \"Adresse du contrat du jeton\",\n \"Token Priority Order\": \"Ordre de priorité des jetons\",\n \"Token already added\": \"Jeton déjà ajouté\",\n \"Tools\": \"Outils\",\n \"Transaction failed\": \"La transaction a échoué\",\n \"Transaction failed:\": \"La transaction a échoué :\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"La transaction est en cours de traitement, cela peut prendre jusqu'à 15 secondes.\",\n \"Transaction successful\": \"Transaction réussie\",\n \"Transaction successful!\": \"Transaction réussie !\",\n \"Try again\": \"Réessayer\",\n \"Try searching with a different term\": \"Essayez de chercher avec un terme différent\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Nom d'utilisateur Twitter\",\n \"Type the receiver address or domain\": \"Tapez l'adresse du destinataire ou le domaine\",\n \"UNAVAILABLE\": \"INDISPONIBLE\",\n \"Unable to fetch the price\": \"Impossible de récupérer le prix\",\n \"Unset current domain\": \"Désélectionner le domaine actuel\",\n \"Unsetting current domain...\": \"Désélection du domaine actuel...\",\n \"Upgrade Smart Account to V3\": \"Mettre à niveau le compte intelligent vers V3\",\n \"Upgrade Successful!\": \"Mise à niveau réussie !\",\n \"Upgrade account\": \"Mettre à niveau le compte\",\n \"Upgrading...\": \"Mise à niveau...\",\n \"Use social login with VeChain\": \"Utiliser la connexion sociale avec VeChain\",\n \"Use this token for future transactions\": \"Utiliser ce jeton pour les transactions futures\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"Le VET est la cryptomonnaie principale du réseau VeChain. Il représente la valeur et la propriété dans l'écosystème VeChain, similaire à la façon dont les actions représentent la propriété dans une entreprise. Détenir du VET génère automatiquement du VTHO, nécessaire pour payer les transactions sur le réseau.\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"Le VTHO (VeThor) est le jeton d'énergie ou de 'gaz' du réseau VeChain. Il est utilisé pour payer les frais de transaction lors de l'interaction avec la blockchain. Le VTHO est automatiquement généré en détenant des jetons VET, créant un système à deux jetons qui aide à maintenir la stabilité du réseau et à gérer les coûts de transaction.\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAO est une organisation décentralisée sur la blockchain VeChain axée sur la durabilité. Les membres participent à la gouvernance du DAO en utilisant des jetons B3TR pour les récompenses et VOT3 pour voter sur les propositions et les cycles d'allocation de jetons hebdomadaires.\",\n \"VeChain Kit\": \"Kit VeChain\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"VeChain, dont le siège est à Saint-Marin, en Europe, est un écosystème blockchain pionnier et créateur de VeChainThor, une plateforme de contrats intelligents de classe mondiale favorisant l'adoption de la blockchain dans le monde réel. Fondée en 2015 par Sunny Lu, VeChain s'efforce constamment de fournir une solution blockchain transparente, efficace, évolutive et adaptable.\",\n \"VeWorld Wallet\": \"Portefeuille VeWorld\",\n \"Vechain Kit Policy\": \"Politique du kit Vechain\",\n \"View Current Policy\": \"Afficher la politique actuelle\",\n \"View on explorer\": \"Voir sur l'explorateur\",\n \"View transaction on the explorer\": \"Voir la transaction sur l'explorateur\",\n \"Waiting for confirmation\": \"En attente de confirmation\",\n \"Waiting for confirmation...\": \"En attente de confirmation...\",\n \"Waiting wallet confirmation...\": \"En attente de la confirmation du portefeuille...\",\n \"Wallet\": \"Portefeuille\",\n \"Wallet secured by\": \"Portefeuille sécurisé par\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"Nous vous recommandons vivement d'exporter votre clé privée pour sauvegarder votre portefeuille. Cela garantit que vous pouvez le restaurer si nécessaire ou le transférer en gestion autonome en utilisant\",\n \"Website\": \"Site web\",\n \"Website URL\": \"URL du site web\",\n \"Website URL must start with https://\": \"L'URL du site web doit commencer par https://\",\n \"What is B3TR?\": \"Qu'est-ce que le B3TR ?\",\n \"What is Privy?\": \"Qu'est-ce que Privy ?\",\n \"What is VET?\": \"Qu'est-ce que VET ?\",\n \"What is VTHO?\": \"Qu'est-ce que VTHO ?\",\n \"What is VeBetterDAO?\": \"Qu'est-ce que VeBetterDAO ?\",\n \"What is VeChain?\": \"Qu'est-ce que VeChain ?\",\n \"What is a Smart Account?\": \"Qu'est-ce qu'un Smart Account ?\",\n \"What is a domain name?\": \"Qu'est-ce qu'un nom de domaine ?\",\n \"What is a network?\": \"Qu'est-ce qu'un réseau ?\",\n \"What is a wallet?\": \"Qu'est-ce qu'un portefeuille ?\",\n \"What is an x2earn application?\": \"Qu'est-ce qu'une application x2earn ?\",\n \"What is fee delegation?\": \"Qu'est-ce que la délégation de frais ?\",\n \"When you have accepted a policy, it will appear here\": \"Lorsque vous avez accepté une politique, elle apparaîtra ici\",\n \"When you have notifications, they will appear here\": \"Lorsque vous avez des notifications, elles apparaîtront ici\",\n \"YOU OWN THIS\": \"VOUS POSSÉDEZ CECI\",\n \"You accepted current policy on {{date}}\": \"Vous avez accepté la politique actuelle le {{date}}\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"Vous utilisez un portefeuille intégré sécurisé par votre méthode de connexion sociale, garantissant une expérience VeChain fluide.\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"Vous pouvez envoyer des jetons en cliquant sur l'icône d'envoi dans la section Actions rapides. Entrez l'adresse du destinataire ou le nom de domaine VeChain, sélectionnez le jeton et spécifiez le montant que vous souhaitez envoyer.\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"Vous n'avez activé aucun jeton de gaz. Veuillez activer au moins un jeton de gaz dans les préférences des jetons de gaz.\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"Vous avez un compte intelligent actif associé à ce portefeuille. Il a été défini comme votre identité principale.\",\n \"You may want to try establishing the connection again.\": \"Vous voudrez peut-être essayer d'établir la connexion à nouveau.\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"Vous devez activer au moins un jeton pour effectuer des transactions. Sans aucun jeton activé, vous ne pourrez pas payer les frais de gaz.\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"Votre compte a été mis à niveau avec succès vers la dernière version. Vous pouvez désormais profiter d'une meilleure expérience utilisateur, de coûts de gaz réduits et d'une sécurité renforcée.\",\n \"Your address has been successfully set to {{name}}\": \"Votre adresse a été correctement définie sur {{name}}\",\n \"Your changes have been saved successfully.\": \"Vos modifications ont été enregistrées avec succès.\",\n \"Your domain has been unset successfully.\": \"Votre domaine a été désélectionné avec succès.\",\n \"Your embedded wallet\": \"Votre portefeuille intégré\",\n \"Your existing domains\": \"Vos domaines existants\",\n \"Your smart account is already upgraded to this version.\": \"Votre compte intelligent est déjà mis à jour vers cette version.\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"Votre compte intelligent doit être mis à niveau vers la dernière version (v3).\",\n \"Your tokens\": \"Vos jetons\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"La sécurité de votre portefeuille dépend de la façon dont vous y accédez. Avec des options d'auto-gardiennage comme l'extension VeWorld, l'application mobile ou le portefeuille matériel, vous avez un contrôle complet sur vos clés privées. Cette extension en elle-même n'a pas accès à vos clés privées. Lors de la connexion avec des comptes sociaux ou VeChain, votre portefeuille est créé et sécurisé par Privy et géré par VeChain, offrant une expérience d'intégration plus facile tout en maintenant la sécurité.\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"ici\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"taux\",\n \"to learn more about embedded wallets.\": \"pour en savoir plus sur les portefeuilles intégrés.\",\n \"unavailable\": \"indisponible\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"votre@email.com\"\n}","{\n \" and \": \" y \",\n \"'{{policyName}}' on connect\": \"'{{policyName}}' al conectarse\",\n \"'{{policyName}}' on {{date}}\": \"'{{policyName}}' el {{date}}\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>Tu privacidad importa.</bold> Tú tienes el control, acepta para habilitar funciones opcionales como cookies que nos ayudan a mejorar tu experiencia.\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \"Se requiere un dominio .vet para personalizar su perfil. Elija un nombre de cuenta para comenzar.\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"Una Cuenta Inteligente es una billetera de contrato inteligente que proporciona seguridad y funcionalidad mejoradas. Permite características como la recuperación social, el procesamiento por lotes de transacciones y más.\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"Un nombre de dominio es una especie de apodo para tu dirección de cartera. Te permite identificar fácilmente tu cartera e interactuar con aplicaciones descentralizadas utilizando un nombre legible por humanos. Por ejemplo, si tu dirección de cartera es 0x1234567890, tu apodo podría ser \\\"alice.vechain\\\".\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"Una red en blockchain se refiere al entorno donde ocurren las transacciones. VeChain tiene dos redes principales: Mainnet (la red en vivo donde ocurren transacciones reales) y Testnet (un entorno de prueba para desarrolladores). La red a la que estás conectado se muestra en la parte superior de este modal.\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"Hay una nueva actualización disponible para su cuenta inteligente. Por favor, diríjase a la sección 'Acceso y Seguridad' para actualizarlo.\",\n \"A new version is available for your account\": \"Una nueva versión está disponible para su cuenta\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"Una billetera es tu puerta de entrada a la blockchain de VeChain. Almacena tus claves privadas y te permite gestionar de manera segura tus activos digitales, enviar y recibir tokens, e interactuar con aplicaciones descentralizadas. Piensa en ella como tu cuenta bancaria digital para transacciones blockchain.\",\n \"AVAILABLE\": \"DISPONIBLE\",\n \"Accept\": \"Aceptar\",\n \"Accept all\": \"Aceptar todo\",\n \"Accept selected\": \"Aceptar seleccionado\",\n \"Access and security\": \"Acceso y seguridad\",\n \"Account Upgrade Required\": \"Actualización de cuenta necesaria\",\n \"Account already upgraded\": \"Cuenta ya actualizada\",\n \"Account upgrade required\": \"Actualización de cuenta requerida\",\n \"Active\": \"Activo\",\n \"Active Wallet\": \"Billetera Activa\",\n \"Add Login Method\": \"Agregar método de inicio de sesión\",\n \"Add New Wallet\": \"Agregar Nueva Billetera\",\n \"Add Token\": \"Agregar Token\",\n \"Add to shortcuts\": \"Agregar a accesos directos\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"Agregar más cuentas vinculadas aumenta la seguridad contra la pérdida de acceso, pero también introduce vectores de ataque adicionales potenciales. Para una mayor seguridad, recomendamos habilitar MFA.\",\n \"Address is required\": \"Se requiere dirección\",\n \"All\": \"Todo\",\n \"All apps\": \"Todas las aplicaciones\",\n \"All policies you have accepted\": \"Todas las políticas que has aceptado\",\n \"All tokens\": \"Todos los tokens\",\n \"Already have an x2earn app wallet?\": \"¿Ya tienes una billetera de aplicación x2earn?\",\n \"Amount\": \"Cantidad\",\n \"Amount is required\": \"Se requiere un monto\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"Una aplicación X2Earn en VeBetterDAO es una app sostenible que recompensa a los usuarios con tokens B3TR por acciones ecológicas. Estas aplicaciones deben distribuir B3TR, vincular las billeteras de los usuarios y proporcionar pruebas de acciones sostenibles. Se unen a VeBetterDAO a través de la recomendación y participan en rondas semanales de asignación de tokens.\",\n \"An unexpected error occurred.\": \"Ocurrió un error inesperado.\",\n \"Apple\": \"Apple\",\n \"Apply\": \"Aplicar\",\n \"Archived\": \"Archivado\",\n \"Archived Notifications\": \"Notificaciones archivadas\",\n \"Are you sure you want to disconnect your wallet?\": \"¿Estás seguro de que quieres desconectar tu billetera?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"¿Estás seguro de que deseas rechazar las políticas y desconectar?\",\n \"Are you sure you want to remove this wallet?\": \"¿Estás seguro de que deseas eliminar esta billetera?\",\n \"Are you sure you want to set your domain name to\": \"¿Estás seguro de que quieres establecer tu nombre de dominio en\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"¿Está seguro de que desea desvincular {{accountType}} como método de inicio de sesión vinculado a {{accountDescription}}?\",\n \"Are you sure you want to unset your current domain?\": \"¿Está seguro de que desea desactivar su dominio actual?\",\n \"Assets\": \"Activos\",\n \"At\": \"En\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TR es el token de incentivo de VeBetterDAO, construido sobre la blockchain VechainThor. Tiene un suministro limitado de 1 mil millones de tokens, emitidos semanalmente durante 12 años. B3TR se utiliza para recompensas, gobernanza y respaldar tokens VOT3 en una proporción de 1:1. Apoya aplicaciones sostenibles y la gestión del tesoro del DAO.\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"Respaldar tu billetera es crucial ya que eres el único con acceso a tus claves privadas. Si algo sale mal, tener tu clave privada es la única manera de recuperar tus activos. Cómo hacer un respaldo depende de cómo accedas a tu billetera: Si usas VeWorld, la opción de respaldo está disponible dentro de la aplicación. Para usuarios de inicio de sesión social, puedes encontrar opciones de respaldo en la sección Billetera. Si estás conectado a través de VeChain u otra aplicación del ecosistema, necesitarás visitar el sitio web original, iniciar sesión y acceder a la sección de Billetera desde allí.\",\n \"Backup\": \"Respaldo\",\n \"Backup your wallet\": \"Respalda tu billetera\",\n \"Backup your wallet, configure MFA and set recovery options\": \"Realiza una copia de seguridad de tu billetera, configura MFA y establece opciones de recuperación\",\n \"Balance\": \"Saldo\",\n \"Benefits of this upgrade:\": \"Beneficios de esta actualización:\",\n \"Best\": \"Mejor\",\n \"Better transaction handling\": \"Mejor manejo de transacciones\",\n \"Bridge\": \"Puente\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"Al confirmar, se actualizarán los siguientes detalles asociados a tu nombre ({{domain}})\",\n \"By confirming, your address will be set to {{domain}}\": \"Al confirmar, tu dirección se establecerá como {{domain}}\",\n \"By confirming, your current domain will be unset\": \"Al confirmar, tu dominio actual será desasignado\",\n \"By continuing, you agree to\": \"Al continuar, aceptas\",\n \"Cancel\": \"Cancelar\",\n \"Checking...\": \"Comprobando...\",\n \"Choose Name\": \"Elegir Nombre\",\n \"Choose a name for your account.\": \"Elija un nombre para su cuenta.\",\n \"Choose a unique .vet domain name for your account.\": \"Elige un nombre de dominio único .vet para tu cuenta.\",\n \"Choose account name\": \"Elige el nombre de la cuenta\",\n \"Choose name\": \"Elige nombre\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"Elige qué tokens usar para las comisiones de transacción cuando la aplicación no las cubra.\",\n \"Choose your account name\": \"Elige el nombre de tu cuenta\",\n \"Claim your vet domain!\": \"¡Reclama tu dominio vet!\",\n \"Claiming name...\": \"Reclamando nombre...\",\n \"Clear all\": \"Borrar todo\",\n \"Cleared notifications will appear here\": \"Las notificaciones borradas aparecerán aquí\",\n \"Click\": \"Haga clic\",\n \"Click below to access {{ name }} and explore its features.\": \"Haga clic abajo para acceder a {{ name }} y explorar sus características.\",\n \"Close\": \"Cerrar\",\n \"Close and do this later\": \"Cerrar y hacer esto después\",\n \"Close announcement\": \"Cerrar anuncio\",\n \"Coming Soon!\": \"¡Próximamente!\",\n \"Coming soon\": \"Próximamente\",\n \"Confirm\": \"Confirmar\",\n \"Confirm Changes\": \"Confirmar cambios\",\n \"Confirm Name\": \"Confirmar Nombre\",\n \"Confirm Unset Domain\": \"Confirmar desactivación de dominio\",\n \"Confirm the transaction in your wallet to complete it.\": \"Confirme la transacción en su monedero para completarla.\",\n \"Confirm transaction\": \"Confirmar transacción\",\n \"Connect an external wallet for easier access\": \"Conectar una billetera externa para un acceso más fácil\",\n \"Connect wallet\": \"Conectar billetera\",\n \"Connect with VeWorld wallet\": \"Conectar con la billetera VeWorld\",\n \"Connect your Apple account for easier access\": \"Conecta tu cuenta de Apple para un acceso más fácil\",\n \"Connect your Discord account for easier access\": \"Conecta tu cuenta de Discord para un acceso más fácil\",\n \"Connect your Farcaster account for easier access\": \"Conecta tu cuenta de Farcaster para un acceso más fácil\",\n \"Connect your Github account for easier access\": \"Conecta tu cuenta de Github para un acceso más fácil\",\n \"Connect your Google account for easier access\": \"Conecta tu cuenta de Google para un acceso más fácil\",\n \"Connect your Instagram account for easier access\": \"Conecta tu cuenta de Instagram para un acceso más fácil\",\n \"Connect your LinkedIn account for easier access\": \"Conecta tu cuenta de LinkedIn para un acceso más fácil\",\n \"Connect your Spotify account for easier access\": \"Conecta tu cuenta de Spotify para un acceso más fácil\",\n \"Connect your Telegram account for easier access\": \"Conecta tu cuenta de Telegram para un acceso más fácil\",\n \"Connect your Tiktok account for easier access\": \"Conecta tu cuenta de Tiktok para un acceso más fácil\",\n \"Connect your Twitter account for easier access\": \"Conecta tu cuenta de Twitter para un acceso más fácil\",\n \"Connect your email for easier access\": \"Conecta tu correo electrónico para un acceso más fácil\",\n \"Connect your phone number for easier access\": \"Conecta tu número de teléfono para un acceso más fácil\",\n \"Connecting to VeChain\": \"Conectando a VeChain\",\n \"Connecting with\": \"Conectando con\",\n \"Connecting with Passkey\": \"Conectando con Passkey\",\n \"Connecting...\": \"Conectando...\",\n \"Connection Details\": \"Detalles de la Conexión\",\n \"Connection Failed\": \"Conexión Fallida\",\n \"Connection Type\": \"Tipo de Conexión\",\n \"Connection details\": \"Detalles de conexión\",\n \"Continue\": \"Continuar\",\n \"Continue with Github\": \"Continuar con Github\",\n \"Continue with Google\": \"Continuar con Google\",\n \"Cookie Policy\": \"Política de Cookies\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"Política de cookies que describe el uso de cookies y tecnologías de seguimiento.\",\n \"Copied!\": \"¡Copiado!\",\n \"Copy your address or scan this QR code\": \"Copia tu dirección o escanea este código QR\",\n \"Currency\": \"Moneda\",\n \"Current\": \"Actual\",\n \"Current domain\": \"Dominio actual\",\n \"Customization\": \"Personalización\",\n \"Customize\": \"Personalizar\",\n \"Customize profile\": \"Personalizar perfil\",\n \"Customize the appearance of your wallet.\": \"Personaliza la apariencia de tu billetera.\",\n \"Description\": \"Descripción\",\n \"Description must be less than 100 characters\": \"La descripción debe tener menos de 100 caracteres\",\n \"Didn't get an email?\": \"¿No recibiste un correo electrónico?\",\n \"Discord\": \"Discord\",\n \"Display Name\": \"Nombre para mostrar\",\n \"Display name must be less than 25 characters\": \"El nombre para mostrar debe tener menos de 25 caracteres\",\n \"Domain set\": \"Dominio configurado\",\n \"Domain unset\": \"Dominio desactivado\",\n \"Done\": \"Hecho\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"Arrastra para reordenar. El sistema usará automáticamente el token de mayor prioridad con saldo suficiente.\",\n \"Ecosystem\": \"Ecosistema\",\n \"Eg: DevRel @ ENS Labs\": \"Ej: DevRel @ ENS Labs\",\n \"Email\": \"Correo Electrónico\",\n \"Email address\": \"Dirección de correo electrónico\",\n \"Embedded wallet\": \"Cartera integrada\",\n \"Enhanced compatibility with dApps\": \"Compatibilidad mejorada con dApps\",\n \"Enter confirmation code\": \"Introducir código de confirmación\",\n \"Enter your display name\": \"Introduce tu nombre para mostrar\",\n \"Enter your name\": \"Ingrese su nombre\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"Intercambia tus activos digitales entre VeChain y otras redes blockchain de manera fácil y segura. Los intercambios se ejecutan a través de socios que aprovechan tanto intercambios descentralizados como centralizados para convertir tokens.\",\n \"Existing Custom Tokens\": \"Tokens Personalizados Existentes\",\n \"Explore ecosystem\": \"Explorar ecosistema\",\n \"Failed to connect with Passkey\": \"Error al conectar con Passkey\",\n \"Failed to connect with VeChain\": \"Error al conectar con VeChain\",\n \"Failed to connect with ecosystem app\": \"Error al conectar con la aplicación del ecosistema\",\n \"Failed to load App Hub apps\": \"Error al cargar aplicaciones de App Hub\",\n \"Farcaster\": \"Farcaster\",\n \"Fee\": \"Comisión\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"La delegación de tarifas es una función única de VeChain que permite que otra persona (un delegado) pague las tarifas de tus transacciones. Aunque muchas aplicaciones descentralizadas (dApps) y proveedores de servicios actúan como delegados para facilitar a los nuevos usuarios el comienzo, es posible que algunas transacciones aún requieran que pagues tarifas usando tu propio VTHO. Las tarifas son necesarias para prevenir el spam en la red y compensar a los nodos que procesan y validan las transacciones en la cadena de bloques. Al pagar las tarifas tú mismo, podrás seleccionar VTHO de tus activos para cubrir el costo de la transacción.\",\n \"Fee token\": \"Token de comisión\",\n \"Filter by category\": \"Filtrar por categoría\",\n \"Finally say goodbye to 0x addresses\": \"Finalmente di adiós a las direcciones 0x\",\n \"For developers\": \"Para desarrolladores\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"Por razones de seguridad, puedes gestionar la configuración de tu billetera integrada solo en la plataforma {{appName}}.\",\n \"Found following rates\": \"Se encontraron las siguientes tasas\",\n \"Frequently asked questions\": \"Preguntas frecuentes\",\n \"From\": \"De\",\n \"Gas Token Preferences\": \"Preferencias de tokens de gas\",\n \"Gas fee\": \"Tarifa de gas\",\n \"General\": \"General\",\n \"Github\": \"Github\",\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.\": \"¡Buenas noticias! Las transacciones multicláusula ahora son totalmente compatibles con las cuentas inteligentes. Ahora puedes disfrutar de una mejor experiencia de usuario, menores costos de gas y mayor seguridad.\",\n \"Google\": \"Google\",\n \"Help\": \"Ayuda\",\n \"Hide\": \"Ocultar\",\n \"How do I backup my wallet?\": \"¿Cómo hago una copia de seguridad de mi billetera?\",\n \"How do I send tokens?\": \"¿Cómo envío tokens?\",\n \"How is my wallet secured?\": \"¿Cómo está asegurada mi billetera?\",\n \"I have read and agree to \": \"He leído y acepto \",\n \"Ignore and continue\": \"Ignorar y continuar\",\n \"Improved security features\": \"Funciones de seguridad mejoradas\",\n \"Instagram\": \"Instagram\",\n \"Insufficient balance\": \"Saldo insuficiente\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"Saldo insuficiente para reclamar este dominio y cubrir las tarifas de gas.\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"Saldo insuficiente para completar esta transacción y cubrir las tarifas de gas.\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"Saldo insuficiente para completar esta transferencia y cubrir las tarifas de gas.\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"Saldo insuficiente para actualizar tu perfil y cubrir las tarifas de gas.\",\n \"Insufficient {{symbol}} balance\": \"Saldo insuficiente de {{symbol}}\",\n \"Invalid address or domain\": \"Dirección o dominio no válido\",\n \"Invalid contract address\": \"Dirección de contrato inválida\",\n \"Invalid token address\": \"Dirección de token no válida\",\n \"Language\": \"Idioma\",\n \"Launch vechain.energy\": \"Lanzar vechain.energy\",\n \"Launch {{name}}\": \"Lanzar {{name}}\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"Acuerdo legal entre tú, Vechain Kit y la aplicación actual, que describe las reglas para usar los servicios de billetera.\",\n \"Link Apple Account\": \"Vincular cuenta de Apple\",\n \"Link Discord Account\": \"Vincular Cuenta de Discord\",\n \"Link Email Account\": \"Vincular cuenta de correo electrónico\",\n \"Link External Wallet\": \"Vincular monedero externo\",\n \"Link Farcaster Account\": \"Vincular cuenta de Farcaster\",\n \"Link Github Account\": \"Vincular cuenta de Github\",\n \"Link Google Account\": \"Vincular cuenta de Google\",\n \"Link Instagram Account\": \"Vincular cuenta de Instagram\",\n \"Link LinkedIn Account\": \"Vincular cuenta de LinkedIn\",\n \"Link Phone Number\": \"Vincular número de teléfono\",\n \"Link Spotify Account\": \"Vincular cuenta de Spotify\",\n \"Link Telegram Account\": \"Vincular cuenta de Telegram\",\n \"Link Tiktok Account\": \"Vincular cuenta de Tiktok\",\n \"Link Twitter Account\": \"Vincular cuenta de Twitter\",\n \"LinkedIn\": \"LinkedIn\",\n \"Loading quote...\": \"Cargando cotización...\",\n \"Loading your domains...\": \"Cargando tus dominios...\",\n \"Loading...\": \"Cargando...\",\n \"Log in or sign up\": \"Iniciar sesión o registrarse\",\n \"Logged in with\": \"Conectado con\",\n \"Login\": \"Iniciar sesión\",\n \"Login failed:\": \"Error de inicio de sesión:\",\n \"Login methods\": \"Métodos de inicio de sesión\",\n \"Login methods and Passkeys\": \"Métodos de inicio de sesión y claves de acceso\",\n \"Logout\": \"Cerrar sesión\",\n \"Manage Custom Tokens\": \"Gestionar tokens personalizados\",\n \"Manage MFA\": \"Gestionar MFA\",\n \"Manage Recovery\": \"Gestionar la Recuperación\",\n \"Manage on {{appName}}\": \"Gestionar en {{appName}}\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"Administra la configuración de seguridad de tu billetera integrada: gestiona tus métodos de inicio de sesión, añade una clave de acceso o realiza una copia de seguridad de tu billetera para no perder nunca el acceso a tus activos.\",\n \"Manage your login methods and passkeys\": \"Gestiona tus métodos de inicio de sesión y claves de acceso\",\n \"Manage your preferences for currency, language, and appearance.\": \"Administra tus preferencias de moneda, idioma y apariencia.\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"La transferencia mínima de {{symbol}} es {{min}}\",\n \"More\": \"Más\",\n \"Multiclause Transactions Are Now Supported\": \"Las transacciones multicláusula ahora son compatibles\",\n \"Name must be at least 3 characters long\": \"El nombre debe tener al menos 3 caracteres\",\n \"Name your account to make it easier to exchange assets\": \"Nombra tu cuenta para facilitar el intercambio de activos\",\n \"Network\": \"Red\",\n \"New\": \"Nuevo\",\n \"New image selected\": \"Nueva imagen seleccionada\",\n \"No additional accounts available to link\": \"No hay cuentas adicionales disponibles para vincular\",\n \"No application from VeChain ecosystem is available to login.\": \"No hay ninguna aplicación del ecosistema VeChain disponible para iniciar sesión.\",\n \"No apps found in this category\": \"No se encontraron aplicaciones en esta categoría\",\n \"No archived notifications\": \"No hay notificaciones archivadas\",\n \"No assets\": \"Sin activos\",\n \"No notifications\": \"No hay notificaciones\",\n \"No policies accepted\": \"Ninguna política aceptada\",\n \"No questions found\": \"No se encontraron preguntas\",\n \"No quotes available\": \"No hay cotizaciones disponibles\",\n \"No tokens found\": \"No se encontraron fichas\",\n \"Node URL\": \"URL del nodo\",\n \"Notifications\": \"Notificaciones\",\n \"Only letters, numbers, and hyphens are allowed\": \"Solo se permiten letras, números y guiones\",\n \"Optional\": \"Opcional\",\n \"Other Wallets\": \"Otras Billeteras\",\n \"Other options\": \"Otras opciones\",\n \"Passkey\": \"Clave de acceso\",\n \"Phone Number\": \"Número de teléfono\",\n \"Please approve the request in the connection request window...\": \"Por favor, aprueba la solicitud en la ventana de solicitud de conexión...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"Por favor, asegúrese de mantener esta billetera segura y respaldada.\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"Por favor, revisa {{email}} para un correo electrónico de privy.io e ingresa tu código a continuación.\",\n \"Please complete the passkey authentication...\": \"Por favor, completa la autenticación de clave de acceso...\",\n \"Please confirm the transaction in your wallet.\": \"Por favor, confirma la transacción en tu billetera.\",\n \"Please enter a valid Twitter handle without @\": \"Por favor, ingrese un identificador de Twitter válido sin @\",\n \"Please enter a valid contract address\": \"Por favor, ingrese una dirección de contrato válida\",\n \"Please enter a valid email address\": \"Por favor, ingrese una dirección de correo electrónico válida\",\n \"Please enter a valid number\": \"Por favor, ingrese un número válido\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"Por favor, tómese un momento para revisar todas las políticas, siendo la aceptación obligatoria para continuar.\",\n \"Policy\": \"Política\",\n \"Preparing changes...\": \"Preparando cambios...\",\n \"Privacy Policy\": \"Política de privacidad\",\n \"Privacy policy outlining the data collection and processing practices.\": \"Política de privacidad que describe las prácticas de recopilación y procesamiento de datos.\",\n \"Privy Status\": \"Privy Status\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy construye la infraestructura de incorporación de usuarios y billetera incrustada para permitir mejores productos construidos sobre rieles de criptomonedas. Esto significa integrar el control de activos dentro de las aplicaciones mismas para permitir que usuarios, empresas o máquinas usen activos digitales a través de experiencias de producto fluidas.\",\n \"Processing transaction...\": \"Procesando transacción...\",\n \"Profile\": \"Perfil\",\n \"Profile Image\": \"Imagen de perfil\",\n \"Profile Picture\": \"Imagen de Perfil\",\n \"Profile Updated\": \"Perfil actualizado\",\n \"Read More\": \"Read More\",\n \"Receive\": \"Recibir\",\n \"Receive tokens\": \"Recibir tokens\",\n \"Reduced gas costs for operations\": \"Reducción de costos de gas para operaciones\",\n \"Reject and logout\": \"Rechazar y cerrar sesión\",\n \"Remove\": \"Eliminar\",\n \"Remove Login Method\": \"Eliminar método de inicio de sesión\",\n \"Remove Wallet\": \"Eliminar Billetera\",\n \"Remove from shortcuts\": \"Eliminar de los accesos directos\",\n \"Remove wallet\": \"Eliminar billetera\",\n \"Remove your current domain name\": \"Eliminar su nombre de dominio actual\",\n \"Resend code\": \"Reenviar código\",\n \"Retry\": \"Reintentar\",\n \"Save Changes\": \"Guardar cambios\",\n \"Saving changes...\": \"Guardando cambios...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"Despídete de las direcciones 0x, ¡reclama tu subdominio .veworld.vet ahora gratis!\",\n \"Search Apps\": \"Buscar aplicaciones\",\n \"Search FAQ\": \"Buscar en las preguntas frecuentes\",\n \"Security preferences\": \"Preferencias de seguridad\",\n \"Security settings\": \"Configuraciones de seguridad\",\n \"Select Additional Login Method\": \"Seleccionar Método de Inicio de Sesión Adicional\",\n \"Select Token\": \"Seleccionar Token\",\n \"Select Wallet\": \"Seleccionar Billetera\",\n \"Select currency\": \"Seleccionar moneda\",\n \"Select language\": \"Seleccionar idioma\",\n \"Select the token to pay the fee with\": \"Selecciona el token con el que pagar la tarifa\",\n \"Select token\": \"Seleccionar token\",\n \"Send\": \"Enviar\",\n \"Send all\": \"Enviar todo\",\n \"Sending Transaction...\": \"Enviando Transacción...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"Enviar a OceanX u otros intercambios puede resultar en la pérdida de fondos.\",\n \"Sending...\": \"Enviando...\",\n \"Set a domain first\": \"Primero establece un dominio\",\n \"Set up Passkey\": \"Configurar clave de acceso\",\n \"Set up a passkey for easier access\": \"Configura una clave de acceso para facilitar el acceso\",\n \"Settings\": \"Configuración\",\n \"Share on\": \"Compartir en\",\n \"Shortcuts\": \"Atajos\",\n \"Show Advanced Options\": \"Mostrar opciones avanzadas\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"Mostrar más\",\n \"Slippage tolerance\": \"Tolerancia al deslizamiento\",\n \"Smart Account\": \"Cuenta Inteligente\",\n \"Smart Account detected\": \"Cuenta inteligente detectada\",\n \"Something went wrong\": \"Algo salió mal\",\n \"Something went wrong. Please try again.\": \"Algo salió mal. Por favor intenta de nuevo.\",\n \"Source\": \"Fuente\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"Mantente atento a nuestra próxima función de Actividad\",\n \"Stay tuned for our upcoming NFT feature\": \"Mantente atento a nuestra próxima función de NFT\",\n \"Submit\": \"Enviar\",\n \"Swap\": \"Intercambiar\",\n \"Swap all\": \"Intercambiar todo\",\n \"Swapping...\": \"Intercambiando...\",\n \"Switch\": \"Cambiar\",\n \"Account Changed\": \"Cuenta cambiada\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"Términos y condiciones\",\n \"Terms and Policies\": \"Términos y políticas\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"Estas cuentas están vinculadas a tu cartera integrada y se pueden usar para iniciar sesión en tu cartera y acceder a tu clave privada.\",\n \"This address only supports VeChain assets.\": \"Esta dirección solo admite activos de VeChain.\",\n \"This domain is already taken\": \"Este dominio ya está en uso\",\n \"This domain is protected\": \"Este dominio está protegido\",\n \"This is taking longer than expected.\": \"Esto está tardando más de lo esperado.\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"Esta es su billetera principal, creada por {{element}} y asegurada por Privy.\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"Esta billetera es la propietaria de tu cuenta inteligente, la cual se utiliza como tu identidad y como puerta de entrada para tus interacciones con la blockchain.\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"Para\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"Para continuar interactuando con la blockchain de VeChain y completar su operación, su cuenta inteligente debe actualizarse a la última versión (v3).\",\n \"Token Contract Address\": \"Dirección del contrato del token\",\n \"Token Priority Order\": \"Orden de prioridad de token\",\n \"Token already added\": \"Token ya agregado\",\n \"Tools\": \"Herramientas\",\n \"Transaction failed\": \"Transacción fallida\",\n \"Transaction failed:\": \"Transacción fallida:\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"La transacción está siendo procesada, puede tardar hasta 15 segundos.\",\n \"Transaction successful\": \"Transacción exitosa\",\n \"Transaction successful!\": \"¡Transacción exitosa!\",\n \"Try again\": \"Inténtalo de nuevo\",\n \"Try searching with a different term\": \"Intente buscar con un término diferente\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Nombre de usuario de Twitter\",\n \"Type the receiver address or domain\": \"Escriba la dirección o dominio del destinatario\",\n \"UNAVAILABLE\": \"NO DISPONIBLE\",\n \"Unable to fetch the price\": \"No se puede obtener el precio\",\n \"Unset current domain\": \"Desactivar dominio actual\",\n \"Unsetting current domain...\": \"Desactivando dominio actual...\",\n \"Upgrade Smart Account to V3\": \"Actualizar cuenta inteligente a V3\",\n \"Upgrade Successful!\": \"¡Actualización exitosa!\",\n \"Upgrade account\": \"Actualizar cuenta\",\n \"Upgrading...\": \"Actualizando...\",\n \"Use social login with VeChain\": \"Usa inicio de sesión social con VeChain\",\n \"Use this token for future transactions\": \"Usar este token para transacciones futuras\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"VET es la criptomoneda principal de la red VeChain. Representa valor y propiedad en el ecosistema VeChain, similar a cómo las acciones representan propiedad en una empresa. Mantener VET genera automáticamente VTHO, que es necesario para pagar las transacciones en la red.\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"VTHO (VeThor) es el token de energía o 'gas' de la red VeChain. Se utiliza para pagar las tarifas de transacción al interactuar con la blockchain. VTHO se genera automáticamente al mantener tokens VET, creando un sistema de dos tokens que ayuda a mantener la estabilidad de la red y gestionar los costos de transacción.\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAO es una organización descentralizada en la blockchain de VeChain enfocada en la sostenibilidad. Los miembros participan en la gobernanza de la DAO usando tokens B3TR para recompensas y VOT3 para votar en propuestas y rondas semanales de asignación de tokens.\",\n \"VeChain Kit\": \"VeChain Kit\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"VeChain, con sede en San Marino, Europa, es un ecosistema pionero de blockchain y creador de VeChainThor, una plataforma de contratos inteligentes de clase mundial que impulsa la adopción de blockchain en el mundo real. Fundada en 2015 por Sunny Lu, VeChain ha trabajado constantemente para ofrecer una solución blockchain transparente, eficiente, escalable y adaptable.\",\n \"VeWorld Wallet\": \"Billetera VeWorld\",\n \"Vechain Kit Policy\": \"Política del Kit Vechain\",\n \"View Current Policy\": \"Ver política actual\",\n \"View on explorer\": \"Ver en el explorador\",\n \"View transaction on the explorer\": \"Ver transacción en el explorador\",\n \"Waiting for confirmation\": \"Esperando confirmación\",\n \"Waiting for confirmation...\": \"Esperando confirmación...\",\n \"Waiting wallet confirmation...\": \"Esperando confirmación de la billetera...\",\n \"Wallet\": \"Billetera\",\n \"Wallet secured by\": \"Billetera asegurada por\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"Le recomendamos encarecidamente exportar su clave privada para respaldar su billetera. Esto asegura que pueda restaurarla si es necesario o transferirla a autocustodia usando\",\n \"Website\": \"Sitio web\",\n \"Website URL\": \"URL del sitio web\",\n \"Website URL must start with https://\": \"La URL del sitio web debe comenzar con https://\",\n \"What is B3TR?\": \"¿Qué es B3TR?\",\n \"What is Privy?\": \"¿Qué es Privy?\",\n \"What is VET?\": \"¿Qué es VET?\",\n \"What is VTHO?\": \"¿Qué es VTHO?\",\n \"What is VeBetterDAO?\": \"¿Qué es VeBetterDAO?\",\n \"What is VeChain?\": \"¿Qué es VeChain?\",\n \"What is a Smart Account?\": \"¿Qué es una Smart Account?\",\n \"What is a domain name?\": \"¿Qué es un nombre de dominio?\",\n \"What is a network?\": \"¿Qué es una red?\",\n \"What is a wallet?\": \"¿Qué es una billetera?\",\n \"What is an x2earn application?\": \"¿Qué es una aplicación x2earn?\",\n \"What is fee delegation?\": \"¿Qué es la delegación de tarifas?\",\n \"When you have accepted a policy, it will appear here\": \"Cuando haya aceptado una política, aparecerá aquí\",\n \"When you have notifications, they will appear here\": \"Cuando tengas notificaciones, aparecerán aquí\",\n \"YOU OWN THIS\": \"ESTO ES TUYO\",\n \"You accepted current policy on {{date}}\": \"Aceptó la política actual el {{date}}\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"Estás usando una Cartera Integrada asegurada por tu método de inicio de sesión social, asegurando una experiencia VeChain sin problemas.\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"Puedes enviar tokens haciendo clic en el icono de enviar en la sección de Acciones Rápidas. Ingresa la dirección del destinatario o el nombre de dominio de VeChain, selecciona el token y especifica la cantidad que deseas enviar.\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"No tienes ningún token de gas habilitado. Por favor, habilita al menos un token de gas en Preferencias de Token de Gas.\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"Tiene una cuenta inteligente activa asociada a esta billetera. Se ha establecido como su identidad principal.\",\n \"You may want to try establishing the connection again.\": \"Es posible que quieras intentar establecer la conexión nuevamente.\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"Debes habilitar al menos un token para realizar transacciones. Sin ningún token habilitado, no podrás pagar las tarifas de gas.\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"Su cuenta ha sido actualizada exitosamente a la última versión. Ahora puede disfrutar de una mejor experiencia de usuario, menores costos de gas y mayor seguridad.\",\n \"Your address has been successfully set to {{name}}\": \"Tu dirección se ha configurado exitosamente a {{name}}\",\n \"Your changes have been saved successfully.\": \"Tus cambios han sido guardados exitosamente.\",\n \"Your domain has been unset successfully.\": \"Su dominio ha sido desactivado exitosamente.\",\n \"Your embedded wallet\": \"Su billetera integrada\",\n \"Your existing domains\": \"Tus dominios existentes\",\n \"Your smart account is already upgraded to this version.\": \"Su cuenta inteligente ya está actualizada a esta versión.\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"Su cuenta inteligente necesita ser actualizada a la última versión (v3).\",\n \"Your tokens\": \"Tus tokens\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"La seguridad de tu billetera depende de cómo accedas a ella. Con opciones de autocustodia como la extensión VeWorld, la aplicación móvil o la billetera de hardware, tienes control total sobre tus claves privadas. Esta extensión no tiene acceso a tus claves privadas. Al iniciar sesión con cuentas sociales o VeChain, tu billetera es creada y asegurada por Privy y gestionada por VeChain, ofreciendo una experiencia de integración más sencilla mientras se mantiene la seguridad.\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"aquí\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"tasa\",\n \"to learn more about embedded wallets.\": \"para saber más sobre carteras integradas.\",\n \"unavailable\": \"no disponible\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"tu@email.com\"\n}","{\n \" and \": \" 和 \",\n \"'{{policyName}}' on connect\": \"连接时的'{{policyName}}'\",\n \"'{{policyName}}' on {{date}}\": \"'{{policyName}}' 于 {{date}}\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>您的隐私很重要。</bold> 您可以自主决定,接受后可启用如 cookies 等可选功能,帮助我们提升您的体验。\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \"需要一个 .vet 域名来自定义您的个人资料。选择一个账户名称以开始。\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"智能账户是一种智能合约钱包,提供增强的安全性和功能。它支持社交恢复、交易批处理等功能。\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"域名是您钱包地址的一种昵称。它可以帮助您轻松识别钱包并使用人性化的名称与dApps进行交互。例如,如果您的钱包地址是0x1234567890,您的昵称可能是“alice.vechain”。\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"区块链中的网络是指交易发生的环境。VeChain有两个主要网络:主网(真实交易发生的活跃网络)和测试网(供开发人员使用的测试环境)。您连接的网络显示在此模态框的顶部。\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"您的智能账户有新的升级可用。请访问“访问和安全”部分以进行升级。\",\n \"A new version is available for your account\": \"您的账户有新版本可用\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"钱包是您访问VeChain区块链的门户。它存储您的私钥,允许您安全地管理数字资产,发送和接收代币,并与去中心化应用程序交互。可以将其视为区块链交易的数字银行账户。\",\n \"AVAILABLE\": \"可用\",\n \"Accept\": \"接受\",\n \"Accept all\": \"全部接受\",\n \"Accept selected\": \"接受已选择\",\n \"Access and security\": \"访问和安全\",\n \"Account Upgrade Required\": \"需要账户升级\",\n \"Account already upgraded\": \"账户已升级\",\n \"Account upgrade required\": \"需要账户升级\",\n \"Active\": \"活跃\",\n \"Active Wallet\": \"当前钱包\",\n \"Add Login Method\": \"添加登录方式\",\n \"Add New Wallet\": \"添加新钱包\",\n \"Add Token\": \"添加令牌\",\n \"Add to shortcuts\": \"添加到快捷方式\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"添加更多关联账户可以增强防止访问丢失的安全性,但也引入了额外的潜在攻击向量。为了增强安全性,我们建议启用多因素认证(MFA)。\",\n \"Address is required\": \"地址是必需的\",\n \"All\": \"所有\",\n \"All apps\": \"所有应用\",\n \"All policies you have accepted\": \"您已接受的所有政策\",\n \"All tokens\": \"所有代币\",\n \"Already have an x2earn app wallet?\": \"已经有一个x2earn应用钱包了吗?\",\n \"Amount\": \"金额\",\n \"Amount is required\": \"金额是必需的\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"VeBetterDAO 的 X2Earn 应用程序是一款可持续发展的应用程序,用户因生态友好行为而获得 B3TR 代币奖励。这些应用程序必须分发 B3TR,链接用户钱包并提供可持续行动的证明。它们通过背书加入 VeBetterDAO,并参与每周的代币分配轮次。\",\n \"An unexpected error occurred.\": \"发生了意外错误。\",\n \"Apple\": \"苹果\",\n \"Apply\": \"应用\",\n \"Archived\": \"已归档\",\n \"Archived Notifications\": \"已归档通知\",\n \"Are you sure you want to disconnect your wallet?\": \"您确定要断开钱包连接吗?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"您确定要拒绝这些政策并断开连接吗?\",\n \"Are you sure you want to remove this wallet?\": \"您确定要移除此钱包吗?\",\n \"Are you sure you want to set your domain name to\": \"您确定要将您的域名设置为\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"您确定要取消链接 {{accountDescription}} 中作为登录方式之一的 {{accountType}} 吗?\",\n \"Are you sure you want to unset your current domain?\": \"您确定要取消设置当前域名吗?\",\n \"Assets\": \"资产\",\n \"At\": \"在\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TR 是 VeBetterDAO 的激励性代币,基于 VechainThor 区块链构建。其供应量上限为 10 亿个代币,分 12 年每周发放。B3TR 用于奖励、治理以及 1:1 支持 VOT3 代币。它支持可持续性应用和 DAO 财务管理。\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"备份您的钱包非常重要,因为您是唯一能访问您的私钥的人。如果出现问题,拥有您的私钥是恢复资产的唯一方法。备份方式取决于您如何访问钱包:如果使用 VeWorld,备份选项在应用内可用。对于社交登录用户,您可以在钱包部分找到备份选项。如果通过 VeChain 或其他生态系统应用连接,您需要访问原始网站,登录并从那里访问钱包部分。\",\n \"Backup\": \"备份\",\n \"Backup your wallet\": \"备份您的钱包\",\n \"Backup your wallet, configure MFA and set recovery options\": \"备份您的钱包,配置多因素身份验证并设置恢复选项\",\n \"Balance\": \"余额\",\n \"Benefits of this upgrade:\": \"此升级的好处:\",\n \"Best\": \"最佳\",\n \"Better transaction handling\": \"更好的交易处理\",\n \"Bridge\": \"桥接\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"确认后,以下附加到您的名称({{domain}})的信息将被更新\",\n \"By confirming, your address will be set to {{domain}}\": \"确认后,您的地址将被设置为 {{domain}}\",\n \"By confirming, your current domain will be unset\": \"确认后,您当前的域名将被取消\",\n \"By continuing, you agree to\": \"继续即表示您同意\",\n \"Cancel\": \"取消\",\n \"Checking...\": \"正在检查...\",\n \"Choose Name\": \"选择姓名\",\n \"Choose a name for your account.\": \"为您的账户选择一个名称。\",\n \"Choose a unique .vet domain name for your account.\": \"为您的帐户选择一个独特的 .vet 域名。\",\n \"Choose account name\": \"选择账户名称\",\n \"Choose name\": \"选择名称\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"请选择在应用未代付手续费时用于交易的币种。\",\n \"Choose your account name\": \"选择您的账户名称\",\n \"Claim your vet domain!\": \"领取您的 vet 域名!\",\n \"Claiming name...\": \"认领名称...\",\n \"Clear all\": \"清除全部\",\n \"Cleared notifications will appear here\": \"已清除的通知将显示在这里\",\n \"Click\": \"点击\",\n \"Click below to access {{ name }} and explore its features.\": \"点击下方以访问 {{ name }} 并探索其功能。\",\n \"Close\": \"关闭\",\n \"Close and do this later\": \"关闭并稍后处理\",\n \"Close announcement\": \"关闭公告\",\n \"Coming Soon!\": \"敬请期待!\",\n \"Coming soon\": \"即将推出\",\n \"Confirm\": \"确认\",\n \"Confirm Changes\": \"确认更改\",\n \"Confirm Name\": \"确认姓名\",\n \"Confirm Unset Domain\": \"确认取消设置域名\",\n \"Confirm the transaction in your wallet to complete it.\": \"在您的钱包中确认交易以完成它。\",\n \"Confirm transaction\": \"确认交易\",\n \"Connect an external wallet for easier access\": \"连接外部钱包以便更轻松访问\",\n \"Connect wallet\": \"连接钱包\",\n \"Connect with VeWorld wallet\": \"连接到 VeWorld 钱包\",\n \"Connect your Apple account for easier access\": \"连接您的 Apple 账户以便更轻松地访问\",\n \"Connect your Discord account for easier access\": \"连接您的 Discord 帐号以更轻松地访问\",\n \"Connect your Farcaster account for easier access\": \"连接您的 Farcaster 账户以便更轻松地访问\",\n \"Connect your Github account for easier access\": \"连接您的 Github 账户以便更轻松地访问\",\n \"Connect your Google account for easier access\": \"连接您的 Google 账户以便更轻松地访问\",\n \"Connect your Instagram account for easier access\": \"连接您的 Instagram 账户以便更轻松地访问\",\n \"Connect your LinkedIn account for easier access\": \"连接您的 LinkedIn 账户以便更轻松地访问\",\n \"Connect your Spotify account for easier access\": \"连接您的 Spotify 账户以便更轻松地访问\",\n \"Connect your Telegram account for easier access\": \"连接您的 Telegram 账户以便更轻松地访问\",\n \"Connect your Tiktok account for easier access\": \"连接您的 Tiktok 账户以便更轻松地访问\",\n \"Connect your Twitter account for easier access\": \"连接您的 Twitter 账户以便更轻松地访问\",\n \"Connect your email for easier access\": \"连接您的电子邮件以便更轻松地访问\",\n \"Connect your phone number for easier access\": \"连接您的电话号码以便更轻松地访问\",\n \"Connecting to VeChain\": \"正在连接到 VeChain\",\n \"Connecting with\": \"连接中\",\n \"Connecting with Passkey\": \"通过Passkey连接\",\n \"Connecting...\": \"正在连接...\",\n \"Connection Details\": \"连接详情\",\n \"Connection Failed\": \"连接失败\",\n \"Connection Type\": \"连接类型\",\n \"Connection details\": \"连接详情\",\n \"Continue\": \"继续\",\n \"Continue with Github\": \"继续使用 Github\",\n \"Continue with Google\": \"通过Google继续\",\n \"Cookie Policy\": \"Cookie 政策\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"Cookie 政策详述了对 cookies 和追踪技术的使用。\",\n \"Copied!\": \"已复制!\",\n \"Copy your address or scan this QR code\": \"复制您的地址或扫描此二维码\",\n \"Currency\": \"货币\",\n \"Current\": \"当前\",\n \"Current domain\": \"当前域名\",\n \"Customization\": \"自定义\",\n \"Customize\": \"自定义\",\n \"Customize profile\": \"自定义个人资料\",\n \"Customize the appearance of your wallet.\": \"自定义您的钱包外观。\",\n \"Description\": \"描述\",\n \"Description must be less than 100 characters\": \"描述必须少于100个字符\",\n \"Didn't get an email?\": \"没有收到电子邮件?\",\n \"Discord\": \"Discord\",\n \"Display Name\": \"显示名称\",\n \"Display name must be less than 25 characters\": \"显示名称必须少于25个字符\",\n \"Domain set\": \"域名已设置\",\n \"Domain unset\": \"域名已取消设置\",\n \"Done\": \"完成\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"拖拽以重新排序。系统会自动优先使用余额充足的优先级最高的币种。\",\n \"Ecosystem\": \"生态系统\",\n \"Eg: DevRel @ ENS Labs\": \"例如:DevRel @ ENS Labs\",\n \"Email\": \"电子邮件\",\n \"Email address\": \"电子邮件地址\",\n \"Embedded wallet\": \"嵌入式钱包\",\n \"Enhanced compatibility with dApps\": \"增强的dApp兼容性\",\n \"Enter confirmation code\": \"输入确认码\",\n \"Enter your display name\": \"输入您的显示名称\",\n \"Enter your name\": \"输入你的名字\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"轻松、安全地在VeChain和其他区块链网络之间交换您的数字资产。兑换通过利用去中心化和中心化交易所的合作伙伴执行,以转换代币。\",\n \"Existing Custom Tokens\": \"现有自定义令牌\",\n \"Explore ecosystem\": \"探索生态系统\",\n \"Failed to connect with Passkey\": \"无法连接到Passkey\",\n \"Failed to connect with VeChain\": \"无法连接到唯链(VeChain)\",\n \"Failed to connect with ecosystem app\": \"无法连接到生态系统应用程序\",\n \"Failed to load App Hub apps\": \"加载 App Hub 应用失败\",\n \"Farcaster\": \"Farcaster\",\n \"Fee\": \"手续费\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"费用委托是唯链(VeChain)的一个独特功能,它允许其他人(即委托者)为您的交易费用买单。虽然许多dApp和服务提供商充当委托者以方便新用户上手,但某些交易可能仍需要您使用自己的VTHO支付费用。费用是防止网络垃圾及补偿处理和验证区块链交易的节点所必需的。在您自己支付费用时,您可以从资产中选择VTHO来覆盖交易成本。\",\n \"Fee token\": \"手续费币种\",\n \"Filter by category\": \"按类别筛选\",\n \"Finally say goodbye to 0x addresses\": \"最终告别0x地址\",\n \"For developers\": \"为开发者\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"出于安全原因,您只能在 {{appName}} 平台上管理嵌入式钱包设置。\",\n \"Found following rates\": \"找到以下汇率\",\n \"Frequently asked questions\": \"常见问题\",\n \"From\": \"自\",\n \"Gas Token Preferences\": \"Gas 代币偏好\",\n \"Gas fee\": \"燃料费\",\n \"General\": \"常规\",\n \"Github\": \"Github\",\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 \"Google\": \"Google\",\n \"Help\": \"帮助\",\n \"Hide\": \"隐藏\",\n \"How do I backup my wallet?\": \"如何备份我的钱包?\",\n \"How do I send tokens?\": \"我如何发送代币?\",\n \"How is my wallet secured?\": \"我的钱包如何保证安全?\",\n \"I have read and agree to \": \"我已阅读并同意\",\n \"Ignore and continue\": \"忽略并继续\",\n \"Improved security features\": \"改进的安全功能\",\n \"Instagram\": \"Instagram\",\n \"Insufficient balance\": \"余额不足\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"余额不足,无法认领该域名并支付手续费。\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"余额不足,无法完成此交易并支付手续费。\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"余额不足,无法完成此转账并支付手续费。\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"余额不足,无法更新您的资料并支付手续费。\",\n \"Insufficient {{symbol}} balance\": \"{{symbol}}余额不足\",\n \"Invalid address or domain\": \"无效的地址或域名\",\n \"Invalid contract address\": \"无效的合约地址\",\n \"Invalid token address\": \"令牌地址无效\",\n \"Language\": \"语言\",\n \"Launch vechain.energy\": \"启动vechain.energy\",\n \"Launch {{name}}\": \"启动 {{name}}\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"您、Vechain Kit 和当前应用之间的法律协议,详细说明了使用钱包服务的规则。\",\n \"Link Apple Account\": \"关联 Apple 账户\",\n \"Link Discord Account\": \"关联 Discord 帐号\",\n \"Link Email Account\": \"关联电子邮件账户\",\n \"Link External Wallet\": \"链接外部钱包\",\n \"Link Farcaster Account\": \"关联 Farcaster 账户\",\n \"Link Github Account\": \"关联 Github 账户\",\n \"Link Google Account\": \"关联 Google 账户\",\n \"Link Instagram Account\": \"关联 Instagram 账户\",\n \"Link LinkedIn Account\": \"关联 LinkedIn 账户\",\n \"Link Phone Number\": \"关联电话号码\",\n \"Link Spotify Account\": \"关联 Spotify 账户\",\n \"Link Telegram Account\": \"关联 Telegram 账户\",\n \"Link Tiktok Account\": \"关联 Tiktok 账户\",\n \"Link Twitter Account\": \"关联 Twitter 账户\",\n \"LinkedIn\": \"LinkedIn\",\n \"Loading quote...\": \"正在加载报价…\",\n \"Loading your domains...\": \"正在加载您的域名...\",\n \"Loading...\": \"加载中...\",\n \"Log in or sign up\": \"登录或注册\",\n \"Logged in with\": \"登录方式\",\n \"Login\": \"登录\",\n \"Login failed:\": \"登录失败:\",\n \"Login methods\": \"登录方式\",\n \"Login methods and Passkeys\": \"登录方法和密码钥匙\",\n \"Logout\": \"登出\",\n \"Manage Custom Tokens\": \"管理自定义代币\",\n \"Manage MFA\": \"管理多因素认证\",\n \"Manage Recovery\": \"管理恢复\",\n \"Manage on {{appName}}\": \"在 {{appName}} 上管理\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"管理您的嵌入式钱包的安全设置:处理您的登录方法,添加密码钥匙或备份您的钱包,以免失去对资产的访问。\",\n \"Manage your login methods and passkeys\": \"管理您的登录方式和通行密钥\",\n \"Manage your preferences for currency, language, and appearance.\": \"管理您对货币、语言和外观的偏好。\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"{{symbol}}的最小转账金额为{{min}}\",\n \"More\": \"更多\",\n \"Multiclause Transactions Are Now Supported\": \"现在支持多条款交易\",\n \"Name must be at least 3 characters long\": \"名称必须至少包含3个字符\",\n \"Name your account to make it easier to exchange assets\": \"命名您的账户以便于交换资产\",\n \"Network\": \"网络\",\n \"New\": \"新\",\n \"New image selected\": \"已选择新图像\",\n \"No additional accounts available to link\": \"没有可链接的其他账户\",\n \"No application from VeChain ecosystem is available to login.\": \"没有可供登录的VeChain生态系统应用程序。\",\n \"No apps found in this category\": \"此类别中未找到应用程序\",\n \"No archived notifications\": \"没有归档通知\",\n \"No assets\": \"没有资产\",\n \"No notifications\": \"没有通知\",\n \"No policies accepted\": \"未接受任何政策\",\n \"No questions found\": \"未找到问题\",\n \"No quotes available\": \"没有可用报价\",\n \"No tokens found\": \"未找到代币\",\n \"Node URL\": \"节点 URL\",\n \"Notifications\": \"通知\",\n \"Only letters, numbers, and hyphens are allowed\": \"只允许使用字母、数字和连字符\",\n \"Optional\": \"可选\",\n \"Other Wallets\": \"其他钱包\",\n \"Other options\": \"其他选项\",\n \"Passkey\": \"通行密钥\",\n \"Phone Number\": \"电话号码\",\n \"Please approve the request in the connection request window...\": \"请在连接请求窗口中批准请求...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"请务必保证此钱包的安全并进行备份。\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"请查看 {{email}} 是否有来自 privy.io 的电子邮件,并在下方输入您的代码。\",\n \"Please complete the passkey authentication...\": \"请完成通行密钥认证...\",\n \"Please confirm the transaction in your wallet.\": \"请在钱包中确认交易。\",\n \"Please enter a valid Twitter handle without @\": \"请输入有效的 Twitter 用户名,不要加 @\",\n \"Please enter a valid contract address\": \"请输入有效的合约地址\",\n \"Please enter a valid email address\": \"请输入有效的电子邮件地址\",\n \"Please enter a valid number\": \"请输入有效的号码\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"请花一点时间查看所有政策,接受是继续的必要条件。\",\n \"Policy\": \"政策\",\n \"Preparing changes...\": \"正在准备更改...\",\n \"Privacy Policy\": \"隐私政策\",\n \"Privacy policy outlining the data collection and processing practices.\": \"隐私政策概述了数据收集和处理的做法。\",\n \"Privy Status\": \"Privy 状态\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy构建用户引导和嵌入式钱包基础设施,以支持基于加密技术的更好产品。这意味着在应用程序中嵌入资产控制,从而使用户、企业或机器能够通过无缝的产品体验使用数字资产。\",\n \"Processing transaction...\": \"正在处理交易...\",\n \"Profile\": \"个人资料\",\n \"Profile Image\": \"个人资料图片\",\n \"Profile Picture\": \"个人资料图片\",\n \"Profile Updated\": \"个人资料已更新\",\n \"Read More\": \"Read More\",\n \"Receive\": \"接收\",\n \"Receive tokens\": \"接收代币\",\n \"Reduced gas costs for operations\": \"降低操作的燃气成本\",\n \"Reject and logout\": \"拒绝并登出\",\n \"Remove\": \"移除\",\n \"Remove Login Method\": \"移除登录方式\",\n \"Remove Wallet\": \"移除钱包\",\n \"Remove from shortcuts\": \"从快捷方式中移除\",\n \"Remove wallet\": \"移除钱包\",\n \"Remove your current domain name\": \"移除当前域名\",\n \"Resend code\": \"重新发送代码\",\n \"Retry\": \"重试\",\n \"Save Changes\": \"保存更改\",\n \"Saving changes...\": \"正在保存更改...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"告别 0x 地址,立即免费领取您的 .veworld.vet 子域名!\",\n \"Search Apps\": \"搜索应用\",\n \"Search FAQ\": \"搜索常见问题\",\n \"Security preferences\": \"安全偏好\",\n \"Security settings\": \"安全设置\",\n \"Select Additional Login Method\": \"选择其他登录方式\",\n \"Select Token\": \"选择代币\",\n \"Select Wallet\": \"选择钱包\",\n \"Select currency\": \"选择货币\",\n \"Select language\": \"选择语言\",\n \"Select the token to pay the fee with\": \"请选择用于支付手续费的代币\",\n \"Select token\": \"选择代币\",\n \"Send\": \"发送\",\n \"Send all\": \"全部发送\",\n \"Sending Transaction...\": \"正在发送交易...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"发送到OceanX或其他交易所可能导致资金损失。\",\n \"Sending...\": \"正在发送...\",\n \"Set a domain first\": \"首先设置一个域名\",\n \"Set up Passkey\": \"设置通行密钥\",\n \"Set up a passkey for easier access\": \"设置通行密钥以方便访问\",\n \"Settings\": \"设置\",\n \"Share on\": \"分享至\",\n \"Shortcuts\": \"快捷键\",\n \"Show Advanced Options\": \"显示高级选项\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"显示更多\",\n \"Slippage tolerance\": \"滑点容差\",\n \"Smart Account\": \"智能账户\",\n \"Smart Account detected\": \"检测到智能账户\",\n \"Something went wrong\": \"出现错误\",\n \"Something went wrong. Please try again.\": \"出了点问题,请重试。\",\n \"Source\": \"来源\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"敬请期待我们即将推出的活动功能\",\n \"Stay tuned for our upcoming NFT feature\": \"敬请期待我们即将推出的 NFT 功能\",\n \"Submit\": \"提交\",\n \"Swap\": \"交换\",\n \"Swap all\": \"全部交换\",\n \"Swapping...\": \"正在兑换...\",\n \"Switch\": \"切换\",\n \"Account Changed\": \"账户已更改\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"条款和条件\",\n \"Terms and Policies\": \"条款和政策\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"这些账户与您的嵌入钱包相关联,可以用于登录您的钱包并访问您的私钥。\",\n \"This address only supports VeChain assets.\": \"此地址仅支持唯链资产。\",\n \"This domain is already taken\": \"该域名已被占用\",\n \"This domain is protected\": \"该域名已受保护\",\n \"This is taking longer than expected.\": \"这比预期花费的时间更长。\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"这是您的主钱包,由{{element}}创建,并由Privy保护。\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"此钱包是您的智能账户所有者,用作您的身份标识以及区块链交互的网关。\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"到\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"要继续与VeChain区块链交互并完成您的操作,您的智能账户需要升级到最新版本(v3)。\",\n \"Token Contract Address\": \"代币合约地址\",\n \"Token Priority Order\": \"代币优先顺序\",\n \"Token already added\": \"代币已添加\",\n \"Tools\": \"工具\",\n \"Transaction failed\": \"交易失败\",\n \"Transaction failed:\": \"交易失败:\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"交易正在处理中,可能需要长达15秒。\",\n \"Transaction successful\": \"交易成功\",\n \"Transaction successful!\": \"交易成功!\",\n \"Try again\": \"重试\",\n \"Try searching with a different term\": \"尝试使用不同的词搜索\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Twitter用户名\",\n \"Type the receiver address or domain\": \"输入接收者地址或域名\",\n \"UNAVAILABLE\": \"不可用\",\n \"Unable to fetch the price\": \"无法获取价格\",\n \"Unset current domain\": \"取消设置当前域名\",\n \"Unsetting current domain...\": \"正在取消设置当前域名...\",\n \"Upgrade Smart Account to V3\": \"将智能账户升级到V3\",\n \"Upgrade Successful!\": \"升级成功!\",\n \"Upgrade account\": \"升级账户\",\n \"Upgrading...\": \"正在升级...\",\n \"Use social login with VeChain\": \"使用VeChain进行社交登录\",\n \"Use this token for future transactions\": \"在未来的交易中使用此代币\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"VET是唯链网络的主要加密货币。它代表了唯链生态系统中的价值和所有权,类似于公司拥有股票。持有VET会自动生成VTHO,而VTHO是用于支付网络交易费用所需的。\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"VTHO(唯链能量)是唯链网络的能量或“燃料”代币。它用于支付与区块链交互时的交易费用。通过持有VET代币,VTHO会自动生成,从而形成一个双代币系统,有助于维护网络稳定性和管理交易成本。\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAO是一个在唯链区块链上的去中心化组织,专注于可持续发展。成员通过B3TR代币参与DAO的治理以获取奖励,并使用VOT3对提案及每周代币分配轮次进行投票。\",\n \"VeChain Kit\": \"唯链工具包\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"唯链,总部位于欧洲圣马力诺,是一个开创性的区块链生态系统,也是VeChainThor的创造者,这是一个世界级的智能合约平台,推动现实世界的区块链应用。唯链由陆扬于2015年创立,始终致力于提供透明、高效、可扩展和适应的区块链解决方案。\",\n \"VeWorld Wallet\": \"VeWorld 钱包\",\n \"Vechain Kit Policy\": \"唯链工具包政策\",\n \"View Current Policy\": \"查看当前政策\",\n \"View on explorer\": \"在浏览器中查看\",\n \"View transaction on the explorer\": \"在浏览器中查看交易\",\n \"Waiting for confirmation\": \"等待确认\",\n \"Waiting for confirmation...\": \"等待确认...\",\n \"Waiting wallet confirmation...\": \"等待钱包确认...\",\n \"Wallet\": \"钱包\",\n \"Wallet secured by\": \"钱包安全由\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"我们强烈建议导出您的私钥以备份钱包。这确保您可以在需要时恢复钱包,或将其转移到自托管。\",\n \"Website\": \"网站\",\n \"Website URL\": \"网站网址\",\n \"Website URL must start with https://\": \"网站网址必须以 https:// 开头\",\n \"What is B3TR?\": \"什么是B3TR?\",\n \"What is Privy?\": \"什么是Privy?\",\n \"What is VET?\": \"什么是VET?\",\n \"What is VTHO?\": \"什么是VTHO?\",\n \"What is VeBetterDAO?\": \"什么是VeBetterDAO?\",\n \"What is VeChain?\": \"什么是唯链?\",\n \"What is a Smart Account?\": \"什么是智能账户?\",\n \"What is a domain name?\": \"什么是域名?\",\n \"What is a network?\": \"什么是网络?\",\n \"What is a wallet?\": \"什么是钱包?\",\n \"What is an x2earn application?\": \"什么是x2earn应用?\",\n \"What is fee delegation?\": \"什么是费用委托?\",\n \"When you have accepted a policy, it will appear here\": \"当您接受一项政策时,它将显示在此处\",\n \"When you have notifications, they will appear here\": \"您有通知时,会显示在这里\",\n \"YOU OWN THIS\": \"这是你的\",\n \"You accepted current policy on {{date}}\": \"您在 {{date}} 接受了当前的政策\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"您正在使用一个通过社交登录方式确保安全的嵌入式钱包,确保您顺畅的唯链体验。\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"您可以通过点击快速操作部分的发送图标来发送代币。输入接收者的地址或唯链域名,选择代币,并指定您想要发送的数量。\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"您尚未启用任何手续费代币。请在手续费代币偏好设置中至少启用一个。\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"您有一个活跃的智能账户与此钱包关联。它已被设为您的主要身份。\",\n \"You may want to try establishing the connection again.\": \"您可能需要尝试重新建立连接。\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"您必须至少启用一个代币才能进行交易。如未启用任何代币,将无法支付手续费。\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"您的账户已成功升级到最新版本。您现在可以享受更好的用户体验、更低的燃气费用和增强的安全性。\",\n \"Your address has been successfully set to {{name}}\": \"您的地址已成功设置为{{name}}\",\n \"Your changes have been saved successfully.\": \"您的更改已成功保存。\",\n \"Your domain has been unset successfully.\": \"您的域名已成功取消设置。\",\n \"Your embedded wallet\": \"您的嵌入钱包\",\n \"Your existing domains\": \"您现有的域名\",\n \"Your smart account is already upgraded to this version.\": \"您的智能账户已升级到此版本。\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"您的智能账户需要升级到最新版本 (v3)。\",\n \"Your tokens\": \"您的代币\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"您的钱包安全性取决于您如何访问它。通过 VeWorld 插件、移动应用或硬件钱包等自我托管选项,您可以完全控制您的私钥。此插件本身无法访问您的私钥。使用社交账户或唯链登录时,您的钱包由 Privy 创建和保护,并由唯链管理,提供更简单的入门体验,同时保持安全性。\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"这里\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"汇率\",\n \"to learn more about embedded wallets.\": \"了解更多关于嵌入式钱包的信息。\",\n \"unavailable\": \"不可用\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"your@email.com\"\n}","{\n \" and \": \" と \",\n \"'{{policyName}}' on connect\": \"接続時の'{{policyName}}'\",\n \"'{{policyName}}' on {{date}}\": \"{{date}}の'{{policyName}}'\",\n \"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\": \"<bold>あなたのプライバシーは重要です。</bold> 操作はあなたの手に委ねられています。クッキーなどの任意の機能を有効にして、より良い体験をお楽しみください。\",\n \"A .vet domain is required to customize your profile. Choose an account name to get started.\": \".vet ドメインはプロフィールをカスタマイズするために必要です。アカウント名を選択して開始してください。\",\n \"A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.\": \"スマートアカウントは、セキュリティと機能が強化されたスマートコントラクトウォレットです。ソーシャルリカバリー、トランザクションのバッチ処理などの機能を利用できます。\",\n \"A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \\\"alice.vechain\\\".\": \"ドメイン名はウォレットアドレスのニックネームのようなもので、人間が読める名前を使用してウォレットを簡単に識別し、dAppsとインタラクションすることができます。例えば、ウォレットアドレスが 0x1234567890 なら、ニックネームは \\\"alice.vechain\\\" となります。\",\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\": \"ブロックチェーンにおけるネットワークとは、トランザクションが行われる環境のことです。VeChainには、Mainnet(実際のトランザクションが行われるライブネットワーク)とTestnet(開発者向けのテスト環境)の2つの主要なネットワークがあります。接続中のネットワークは、このモーダルの上部に表示されます。\",\n \"A new upgrade is available for your smart account. Please head over to the 'Access and Security' section to upgrade it.\": \"スマートアカウントに新しいアップグレードが利用可能です。「アクセスとセキュリティ」セクションに移動してアップグレードしてください。\",\n \"A new version is available for your account\": \"アカウントの新バージョンが利用可能です\",\n \"A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.\": \"ウォレットはVeChainブロックチェーンへのゲートウェイです。プライベートキーを保存し、デジタル資産を安全に管理し、トークンを送受信し、分散型アプリケーションとやり取りすることができます。これを、ブロックチェーントランザクションのためのデジタル銀行口座と考えてください。\",\n \"AVAILABLE\": \"利用可能\",\n \"Accept\": \"承諾\",\n \"Accept all\": \"すべて承諾\",\n \"Accept selected\": \"選択を受け入れる\",\n \"Access and security\": \"アクセスとセキュリティ\",\n \"Account Upgrade Required\": \"アカウントのアップグレードが必要です\",\n \"Account already upgraded\": \"アカウントはすでにアップグレードされています\",\n \"Account upgrade required\": \"アカウントのアップグレードが必要です\",\n \"Active\": \"アクティブ\",\n \"Active Wallet\": \"アクティブウォレット\",\n \"Add Login Method\": \"ログイン方法を追加\",\n \"Add New Wallet\": \"新しいウォレットを追加\",\n \"Add Token\": \"トークンを追加\",\n \"Add to shortcuts\": \"ショートカットに追加\",\n \"Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.\": \"リンクされたアカウントを追加することで、アクセス喪失に対するセキュリティが向上しますが、新たな攻撃の可能性も生じます。セキュリティを強化するために、MFAを有効にすることをお勧めします。\",\n \"Address is required\": \"アドレスが必要です\",\n \"All\": \"すべて\",\n \"All apps\": \"すべてのアプリ\",\n \"All policies you have accepted\": \"あなたが承諾したすべてのポリシー\",\n \"All tokens\": \"すべてのトークン\",\n \"Already have an x2earn app wallet?\": \"既にx2earnアプリのウォレットをお持ちですか?\",\n \"Amount\": \"金額\",\n \"Amount is required\": \"金額が必要です\",\n \"An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.\": \"VeBetterDAOのX2Earnアプリケーションは、環境に優しい行動をとるユーザーにB3TRトークンを報酬として提供する持続可能なアプリです。これらのアプリはB3TRを配布し、ユーザのウォレットをリンクし、持続可能な行動の証明を提供しなければなりません。これらは推薦を通じてVeBetterDAOに参加し、週ごとのトークン割り当てラウンドに参加します。\",\n \"An unexpected error occurred.\": \"予期せぬエラーが発生しました。\",\n \"Apple\": \"Apple\",\n \"Apply\": \"適用\",\n \"Archived\": \"アーカイブ済み\",\n \"Archived Notifications\": \"アーカイブされた通知\",\n \"Are you sure you want to disconnect your wallet?\": \"ウォレットを切断してもよろしいですか?\",\n \"Are you sure you want to reject the policies and disconnect?\": \"ポリシーを拒否して切断してもよろしいですか?\",\n \"Are you sure you want to remove this wallet?\": \"このウォレットを削除してもよろしいですか?\",\n \"Are you sure you want to set your domain name to\": \"ドメイン名を設定してもよろしいですか\",\n \"Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?\": \"{{accountDescription}}にリンクされたログイン方法として{{accountType}}のリンクを解除してもよろしいですか?\",\n \"Are you sure you want to unset your current domain?\": \"現在のドメインを解除してもよろしいですか?\",\n \"Assets\": \"資産\",\n \"At\": \"で\",\n \"B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.\": \"B3TRはVeBetterDAOのインセンティブトークンであり、VechainThorブロックチェーン上に構築されています。総供給量は10億トークンに限定され、12年間にわたって毎週発行されます。B3TRは報酬、ガバナンス、およびVOT3トークンの1:1の保護に使用されます。それはサステナビリティアプリケーションとDAOトレジャリ管理をサポートします。\",\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\": \"ウォレットのバックアップは非常に重要です。なぜなら、あなただけが秘密鍵にアクセスできるからです。何か問題が発生した場合、秘密鍵を持っていることが資産を回復する唯一の手段です。バックアップの方法はウォレットへのアクセス方法によります:VeWorldを使用している場合、バックアップオプションはアプリ内で利用可能です。ソーシャルログインユーザーの場合、ウォレットセクションでバックアップオプションを見つけることができます。VeChainまたは別のエコシステムアプリを通じて接続している場合、元のWebサイトにアクセスし、ログインしてウォレットセクションにアクセスする必要があります。\",\n \"Backup\": \"バックアップ\",\n \"Backup your wallet\": \"ウォレットをバックアップする\",\n \"Backup your wallet, configure MFA and set recovery options\": \"ウォレットをバックアップし、MFAを設定し、回復オプションを設定してください。\",\n \"Balance\": \"残高\",\n \"Benefits of this upgrade:\": \"このアップグレードの利点:\",\n \"Best\": \"最適\",\n \"Better transaction handling\": \"より良いトランザクション処理\",\n \"Bridge\": \"ブリッジ\",\n \"By confirming, the following details attached to your name ({{domain}}) will be updated\": \"確認することで、あなたの名前({{domain}})に紐づく以下の情報が更新されます\",\n \"By confirming, your address will be set to {{domain}}\": \"確認することで、あなたのアドレスが{{domain}}に設定されます\",\n \"By confirming, your current domain will be unset\": \"確認することで、現在のドメイン設定が解除されます\",\n \"By continuing, you agree to\": \"続行することで、あなたは以下に同意します\",\n \"Cancel\": \"キャンセル\",\n \"Checking...\": \"確認中...\",\n \"Choose Name\": \"名前を選択\",\n \"Choose a name for your account.\": \"アカウントの名前を選んでください。\",\n \"Choose a unique .vet domain name for your account.\": \"アカウントにユニークな.vetドメイン名を選択してください。\",\n \"Choose account name\": \"アカウント名を選択\",\n \"Choose name\": \"名前を選択\",\n \"Choose which tokens to use for transaction fees when the app is not covering them.\": \"アプリが手数料を負担しない場合に、どのトークンを手数料支払いに使用するか選択してください。\",\n \"Choose your account name\": \"アカウント名を選択\",\n \"Claim your vet domain!\": \"あなたのvetドメインを取得しましょう!\",\n \"Claiming name...\": \"名前をクレーム中...\",\n \"Clear all\": \"すべてクリア\",\n \"Cleared notifications will appear here\": \"クリアされた通知はここに表示されます\",\n \"Click\": \"クリック\",\n \"Click below to access {{ name }} and explore its features.\": \"以下をクリックして{{ name }}にアクセスし、その機能を探索してください。\",\n \"Close\": \"閉じる\",\n \"Close and do this later\": \"閉じて後でやる\",\n \"Close announcement\": \"お知らせを閉じる\",\n \"Coming Soon!\": \"近日公開!\",\n \"Coming soon\": \"近日公開\",\n \"Confirm\": \"確認\",\n \"Confirm Changes\": \"変更を確認\",\n \"Confirm Name\": \"名前を確認\",\n \"Confirm Unset Domain\": \"ドメイン解除を確認\",\n \"Confirm the transaction in your wallet to complete it.\": \"ウォレットでトランザクションを確認して完了してください。\",\n \"Confirm transaction\": \"取引を確認\",\n \"Connect an external wallet for easier access\": \"外部ウォレットを接続して簡単にアクセス\",\n \"Connect wallet\": \"ウォレットを接続\",\n \"Connect with VeWorld wallet\": \"VeWorldウォレットと接続\",\n \"Connect your Apple account for easier access\": \"Appleアカウントを接続して簡単にアクセス\",\n \"Connect your Discord account for easier access\": \"簡単なアクセスのためにあなたのDiscordアカウントを接続してください\",\n \"Connect your Farcaster account for easier access\": \"Farcasterアカウントを接続して簡単にアクセス\",\n \"Connect your Github account for easier access\": \"Githubアカウントを接続して簡単にアクセス\",\n \"Connect your Google account for easier access\": \"Googleアカウントを接続して簡単にアクセス\",\n \"Connect your Instagram account for easier access\": \"Instagramアカウントを接続して簡単にアクセス\",\n \"Connect your LinkedIn account for easier access\": \"LinkedInアカウントを接続して簡単にアクセス\",\n \"Connect your Spotify account for easier access\": \"Spotifyアカウントを接続して簡単にアクセス\",\n \"Connect your Telegram account for easier access\": \"Telegramアカウントを接続して簡単にアクセス\",\n \"Connect your Tiktok account for easier access\": \"Tiktokアカウントを接続して簡単にアクセス\",\n \"Connect your Twitter account for easier access\": \"Twitterアカウントを接続して簡単にアクセス\",\n \"Connect your email for easier access\": \"メールを接続して簡単にアクセス\",\n \"Connect your phone number for easier access\": \"電話番号を接続して簡単にアクセス\",\n \"Connecting to VeChain\": \"VeChainに接続中\",\n \"Connecting with\": \"で接続中\",\n \"Connecting with Passkey\": \"パスキーで接続中\",\n \"Connecting...\": \"接続中...\",\n \"Connection Details\": \"接続の詳細\",\n \"Connection Failed\": \"接続に失敗しました\",\n \"Connection Type\": \"接続タイプ\",\n \"Connection details\": \"接続の詳細\",\n \"Continue\": \"続ける\",\n \"Continue with Github\": \"Githubで続行\",\n \"Continue with Google\": \"Googleで続行\",\n \"Cookie Policy\": \"クッキーポリシー\",\n \"Cookie policy outlining the use of cookies and tracking technologies.\": \"クッキーと追跡技術の使用を説明するクッキーポリシー。\",\n \"Copied!\": \"コピーしました!\",\n \"Copy your address or scan this QR code\": \"アドレスをコピーするか、このQRコードをスキャンしてください\",\n \"Currency\": \"通貨\",\n \"Current\": \"現在\",\n \"Current domain\": \"現在のドメイン\",\n \"Customization\": \"カスタマイズ\",\n \"Customize\": \"カスタマイズ\",\n \"Customize profile\": \"プロフィールをカスタマイズ\",\n \"Customize the appearance of your wallet.\": \"ウォレットの外観をカスタマイズします。\",\n \"Description\": \"説明\",\n \"Description must be less than 100 characters\": \"説明は100文字未満でなければなりません\",\n \"Didn't get an email?\": \"メールを受け取りませんでしたか?\",\n \"Discord\": \"ディスコード\",\n \"Display Name\": \"表示名\",\n \"Display name must be less than 25 characters\": \"表示名は25文字未満でなければなりません\",\n \"Domain set\": \"ドメインが設定されました\",\n \"Domain unset\": \"ドメインが解除されました\",\n \"Done\": \"完了\",\n \"Drag to reorder. The system will automatically use the highest priority token with sufficient balance.\": \"ドラッグして並び替えてください。残高が十分な場合、システムは自動的に優先順位が最も高いトークンを使用します。\",\n \"Ecosystem\": \"エコシステム\",\n \"Eg: DevRel @ ENS Labs\": \"例: DevRel @ ENS Labs\",\n \"Email\": \"メール\",\n \"Email address\": \"メールアドレス\",\n \"Embedded wallet\": \"埋め込みウォレット\",\n \"Enhanced compatibility with dApps\": \"dAppsとの互換性の強化\",\n \"Enter confirmation code\": \"確認コードを入力\",\n \"Enter your display name\": \"表示名を入力してください\",\n \"Enter your name\": \"お名前を入力してください\",\n \"Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.\": \"デジタル資産を、VeChainと他のブロックチェーンネットワーク間で簡単かつ安全に交換できます。スワップは、トークンを変換するために、非中央集権型と中央集権型の両方の取引所を活用するパートナーを通じて実行されます。\",\n \"Existing Custom Tokens\": \"既存のカスタムトークン\",\n \"Explore ecosystem\": \"エコシステムを見る\",\n \"Failed to connect with Passkey\": \"パスキーとの接続に失敗しました\",\n \"Failed to connect with VeChain\": \"VeChainとの接続に失敗しました\",\n \"Failed to connect with ecosystem app\": \"エコシステムアプリとの接続に失敗しました\",\n \"Failed to load App Hub apps\": \"App Hubアプリの読み込みに失敗しました\",\n \"Farcaster\": \"ファーカスター\",\n \"Fee\": \"手数料\",\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\": \"手数料デリゲーションは、VeChainのユニークな機能であり、他の誰か(デリゲーター)があなたの取引手数料を支払うことを可能にします。多くのdAppsおよびサービスプロバイダーがデリゲーターとして機能し、新規ユーザーが開始しやすくしていますが、一部の取引では依然として独自のVTHOを使用して手数料を支払う必要がある場合があります。手数料は、ネットワークスパムを防ぎ、ブロックチェーン上の取引を処理および検証するノードに報酬を与えるために必要です。手数料を自分で支払う場合は、資産からVTHOを選択して取引コストをカバーすることができます。\",\n \"Fee token\": \"手数料トークン\",\n \"Filter by category\": \"カテゴリでフィルター\",\n \"Finally say goodbye to 0x addresses\": \"ついに0xアドレスにお別れを言いましょう\",\n \"For developers\": \"開発者向け\",\n \"For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.\": \"セキュリティ上の理由から、埋め込みウォレットの設定は{{appName}}プラットフォームでのみ管理できます。\",\n \"Found following rates\": \"次のレートが見つかりました\",\n \"Frequently asked questions\": \"よくある質問\",\n \"From\": \"送信元\",\n \"Gas Token Preferences\": \"ガストークンの優先設定\",\n \"Gas fee\": \"ガス代\",\n \"General\": \"一般\",\n \"Github\": \"ギットハブ\",\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 \"Google\": \"グーグル\",\n \"Help\": \"ヘルプ\",\n \"Hide\": \"非表示\",\n \"How do I backup my wallet?\": \"ウォレットのバックアップはどうすればいいですか?\",\n \"How do I send tokens?\": \"トークンを送信するにはどうすればよいですか?\",\n \"How is my wallet secured?\": \"ウォレットはどのようにして保護されていますか?\",\n \"I have read and agree to \": \"私は読み、同意します \",\n \"Ignore and continue\": \"無視して続行\",\n \"Improved security features\": \"改善されたセキュリティ機能\",\n \"Instagram\": \"インスタグラム\",\n \"Insufficient balance\": \"残高不足\",\n \"Insufficient balance to claim this domain and cover gas fees.\": \"このドメインの取得およびガス代を支払うための残高が不足しています。\",\n \"Insufficient balance to complete this transaction and cover gas fees.\": \"この取引およびガス代を完了するための残高が不足しています。\",\n \"Insufficient balance to complete this transfer and cover gas fees.\": \"この送金およびガス代を完了するための残高が不足しています。\",\n \"Insufficient balance to update your profile and cover gas fees.\": \"プロフィールの更新およびガス代を支払うための残高が不足しています。\",\n \"Insufficient {{symbol}} balance\": \"残高が不足しています ({{symbol}})\",\n \"Invalid address or domain\": \"無効なアドレスまたはドメイン\",\n \"Invalid contract address\": \"無効なコントラクトアドレス\",\n \"Invalid token address\": \"無効なトークンアドレス\",\n \"Language\": \"言語\",\n \"Launch vechain.energy\": \"vechain.energyを起動\",\n \"Launch {{name}}\": \"{{name}}を起動\",\n \"Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.\": \"あなた、Vechain Kit、および現在のアプリ間のウォレットサービスの使用規則を説明する法的契約。\",\n \"Link Apple Account\": \"Appleアカウントをリンク\",\n \"Link Discord Account\": \"ディスコードアカウントをリンクする\",\n \"Link Email Account\": \"メールアカウントをリンク\",\n \"Link External Wallet\": \"外部ウォレットをリンクする\",\n \"Link Farcaster Account\": \"Farcasterアカウントをリンク\",\n \"Link Github Account\": \"Githubアカウントをリンク\",\n \"Link Google Account\": \"Googleアカウントをリンク\",\n \"Link Instagram Account\": \"Instagramアカウントをリンク\",\n \"Link LinkedIn Account\": \"LinkedInアカウントをリンク\",\n \"Link Phone Number\": \"電話番号をリンク\",\n \"Link Spotify Account\": \"Spotifyアカウントをリンク\",\n \"Link Telegram Account\": \"Telegramアカウントをリンク\",\n \"Link Tiktok Account\": \"Tiktokアカウントをリンク\",\n \"Link Twitter Account\": \"Twitterアカウントをリンク\",\n \"LinkedIn\": \"リンクトイン\",\n \"Loading quote...\": \"見積もりを読み込み中...\",\n \"Loading your domains...\": \"ドメインを読み込んでいます...\",\n \"Loading...\": \"読み込み中...\",\n \"Log in or sign up\": \"ログインまたはサインアップ\",\n \"Logged in with\": \"でログイン\",\n \"Login\": \"ログイン\",\n \"Login failed:\": \"ログインに失敗しました:\",\n \"Login methods\": \"ログイン方法\",\n \"Login methods and Passkeys\": \"ログイン方法とパスキー\",\n \"Logout\": \"ログアウト\",\n \"Manage Custom Tokens\": \"カスタムトークンの管理\",\n \"Manage MFA\": \"MFAを管理する\",\n \"Manage Recovery\": \"リカバリーの管理\",\n \"Manage on {{appName}}\": \"{{appName}}で管理する\",\n \"Manage your embedded wallet security settings: handle your login methods, add a passkey or back up your wallet to never lose access to your assets.\": \"埋め込みウォレットのセキュリティ設定を管理します: ログイン方法を処理したり、パスキーを追加したり、資産へのアクセスを失わないようにウォレットをバックアップしたりします。\",\n \"Manage your login methods and passkeys\": \"ログイン方法とパスキーを管理する\",\n \"Manage your preferences for currency, language, and appearance.\": \"通貨、言語、外観の設定を管理します。\",\n \"Minimum {{symbol}} transfer is {{min}}\": \"最小{{symbol}}転送量は{{min}}です\",\n \"More\": \"もっと見る\",\n \"Multiclause Transactions Are Now Supported\": \"マルチクローズ取引がサポートされました\",\n \"Name must be at least 3 characters long\": \"名前は少なくとも3文字以上必要です\",\n \"Name your account to make it easier to exchange assets\": \"資産の交換を簡単にするためにアカウントに名前を付けてください。\",\n \"Network\": \"ネットワーク\",\n \"New\": \"新規\",\n \"New image selected\": \"新しい画像が選択されました\",\n \"No additional accounts available to link\": \"リンク可能な追加アカウントはありません\",\n \"No application from VeChain ecosystem is available to login.\": \"VeChainエコシステムからはログイン可能なアプリケーションがありません。\",\n \"No apps found in this category\": \"このカテゴリにはアプリが見つかりません\",\n \"No archived notifications\": \"アーカイブされた通知はありません\",\n \"No assets\": \"資産なし\",\n \"No notifications\": \"通知はありません\",\n \"No policies accepted\": \"承認されたポリシーはありません\",\n \"No questions found\": \"質問が見つかりませんでした\",\n \"No quotes available\": \"利用可能な見積もりがありません\",\n \"No tokens found\": \"トークンが見つかりません\",\n \"Node URL\": \"ノードURL\",\n \"Notifications\": \"通知\",\n \"Only letters, numbers, and hyphens are allowed\": \"使用できるのは文字、数字、ハイフンのみです\",\n \"Optional\": \"任意\",\n \"Other Wallets\": \"その他のウォレット\",\n \"Other options\": \"その他のオプション\",\n \"Passkey\": \"パスキー\",\n \"Phone Number\": \"電話番号\",\n \"Please approve the request in the connection request window...\": \"接続リクエストウィンドウでリクエストを承認してください...\",\n \"Please be sure to keep this wallet safe and backed up.\": \"このウォレットを安全に保管し、バックアップを取るようにしてください。\",\n \"Please check {{email}} for an email from privy.io and enter your code below.\": \"{{email}} に privy.io からのメールが届いていることを確認し、以下にコードを入力してください。\",\n \"Please complete the passkey authentication...\": \"パスキー認証を完了してください...\",\n \"Please confirm the transaction in your wallet.\": \"ウォレットでトランザクションを確認してください。\",\n \"Please enter a valid Twitter handle without @\": \"@を付けずに有効なTwitterハンドルを入力してください\",\n \"Please enter a valid contract address\": \"有効な契約アドレスを入力してください\",\n \"Please enter a valid email address\": \"有効なメールアドレスを入力してください\",\n \"Please enter a valid number\": \"有効な番号を入力してください\",\n \"Please take a moment to review all the policies, with acceptance being mandatory to continue.\": \"すべてのポリシーを確認する時間を取ってください。続行するには承認が必須です。\",\n \"Policy\": \"ポリシー\",\n \"Preparing changes...\": \"変更を準備しています...\",\n \"Privacy Policy\": \"プライバシーポリシー\",\n \"Privacy policy outlining the data collection and processing practices.\": \"データ収集と処理の実践についてのプライバシーポリシー。\",\n \"Privy Status\": \"Privy ステータス\",\n \"Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.\": \"Privy は、暗号化レールに基づいて構築されたより良い製品を実現するために、ユーザーオンボーディングと組み込みウォレットのインフラストラクチャを構築します。 つまり、アプリケーション自体に資産管理を組み込むことにより、ユーザー、企業、または機械がシームレスな製品体験を通じてデジタル資産を使用できるようにします。\",\n \"Processing transaction...\": \"トランザクションを処理しています...\",\n \"Profile\": \"プロフィール\",\n \"Profile Image\": \"プロフィール画像\",\n \"Profile Picture\": \"プロフィール画像\",\n \"Profile Updated\": \"プロフィールが更新されました\",\n \"Read More\": \"Read More\",\n \"Receive\": \"受け取る\",\n \"Receive tokens\": \"トークンを受け取る\",\n \"Reduced gas costs for operations\": \"オペレーションのガスコストを削減\",\n \"Reject and logout\": \"拒否してログアウト\",\n \"Remove\": \"削除\",\n \"Remove Login Method\": \"ログイン方法の削除\",\n \"Remove Wallet\": \"ウォレットを削除\",\n \"Remove from shortcuts\": \"ショートカットから削除\",\n \"Remove wallet\": \"ウォレットを削除\",\n \"Remove your current domain name\": \"現在のドメイン名を削除する\",\n \"Resend code\": \"コードを再送信\",\n \"Retry\": \"再試行\",\n \"Save Changes\": \"変更を保存\",\n \"Saving changes...\": \"変更を保存しています...\",\n \"Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!\": \"0xアドレスに別れを告げ、今すぐ無料で.veworld.vetサブドメインを取得しましょう!\",\n \"Search Apps\": \"アプリを検索\",\n \"Search FAQ\": \"FAQを検索\",\n \"Security preferences\": \"セキュリティ設定\",\n \"Security settings\": \"セキュリティ設定\",\n \"Select Additional Login Method\": \"追加のログイン方法を選択\",\n \"Select Token\": \"トークンを選択\",\n \"Select Wallet\": \"ウォレットを選択\",\n \"Select currency\": \"通貨を選択\",\n \"Select language\": \"言語を選択\",\n \"Select the token to pay the fee with\": \"手数料を支払うトークンを選択してください\",\n \"Select token\": \"トークンを選択\",\n \"Send\": \"送る\",\n \"Send all\": \"すべて送信\",\n \"Sending Transaction...\": \"取引を送信中...\",\n \"Sending to OceanX or other exchanges may result in loss of funds.\": \"OceanXまたは他の取引所に送ると資金を失う可能性があります。\",\n \"Sending...\": \"送信中...\",\n \"Set a domain first\": \"先にドメインを設定してください\",\n \"Set up Passkey\": \"パスキーを設定\",\n \"Set up a passkey for easier access\": \"簡単にアクセスするためにパスキーを設定\",\n \"Settings\": \"設定\",\n \"Share on\": \"共有する\",\n \"Shortcuts\": \"ショートカット\",\n \"Show Advanced Options\": \"詳細オプションを表示\",\n \"Show Less\": \"Show Less\",\n \"Show More\": \"さらに表示\",\n \"Slippage tolerance\": \"スリッページ許容範囲\",\n \"Smart Account\": \"スマートアカウント\",\n \"Smart Account detected\": \"スマートアカウントが検出されました。\",\n \"Something went wrong\": \"何かがうまくいきませんでした\",\n \"Something went wrong. Please try again.\": \"問題が発生しました。もう一度お試しください。\",\n \"Source\": \"ソース\",\n \"Spotify\": \"Spotify\",\n \"Stay tuned for our upcoming Activity feature\": \"今後のアクティビティ機能にご期待ください\",\n \"Stay tuned for our upcoming NFT feature\": \"今後のNFT機能にご期待ください\",\n \"Submit\": \"送信する\",\n \"Swap\": \"スワップ\",\n \"Swap all\": \"すべてスワップ\",\n \"Swapping...\": \"スワップ中...\",\n \"Switch\": \"切り替え\",\n \"Account Changed\": \"アカウントが変更されました\",\n \"Telegram\": \"Telegram\",\n \"Terms and Conditions\": \"利用規約\",\n \"Terms and Policies\": \"利用規約とポリシー\",\n \"These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.\": \"これらのアカウントは埋め込みウォレットにリンクされており、ウォレットへのログインや秘密鍵へのアクセスに使用できます。\",\n \"This address only supports VeChain assets.\": \"このアドレスはVeChain資産のみをサポートしています。\",\n \"This domain is already taken\": \"このドメインは既に使用されています\",\n \"This domain is protected\": \"このドメインは保護されています\",\n \"This is taking longer than expected.\": \"予想以上に時間がかかっています。\",\n \"This is your main wallet, created by {{element}} and secured by Privy.\": \"これは、{{element}}によって作成され、Privyによって保護されたあなたのメインウォレットです。\",\n \"This wallet is the owner of your smart account, which is used as your identity and as a gateway for your blockchain interactions.\": \"このウォレットは、アイデンティティとして使用されるスマートアカウントの所有者であり、ブロックチェーンとのやり取りのゲートウェイとして機能します。\",\n \"Tiktok\": \"Tiktok\",\n \"To\": \"宛先\",\n \"To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).\": \"VeChainブロックチェーンと対話しオペレーションを完了するためには、スマートアカウントを最新バージョン(v3)にアップグレードする必要があります。\",\n \"Token Contract Address\": \"トークン契約アドレス\",\n \"Token Priority Order\": \"トークン優先順位\",\n \"Token already added\": \"トークンは既に追加されています\",\n \"Tools\": \"ツール\",\n \"Transaction failed\": \"取引に失敗しました\",\n \"Transaction failed:\": \"取引に失敗しました:\",\n \"Transaction is being processed, it can take up to 15 seconds.\": \"トランザクションを処理しています。最大で15秒かかる可能性があります。\",\n \"Transaction successful\": \"取引が成功しました\",\n \"Transaction successful!\": \"取引に成功しました!\",\n \"Try again\": \"再試行する\",\n \"Try searching with a different term\": \"別の用語で検索してみてください\",\n \"Twitter\": \"Twitter\",\n \"Twitter username\": \"Twitterユーザー名\",\n \"Type the receiver address or domain\": \"受信者のアドレスまたはドメインを入力してください\",\n \"UNAVAILABLE\": \"利用不可\",\n \"Unable to fetch the price\": \"価格を取得できません\",\n \"Unset current domain\": \"現在のドメインを解除する\",\n \"Unsetting current domain...\": \"現在のドメインを解除中...\",\n \"Upgrade Smart Account to V3\": \"スマートアカウントをV3にアップグレード\",\n \"Upgrade Successful!\": \"アップグレード成功!\",\n \"Upgrade account\": \"アカウントをアップグレード\",\n \"Upgrading...\": \"アップグレード中...\",\n \"Use social login with VeChain\": \"VeChainでソーシャルログインを使用\",\n \"Use this token for future transactions\": \"今後の取引にこのトークンを使用する\",\n \"VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.\": \"VETはVeChainネットワークの主要な暗号通貨です。それはVeChainエコシステムでの価値と所有権を表し、株が企業での所有権を表すのと似ています。VETを保有すると、ネットワークのトランザクションに必要なVTHOが自動的に生成されます。\",\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\": \"VTHO(VeThor)はVeChainネットワークのエネルギーまたは「ガス」トークンです。ブロックチェーンとやり取りする際のトランザクション手数料を支払うために使用されます。VTHOはVETトークンを保有することで自動的に生成され、ネットワークの安定性を維持し、トランザクションコストを管理するための2トークンシステムが作成されます。\",\n \"VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.\": \"VeBetterDAOはVeChainブロックチェーン上の持続可能性に焦点を当てた分散型組織です。メンバーは、報酬としてB3TRトークンを使用し、提案での投票や週次トークン配分ラウンドでVOT3を使用してDAOのガバナンスに参加します。\",\n \"VeChain Kit\": \"VeChainキット\",\n \"VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.\": \"ヨーロッパのサンマリノに本社を置くVeChainは、画期的なブロックチェーンエコシステムであり、実世界のブロックチェーンの採用を推進する世界クラスのスマートコントラクトプラットフォームVeChainThorの開発者です。2015年にSunny Luによって設立されたVeChainは、透明で効率的、拡張可能で適応性のあるブロックチェーンソリューションの提供に一貫して取り組んでいます。\",\n \"VeWorld Wallet\": \"VeWorldウォレット\",\n \"Vechain Kit Policy\": \"Vechainキットポリシー\",\n \"View Current Policy\": \"現在のポリシーを見る\",\n \"View on explorer\": \"エクスプローラーで表示\",\n \"View transaction on the explorer\": \"エクスプローラーでトランザクションを表示\",\n \"Waiting for confirmation\": \"確認待ち\",\n \"Waiting for confirmation...\": \"確認を待っています...\",\n \"Waiting wallet confirmation...\": \"ウォレットの確認を待っています...\",\n \"Wallet\": \"ウォレット\",\n \"Wallet secured by\": \"によって保護されたウォレット\",\n \"We highly recommend exporting your private key to back up your wallet. This ensures you can restore it if needed or transfer it to self-custody using\": \"ウォレットをバックアップするために、秘密鍵をエクスポートすることを強くお勧めします。これにより、必要に応じて復元するか、自己管理に移行することができます。\",\n \"Website\": \"ウェブサイト\",\n \"Website URL\": \"ウェブサイトURL\",\n \"Website URL must start with https://\": \"ウェブサイトのURLはhttps://で始まる必要があります\",\n \"What is B3TR?\": \"B3TRとは?\",\n \"What is Privy?\": \"Privyとは何ですか?\",\n \"What is VET?\": \"VETとは何ですか?\",\n \"What is VTHO?\": \"VTHOとは何ですか?\",\n \"What is VeBetterDAO?\": \"VeBetterDAOとは何ですか?\",\n \"What is VeChain?\": \"VeChainとは何ですか?\",\n \"What is a Smart Account?\": \"スマートアカウントとは何ですか?\",\n \"What is a domain name?\": \"ドメイン名とは何ですか?\",\n \"What is a network?\": \"ネットワークとは何ですか?\",\n \"What is a wallet?\": \"ウォレットとは何ですか?\",\n \"What is an x2earn application?\": \"x2earnアプリケーションとは何ですか?\",\n \"What is fee delegation?\": \"料金の委任とは何ですか?\",\n \"When you have accepted a policy, it will appear here\": \"ポリシーを承認すると、ここに表示されます\",\n \"When you have notifications, they will appear here\": \"通知がある場合、ここに表示されます\",\n \"YOU OWN THIS\": \"所有しています\",\n \"You accepted current policy on {{date}}\": \"あなたは{{date}}に現在のポリシーを承認しました\",\n \"You are using an Embedded Wallet secured by your social login method, ensuring a seamless VeChain experience.\": \"ソーシャルログイン方法で保護された埋め込みウォレットを使用して、スムーズなVeChain体験を確保しています。\",\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\": \"クイックアクションセクションの送信アイコンをクリックしてトークンを送信できます。受取人のアドレスまたはVeChainのドメイン名を入力し、トークンを選択し、送信したい金額を指定します。\",\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\": \"ガストークンが有効になっていません。ガストークン設定で少なくとも1つのガストークンを有効にしてください。\",\n \"You have an active smart account associated to this wallet. It has been set as your main identity.\": \"このウォレットに関連付けられたアクティブなスマートアカウントがあります。これがあなたの主要な身元として設定されています。\",\n \"You may want to try establishing the connection again.\": \"接続の再確立を試みてください。\",\n \"You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.\": \"取引を行うには少なくとも1つのトークンを有効にする必要があります。有効なトークンがない場合、ガス代を支払うことができません。\",\n \"Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.\": \"あなたのアカウントは最新バージョンに正常にアップグレードされました。より良いユーザー体験、低いガスコスト、強化されたセキュリティをお楽しみください。\",\n \"Your address has been successfully set to {{name}}\": \"あなたのアドレスは正常に{{name}}に設定されました\",\n \"Your changes have been saved successfully.\": \"変更は正常に保存されました。\",\n \"Your domain has been unset successfully.\": \"あなたのドメインは正常に解除されました。\",\n \"Your embedded wallet\": \"あなたの埋め込みウォレット\",\n \"Your existing domains\": \"既存のドメイン\",\n \"Your smart account is already upgraded to this version.\": \"あなたのスマートアカウントはすでにこのバージョンにアップグレードされています。\",\n \"Your smart account needs to be upgraded to the latest version (v3).\": \"あなたのスマートアカウントは最新バージョン(v3)にアップグレードする必要があります。\",\n \"Your tokens\": \"あなたのトークン\",\n \"Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.\": \"ウォレットのセキュリティは、アクセス方法に依存します。VeWorld拡張機能やモバイルアプリ、ハードウェアウォレットなどの自己管理オプションを使用することで、秘密鍵を完全に管理できます。この拡張機能自体はあなたの秘密鍵にアクセスすることはありません。ソーシャルアカウントやVeChainを使用してログインする場合、ウォレットはPrivyによって作成され、保護され、VeChainによって管理され、セキュリティを維持しつつ容易なオンボーディング体験を提供します。\",\n \"collectibles\": \"Collectibles\",\n \"defi\": \"DeFi\",\n \"games\": \"Games\",\n \"here\": \"こちら\",\n \"marketplaces\": \"Marketplaces\",\n \"rate\": \"レート\",\n \"to learn more about embedded wallets.\": \"埋め込みウォレットについて詳しくはこちらをご覧ください。\",\n \"unavailable\": \"利用不可\",\n \"utilities\": \"Utilities\",\n \"vebetter\": \"VeBetter\",\n \"your@email.com\": \"your@email.com\"\n}","import i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\n// Import all language JSON files\nimport en from './src/languages/en.json';\nimport de from './src/languages/de.json';\nimport it from './src/languages/it.json';\nimport fr from './src/languages/fr.json';\nimport es from './src/languages/es.json';\nimport zh from './src/languages/zh.json';\nimport ja from './src/languages/ja.json';\n\n// Define supported languages\nexport const supportedLanguages = ['en', 'de', 'it', 'fr', 'es', 'zh', 'ja'];\n\nexport const resources = {\n en: { translation: en },\n de: { translation: de },\n it: { translation: it },\n fr: { translation: fr },\n es: { translation: es },\n zh: { translation: zh },\n ja: { translation: ja },\n};\n\n// Language names mapping\nexport const languageNames = {\n en: 'English',\n de: 'Deutsch',\n it: 'Italiano',\n fr: 'Français',\n es: 'Español',\n zh: '中文',\n ja: '日本語',\n};\n\nexport const bcp47LanguageCodes: Record<string, string> = {\n en: 'en-US',\n de: 'de-DE',\n it: 'it-IT',\n fr: 'fr-FR',\n es: 'es-ES',\n zh: 'zh-CN',\n ja: 'ja-JP',\n};\n\n// Custom language detector that checks localStorage first, then prop, then browser\nconst customLanguageDetector = {\n name: 'customDetector',\n lookup: (options?: { languages?: string[] } | undefined) => {\n // Check localStorage first (for persistence across page refreshes)\n if (typeof window !== 'undefined') {\n const storedLanguage = localStorage.getItem('i18nextLng');\n if (storedLanguage && supportedLanguages.includes(storedLanguage)) {\n return storedLanguage;\n }\n }\n\n // Get language from VechainKitProvider prop\n const propLanguage = options?.languages?.[0];\n\n if (propLanguage && supportedLanguages.includes(propLanguage)) {\n return propLanguage;\n }\n\n // Check if we're in a browser environment\n if (typeof window !== 'undefined') {\n // Get browser language\n const browserLang = navigator.language.split('-')[0];\n if (browserLang && supportedLanguages.includes(browserLang)) {\n return browserLang;\n }\n }\n\n return 'en'; // fallback\n },\n cacheUserLanguage: (lng: string) => {\n if (typeof window !== 'undefined') {\n localStorage.setItem('i18nextLng', lng);\n }\n },\n};\n\ni18n.use({\n type: 'languageDetector',\n async: false,\n init: () => {},\n detect: customLanguageDetector.lookup,\n cacheUserLanguage: customLanguageDetector.cacheUserLanguage,\n})\n .use(initReactI18next)\n .init({\n resources,\n fallbackLng: 'en',\n interpolation: {\n escapeValue: false,\n },\n });\n\nexport default i18n;\n","import { resources } from '../../i18n';\n\nexport const initializeI18n = (i18nInstance: any) => {\n // Get all languages from VeChainKit resources\n const languages = Object.keys(resources);\n\n // Add each language's translations to the existing i18n instance\n languages.forEach((lang) => {\n // Check if the namespace exists to avoid duplicates\n const hasNamespace = i18nInstance.hasResourceBundle(\n lang,\n 'translation',\n );\n\n if (!hasNamespace) {\n i18nInstance.addResourceBundle(\n lang,\n 'translation',\n resources[lang as keyof typeof resources].translation,\n true,\n true,\n );\n } else {\n // Merge with existing translations if namespace exists\n i18nInstance.addResourceBundle(\n lang,\n 'translation',\n resources[lang as keyof typeof resources].translation,\n true,\n true,\n );\n }\n });\n};\n","/**\n * Theme token system for VeChain Kit\n * Provides a single source of truth for all styling values\n */\n\n/**\n * Complete internal token type - all fields required\n */\nexport interface ThemeTokens {\n colors: {\n // Main structural backgrounds for components\n background: {\n modal: string; // Modal dialog background\n overlay: string; // Modal overlay background\n card: string; // Card container background\n cardElevated: string; // Elevated card background\n stickyHeader: string; // Sticky header background\n };\n text: {\n primary: string;\n secondary: string;\n tertiary: string;\n disabled: string;\n };\n border: {\n default: string;\n hover: string;\n focus: string;\n button: string;\n modal: string; // Modal dialog border\n };\n success: string;\n error: string;\n warning: string;\n };\n // Button-specific tokens - use these for button variants\n buttons: {\n button: {\n bg: string;\n color: string;\n border: string;\n hoverBg?: string; // Optional custom hover background color\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Optional border radius (Chakra UI rounded prop)\n };\n primaryButton: {\n bg: string;\n color: string;\n border: string;\n hoverBg?: string; // Optional custom hover background color\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Optional border radius (Chakra UI rounded prop)\n };\n tertiaryButton: {\n bg: string;\n color: string;\n border: string;\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Optional border radius (Chakra UI rounded prop)\n };\n loginButton: {\n bg: string;\n color: string;\n border: string;\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Optional border radius (Chakra UI rounded prop)\n };\n };\n effects: {\n backdropFilter: {\n modal: string;\n overlay: string;\n stickyHeader: string;\n };\n glassOpacity: {\n modal: number;\n overlay: number;\n stickyHeader: number;\n };\n };\n fonts: {\n body: string; // Font family for body text\n heading: string; // Font family for headings (h1-h6)\n sizes: {\n small: string;\n medium: string;\n large: string;\n };\n weights: {\n normal: number;\n medium: number;\n bold: number;\n };\n };\n borders: {\n radius: {\n small: string;\n medium: string;\n large: string;\n xl: string;\n full: string;\n modal: string; // Modal dialog border radius\n };\n };\n modal: {\n rounded?: string | number; // Optional border radius (Chakra UI rounded prop)\n };\n}\n\n/**\n * Developer-facing theme configuration\n * Simplified interface - only modal.backgroundColor and textColor required\n * All other colors are automatically derived from these base colors\n */\nexport interface VechainKitThemeConfig {\n textColor?: string;\n overlay?: {\n backgroundColor?: string; // Customize overlay background color\n blur?: string; // Customize overlay blur effect (e.g., \"blur(10px)\")\n };\n modal?: {\n backgroundColor?: string; // Base background color for modal (used to derive card, stickyHeader, etc. via opacity)\n border?: string; // Full CSS border string for modal dialog (e.g., \"1px solid rgba(255, 255, 255, 0.1)\")\n backdropFilter?: string; // Backdrop filter for modal dialog (e.g., \"blur(10px)\")\n borderRadius?: string; // Modal dialog border radius (e.g., \"24px\", \"1rem\") - deprecated, use rounded instead\n rounded?: string | number; // Border radius (Chakra UI rounded prop: \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"full\", or number)\n /**\n * Whether to use bottom sheet on mobile devices.\n * When false (default), uses regular modal on all screen sizes.\n * When true, uses bottom sheet on mobile (< 768px) and regular modal on desktop.\n */\n useBottomSheetOnMobile?: boolean;\n };\n buttons?: {\n secondaryButton?: {\n bg?: string;\n color?: string;\n border?: string; // Full CSS border string like \"1px solid #color\"\n hoverBg?: string; // Optional custom hover background color (if not provided, uses opacity)\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Border radius (Chakra UI rounded prop: \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"full\", or number)\n };\n primaryButton?: {\n bg?: string;\n color?: string;\n border?: string; // Full CSS border string like \"1px solid #color\"\n hoverBg?: string; // Optional custom hover background color (if not provided, uses opacity)\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Border radius (Chakra UI rounded prop: \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"full\", or number)\n };\n tertiaryButton?: {\n bg?: string;\n color?: string;\n border?: string; // Full CSS border string like \"1px solid #color\"\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Border radius (Chakra UI rounded prop: \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"full\", or number)\n };\n loginButton?: {\n bg?: string;\n color?: string;\n border?: string; // Full CSS border string like \"1px solid #color\"\n backdropFilter?: string; // Optional backdrop filter (e.g., \"blur(10px)\")\n rounded?: string | number; // Border radius (Chakra UI rounded prop: \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"full\", or number)\n };\n };\n fonts?: {\n family?: string; // Font family for both body and headings (backward compatibility)\n body?: string; // Font family for body text (e.g., \"Inter, sans-serif\")\n heading?: string; // Font family for headings (e.g., \"Satoshi, sans-serif\")\n sizes?: {\n small?: string; // Font size for small text (e.g., \"12px\")\n medium?: string; // Font size for medium text (e.g., \"14px\")\n large?: string; // Font size for large text (e.g., \"16px\")\n };\n weights?: {\n normal?: number; // Normal font weight (e.g., 400)\n medium?: number; // Medium font weight (e.g., 500)\n bold?: number; // Bold font weight (e.g., 700)\n };\n };\n effects?: {\n glass?: {\n enabled?: boolean;\n intensity?: 'low' | 'medium' | 'high';\n };\n backdropFilter?: {\n modal?: string; // Optional custom blur for modal\n overlay?: string; // Optional custom blur for overlay (deprecated, use overlay.blur)\n };\n };\n}\n\n/**\n * Convert hex color to rgba with opacity\n */\nfunction hexToRgba(hex: string, opacity: number): string {\n // Remove # if present\n hex = hex.replace('#', '');\n\n // Parse hex values\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n\n return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n}\n\n/**\n * Parse color string (hex, rgba, rgb, or named color) and return rgba with new opacity\n */\nfunction applyOpacity(color: string, opacity: number): string {\n // If already rgba/rgb, extract RGB values and apply new opacity\n const rgbaMatch = color.match(\n /rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*[\\d.]+)?\\)/,\n );\n if (rgbaMatch) {\n return `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, ${opacity})`;\n }\n\n // If hex, convert to rgba\n if (color.startsWith('#')) {\n return hexToRgba(color, opacity);\n }\n\n // Try to parse named colors or other formats by creating a temporary element\n // This handles CSS named colors like 'red', 'blue', etc.\n // Only works in browser environment (not SSR)\n if (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n document.body\n ) {\n try {\n const tempEl = document.createElement('div');\n tempEl.style.color = color;\n document.body.appendChild(tempEl);\n const computedColor = window.getComputedStyle(tempEl).color;\n document.body.removeChild(tempEl);\n\n // If we got a valid rgb/rgba color, extract and apply opacity\n const computedMatch = computedColor.match(\n /rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*[\\d.]+)?\\)/,\n );\n if (computedMatch) {\n return `rgba(${computedMatch[1]}, ${computedMatch[2]}, ${computedMatch[3]}, ${opacity})`;\n }\n } catch {\n // Fall through to fallback\n }\n }\n\n // Fallback: return as-is (for SSR or unsupported formats)\n // In practice, users should use hex or rgba colors\n return color;\n}\n\n/**\n * Derive background colors from base color with different opacities\n */\nfunction deriveBackgroundColors(\n baseColor: string,\n darkMode: boolean,\n defaultOverlayColor: string,\n overlayColor?: string,\n): ThemeTokens['colors']['background'] {\n // Use custom overlayColor if provided, otherwise use default overlay color\n // Never derive overlay from backgroundColor - always use default unless explicitly set\n const overlay = overlayColor || defaultOverlayColor;\n\n return {\n modal: baseColor, // 100% opacity\n card: applyOpacity(baseColor, 0.8),\n cardElevated: baseColor, // Same as modal for elevated\n overlay: overlay,\n stickyHeader: applyOpacity(baseColor, 0.9),\n };\n}\n\n/**\n * Derive text colors from base text color with opacity\n */\nfunction deriveTextColors(\n baseColor: string,\n darkMode: boolean,\n): ThemeTokens['colors']['text'] {\n return {\n primary: baseColor,\n secondary: applyOpacity(baseColor, 0.7),\n tertiary: applyOpacity(baseColor, 0.5),\n disabled: darkMode ? '#4A5568' : '#A0AEC0',\n };\n}\n\n/**\n * Derive border colors from background color with low opacity\n */\nfunction deriveBorderColors(\n baseColor: string,\n darkMode: boolean,\n modalBorder?: string,\n): ThemeTokens['colors']['border'] {\n const overlayColor = darkMode ? '#ffffff' : '#000000';\n return {\n default: applyOpacity(overlayColor, 0.1),\n hover: applyOpacity(overlayColor, 0.2),\n focus: darkMode ? '#3182CE' : '#2B6CB0',\n button: applyOpacity(overlayColor, 0.1),\n modal: modalBorder || 'none', // Use custom modal border or default to 'none'\n };\n}\n\ntype ButtonConfig = {\n hoverBg?: string; // Optional custom hover background color\n bg?: string;\n color?: string;\n border?: string;\n backdropFilter?: string; // Optional backdrop filter\n rounded?: string | number; // Optional border radius (Chakra UI rounded prop)\n};\n\n/**\n * Derive secondary button styles from backgroundColor and textColor\n */\nfunction deriveSecondaryButtonStyles(\n backgroundColor: string | undefined,\n textColor: string | undefined,\n darkMode: boolean,\n customConfig: ButtonConfig | undefined,\n defaultTokens: ThemeTokens,\n): ThemeTokens['buttons']['button'] {\n // Use custom config if provided\n if (customConfig) {\n return {\n bg: customConfig.bg || defaultTokens.buttons.button.bg,\n color: customConfig.color || defaultTokens.buttons.button.color,\n border: customConfig.border || defaultTokens.buttons.button.border,\n hoverBg: customConfig.hoverBg,\n backdropFilter: customConfig.backdropFilter,\n rounded: customConfig.rounded,\n };\n }\n\n // Derive from backgroundColor and textColor if available\n if (backgroundColor && textColor) {\n const overlayColor = darkMode ? '#ffffff' : '#000000';\n return {\n bg: applyOpacity(overlayColor, 0.1), // Similar to secondary.base\n color: textColor,\n border: `1px solid ${applyOpacity(overlayColor, 0.1)}`, // Similar to border.button\n };\n }\n\n // Use defaults\n return defaultTokens.buttons.button;\n}\n\n/**\n * Derive primary button styles\n */\nfunction derivePrimaryButtonStyles(\n backgroundColor: string | undefined,\n textColor: string | undefined,\n darkMode: boolean,\n customConfig: ButtonConfig | undefined,\n defaultTokens: ThemeTokens,\n): ThemeTokens['buttons']['primaryButton'] {\n // Use custom config if provided\n if (customConfig) {\n return {\n bg: customConfig.bg || defaultTokens.buttons.primaryButton.bg,\n color:\n customConfig.color || defaultTokens.buttons.primaryButton.color,\n border:\n customConfig.border ||\n defaultTokens.buttons.primaryButton.border,\n hoverBg: customConfig.hoverBg,\n backdropFilter: customConfig.backdropFilter,\n rounded: customConfig.rounded,\n };\n }\n\n // Derive from backgroundColor and textColor if available\n // Primary buttons typically use a primary color (defaults to blue)\n if (backgroundColor && textColor) {\n // Use default primary button color (which defaults to blue)\n // But allow customization via primaryButton config\n return {\n bg: defaultTokens.buttons.primaryButton.bg,\n color: defaultTokens.buttons.primaryButton.color,\n border: 'none',\n };\n }\n\n // Use defaults\n return defaultTokens.buttons.primaryButton;\n}\n\n/**\n * Derive tertiary button styles\n */\nfunction deriveTertiaryButtonStyles(\n backgroundColor: string | undefined,\n textColor: string | undefined,\n darkMode: boolean,\n customConfig: ButtonConfig | undefined,\n defaultTokens: ThemeTokens,\n): ThemeTokens['buttons']['tertiaryButton'] {\n // Use custom config if provided\n if (customConfig) {\n return {\n bg: customConfig.bg || defaultTokens.buttons.tertiaryButton.bg,\n color:\n customConfig.color ||\n defaultTokens.buttons.tertiaryButton.color,\n border:\n customConfig.border ||\n defaultTokens.buttons.tertiaryButton.border,\n backdropFilter: customConfig.backdropFilter,\n rounded: customConfig.rounded,\n };\n }\n\n // Derive from backgroundColor and textColor if available\n if (backgroundColor && textColor) {\n // Tertiary buttons are typically transparent with hover effects\n return {\n bg: 'transparent',\n color: textColor,\n border: 'none',\n };\n }\n\n // Use defaults\n return defaultTokens.buttons.tertiaryButton;\n}\n\n/**\n * Derive login button styles\n */\nfunction deriveLoginButtonStyles(\n backgroundColor: string | undefined,\n textColor: string | undefined,\n darkMode: boolean,\n customConfig: ButtonConfig | undefined,\n defaultTokens: ThemeTokens,\n): ThemeTokens['buttons']['loginButton'] {\n // Use custom config if provided\n if (customConfig) {\n return {\n bg: customConfig.bg || defaultTokens.buttons.loginButton.bg,\n color:\n customConfig.color || defaultTokens.buttons.loginButton.color,\n border:\n customConfig.border || defaultTokens.buttons.loginButton.border,\n backdropFilter: customConfig.backdropFilter,\n rounded: customConfig.rounded,\n };\n }\n\n // Use default login button styles (current hardcoded behavior)\n return defaultTokens.buttons.loginButton;\n}\n\n/**\n * Get glass effect settings based on intensity\n */\nfunction getGlassEffectSettings(\n intensity: 'low' | 'medium' | 'high',\n enabled: boolean,\n): {\n blur: string;\n modalOpacity: number;\n overlayOpacity: number;\n stickyHeaderOpacity: number;\n} {\n // Default blur values (used when glass is disabled or as fallback)\n const defaultBlur = {\n modal: 'blur(3px)',\n overlay: 'blur(3px)',\n stickyHeader: 'blur(20px)',\n };\n\n if (!enabled) {\n return {\n blur: defaultBlur.modal, // Use default blur even when glass is disabled\n modalOpacity: 1,\n overlayOpacity: 0.4,\n stickyHeaderOpacity: 0.9,\n };\n }\n\n const settings = {\n low: {\n blur: 'blur(4px)',\n modalOpacity: 0.4,\n overlayOpacity: 0.3,\n stickyHeaderOpacity: 0.7,\n },\n medium: {\n blur: 'blur(4px)',\n modalOpacity: 0.6,\n overlayOpacity: 0.4,\n stickyHeaderOpacity: 0.8,\n },\n high: {\n blur: 'blur(5px)',\n modalOpacity: 0.8,\n overlayOpacity: 0.5,\n stickyHeaderOpacity: 0.85,\n },\n };\n\n return settings[intensity];\n}\n\n/**\n * Default tokens for light mode\n */\nconst defaultLightTokens: ThemeTokens = {\n colors: {\n background: {\n modal: '#ffffff',\n overlay: 'rgba(0, 0, 0, 0.4)',\n card: '#f5f5f5',\n cardElevated: '#ffffff',\n stickyHeader: 'rgba(255, 255, 255, 0.69)',\n },\n text: {\n primary: '#2e2e2e',\n secondary: '#4d4d4d',\n tertiary: '#718096',\n disabled: '#A0AEC0',\n },\n border: {\n default: 'transparent',\n hover: '#d0d0d0',\n focus: '#2B6CB0',\n button: '#ebebeb',\n modal: 'none',\n },\n success: '#10ba3e',\n error: '#ef4444',\n warning: '#F6AD55',\n },\n buttons: {\n button: {\n bg: 'rgba(0, 0, 0, 0.1)',\n color: '#2e2e2e',\n border: 'none',\n },\n primaryButton: {\n bg: '#272A2E',\n color: 'white',\n rounded: 'full',\n border: 'none',\n },\n tertiaryButton: {\n bg: 'transparent',\n color: '#2e2e2e',\n border: 'none',\n },\n loginButton: {\n bg: 'white',\n color: '#1a1a1a',\n border: '1px solid transparent',\n },\n },\n effects: {\n backdropFilter: {\n modal: 'blur(3px)',\n overlay: 'blur(3px)',\n stickyHeader: 'blur(12px)',\n },\n glassOpacity: {\n modal: 1,\n overlay: 0.4,\n stickyHeader: 0.69,\n },\n },\n fonts: {\n body: 'Inter, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n heading:\n 'Satoshi, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n sizes: {\n small: '12px',\n medium: '14px',\n large: '16px',\n },\n weights: {\n normal: 400,\n medium: 500,\n bold: 700,\n },\n },\n borders: {\n radius: {\n small: '8px',\n medium: '12px',\n large: '16px',\n xl: '24px',\n full: '9999px',\n modal: '24px',\n },\n },\n modal: {\n rounded: undefined,\n },\n};\n\n/**\n * Default tokens for dark mode\n */\nconst defaultDarkTokens: ThemeTokens = {\n colors: {\n background: {\n modal: '#151515',\n overlay: 'rgba(0, 0, 0, 0.6)',\n card: 'rgba(0, 0, 0, 0.3)',\n cardElevated: '#2a2a2a',\n stickyHeader: 'rgba(31, 31, 30, 0.9)',\n },\n text: {\n primary: 'rgb(223, 223, 221)',\n secondary: 'rgba(223, 223, 221, 0.6)',\n tertiary: 'rgba(223, 223, 221, 0.4)',\n disabled: 'rgba(223, 223, 221, 0.2)',\n },\n border: {\n default: 'rgba(255, 255, 255, 0.1)',\n hover: 'rgba(255, 255, 255, 0.2)',\n focus: '#3182CE',\n button: 'rgba(255, 255, 255, 0.1)',\n modal: 'none',\n },\n success: '#00ff45de',\n error: '#ef4444',\n warning: '#F6AD55',\n },\n buttons: {\n button: {\n bg: 'rgba(255, 255, 255, 0.05)',\n color: 'rgb(223, 223, 221)',\n border: 'none',\n },\n primaryButton: {\n bg: 'white',\n color: 'blackAlpha.900',\n border: 'none',\n rounded: 'full',\n },\n tertiaryButton: {\n bg: 'transparent',\n color: 'rgb(223, 223, 221)',\n border: 'none',\n },\n loginButton: {\n bg: 'transparent',\n color: 'white',\n border: '1px solid rgba(255, 255, 255, 0.1)',\n },\n },\n effects: {\n backdropFilter: {\n modal: 'blur(3px)',\n overlay: 'blur(3px)',\n stickyHeader: 'blur(12px)',\n },\n glassOpacity: {\n modal: 1,\n overlay: 0.6,\n stickyHeader: 0.9,\n },\n },\n fonts: {\n body: 'Inter, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n heading:\n 'Satoshi, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n sizes: {\n small: '12px',\n medium: '14px',\n large: '16px',\n },\n weights: {\n normal: 400,\n medium: 500,\n bold: 700,\n },\n },\n borders: {\n radius: {\n small: '8px',\n medium: '12px',\n large: '16px',\n xl: '24px',\n full: '9999px',\n modal: '24px',\n },\n },\n modal: {\n rounded: undefined,\n },\n};\n\n/**\n * Get default tokens for a given mode\n */\nexport const getDefaultTokens = (darkMode: boolean): ThemeTokens => {\n return darkMode ? defaultDarkTokens : defaultLightTokens;\n};\n\n/**\n * Deep merge utility for tokens\n * Merges custom tokens into default tokens, only including provided keys\n */\nexport function mergeTokens(\n defaultTokens: ThemeTokens,\n customTokens: Partial<ThemeTokens>,\n): ThemeTokens {\n const merged: ThemeTokens = { ...defaultTokens };\n\n if (customTokens.colors) {\n merged.colors = {\n ...defaultTokens.colors,\n ...customTokens.colors,\n };\n\n if (customTokens.colors.background) {\n merged.colors.background = {\n ...defaultTokens.colors.background,\n ...customTokens.colors.background,\n };\n }\n\n if (customTokens.colors.text) {\n merged.colors.text = {\n ...defaultTokens.colors.text,\n ...customTokens.colors.text,\n };\n }\n\n if (customTokens.colors.border) {\n merged.colors.border = {\n ...defaultTokens.colors.border,\n ...customTokens.colors.border,\n };\n // Ensure button border defaults to default if not provided\n if (!customTokens.colors.border.button) {\n merged.colors.border.button =\n defaultTokens.colors.border.button;\n }\n }\n }\n\n if (customTokens.effects) {\n merged.effects = {\n ...defaultTokens.effects,\n ...customTokens.effects,\n };\n\n if (customTokens.effects.backdropFilter) {\n merged.effects.backdropFilter = {\n ...defaultTokens.effects.backdropFilter,\n ...customTokens.effects.backdropFilter,\n };\n }\n\n if (customTokens.effects.glassOpacity) {\n merged.effects.glassOpacity = {\n ...defaultTokens.effects.glassOpacity,\n ...customTokens.effects.glassOpacity,\n };\n }\n }\n\n if (customTokens.fonts) {\n merged.fonts = {\n ...defaultTokens.fonts,\n ...customTokens.fonts,\n };\n\n // Ensure body and heading are set (use body as fallback for heading if not provided)\n if (customTokens.fonts.body) {\n merged.fonts.body = customTokens.fonts.body;\n }\n if (customTokens.fonts.heading) {\n merged.fonts.heading = customTokens.fonts.heading;\n }\n\n if (customTokens.fonts.sizes) {\n merged.fonts.sizes = {\n ...defaultTokens.fonts.sizes,\n ...customTokens.fonts.sizes,\n };\n }\n\n if (customTokens.fonts.weights) {\n merged.fonts.weights = {\n ...defaultTokens.fonts.weights,\n ...customTokens.fonts.weights,\n };\n }\n }\n\n if (customTokens.borders) {\n merged.borders = {\n ...defaultTokens.borders,\n ...customTokens.borders,\n };\n\n if (customTokens.borders.radius) {\n merged.borders.radius = {\n ...defaultTokens.borders.radius,\n ...customTokens.borders.radius,\n };\n }\n }\n\n if (customTokens.buttons) {\n merged.buttons = {\n ...defaultTokens.buttons,\n ...customTokens.buttons,\n };\n\n if (customTokens.buttons.button) {\n merged.buttons.button = {\n ...defaultTokens.buttons.button,\n ...customTokens.buttons.button,\n };\n }\n\n if (customTokens.buttons.primaryButton) {\n merged.buttons.primaryButton = {\n ...defaultTokens.buttons.primaryButton,\n ...customTokens.buttons.primaryButton,\n };\n }\n\n if (customTokens.buttons.tertiaryButton) {\n merged.buttons.tertiaryButton = {\n ...defaultTokens.buttons.tertiaryButton,\n ...customTokens.buttons.tertiaryButton,\n };\n }\n\n if (customTokens.buttons.loginButton) {\n merged.buttons.loginButton = {\n ...defaultTokens.buttons.loginButton,\n ...customTokens.buttons.loginButton,\n };\n }\n }\n\n return merged;\n}\n\n/**\n * Convert developer-facing config to internal tokens\n * Derives all colors from modal.backgroundColor and textColor\n */\nexport function convertThemeConfigToTokens(\n config: VechainKitThemeConfig | undefined,\n darkMode: boolean,\n): Partial<ThemeTokens> {\n if (!config) {\n return {};\n }\n\n const tokens: Partial<ThemeTokens> = {};\n const defaultTokens = getDefaultTokens(darkMode);\n\n // Derive colors from modal.backgroundColor and textColor\n // Always initialize colors if any color-related config is provided\n const overlayBgColor = config.overlay?.backgroundColor;\n\n const modalBgColor = config.modal?.backgroundColor;\n\n if (\n modalBgColor ||\n config.textColor ||\n overlayBgColor ||\n config.buttons ||\n config.modal\n ) {\n tokens.colors = {} as ThemeTokens['colors'];\n\n // Derive background colors from modal.backgroundColor\n if (modalBgColor) {\n tokens.colors.background = deriveBackgroundColors(\n modalBgColor,\n darkMode,\n defaultTokens.colors.background.overlay, // Pass default overlay color\n overlayBgColor, // Use custom overlay backgroundColor if provided\n );\n } else if (overlayBgColor) {\n // If only overlay backgroundColor is provided, use defaults for other backgrounds\n const defaultBg = defaultTokens.colors.background;\n tokens.colors.background = {\n ...defaultBg,\n overlay: overlayBgColor,\n };\n } else {\n // Use defaults if no modal backgroundColor or overlay backgroundColor provided\n tokens.colors.background = defaultTokens.colors.background;\n }\n\n // Derive text colors from textColor\n if (config.textColor) {\n tokens.colors.text = deriveTextColors(config.textColor, darkMode);\n }\n\n // Derive border colors from modal.backgroundColor or handle modal border customization\n if (modalBgColor) {\n tokens.colors.border = deriveBorderColors(\n modalBgColor,\n darkMode,\n config.modal?.border,\n );\n } else if (config.modal?.border) {\n // If only modal border is provided, use default borders but override modal border\n tokens.colors.border = {\n ...defaultTokens.colors.border,\n modal: config.modal.border,\n };\n }\n\n // Keep error/success/warning as defaults\n tokens.colors.error = defaultTokens.colors.error;\n tokens.colors.success = defaultTokens.colors.success;\n tokens.colors.warning = defaultTokens.colors.warning;\n }\n\n // Handle modal border radius (support both borderRadius for backward compatibility and rounded)\n const modalBorderRadius =\n config.modal?.rounded ?? config.modal?.borderRadius;\n if (modalBorderRadius) {\n if (!tokens.borders) {\n tokens.borders = {\n ...defaultTokens.borders,\n };\n }\n // Convert rounded to string if it's a number or Chakra size string\n const borderRadiusValue =\n typeof modalBorderRadius === 'number'\n ? `${modalBorderRadius}px`\n : modalBorderRadius;\n tokens.borders.radius = {\n ...defaultTokens.borders.radius,\n ...tokens.borders.radius,\n modal: borderRadiusValue,\n };\n }\n\n // Handle modal rounded property\n tokens.modal = {\n rounded: config.modal?.rounded ?? defaultTokens.modal.rounded,\n };\n\n // Handle glass effect settings\n // Always initialize effects to ensure they're always available\n tokens.effects = {} as ThemeTokens['effects'];\n\n if (config.effects) {\n const glassEnabled =\n config.effects.glass?.enabled !== undefined\n ? config.effects.glass.enabled\n : true;\n const glassIntensity = config.effects.glass?.intensity || 'medium';\n\n const glassSettings = getGlassEffectSettings(\n glassIntensity,\n glassEnabled,\n );\n\n // Apply glass effect to backdrop filters\n // When glass is disabled, use default blur values instead of 'none'\n // Overlay blur can be customized independently via overlay.blur (new) or effects.backdropFilter.overlay (deprecated)\n const overlayBlur =\n config.overlay?.blur || config.effects.backdropFilter?.overlay;\n\n // Modal backdropFilter priority: modal.backdropFilter > effects.backdropFilter.modal > glass settings > default\n const modalBackdropFilter =\n config.modal?.backdropFilter ||\n config.effects.backdropFilter?.modal ||\n (glassEnabled\n ? glassSettings.blur\n : defaultTokens.effects.backdropFilter.modal);\n\n tokens.effects.backdropFilter = {\n modal: modalBackdropFilter,\n overlay:\n overlayBlur ||\n (glassEnabled\n ? glassSettings.blur\n : defaultTokens.effects.backdropFilter.overlay),\n stickyHeader: glassEnabled\n ? glassSettings.blur\n : defaultTokens.effects.backdropFilter.stickyHeader,\n };\n\n // Apply glass opacity to backgrounds if enabled\n // Note: overlay color is NOT affected by glass opacity - it uses overlay.backgroundColor directly\n tokens.effects.glassOpacity = {\n modal: glassSettings.modalOpacity,\n overlay: glassSettings.overlayOpacity,\n stickyHeader: glassSettings.stickyHeaderOpacity,\n };\n\n // Update background colors with glass opacity if glass is enabled\n if (glassEnabled) {\n // Ensure colors.background is initialized\n if (!tokens.colors) {\n tokens.colors = {} as ThemeTokens['colors'];\n }\n if (!tokens.colors.background) {\n tokens.colors.background = {\n ...defaultTokens.colors.background,\n };\n }\n\n if (modalBgColor) {\n // Use custom modal.backgroundColor with glass opacity\n tokens.colors.background.modal = applyOpacity(\n modalBgColor,\n glassSettings.modalOpacity,\n );\n tokens.colors.background.stickyHeader = applyOpacity(\n modalBgColor,\n glassSettings.stickyHeaderOpacity,\n );\n } else {\n // Apply glass opacity to default background colors\n const defaultModalBg = defaultTokens.colors.background.modal;\n const defaultStickyHeaderBg =\n defaultTokens.colors.background.stickyHeader;\n\n // Extract base color from default backgrounds and apply glass opacity\n // For rgba colors, we need to extract the RGB values and apply new opacity\n tokens.colors.background.modal = applyOpacity(\n defaultModalBg,\n glassSettings.modalOpacity,\n );\n tokens.colors.background.stickyHeader = applyOpacity(\n defaultStickyHeaderBg,\n glassSettings.stickyHeaderOpacity,\n );\n }\n // Overlay color is already set correctly from overlay.backgroundColor or default\n // Don't modify it here\n }\n } else {\n // If no effects config provided, use default backdrop filters\n // But still check for overlay.blur and modal.backdropFilter\n const overlayBlur = config.overlay?.blur;\n tokens.effects.backdropFilter = {\n ...defaultTokens.effects.backdropFilter,\n modal:\n config.modal?.backdropFilter ||\n defaultTokens.effects.backdropFilter.modal,\n overlay:\n overlayBlur || defaultTokens.effects.backdropFilter.overlay,\n };\n tokens.effects.glassOpacity = defaultTokens.effects.glassOpacity;\n }\n\n // Ensure overlay backgroundColor is always respected (after all processing)\n if (overlayBgColor && tokens.colors?.background) {\n tokens.colors.background.overlay = overlayBgColor;\n }\n\n // Handle font customization\n if (config.fonts) {\n tokens.fonts = {} as ThemeTokens['fonts'];\n const defaultFonts = defaultTokens.fonts;\n\n // Font families - support backward compatibility with `family` prop\n // If `family` is provided, use it for both body and heading\n // Otherwise, use separate `body` and `heading` props\n if (config.fonts.family) {\n // Backward compatibility: use `family` for both\n tokens.fonts.body = config.fonts.family;\n tokens.fonts.heading = config.fonts.family;\n } else {\n tokens.fonts.body = config.fonts.body ?? defaultFonts.body;\n tokens.fonts.heading = config.fonts.heading ?? defaultFonts.heading;\n }\n\n // Font sizes\n tokens.fonts.sizes = {\n small: config.fonts.sizes?.small ?? defaultFonts.sizes.small,\n medium: config.fonts.sizes?.medium ?? defaultFonts.sizes.medium,\n large: config.fonts.sizes?.large ?? defaultFonts.sizes.large,\n };\n\n // Font weights\n tokens.fonts.weights = {\n normal: config.fonts.weights?.normal ?? defaultFonts.weights.normal,\n medium: config.fonts.weights?.medium ?? defaultFonts.weights.medium,\n bold: config.fonts.weights?.bold ?? defaultFonts.weights.bold,\n };\n }\n\n // Derive button styles\n tokens.buttons = {} as ThemeTokens['buttons'];\n tokens.buttons.button = deriveSecondaryButtonStyles(\n modalBgColor,\n config.textColor,\n darkMode,\n config.buttons?.secondaryButton,\n defaultTokens,\n );\n tokens.buttons.primaryButton = derivePrimaryButtonStyles(\n modalBgColor,\n config.textColor,\n darkMode,\n config.buttons?.primaryButton,\n defaultTokens,\n );\n tokens.buttons.tertiaryButton = deriveTertiaryButtonStyles(\n modalBgColor,\n config.textColor,\n darkMode,\n config.buttons?.tertiaryButton,\n defaultTokens,\n );\n tokens.buttons.loginButton = deriveLoginButtonStyles(\n modalBgColor,\n config.textColor,\n darkMode,\n config.buttons?.loginButton,\n defaultTokens,\n );\n\n return tokens;\n}\n","/**\n * CSS variable generators for DAppKit and Privy\n * Converts ThemeTokens to CSS variable objects\n */\n\nimport { ThemeTokens } from '@/theme/tokens';\nimport { CustomizedStyle } from '@vechain/dapp-kit-ui';\n\n/**\n * Slightly increase opacity for Privy modals to improve readability\n * while maintaining the glass effect appearance\n */\nexport function improvePrivyReadability(\n color: string,\n darkMode: boolean,\n): string {\n // If it's already a solid color (hex or rgb without alpha), return as-is\n if (!color.includes('rgba') && !color.includes('hsla')) {\n return color;\n }\n\n // Extract rgba values\n const rgbaMatch = color.match(\n /rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*([\\d.]+))?\\)/,\n );\n if (rgbaMatch) {\n const r = parseInt(rgbaMatch[1], 10);\n const g = parseInt(rgbaMatch[2], 10);\n const b = parseInt(rgbaMatch[3], 10);\n const alpha = rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1;\n\n // If alpha is already high, return as-is to maintain glass effect\n if (alpha >= 0.9) {\n return color;\n }\n\n // Only slightly increase opacity (by ~0.15-0.2) to improve readability\n // while maintaining the glass effect look\n const minAlpha = darkMode ? 0.9 : 0.91;\n const targetAlpha = Math.min(Math.max(alpha + 0.15, minAlpha), 0.91);\n return `rgba(${r}, ${g}, ${b}, ${targetAlpha})`;\n }\n\n // If we can't parse it, return the original color\n return color;\n}\n\n/**\n * Generate DAppKit CSS variables from ThemeTokens\n */\nexport function generateDAppKitCSSVariables(\n tokens: ThemeTokens,\n darkMode: boolean,\n): CustomizedStyle {\n const vars: CustomizedStyle = {\n '--vdk-modal-z-index': '10000',\n '--vdk-modal-width': '22rem',\n '--vdk-modal-backdrop-filter': tokens.effects.backdropFilter.modal,\n '--vdk-border-dark-source-card': `1px solid ${tokens.colors.border.default}`,\n '--vdk-border-light-source-card': `1px solid ${tokens.colors.border.default}`,\n '--vdk-font-family': tokens.fonts.body,\n '--vdk-font-size-medium': tokens.fonts.sizes.medium,\n '--vdk-font-size-large': tokens.fonts.sizes.large,\n '--vdk-font-weight-medium': tokens.fonts.weights.medium.toString(),\n };\n\n // Use loginIn variant style: white (light) / transparent (dark) background\n // For hover/active, derive colors that simulate the opacity: 0.5 effect\n // DAppKit uses these CSS variables for background colors\n if (darkMode) {\n vars['--vdk-color-dark-primary'] = 'transparent'; // loginIn dark mode bg\n // For transparent base, use a subtle white overlay to simulate dimming\n // This creates a visual effect similar to opacity: 0.5\n vars['--vdk-color-dark-primary-hover'] = 'rgba(255, 255, 255, 0.05)'; // Subtle white overlay\n vars['--vdk-color-dark-primary-active'] = 'rgba(255, 255, 255, 0.1)'; // Slightly more visible\n // DAppKit uses secondary color for modal background\n vars['--vdk-color-dark-secondary'] = tokens.colors.background.modal;\n // DAppKit uses tertiary color for text\n vars['--vdk-color-dark-tertiary'] = tokens.colors.text.primary;\n } else {\n vars['--vdk-color-light-primary'] = '#ffffff'; // loginIn light mode bg\n // For white base, use a slightly grayed white to simulate opacity: 0.5\n // This makes the button appear dimmed on hover\n vars['--vdk-color-light-primary-hover'] = 'rgba(245, 245, 245, 0.8)'; // Slightly grayed white\n vars['--vdk-color-light-primary-active'] = 'rgba(240, 240, 240, 0.8)'; // Slightly darker for active\n // DAppKit uses secondary color for modal background\n vars['--vdk-color-light-secondary'] = tokens.colors.background.modal;\n // DAppKit uses tertiary color for text\n vars['--vdk-color-light-tertiary'] = tokens.colors.text.primary;\n }\n\n return vars;\n}\n\n/**\n * Generate Privy CSS variables from ThemeTokens\n * Note: Privy modals don't support backdrop filters natively, so we:\n * 1. Slightly increase opacity for readability while maintaining glass effect\n * 2. Inject CSS to apply backdrop filters to Privy modals\n * 3. Map primary hover/active colors to Privy button states (background-2/background-3)\n * 4. Inject CSS to apply card colors to Privy card elements directly\n */\nexport function generatePrivyCSSVariables(\n tokens: ThemeTokens,\n darkMode: boolean,\n): Record<string, string> {\n // Slightly improve readability while maintaining glass effect\n const privyModalBg = improvePrivyReadability(\n tokens.colors.background.modal,\n darkMode,\n );\n\n // Use loginIn variant style: white (light) / transparent (dark) background\n // For hover/active, we'll apply opacity: 0.5 via CSS injection\n const privyButtonBaseBg = darkMode ? 'transparent' : '#ffffff';\n const privyButtonHoverBg = darkMode ? 'transparent' : '#ffffff';\n const privyButtonActiveBg = darkMode ? 'transparent' : '#ffffff';\n\n const variables: Record<string, string> = {\n '--privy-border-radius-sm': tokens.borders.radius.small,\n '--privy-border-radius-md': tokens.borders.radius.medium,\n '--privy-border-radius-lg': tokens.borders.radius.large,\n '--privy-border-radius-full': tokens.borders.radius.full,\n '--privy-color-background': privyModalBg,\n // Use loginIn variant style: white (light) / transparent (dark) background\n // Hover/active will use opacity: 0.5 via CSS injection\n '--privy-color-background-2': privyButtonHoverBg,\n '--privy-color-background-3': privyButtonActiveBg,\n '--privy-color-foreground': tokens.colors.text.primary,\n '--privy-color-foreground-2': tokens.colors.text.primary, // Privy uses this for primary text\n '--privy-color-foreground-3': tokens.colors.text.secondary, // Privy uses this for secondary text\n '--privy-color-foreground-4': tokens.colors.text.tertiary, // Privy uses this for tertiary text\n // Use loginIn text colors: #1a1a1a (light) / white (dark)\n '--privy-color-foreground-accent': darkMode ? '#ffffff' : '#1a1a1a',\n '--privy-color-accent': privyButtonBaseBg, // loginIn background color\n '--privy-color-accent-light': privyButtonHoverBg,\n '--privy-color-accent-lightest': privyButtonActiveBg,\n '--privy-color-accent-dark': privyButtonHoverBg,\n '--privy-color-accent-darkest': privyButtonActiveBg,\n '--privy-color-success': tokens.colors.success,\n '--privy-color-error': tokens.colors.error,\n '--privy-color-error-light': tokens.colors.error + '33',\n };\n\n return variables;\n}\n\n/**\n * Apply DAppKit button styles (hover opacity matching loginIn variant)\n */\nexport function applyDAppKitButtonStyles(): void {\n if (typeof document === 'undefined') return;\n\n const styleId = 'vechain-kit-dappkit-button-styles';\n let styleElement = document.getElementById(styleId);\n\n if (!styleElement) {\n styleElement = document.createElement('style');\n styleElement.id = styleId;\n document.head.appendChild(styleElement);\n }\n\n // Target DAppKit wallet source buttons/cards\n // Apply hover/active opacity to match loginIn variant style\n // Target all button-like elements (buttons, clickable divs, elements with cursor pointer)\n const cssRules = `\n /* CRITICAL: Ensure dappkit modal always has pointer-events enabled */\n /* This fixes an issue where the modal becomes unclickable when opened on top of bottom sheet */\n vdk-modal,\n [data-vdk-modal],\n [id*=\"vdk-modal\"] {\n pointer-events: all !important;\n }\n \n /* DAppKit wallet source buttons - apply loginIn hover style */\n /* Target all button-like elements within DAppKit containers */\n [class*=\"vdk\"] button,\n [class*=\"vdk\"] [role=\"button\"],\n [class*=\"vdk\"] [tabindex],\n [id*=\"vdk\"] button,\n [id*=\"vdk\"] [role=\"button\"],\n [id*=\"vdk\"] [tabindex],\n [data-vdk-modal] button,\n [data-vdk-modal] [role=\"button\"],\n [data-vdk-modal] [tabindex],\n [data-vdk-source-card],\n [class*=\"vdk-source-card\"],\n [class*=\"source-card\"],\n button[class*=\"vdk\"],\n [data-vdk-button],\n [class*=\"vdk-button\"],\n /* Target elements that are likely buttons based on styling */\n [class*=\"vdk\"] [style*=\"cursor\"][style*=\"pointer\"],\n [id*=\"vdk\"] [style*=\"cursor\"][style*=\"pointer\"],\n [data-vdk-modal] [style*=\"cursor\"][style*=\"pointer\"] {\n transition: opacity 0.2s ease !important;\n }\n \n /* Hover states */\n [class*=\"vdk\"] button:hover,\n [class*=\"vdk\"] [role=\"button\"]:hover,\n [class*=\"vdk\"] [tabindex]:hover,\n [id*=\"vdk\"] button:hover,\n [id*=\"vdk\"] [role=\"button\"]:hover,\n [id*=\"vdk\"] [tabindex]:hover,\n [data-vdk-modal] button:hover,\n [data-vdk-modal] [role=\"button\"]:hover,\n [data-vdk-modal] [tabindex]:hover,\n [data-vdk-source-card]:hover,\n [class*=\"vdk-source-card\"]:hover,\n [class*=\"source-card\"]:hover,\n button[class*=\"vdk\"]:hover,\n [data-vdk-button]:hover,\n [class*=\"vdk-button\"]:hover,\n [class*=\"vdk\"] [style*=\"cursor\"][style*=\"pointer\"]:hover,\n [id*=\"vdk\"] [style*=\"cursor\"][style*=\"pointer\"]:hover,\n [data-vdk-modal] [style*=\"cursor\"][style*=\"pointer\"]:hover {\n opacity: 0.5 !important;\n }\n \n /* Active states */\n [class*=\"vdk\"] button:active,\n [class*=\"vdk\"] [role=\"button\"]:active,\n [class*=\"vdk\"] [tabindex]:active,\n [id*=\"vdk\"] button:active,\n [id*=\"vdk\"] [role=\"button\"]:active,\n [id*=\"vdk\"] [tabindex]:active,\n [data-vdk-modal] button:active,\n [data-vdk-modal] [role=\"button\"]:active,\n [data-vdk-modal] [tabindex]:active,\n [data-vdk-source-card]:active,\n [class*=\"vdk-source-card\"]:active,\n [class*=\"source-card\"]:active,\n button[class*=\"vdk\"]:active,\n [data-vdk-button]:active,\n [class*=\"vdk-button\"]:active,\n [class*=\"vdk\"] [style*=\"cursor\"][style*=\"pointer\"]:active,\n [id*=\"vdk\"] [style*=\"cursor\"][style*=\"pointer\"]:active,\n [data-vdk-modal] [style*=\"cursor\"][style*=\"pointer\"]:active {\n opacity: 0.5 !important;\n }\n `;\n\n styleElement.textContent = cssRules;\n\n // Use MutationObserver to apply styles to dynamically added DAppKit elements\n if (typeof MutationObserver !== 'undefined') {\n const observer = new MutationObserver(() => {\n // Ensure dappkit modal always has pointer-events enabled\n const dappKitModals = document.querySelectorAll(\n 'vdk-modal, [data-vdk-modal], [id*=\"vdk-modal\"]',\n );\n for (const element of dappKitModals) {\n if (!(element instanceof HTMLElement)) continue;\n element.style.setProperty('pointer-events', 'all', 'important');\n }\n\n // Re-apply styles when DAppKit adds new elements\n const dappKitElements = document.querySelectorAll(\n '[data-vdk-source-card], [class*=\"vdk-source-card\"], [class*=\"source-card\"], [data-vdk-modal] button, [data-vdk-modal] [role=\"button\"]',\n );\n for (const element of dappKitElements) {\n if (!(element instanceof HTMLElement)) continue;\n element.style.setProperty('opacity', '1', 'important');\n element.style.setProperty(\n 'transition',\n 'opacity 0.2s ease',\n 'important',\n );\n }\n });\n\n // Observe the document body for DAppKit modal additions\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n // Cleanup observer after a delay (DAppKit modals are typically short-lived)\n setTimeout(() => {\n observer.disconnect();\n }, 60000); // Disconnect after 60 seconds\n }\n}\n\n/**\n * Apply Privy CSS variables to document body and inject backdrop filter + card styles\n */\nexport function applyPrivyCSSVariables(\n variables: Record<string, string>,\n backdropFilter?: string,\n cardBg?: string,\n cardElevatedBg?: string,\n buttonBaseColor?: string,\n buttonHoverColor?: string,\n buttonActiveColor?: string,\n borderColor?: string,\n): void {\n if (typeof document === 'undefined') return;\n\n const root = document.documentElement;\n Object.entries(variables).forEach(([key, value]) => {\n root.style.setProperty(key, value);\n });\n\n // Inject CSS for backdrop filters, card backgrounds, and button colors\n const styleId = 'vechain-kit-privy-styles';\n let styleElement = document.getElementById(styleId);\n\n if (!styleElement) {\n styleElement = document.createElement('style');\n styleElement.id = styleId;\n document.head.appendChild(styleElement);\n }\n\n const cssRules: string[] = [];\n\n // Apply backdrop filter to Privy modal containers\n if (backdropFilter) {\n cssRules.push(`\n [data-privy-dialog-overlay],\n [data-privy-dialog-content],\n .privy-dialog-overlay,\n .privy-dialog-content {\n backdrop-filter: ${backdropFilter} !important;\n -webkit-backdrop-filter: ${backdropFilter} !important;\n }\n `);\n }\n\n // Apply card backgrounds to Privy card/container elements\n // Target common Privy card selectors without affecting button hover states\n if (cardBg) {\n cssRules.push(`\n [data-privy-card],\n .privy-card,\n [class*=\"privy-card\"],\n [class*=\"privy-connect-wallet-card\"],\n [class*=\"privy-account-card\"] {\n background-color: ${cardBg} !important;\n }\n `);\n }\n\n if (cardElevatedBg) {\n cssRules.push(`\n [data-privy-card][data-elevated],\n .privy-card-elevated,\n [class*=\"privy-card\"][class*=\"elevated\"] {\n background-color: ${cardElevatedBg} !important;\n }\n `);\n }\n\n // Apply loginIn variant style to Privy login method buttons\n // Base: white (light) / transparent (dark)\n // Hover/Active: opacity: 0.5 (matching loginIn variant)\n if (buttonBaseColor) {\n const borderColorValue = borderColor || 'rgba(0, 0, 0, 0.1)';\n cssRules.push(`\n #headlessui-portal-root .login-method-button,\n #headlessui-portal-root [class*=\"login-method-button\"],\n .login-method-button {\n background-color: ${buttonBaseColor} !important;\n border: 1px solid ${borderColorValue} !important;\n }\n `);\n }\n\n // Apply hover state with opacity: 0.5 (matching loginIn variant)\n if (buttonHoverColor) {\n cssRules.push(`\n #headlessui-portal-root .login-method-button:hover,\n #headlessui-portal-root [class*=\"login-method-button\"]:hover,\n .login-method-button:hover {\n background-color: ${buttonHoverColor} !important;\n opacity: 0.5 !important;\n }\n `);\n }\n\n // Apply active state with opacity: 0.5 (matching loginIn variant)\n if (buttonActiveColor) {\n cssRules.push(`\n #headlessui-portal-root .login-method-button:active,\n #headlessui-portal-root [class*=\"login-method-button\"]:active,\n .login-method-button:active {\n background-color: ${buttonActiveColor} !important;\n opacity: 0.5 !important;\n }\n `);\n }\n\n if (cssRules.length > 0) {\n styleElement.textContent = cssRules.join('\\n');\n }\n}\n","import React, { ReactNode } from 'react';\nimport {\n QueryClient,\n QueryClientProvider,\n QueryClientContext,\n} from '@tanstack/react-query';\nimport { hashFn } from 'wagmi/query';\n\n// Singleton instance for internal QueryClient\nlet internalQueryClient: QueryClient | null = null;\n\n// Function to safely get the QueryClient\nexport function getOrCreateQueryClient(): QueryClient {\n if (!internalQueryClient) {\n internalQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n queryKeyHashFn: hashFn,\n retry: 0,\n staleTime: 30000,\n refetchOnWindowFocus: true,\n refetchOnMount: true,\n refetchOnReconnect: true,\n refetchInterval: false,\n refetchIntervalInBackground: false,\n },\n },\n });\n }\n return internalQueryClient;\n}\n\n// A wrapper component to ensure a QueryClientProvider exists\ninterface EnsureQueryClientProps {\n children: ReactNode;\n}\n\nexport const EnsureQueryClient = ({ children }: EnsureQueryClientProps) => {\n try {\n // Attempt to use the existing QueryClient context\n const existingQueryClient = React.useContext(QueryClientContext);\n\n if (existingQueryClient) {\n return <>{children}</>;\n }\n } catch (e) {\n // Handle any potential errors\n // eslint-disable-next-line no-console\n console.log(e);\n }\n\n // If no QueryClient exists or there was an error, provide one\n const queryClient = getOrCreateQueryClient();\n return (\n <QueryClientProvider client={queryClient}>\n {children}\n </QueryClientProvider>\n );\n};\n","import { IconButton, IconButtonProps, Icon } from '@chakra-ui/react';\nimport { LuChevronLeft } from 'react-icons/lu';\n\ntype BackButtonProps = {\n onClick: () => void;\n} & Partial<IconButtonProps>;\n\nexport const ModalBackButton = ({ onClick, ...props }: BackButtonProps) => {\n return (\n <IconButton\n aria-label=\"Back\"\n icon={<Icon as={LuChevronLeft} fontSize={'20px'} />}\n size=\"sm\"\n variant=\"vechainKitHeaderIconButtons\"\n position=\"absolute\"\n left=\"10px\"\n top=\"8px\"\n onClick={onClick}\n lineHeight={'0'}\n {...props}\n />\n );\n};\n","'use client';\n\nimport {\n Text,\n VStack,\n Icon,\n PropsOf,\n useToken,\n IconButton,\n HStack,\n useColorModeValue,\n} from '@chakra-ui/react';\nimport { useState } from 'react';\nimport {\n LuCopy,\n LuCheck,\n LuWallet,\n LuSquareUser,\n LuPencil,\n LuLogOut,\n} from 'react-icons/lu';\nimport { humanAddress } from '@/utils';\nimport { copyToClipboard as safeCopyToClipboard } from '@/utils/ssrUtils';\nimport { Wallet } from '@/types';\nimport { AccountModalContentTypes } from '@/components/AccountModal/Types';\nimport { useTranslation } from 'react-i18next';\n\ntype Props = {\n wallet: Wallet;\n label?: string;\n style?: PropsOf<typeof VStack>;\n showHumanAddress?: boolean;\n setCurrentContent?: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onLogout?: () => void;\n};\n\nexport const AddressDisplay = ({\n wallet,\n label,\n style,\n showHumanAddress = true,\n setCurrentContent,\n onLogout,\n}: Props) => {\n const { t } = useTranslation();\n const [copied, setCopied] = useState(false);\n const [copiedDomain, setCopiedDomain] = useState(false);\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const borderColor = useColorModeValue('#ebebeb', '#ffffff0a');\n const bgColor = useColorModeValue('#ffffff', 'transparent');\n\n const copyToClipboard = async (\n textToCopy: string,\n setCopied: (value: boolean) => void,\n ) => {\n const success = await safeCopyToClipboard(textToCopy);\n if (success) {\n setCopied(true);\n setTimeout(() => {\n setCopied(false);\n }, 2000);\n }\n };\n\n const handleDomainEdit = () => {\n if (!setCurrentContent) return;\n\n if (wallet?.domain) {\n setCurrentContent({\n type: 'choose-name-search',\n props: {\n name: '',\n setCurrentContent,\n initialContentSource: 'profile',\n },\n });\n } else {\n setCurrentContent({\n type: 'choose-name',\n props: {\n setCurrentContent,\n initialContentSource: 'profile',\n onBack: () => setCurrentContent('profile'),\n },\n });\n }\n };\n\n return (\n <VStack w={'full'} justifyContent={'center'} {...style}>\n <VStack w={'full'} spacing={4}>\n {label && (\n <Text fontSize={'sm'} color={textSecondary}>\n {label}\n </Text>\n )}\n\n <VStack spacing={2} w={'full'}>\n {wallet?.domain && (\n <HStack\n w={'full'}\n spacing={3}\n px={4}\n py={2}\n borderWidth={1}\n borderColor={borderColor}\n borderRadius=\"md\"\n bg={bgColor}\n >\n <Icon as={LuSquareUser} color={textSecondary} />\n <Text\n flex={1}\n fontSize={'sm'}\n fontWeight={'700'}\n color={textPrimary}\n noOfLines={1}\n >\n {copiedDomain ? t('Copied!') : wallet.domain}\n </Text>\n <HStack spacing={2}>\n {setCurrentContent && (\n <IconButton\n icon={<LuPencil />}\n height=\"30px\"\n borderRadius=\"5px\"\n variant=\"vechainKitSecondary\"\n onClick={handleDomainEdit}\n aria-label=\"Edit domain\"\n />\n )}\n <IconButton\n icon={\n copiedDomain ? <LuCheck /> : <LuCopy />\n }\n height=\"30px\"\n borderRadius=\"5px\"\n variant=\"vechainKitSecondary\"\n onClick={() =>\n copyToClipboard(\n wallet.domain || '',\n setCopiedDomain,\n )\n }\n aria-label=\"Copy domain\"\n />\n </HStack>\n </HStack>\n )}\n\n <HStack\n w={'full'}\n spacing={3}\n px={4}\n py={2}\n borderWidth={1}\n borderColor={borderColor}\n borderRadius=\"md\"\n bg={bgColor}\n >\n <Icon as={LuWallet} color={textSecondary} />\n <Text\n flex={1}\n fontSize={'sm'}\n fontWeight={'700'}\n color={textPrimary}\n noOfLines={1}\n >\n {copied\n ? t('Copied!')\n : showHumanAddress\n ? humanAddress(wallet?.address ?? '', 8, 7)\n : wallet?.address}\n </Text>\n <HStack spacing={2}>\n <IconButton\n icon={<LuLogOut />}\n onClick={() =>\n setCurrentContent?.({\n type: 'disconnect-confirm',\n props: {\n onDisconnect: () => onLogout?.(),\n onBack: () =>\n setCurrentContent?.('profile'),\n },\n })\n }\n variant=\"vechainKitSecondary\"\n height=\"30px\"\n w=\"30px\"\n borderRadius=\"5px\"\n aria-label=\"Copy address\"\n />\n\n <IconButton\n icon={copied ? <LuCheck /> : <LuCopy />}\n onClick={() =>\n copyToClipboard(\n wallet?.address ?? '',\n setCopied,\n )\n }\n variant=\"vechainKitSecondary\"\n height=\"30px\"\n w=\"30px\"\n borderRadius=\"5px\"\n aria-label=\"Copy address\"\n />\n </HStack>\n </HStack>\n </VStack>\n </VStack>\n </VStack>\n );\n};\n","{\n \"name\": \"@vechain/vechain-kit\",\n \"version\": \"2.4.2\",\n \"author\": \"VeChain Foundation\",\n \"homepage\": \"https://github.com/vechain/vechain-kit\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/vechain/vechain-kit.git\",\n \"directory\": \"packages/vechain-kit\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/vechain/vechain-kit/issues\"\n },\n \"description\": \"All-in-one React library for building VeChain applications with wallet integration, social logins, developer hooks, and pre-built UI components.\",\n \"license\": \"MIT\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"keywords\": [\n \"vechain\",\n \"vechain-kit\",\n \"blockchain\",\n \"web3\",\n \"dapp\",\n \"react\",\n \"nextjs\",\n \"typescript\",\n \"vechain-thor\",\n \"social\",\n \"login\",\n \"wallet\",\n \"cross-app\",\n \"ecosystem\",\n \"privy\",\n \"veworld\",\n \"sync2\",\n \"walletconnect\",\n \"embedded-wallet\",\n \"smart-account\"\n ],\n \"files\": [\n \"dist\",\n \"package.json\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsc --noEmit && cross-env NODE_OPTIONS='--max-old-space-size=8192' tsdown\",\n \"watch\": \"cross-env NODE_OPTIONS='--max-old-space-size=8192' tsdown --watch\",\n \"clean\": \"rm -rf dist .turbo\",\n \"lint\": \"eslint\",\n \"purge\": \"yarn clean && rm -rf node_modules\",\n \"translate\": \"dotenv -e .env -- translo-cli\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"@adraffy/ens-normalize\": \"^1.11.0\",\n \"@chakra-ui/react\": \"^2.8.2\",\n \"@emotion/styled\": \"^11.14.1\",\n \"@privy-io/cross-app-connect\": \"0.2.2\",\n \"@privy-io/react-auth\": \"2.24.0\",\n \"@solana/web3.js\": \"^1.98.0\",\n \"@tanstack/react-query\": \"^5.64.2\",\n \"@tanstack/react-query-devtools\": \"^5.64.1\",\n \"@vechain/contract-getters\": \"1.0.4\",\n \"@vechain/dapp-kit-react\": \"2.1.0-rc.5\",\n \"@vechain/picasso\": \"^2.1.1\",\n \"@vechain/vechain-contract-types\": \"1.6.0-rc\",\n \"@wagmi/core\": \"^2.17.2\",\n \"bignumber.js\": \"^9.1.2\",\n \"browser-image-compression\": \"^2.0.2\",\n \"dotenv\": \"^16.4.7\",\n \"ethers\": \"^6.13.5\",\n \"framer-motion\": \"^11.15.0\",\n \"i18next\": \"^24.2.1\",\n \"i18next-browser-languagedetector\": \"^8.0.2\",\n \"net\": \"^1.0.2\",\n \"process\": \"^0.11.10\",\n \"react\": \"^18.2.0\",\n \"react-device-detect\": \"^2.2.3\",\n \"react-hook-form\": \"^7.54.2\",\n \"react-i18next\": \"^15.4.0\",\n \"react-icons\": \"^5.4.0\",\n \"react-qrcode-logo\": \"^3.0.0\",\n \"vaul\": \"^1.1.2\",\n \"viem\": \"^2.29.3\",\n \"wagmi\": \"^2.15.4\"\n },\n \"devDependencies\": {\n \"@types/react\": \"^18.2.28\",\n \"@types/react-dom\": \"^18.2.13\",\n \"cross-env\": \"^7.0.3\",\n \"dotenv-cli\": \"^8.0.0\",\n \"eslint\": \"^9.12.0\",\n \"eslint-plugin-i18next\": \"^6.1.1\",\n \"translo-cli\": \"^1.0.6\",\n \"tsdown\": \"^0.16.5\",\n \"typescript\": \"*\"\n },\n \"peerDependencies\": {\n \"@chakra-ui/react\": \"^2.8.2\",\n \"@emotion/react\": \"^11.0.0\",\n \"@emotion/styled\": \"^11.0.0\",\n \"@tanstack/react-query\": \"^5.64.2\",\n \"@vechain/dapp-kit-react\": \"2.1.0-rc.5\",\n \"framer-motion\": \"^11.0.0\",\n \"react\": \"^18.0.0\",\n \"react-dom\": \"^18.0.0\"\n },\n \"peerDependenciesMeta\": {\n \"@chakra-ui/react\": {\n \"optional\": true\n },\n \"@emotion/react\": {\n \"optional\": true\n },\n \"@emotion/styled\": {\n \"optional\": true\n },\n \"@tanstack/react-query\": {\n \"optional\": true\n },\n \"@vechain/dapp-kit-react\": {\n \"optional\": true\n },\n \"framer-motion\": {\n \"optional\": true\n }\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./utils\": {\n \"import\": {\n \"types\": \"./dist/utils/index.d.mts\",\n \"default\": \"./dist/utils/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/utils/index.d.cts\",\n \"default\": \"./dist/utils/index.cjs\"\n }\n },\n \"./assets\": {\n \"import\": {\n \"types\": \"./dist/assets/index.d.mts\",\n \"default\": \"./dist/assets/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/assets/index.d.cts\",\n \"default\": \"./dist/assets/index.cjs\"\n }\n }\n }\n}\n","import { HStack, Link, StackProps } from '@chakra-ui/react';\nimport { VechainLogo } from '../../assets';\nimport packageJson from '../../../package.json';\nimport { useVeChainKitConfig } from '@/providers';\n\ntype Props = {} & Omit<StackProps, 'dangerouslySetInnerHTML'>;\n\nexport const VersionFooter = ({ ...props }: Props) => {\n const { darkMode: isDark } = useVeChainKitConfig();\n\n return (\n <HStack\n w={'full'}\n justifyContent={'center'}\n alignItems={'center'}\n spacing={0}\n {...props}\n >\n <VechainLogo\n isDark={isDark}\n w={'70px'}\n h={'auto'}\n opacity={0.4}\n mr={1}\n ml={'-16px'}\n />\n <Link\n fontSize={'11px'}\n fontWeight={'500'}\n opacity={0.4}\n textAlign={'left'}\n href={`https://github.com/vechain/vechain-kit/releases/tag/${packageJson.version}`}\n isExternal\n pt={'1px'}\n >\n v{packageJson.version}\n </Link>\n </HStack>\n );\n};\n","import { Box } from '@chakra-ui/react';\nimport { useEffect, useState, useRef, createContext, useContext } from 'react';\nimport { useVechainKitThemeConfig } from '@/providers';\n\ntype Props = {\n children: React.ReactNode;\n};\n\n// Context to share hasContentBelow state with bottom sheet handle\nconst StickyHeaderContext = createContext<{\n hasContentBelow: boolean;\n}>({ hasContentBelow: false });\n\nexport const useStickyHeaderContext = () => useContext(StickyHeaderContext);\n\nexport const StickyHeaderContainer = ({ children }: Props) => {\n const [hasContentBelow, setHasContentBelow] = useState(false);\n const observerRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isInitialMountRef = useRef(true);\n\n // Use semantic tokens for sticky header\n const { tokens } = useVechainKitThemeConfig();\n const backdropFilter =\n tokens?.effects?.backdropFilter?.stickyHeader ?? 'blur(20px)';\n\n useEffect(() => {\n // Find the scrollable container (parent with overflow-y: auto)\n const findScrollableContainer = (\n element: HTMLElement | null,\n ): HTMLElement | null => {\n if (!element) return null;\n let current: HTMLElement | null = element.parentElement;\n while (current) {\n const style = window.getComputedStyle(current);\n if (\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll'\n ) {\n return current;\n }\n current = current.parentElement;\n }\n return null;\n };\n\n // Ignore intersection changes during initial mount and transitions\n // This prevents the glitch when content is animating in\n const handleIntersection = ([entry]: IntersectionObserverEntry[]) => {\n // Clear any pending timeout\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n // Debounce the state update to prevent rapid changes during animations\n timeoutRef.current = setTimeout(() => {\n // On initial mount, always start with false to prevent glitch\n if (isInitialMountRef.current) {\n isInitialMountRef.current = false;\n setHasContentBelow(false);\n return;\n }\n setHasContentBelow(!entry.isIntersecting);\n }, 50); // Small debounce to let animations settle\n };\n\n const scrollableContainer = findScrollableContainer(headerRef.current);\n\n const observerOptions: IntersectionObserverInit = {\n threshold: 0,\n };\n\n // If we found a scrollable container, use it as the root\n if (scrollableContainer) {\n observerOptions.root = scrollableContainer;\n observerOptions.rootMargin = '0px';\n }\n\n const observer = new IntersectionObserver(\n handleIntersection,\n observerOptions,\n );\n\n // Delay observation slightly to avoid initial glitch\n const observeTimeout = setTimeout(() => {\n if (observerRef.current) {\n observer.observe(observerRef.current);\n }\n }, 200); // Wait for animation to complete (0.17s + small buffer)\n\n return () => {\n clearTimeout(observeTimeout);\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n observer.disconnect();\n };\n }, []);\n\n return (\n <StickyHeaderContext.Provider value={{ hasContentBelow }}>\n <Box\n ref={headerRef}\n position={'sticky'}\n top={'0'}\n left={'0'}\n w={'full'}\n borderRadius={'24px 24px 0px 0px'}\n backdropFilter={hasContentBelow ? backdropFilter : 'none'}\n style={{\n WebkitBackdropFilter: hasContentBelow\n ? backdropFilter\n : 'none',\n }}\n zIndex={1000}\n boxShadow={\n hasContentBelow\n ? '0px 2px 4px 1px rgb(0 0 0 / 10%)'\n : 'none'\n }\n transition=\"box-shadow 0.2s ease-in-out\"\n >\n {children}\n </Box>\n <div\n ref={observerRef}\n style={{\n height: '1px',\n width: '100%',\n pointerEvents: 'none',\n visibility: 'hidden',\n marginTop: '-1px',\n }}\n />\n </StickyHeaderContext.Provider>\n );\n};\n","import { Box, useToken } from '@chakra-ui/react';\n\ntype Props = {\n children: React.ReactNode;\n};\n\nexport const StickyFooterContainer = ({ children }: Props) => {\n // Use semantic token for sticky footer background (same as modal)\n const footerBg = useToken('colors', 'vechain-kit-modal');\n\n return (\n <Box\n position=\"absolute\"\n bottom=\"0\"\n left=\"0\"\n right=\"0\"\n bg={footerBg}\n zIndex=\"1000\"\n p={4}\n w=\"full\"\n >\n {children}\n </Box>\n );\n};\n","import { Box, useToken } from '@chakra-ui/react';\nimport { Drawer } from 'vaul';\nimport { useEffect, useState, useRef } from 'react';\nimport { useVechainKitThemeConfig } from '@/providers';\n\ntype Props = {\n isOpen: boolean;\n onClose: () => void;\n height?: string;\n children: React.ReactNode;\n ariaTitle: string;\n ariaDescription: string;\n isDismissable?: boolean;\n minHeight?: string;\n maxHeight?: string;\n closeThreshold?: number;\n};\n\n/**\n * HandleArea component for the bottom sheet drag indicator\n *\n * PROBLEM: When content scrolls in the bottom sheet, the sticky header (from StickyHeaderContainer)\n * gets a backdrop filter effect, but the drawer handle (drag indicator) above it doesn't,\n * creating a visual inconsistency where part of the top area has the effect and part doesn't.\n *\n * SOLUTION: This component makes the handle area also sticky and applies the same backdrop filter\n * effect when content scrolls below it. It uses an IntersectionObserver to detect when content\n * has scrolled past a sentinel element, similar to how StickyHeaderContainer works.\n *\n * IMPORTANT: The handle must be rendered INSIDE the scrollable container (not as a sibling)\n * so that the IntersectionObserver can properly detect scrolling within that container's viewport.\n * If the handle were outside the scrollable container, the observer wouldn't detect scroll events.\n */\nconst HandleArea = ({\n scrollableContainerRef,\n observerRef,\n}: {\n scrollableContainerRef: React.RefObject<HTMLDivElement>;\n observerRef: React.RefObject<HTMLDivElement>;\n}) => {\n const handleBg = useToken('colors', 'vechain-kit-border');\n const { tokens } = useVechainKitThemeConfig();\n const backdropFilter =\n tokens?.effects?.backdropFilter?.stickyHeader ?? 'blur(20px)';\n const [hasContentBelow, setHasContentBelow] = useState(false);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isInitialMountRef = useRef(true);\n\n useEffect(() => {\n /**\n * IntersectionObserver callback that detects when the sentinel element\n * (observerRef) scrolls out of view. When it's not intersecting, it means\n * content has scrolled past the handle area, so we apply the backdrop filter.\n */\n const handleIntersection = ([entry]: IntersectionObserverEntry[]) => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n\n // Debounce state updates to prevent rapid changes during animations\n timeoutRef.current = setTimeout(() => {\n // On initial mount, always start with false to prevent visual glitch\n if (isInitialMountRef.current) {\n isInitialMountRef.current = false;\n setHasContentBelow(false);\n return;\n }\n // When sentinel is not intersecting, content has scrolled below\n setHasContentBelow(!entry.isIntersecting);\n }, 50);\n };\n\n const observerOptions: IntersectionObserverInit = {\n threshold: 0,\n };\n\n // Use the scrollable container as the root for the observer\n // This ensures we detect intersections relative to the scrollable viewport,\n // not the document viewport\n if (scrollableContainerRef.current) {\n observerOptions.root = scrollableContainerRef.current;\n observerOptions.rootMargin = '0px';\n }\n\n const observer = new IntersectionObserver(\n handleIntersection,\n observerOptions,\n );\n\n // Delay observation to avoid initial glitch when content is animating in\n const observeTimeout = setTimeout(() => {\n if (observerRef.current) {\n observer.observe(observerRef.current);\n }\n }, 200);\n\n return () => {\n clearTimeout(observeTimeout);\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n observer.disconnect();\n };\n }, [scrollableContainerRef, observerRef]);\n\n return (\n <Box\n position=\"sticky\"\n top=\"0\"\n w=\"full\"\n // Apply backdrop filter when content has scrolled below the handle\n // This matches the effect applied to StickyHeaderContainer for visual consistency\n backdropFilter={hasContentBelow ? backdropFilter : 'none'}\n style={{\n WebkitBackdropFilter: hasContentBelow ? backdropFilter : 'none',\n }}\n zIndex={999}\n transition=\"backdrop-filter 0.2s ease-in-out\"\n >\n {/* Drawer handle / drag indicator */}\n <Box\n mx={'auto'}\n w={'34px'}\n h={'5px'}\n bg={handleBg}\n mt={4}\n rounded={'full'}\n />\n </Box>\n );\n};\n\nexport const BaseBottomSheet = ({\n isOpen,\n onClose,\n children,\n ariaTitle,\n ariaDescription,\n isDismissable = true,\n minHeight,\n maxHeight = '68vh',\n closeThreshold = 0.5,\n}: Props) => {\n // Use semantic tokens for bottom sheet and overlay colors\n const modalBg = useToken('colors', 'vechain-kit-modal');\n const overlayBg = useToken('colors', 'vechain-kit-overlay');\n const scrollableContainerRef = useRef<HTMLDivElement>(null);\n const handleObserverRef = useRef<HTMLDivElement>(null);\n\n // Get backdrop filter from tokens context\n const { tokens } = useVechainKitThemeConfig();\n const overlayBackdropFilter = tokens?.effects?.backdropFilter?.overlay;\n const modalBorder = tokens?.colors?.border?.modal || 'none';\n\n return (\n <Drawer.Root\n dismissible={isDismissable}\n shouldScaleBackground\n repositionInputs={false}\n open={isOpen}\n closeThreshold={closeThreshold}\n onOpenChange={(open) => {\n if (!open) {\n onClose();\n }\n }}\n >\n <Drawer.Portal>\n <Drawer.Overlay\n style={{\n zIndex: 100,\n position: 'fixed',\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n backgroundColor: overlayBg,\n backdropFilter: overlayBackdropFilter,\n WebkitBackdropFilter: overlayBackdropFilter,\n }}\n />\n <Drawer.Content\n aria-description={ariaDescription}\n style={{\n zIndex: 101,\n backgroundColor: modalBg,\n borderRadius: '24px 24px 0 0',\n border: modalBorder,\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n ...(minHeight && { minHeight }),\n maxHeight,\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n <Drawer.Title\n style={{\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n borderWidth: 0,\n }}\n >\n {ariaTitle}\n </Drawer.Title>\n\n {/* \n Scrollable container that wraps all content.\n The handle must be INSIDE this container (not as a sibling) so that:\n 1. The IntersectionObserver can detect scrolling within this container's viewport\n 2. The handle can be sticky relative to this scrollable container\n 3. The backdrop filter effect works consistently with StickyHeaderContainer\n */}\n <Box ref={scrollableContainerRef} flex=\"1\" overflowY=\"auto\">\n {/* \n Sticky handle area that gets backdrop filter when content scrolls.\n Positioned first so it stays at the top when scrolling.\n */}\n <HandleArea\n scrollableContainerRef={scrollableContainerRef}\n observerRef={handleObserverRef}\n />\n {/* \n Sentinel element for IntersectionObserver.\n When this invisible 1px element scrolls out of view, it means content\n has scrolled past the handle area, triggering the backdrop filter effect.\n Positioned right after the handle so it's at the boundary between\n handle and content.\n */}\n <div\n ref={handleObserverRef}\n style={{\n height: '1px',\n width: '100%',\n // pointerEvents: 'none',\n visibility: 'hidden',\n marginTop: '-1px',\n }}\n />\n {children}\n </Box>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n );\n};\n","import {\n Modal,\n ModalContent,\n ModalContentProps,\n ModalOverlay,\n useMediaQuery,\n useToken,\n} from '@chakra-ui/react';\nimport { ReactNode } from 'react';\nimport { useVechainKitThemeConfig } from '@/providers';\nimport { BaseBottomSheet } from './BaseBottomSheet';\n\ntype BaseModalProps = {\n isOpen: boolean;\n onClose: () => void;\n children: ReactNode;\n size?: string;\n isCentered?: boolean;\n motionPreset?: 'slideInBottom' | 'none';\n trapFocus?: boolean;\n closeOnOverlayClick?: boolean;\n blockScrollOnMount?: boolean;\n autoFocus?: boolean;\n initialFocusRef?: React.RefObject<HTMLElement>;\n allowExternalFocus?: boolean;\n backdropFilter?: string;\n isCloseable?: boolean;\n /**\n * Whether to use bottom sheet on mobile devices.\n * When false (default), uses regular modal on all screen sizes.\n * When true, uses bottom sheet on mobile (< 768px) and regular modal on desktop.\n */\n useBottomSheetOnMobile?: boolean;\n /**\n * Minimum and maximum height for the modal on mobile devices.\n */\n mobileMinHeight?: string;\n mobileMaxHeight?: string;\n desktopMinHeight?: string;\n desktopMaxHeight?: string;\n};\n\nexport const BaseModal = ({\n isOpen,\n onClose,\n children,\n size = 'sm',\n isCentered = true,\n motionPreset = 'slideInBottom',\n closeOnOverlayClick = true,\n blockScrollOnMount = false,\n allowExternalFocus = false,\n backdropFilter,\n isCloseable = true,\n useBottomSheetOnMobile,\n mobileMinHeight,\n mobileMaxHeight = '57vh',\n desktopMinHeight,\n desktopMaxHeight,\n}: BaseModalProps) => {\n const [isDesktop] = useMediaQuery('(min-width: 768px)');\n const { portalRootRef, themeConfig, tokens } = useVechainKitThemeConfig();\n\n // Get useBottomSheetOnMobile from theme config if not provided as prop\n // Prop takes precedence over theme config\n const shouldUseBottomSheetOnMobile =\n useBottomSheetOnMobile ??\n themeConfig?.modal?.useBottomSheetOnMobile ??\n false;\n\n // Use semantic tokens for modal and overlay colors\n const modalBg = useToken('colors', 'vechain-kit-modal');\n const overlayBg = useToken('colors', 'vechain-kit-overlay');\n\n // Get backdrop filter from tokens context\n const defaultBackdropFilter = tokens?.effects?.backdropFilter?.overlay;\n const modalBackdropFilter = tokens?.effects?.backdropFilter?.modal;\n const effectiveBackdropFilter =\n backdropFilter ?? defaultBackdropFilter ?? 'blur(3px)';\n\n const modalContentProps: ModalContentProps = isDesktop\n ? {\n minHeight: desktopMinHeight,\n maxHeight: desktopMaxHeight,\n }\n : {\n position: 'fixed',\n bottom: '0',\n mb: '0',\n maxW: '2xl',\n borderRadius: '24px 24px 0px 0px !important',\n overflowY: 'auto',\n overflowX: 'hidden',\n scrollBehavior: 'smooth',\n minHeight: mobileMinHeight,\n maxHeight: mobileMaxHeight,\n };\n\n const modalContent = (\n <Modal\n motionPreset={motionPreset}\n isOpen={isOpen}\n onClose={onClose}\n isCentered={isCentered}\n size={size}\n returnFocusOnClose={false}\n blockScrollOnMount={blockScrollOnMount}\n closeOnOverlayClick={closeOnOverlayClick && isCloseable}\n preserveScrollBarGap={true}\n portalProps={{ containerRef: portalRootRef }}\n trapFocus={!allowExternalFocus}\n autoFocus={!allowExternalFocus}\n variant=\"vechainKitBase\"\n >\n <ModalOverlay\n bg={overlayBg}\n backdropFilter={effectiveBackdropFilter}\n />\n <ModalContent\n role=\"dialog\"\n aria-modal={!allowExternalFocus}\n bg={modalBg}\n sx={{\n backdropFilter: modalBackdropFilter,\n WebkitBackdropFilter: modalBackdropFilter,\n }}\n {...modalContentProps}\n >\n {children}\n </ModalContent>\n </Modal>\n );\n\n // We still wrap the bottomsheet within the modal,\n // because we need access to the modal context (eg: setCurrentContent())\n const bottomSheetContent = (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n size={size}\n blockScrollOnMount={false}\n trapFocus={false}\n >\n <BaseBottomSheet\n isOpen={isOpen}\n onClose={onClose}\n ariaTitle={'Dialog'}\n ariaDescription={'Dialog content area'}\n isDismissable={isCloseable}\n minHeight={mobileMinHeight}\n maxHeight={mobileMaxHeight}\n >\n {children}\n </BaseBottomSheet>\n </Modal>\n );\n\n // Use bottom sheet only on mobile when explicitly enabled\n // By default, use regular modal on all screen sizes\n const shouldUseBottomSheet = !isDesktop && shouldUseBottomSheetOnMobile;\n\n return <>{shouldUseBottomSheet ? bottomSheetContent : modalContent}</>;\n};\n","import { 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 { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getAddressDomain, getDomainAddress, isValidDomain, isPrimaryDomain } from '@vechain/contract-getters';\nimport { isValidAddress } from '@/utils/addressUtils';\n\ninterface VeChainDomainResult {\n address?: string;\n domain?: string;\n isValidAddressOrDomain: boolean;\n isPrimaryDomain: boolean;\n}\n\n\nexport const getVechainDomainQueryKey = (addressOrDomain?: string | null) => [\n 'VECHAIN_KIT_DOMAIN',\n addressOrDomain,\n];\n\nexport const useVechainDomain = (addressOrDomain?: string | null) => {\n const { network } = useVeChainKitConfig();\n\n return useQuery<VeChainDomainResult>({\n queryKey: getVechainDomainQueryKey(addressOrDomain),\n queryFn: async () => {\n if (!addressOrDomain) throw new Error('Address or domain is required');\n \n // Determine input type\n const isDomain = await isValidDomain(addressOrDomain, {\n networkUrl: network.nodeUrl,\n });\n const isAddress = isValidAddress(addressOrDomain);\n \n // Validate that input is either a valid domain or valid address\n if (!isDomain && !isAddress) {\n throw new Error('Input must be a valid domain or address');\n }\n\n let address: string | null = null;\n let domain: string | null = null;\n let isPrimary = false;\n\n if (isDomain) {\n // Input is a domain, get the corresponding address\n address = await getDomainAddress(addressOrDomain, {\n networkUrl: network.nodeUrl,\n });\n domain = addressOrDomain;\n \n // Check if this domain is the primary domain for the address\n if (address) {\n isPrimary = await isPrimaryDomain(addressOrDomain, address, {\n networkUrl: network.nodeUrl,\n });\n }\n } else {\n // Input is an address, get the corresponding domain\n domain = await getAddressDomain(addressOrDomain, {\n networkUrl: network.nodeUrl,\n });\n address = addressOrDomain;\n \n // If we found a domain, check if it's the primary domain\n if (domain) {\n isPrimary = await isPrimaryDomain(domain, addressOrDomain, {\n networkUrl: network.nodeUrl,\n });\n }\n }\n\n return {\n address: address || undefined,\n domain: domain || undefined,\n isValidAddressOrDomain: isDomain || isAddress,\n isPrimaryDomain: isPrimary,\n };\n },\n enabled: !!addressOrDomain && !!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 or domain is required' ||\n errorMessage === 'input must be a valid domain or address') {\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';\nimport { useQuery } from '@tanstack/react-query';\nimport { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getEnsRecordExistsQueryKey(name),\n queryFn: () => getEnsRecordExists(thor, network.type, name),\n enabled: !!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","import { useQueryClient } from '@tanstack/react-query';\nimport {\n getAvatarOfAddressQueryKey,\n getAvatarQueryKey,\n getTextRecordsQueryKey,\n} from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\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 {\n getAvatarOfAddressQueryKey,\n getDomainsOfAddressQueryKey,\n getEnsRecordExistsQueryKey,\n getTextRecordsQueryKey,\n getVechainDomainQueryKey,\n getAvatarQueryKey,\n} from '@/hooks';\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","import {\n UseSendTransactionReturnValue,\n useSendTransaction,\n useWallet,\n} from '@/hooks';\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';\nimport { humanAddress } from '@/utils';\nimport { ethers } from 'ethers';\nimport { useRefreshMetadata } from '../wallet/useRefreshMetadata';\nimport { invalidateAndRefetchDomainQueries } from './utils/domainQueryUtils';\nimport { 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","import {\n UseSendTransactionReturnValue,\n useSendTransaction,\n useWallet,\n} from '@/hooks';\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';\nimport { ethers } from 'ethers';\nimport { invalidateAndRefetchDomainQueries } from './utils/domainQueryUtils';\nimport { humanAddress } from '@/utils';\nimport { 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 { useThor } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '@/providers';\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 const thor = useThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getIsDomainProtectedQueryKey(domain),\n queryFn: () => getIsDomainProtected(thor, network.type, domain),\n enabled: !!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 { getConfig } from '@/config';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { useVeChainKitConfig } from '@/providers';\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 { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '@/providers';\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 { useQuery } from '@tanstack/react-query';\nimport { Interface, namehash } from 'ethers';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getConfig } from '@/config';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { ENS_TEXT_RECORDS, TextRecords } from '@/types';\n\nconst nameInterface = new Interface([\n 'function resolver(bytes32 node) returns (address resolverAddress)',\n 'function text(bytes32 node, string key) view returns (string)',\n]);\n\n/**\n * Get text records for a VET domain from the contract\n * @param nodeUrl The node URL to query\n * @param network The network type\n * @param domain The domain to get text records for. If not provided, will return empty object\n * @returns Object containing text records in the form of {@link TextRecords}\n */\nexport const getTextRecords = async (\n nodeUrl: string,\n network: NETWORK_TYPE,\n domain?: string,\n): Promise<TextRecords> => {\n if (!domain) return {};\n\n const node = namehash(domain);\n\n try {\n // First get the 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(network).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 {};\n }\n\n const { resolverAddress } = nameInterface.decodeFunctionResult(\n 'resolver',\n resolverData,\n );\n\n // Then get all text records from the resolver\n const response = await fetch(accountsUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n clauses: ENS_TEXT_RECORDS.map((key) => ({\n to: resolverAddress,\n data: nameInterface.encodeFunctionData('text', [node, key]),\n })),\n }),\n });\n\n const results = await response.json();\n\n return results.reduce(\n (acc: TextRecords, { data, reverted }: any, index: number) => {\n if (!reverted && data && data !== '0x') {\n try {\n const value = nameInterface.decodeFunctionResult(\n 'text',\n data,\n )[0];\n if (value) {\n acc[ENS_TEXT_RECORDS[index]] = value;\n }\n } catch (error) {\n console.error(\n `Failed to decode text record for ${ENS_TEXT_RECORDS[index]}:`,\n error,\n );\n }\n }\n\n return acc;\n },\n {},\n );\n } catch (error) {\n console.error('Error fetching text records:', error);\n throw error;\n }\n};\n\nexport const getTextRecordsQueryKey = (\n domain?: string,\n network?: NETWORK_TYPE,\n) => ['VECHAIN_KIT_TEXT_RECORDS', domain, network];\n\nexport const useGetTextRecords = (domain?: string) => {\n const { network } = useVeChainKitConfig();\n const nodeUrl = network.nodeUrl ?? getConfig(network.type).nodeUrl;\n\n return useQuery({\n queryKey: getTextRecordsQueryKey(domain, network.type),\n queryFn: () => getTextRecords(nodeUrl, network.type, domain),\n enabled: !!domain && !!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 { Interface, namehash } from 'ethers';\nimport { useCallback } from 'react';\nimport { UseSendTransactionReturnValue, useSendTransaction } from '@/hooks';\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';\nimport { getConfig } from '@/config';\nimport { useCallClause } from '@/hooks';\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","import { useQuery } from '@tanstack/react-query';\nimport { getPicassoImage } from '@/utils';\nimport { getAddressDomain, getAvatar } from '@vechain/contract-getters';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getLocalStorageItem } from '@/utils/ssrUtils';\nimport { CrossAppConnectionCache } from '@/types';\nimport { VECHAIN_KIT_DOCS_IMAGES_S3_BASE_URL } from '@/constants';\n\n/**\n * Avatar resolution priority:\n * 1. Avatar from VET domain (if address has a domain with avatar set)\n * 2. Cross-app avatar (if user is connected via cross-app and no domain avatar exists)\n * 3. Picasso generated image (fallback)\n *\n * Cross-app avatars are app-specific defaults used when a user connects via\n * the VeChain cross-app ecosystem (e.g., Mugshot, Greencart, Cleanify, EVearn)\n * and doesn't have a custom avatar set on their domain.\n */\n\nconst CROSSAPP_AVATAR_MAP: Record<string, string> = {\n Mugshot:\n new URL('mugshot.png', VECHAIN_KIT_DOCS_IMAGES_S3_BASE_URL).toString(),\n Greencart:\n new URL('greencart.png', VECHAIN_KIT_DOCS_IMAGES_S3_BASE_URL).toString(),\n Cleanify:\n new URL('cleanify.png', VECHAIN_KIT_DOCS_IMAGES_S3_BASE_URL).toString(),\n EVearn: new URL('evearn.png', VECHAIN_KIT_DOCS_IMAGES_S3_BASE_URL).toString(),\n};\n\nconst CACHE_KEY = 'vechain_kit_cross_app_connection';\n\nconst getCrossAppAvatar = (): string | null => {\n const cached = getLocalStorageItem(CACHE_KEY);\n if (!cached) return null;\n\n try {\n const connectionCache = JSON.parse(cached) as CrossAppConnectionCache;\n const appName = connectionCache?.ecosystemApp?.name;\n if (!appName) return null;\n return CROSSAPP_AVATAR_MAP[appName] ?? null;\n } catch {\n return null;\n }\n};\n\nexport const getAvatarOfAddressQueryKey = (address?: string) => [\n 'VECHAIN_KIT',\n 'VET_DOMAINS',\n 'AVATAR_OF_ADDRESS',\n address,\n];\n\n/**\n * Hook to fetch the avatar for an address by first getting their domains\n * and then fetching the avatar for the first domain found\n * @param address The owner's address\n * @returns The avatar URL for the address's primary domain\n */\nexport const useGetAvatarOfAddress = (address?: string) => {\n const { network } = useVeChainKitConfig();\n return useQuery({\n queryKey: getAvatarOfAddressQueryKey(address),\n queryFn: async () => {\n if (!address || !network.nodeUrl) {\n const crossAppAvatar = getCrossAppAvatar();\n return crossAppAvatar ?? getPicassoImage(address ?? '');\n }\n\n const addressDomain = await getAddressDomain(address, {\n networkUrl: network.nodeUrl,\n });\n if (!addressDomain) {\n const crossAppAvatar = getCrossAppAvatar();\n return crossAppAvatar ?? getPicassoImage(address ?? '');\n }\n\n const avatar = await getAvatar(addressDomain, {\n networkUrl: network.nodeUrl,\n });\n if (!avatar) {\n const crossAppAvatar = getCrossAppAvatar();\n return crossAppAvatar ?? getPicassoImage(address ?? '');\n }\n return avatar;\n },\n enabled: !!address && !!network.nodeUrl,\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","/**\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';\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","import {\n UseSendTransactionReturnValue,\n useSendTransaction,\n useWallet,\n} from '@/hooks';\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';\nimport { humanAddress } from '@/utils';\nimport { invalidateAndRefetchDomainQueries } from './utils/domainQueryUtils';\nimport { 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 { useMemo } from 'react';\nimport {\n useAccountBalance,\n useGetB3trBalance,\n useGetVot3Balance,\n useGetErc20Balance,\n useGetCustomTokenBalances,\n} from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\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 { useThor } from '@vechain/dapp-kit-react';\nimport { OracleVechainEnergy__factory } from '@vechain/vechain-contract-types';\nimport { BigNumber } from 'bignumber.js';\nimport { getConfig } from '@/config';\nimport { useVeChainKitConfig } from '@/providers';\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 const thor = useThor();\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';\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';\nimport { useVeChainKitConfig } from '@/providers';\nimport { 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';\nimport { useCallClause, getCallClauseQueryKey } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\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 { useVeChainKitConfig } from '@/providers';\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","import { LocalStorageKey, useLocalStorage } from '@/hooks';\nimport { compareAddresses } from '@/utils';\nimport { useVeChainKitConfig } from '@/providers';\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 { useVeChainKitConfig } from '@/providers';\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 { useQueries } from '@tanstack/react-query';\nimport { useCustomTokens } from '@/hooks';\nimport { type CustomTokenInfo, getErc20Balance } from '@vechain/contract-getters';\nimport { TokenBalance } from '@/types';\nimport { useVeChainKitConfig } from '@/providers';\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 { useQuery } from '@tanstack/react-query';\nimport { useVeChainKitConfig } from '@/providers';\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';\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 { NETWORK_TYPE } from '@/config/network';\nimport { useVeChainKitConfig } from '@/providers';\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';\nimport { getCallClauseQueryKeyWithArgs, useCallClause } from '@/hooks';\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 { useThor } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '@/providers';\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 const thor = useThor();\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 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: !!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 { isMobile } from 'react-device-detect';\nimport { isRejectionError } from './stringUtils';\n\ntype PopupErrorOptions = {\n error: unknown;\n mobileBrowserPopupMessage?: string;\n rejectedMessage?: string;\n defaultMessage?: string;\n};\n\nexport const handlePopupError = ({\n error,\n mobileBrowserPopupMessage = 'Mobile browser blocked the window. Please try again.',\n rejectedMessage = 'Request was cancelled.',\n defaultMessage = 'Operation failed',\n}: PopupErrorOptions): Error => {\n const errorMsg = (error as { message?: string })?.message;\n\n // If it's mobile browser and not a user rejection, it might be due to popup blocking\n if (isMobile && errorMsg && !isRejectionError(errorMsg)) {\n return new Error(mobileBrowserPopupMessage);\n }\n\n // Handle user rejection or other errors\n if (errorMsg && isRejectionError(errorMsg)) {\n return new Error(rejectedMessage);\n }\n\n // If it's an Error instance, return it, otherwise create new Error\n return error instanceof Error ? error : new Error(defaultMessage);\n};\n","import React, { useCallback, useRef, useState } from 'react';\nimport { toPrivyWalletConnector } from '@privy-io/cross-app-connect/rainbow-kit';\nimport {\n useConnect,\n useDisconnect,\n createConfig,\n useSignMessage,\n useSignTypedData,\n WagmiProvider,\n http,\n useAccount,\n} from 'wagmi';\nimport { SignTypedDataParameters } from '@wagmi/core';\nimport { VECHAIN_PRIVY_APP_ID } from '../utils';\nimport { defineChain } from 'viem';\nimport { handlePopupError } from '@/utils/handlePopupError';\nimport { isBrowser } from '@/utils/ssrUtils';\nimport {\n VECHAIN_EXPLORER_BASE_URL,\n VECHAIN_MAINNET_NODE_BASE_URL,\n VECHAINSTATS_BASE_URL,\n} from '@/constants';\n\nexport const vechain = defineChain({\n id: '1176455790972829965191905223412607679856028701100105089447013101863' as unknown as number,\n name: 'Vechain',\n nativeCurrency: { name: 'VeChain', symbol: 'VET', decimals: 18 },\n rpcUrls: {\n default: {\n http: [VECHAIN_MAINNET_NODE_BASE_URL],\n },\n },\n blockExplorers: {\n default: {\n name: 'Vechain Explorer',\n url: VECHAIN_EXPLORER_BASE_URL,\n },\n vechainStats: {\n name: 'Vechain Stats',\n url: VECHAINSTATS_BASE_URL,\n },\n },\n});\n\nexport const vechainConnector = () => {\n return toPrivyWalletConnector({\n id: VECHAIN_PRIVY_APP_ID,\n name: 'VeChain',\n iconUrl:\n 'https://imagedelivery.net/oHBRUd2clqykxgDWmeAyLg/661dd77c-2f9d-40e7-baa1-f4e24fd7bf00/icon',\n smartWalletMode: false,\n });\n};\n\ninterface PrivyCrossAppProviderProps {\n privyEcosystemAppIDS: string[];\n children: React.ReactNode;\n}\n\nexport const PrivyCrossAppProvider = ({\n privyEcosystemAppIDS,\n children,\n}: PrivyCrossAppProviderProps) => {\n // Use useRef to store the config to prevent recreation on re-renders\n const wagmiConfigRef = useRef(\n createConfig({\n chains: [vechain],\n ssr: true,\n connectors: [\n vechainConnector(),\n ...privyEcosystemAppIDS.map((appId) =>\n toPrivyWalletConnector({\n id: appId,\n name: '',\n iconUrl: '',\n }),\n ),\n ],\n transports: { [vechain.id]: http() },\n multiInjectedProviderDiscovery: false,\n }),\n );\n\n return (\n <WagmiProvider config={wagmiConfigRef.current}>\n {children}\n </WagmiProvider>\n );\n};\n\nexport const usePrivyCrossAppSdk = () => {\n const { connectAsync, connectors } = useConnect();\n const { signTypedDataAsync } = useSignTypedData();\n const { signMessageAsync } = useSignMessage();\n const { disconnectAsync } = useDisconnect();\n const { isConnected } = useAccount();\n\n // Add local state to track connection\n const [isConnecting, setIsConnecting] = useState(false);\n const [connectionError, setConnectionError] = useState<Error | null>(null);\n\n const logout = useCallback(async () => {\n try {\n if (isConnected) {\n await disconnectAsync();\n // Force a state update after disconnect\n if (isBrowser()) {\n window.dispatchEvent(new Event('wallet_disconnected'));\n }\n }\n } catch (error) {\n console.error('Error during logout:', error);\n throw error;\n }\n }, [disconnectAsync, isConnected]);\n\n const login = useCallback(\n async (appID: string) => {\n try {\n setIsConnecting(true);\n setConnectionError(null);\n\n const connector = connectors.find(\n (c) => c.id === (appID || VECHAIN_PRIVY_APP_ID),\n );\n\n if (!connector) {\n throw new Error('Connector not found');\n }\n\n const result = await connectAsync({ connector });\n\n return result;\n } catch (error) {\n setConnectionError(error as Error);\n throw error;\n } finally {\n setIsConnecting(false);\n }\n },\n [connectAsync, connectors],\n );\n\n // Keep the other methods unchanged\n const signMessage = useCallback(\n async (message: string) => {\n try {\n return await signMessageAsync({ message });\n } catch (error) {\n throw handlePopupError({\n error,\n mobileBrowserPopupMessage:\n \"Your mobile browser blocked the signing window. Please click 'Try again' to open the signing window or change your browser settings.\",\n rejectedMessage: 'Signing request was cancelled.',\n defaultMessage:\n 'An unexpected issue occurred while signing a message. Please try again or contact support.',\n });\n }\n },\n [signMessageAsync],\n );\n\n const signTypedData = useCallback(\n async (data: SignTypedDataParameters) => {\n try {\n return await signTypedDataAsync(data);\n } catch (error) {\n const errorType = handlePopupError({\n error,\n mobileBrowserPopupMessage:\n \"Your mobile browser blocked the signing window. Please click 'Try again' to open the signing window or change your browser settings.\",\n rejectedMessage: 'Signing request was cancelled.',\n defaultMessage:\n 'An unexpected issue occurred while signing typed data. Please try again or contact support.',\n });\n throw errorType;\n }\n },\n [signTypedDataAsync],\n );\n\n return {\n login,\n logout,\n signMessage,\n signTypedData,\n isConnecting,\n connectionError,\n };\n};\n","import { NETWORK_TYPE } from '@/config/network';\nimport {\n useVechainDomain,\n useGetTextRecords,\n useGetAvatarOfAddress,\n} from '@/hooks';\nimport { convertUriToUrl } from '@/utils';\nimport { ENSRecords } from '@/types';\n\nexport const useWalletMetadata = (\n address: string,\n networkType: NETWORK_TYPE,\n) => {\n const { data: domain, isLoading: isLoadingVechainDomain } =\n useVechainDomain(address ?? '');\n const { data: avatar, isLoading: isLoadingMetadata } =\n useGetAvatarOfAddress(address ?? '');\n const { data: textRecords, isLoading: isLoadingRecords } =\n useGetTextRecords(domain?.domain ?? '');\n const headerUrl = textRecords?.header\n ? convertUriToUrl(textRecords.header, networkType)\n : null;\n\n return {\n domain: domain?.domain,\n image: avatar,\n records: {\n ...textRecords,\n header: headerUrl,\n } as ENSRecords,\n isLoading:\n isLoadingVechainDomain || isLoadingMetadata || isLoadingRecords,\n };\n};\n","import { useCallback } from 'react';\nimport { useVeChainKitConfig } from '@/providers';\nimport { NETWORK_TYPE } from '@/config/network';\nimport {\n getLocalStorageItem,\n setLocalStorageItem,\n removeLocalStorageItem,\n isBrowser,\n} from '@/utils/ssrUtils';\n\nexport type StoredWallet = {\n address: string;\n connectedAt: number;\n isActive: boolean;\n};\n\nexport const useWalletStorage = () => {\n const { network } = useVeChainKitConfig();\n\n const getStorageKeys = useCallback((networkType: NETWORK_TYPE) => {\n return {\n wallets: `vechain_kit_wallets_${networkType}`,\n activeWallet: `vechain_kit_active_wallet_${networkType}`,\n };\n }, []);\n\n const getStoredWallets = useCallback((): StoredWallet[] => {\n if (!isBrowser()) return [];\n\n const keys = getStorageKeys(network.type);\n const cached = getLocalStorageItem(keys.wallets);\n if (!cached) return [];\n return JSON.parse(cached) as StoredWallet[];\n }, [network.type, getStorageKeys]);\n\n const getActiveWallet = useCallback((): string | null => {\n if (!isBrowser()) return null;\n\n const keys = getStorageKeys(network.type);\n return getLocalStorageItem(keys.activeWallet);\n }, [network.type, getStorageKeys]);\n\n const saveWallet = useCallback(\n (address: string) => {\n if (!isBrowser()) return;\n\n const keys = getStorageKeys(network.type);\n const wallets = getStoredWallets();\n const existingIndex = wallets.findIndex(\n (w) => w.address.toLowerCase() === address.toLowerCase(),\n );\n\n const walletToSave: StoredWallet = {\n address: address,\n connectedAt:\n existingIndex >= 0\n ? wallets[existingIndex].connectedAt\n : Date.now(),\n isActive: false,\n };\n\n if (existingIndex >= 0) {\n wallets[existingIndex] = walletToSave;\n } else {\n wallets.push(walletToSave);\n }\n\n setLocalStorageItem(keys.wallets, JSON.stringify(wallets));\n },\n [network.type, getStorageKeys, getStoredWallets],\n );\n\n const setActiveWallet = useCallback(\n (address: string) => {\n if (!isBrowser()) return;\n\n const keys = getStorageKeys(network.type);\n const wallets = getStoredWallets();\n\n // Update all wallets to set isActive\n const updatedWallets = wallets.map((w) => ({\n ...w,\n isActive: w.address.toLowerCase() === address.toLowerCase(),\n }));\n\n setLocalStorageItem(keys.wallets, JSON.stringify(updatedWallets));\n setLocalStorageItem(keys.activeWallet, address);\n },\n [network.type, getStorageKeys, getStoredWallets],\n );\n\n const removeWallet = useCallback(\n (address: string) => {\n if (!isBrowser()) return;\n\n const keys = getStorageKeys(network.type);\n const wallets = getStoredWallets();\n const updatedWallets = wallets.filter(\n (w) => w.address.toLowerCase() !== address.toLowerCase(),\n );\n\n setLocalStorageItem(keys.wallets, JSON.stringify(updatedWallets));\n\n // If removed wallet was active, clear active wallet\n const activeWallet = getActiveWallet();\n if (\n activeWallet &&\n activeWallet.toLowerCase() === address.toLowerCase()\n ) {\n removeLocalStorageItem(keys.activeWallet);\n }\n\n // Dispatch event to notify that a wallet was removed\n // This prevents useWallet from setting it as active again if it's still connected\n if (isBrowser()) {\n window.dispatchEvent(\n new CustomEvent('wallet_removed', { detail: { address } }),\n );\n }\n },\n [network.type, getStorageKeys, getStoredWallets, getActiveWallet],\n );\n\n const initializeCurrentWallet = useCallback(\n (address: string) => {\n if (!isBrowser()) return;\n\n const wallets = getStoredWallets();\n if (wallets.length === 0) {\n // No wallets stored, save current wallet\n saveWallet(address);\n setActiveWallet(address);\n }\n },\n [getStoredWallets, saveWallet, setActiveWallet],\n );\n\n return {\n getStoredWallets,\n getActiveWallet,\n saveWallet,\n setActiveWallet,\n removeWallet,\n initializeCurrentWallet,\n };\n};\n","'use client';\n\nimport {\n Wallet as PrivyWallet,\n useLoginWithOAuth,\n usePrivy,\n User,\n} from '@privy-io/react-auth';\nimport {\n useGetChainId,\n useGetNodeUrl,\n useGetAccountVersion,\n useDAppKitWallet,\n useSmartAccount,\n useCrossAppConnectionCache,\n} from '@/hooks';\nimport { compareAddresses, VECHAIN_PRIVY_APP_ID } from '@/utils';\nimport { ConnectionSource, SmartAccount, Wallet } from '@/types';\nimport { useVeChainKitConfig } from '@/providers';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { useAccount } from 'wagmi';\nimport { usePrivyCrossAppSdk } from '@/providers/PrivyCrossAppProvider';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useWalletMetadata } from './useWalletMetadata';\nimport { useWalletStorage } from './useWalletStorage';\nimport { isBrowser } from '@/utils/ssrUtils';\n\nexport type UseWalletReturnType = {\n // This will be the smart account if connected with privy, otherwise it will be wallet connected with dappkit\n account: Wallet;\n\n // The wallet in use between dappKitWallet, embeddedWallet and crossAppWallet\n connectedWallet: Wallet;\n\n // Every user connected with privy has one\n smartAccount: SmartAccount;\n\n // Privy user if user is connected with privy\n privyUser: User | null;\n\n // Connection status\n connection: {\n isConnected: boolean;\n isLoading: boolean;\n isConnectedWithSocialLogin: boolean;\n isConnectedWithDappKit: boolean;\n isConnectedWithCrossApp: boolean;\n isConnectedWithPrivy: boolean;\n isConnectedWithVeChain: boolean;\n source: ConnectionSource;\n isInAppBrowser: boolean;\n nodeUrl: string;\n delegatorUrl?: string;\n chainId?: string;\n network: NETWORK_TYPE;\n };\n\n // Disconnect function\n disconnect: () => Promise<void>;\n};\n\nexport const useWallet = (): UseWalletReturnType => {\n const {\n address: crossAppAddress,\n isConnected: isConnectedWithCrossApp,\n isConnecting: isConnectingWithCrossApp,\n isReconnecting: isReconnectingWithCrossApp,\n } = useAccount();\n const { logout: disconnectCrossApp } = usePrivyCrossAppSdk();\n const { loading: isLoadingLoginOAuth } = useLoginWithOAuth({});\n const { feeDelegation, network, privy } = useVeChainKitConfig();\n const { user, authenticated, logout, ready } = usePrivy();\n const { data: chainId } = useGetChainId();\n const { account: dappKitAccount, disconnect: dappKitDisconnect } =\n useDAppKitWallet();\n const { getConnectionCache, clearConnectionCache } =\n useCrossAppConnectionCache();\n const connectionCache = getConnectionCache();\n const {\n initializeCurrentWallet,\n getActiveWallet,\n saveWallet,\n getStoredWallets,\n } = useWalletStorage();\n\n const nodeUrl = useGetNodeUrl();\n\n // Check if in-app browser (calculate before using in useState)\n const isInAppBrowser = useMemo(\n () => (isBrowser() ? Boolean(window.vechain?.isInAppBrowser) : false),\n [],\n );\n\n // Connection states\n const isConnectedWithDappKit = !!dappKitAccount;\n const isConnectedWithSocialLogin = authenticated && !!user;\n const isConnectedWithPrivy =\n isConnectedWithSocialLogin || isConnectedWithCrossApp;\n\n const isConnectedWithVeChain =\n (isConnectedWithSocialLogin && privy?.appId === VECHAIN_PRIVY_APP_ID) ||\n (isConnectedWithCrossApp &&\n connectionCache?.ecosystemApp?.appId === VECHAIN_PRIVY_APP_ID);\n\n const isLoading =\n isConnectingWithCrossApp ||\n isReconnectingWithCrossApp ||\n isLoadingLoginOAuth ||\n !ready;\n\n // Add a single connection state that considers all factors\n const [isConnected, setIsConnected] = useState(false);\n\n // Connection type\n const connectionSource: ConnectionSource = isConnectedWithCrossApp\n ? {\n type: 'privy-cross-app',\n displayName: 'Ecosystem',\n }\n : isConnectedWithDappKit\n ? {\n type: 'wallet',\n displayName: 'Wallet',\n }\n : {\n type: 'privy',\n displayName: 'Social Login',\n };\n\n useEffect(() => {\n const isNowConnected =\n isConnectedWithDappKit ||\n isConnectedWithSocialLogin ||\n isConnectedWithCrossApp;\n\n if (isConnected !== isNowConnected) {\n setIsConnected(isNowConnected);\n\n // Only clear cache and dispatch event when disconnecting\n if (!isNowConnected) {\n // Clear any cached wallet data\n clearConnectionCache();\n // Dispatch event to trigger re-renders\n if (isBrowser()) {\n window.dispatchEvent(new Event('wallet_disconnected'));\n }\n }\n }\n }, [\n isConnectedWithDappKit,\n isConnectedWithSocialLogin,\n isConnectedWithCrossApp,\n clearConnectionCache,\n isConnected,\n ]);\n\n // Get embedded wallet\n const privyEmbeddedWallet = user?.linkedAccounts?.find(\n (account) =>\n account.type === 'wallet' && account.connectorType === 'embedded',\n ) as PrivyWallet;\n const privyEmbeddedWalletAddress = privyEmbeddedWallet?.address;\n\n // Get connected and selected accounts\n const connectedWalletAddress = isConnectedWithDappKit\n ? dappKitAccount\n : isConnectedWithCrossApp\n ? crossAppAddress\n : privyEmbeddedWalletAddress;\n\n // For desktop dappkit wallets, check if there's a stored active wallet\n // Use state to track active wallet so it updates immediately on switch\n const [storedActiveWalletAddress, setStoredActiveWalletAddress] = useState<\n string | null\n >(() => {\n if (isConnectedWithDappKit && !isInAppBrowser) {\n return getActiveWallet();\n }\n return null;\n });\n\n // Update stored active wallet when it changes in storage\n // Also reset when disconnecting\n useEffect(() => {\n if (isConnectedWithDappKit && !isInAppBrowser) {\n const activeWallet = getActiveWallet();\n setStoredActiveWalletAddress(activeWallet);\n } else {\n // Reset when disconnected or in-app browser\n setStoredActiveWalletAddress(null);\n }\n }, [isConnectedWithDappKit, isInAppBrowser, getActiveWallet]);\n\n // Track if a wallet switch is in progress to prevent overriding the user's selection\n const [isWalletSwitchInProgress, setIsWalletSwitchInProgress] =\n useState(false);\n\n // Listen for wallet switch events\n useEffect(() => {\n if (!isBrowser() || !isConnectedWithDappKit || isInAppBrowser) return;\n\n const handleWalletSwitch = (\n event: CustomEvent<{ address: string }>,\n ) => {\n setIsWalletSwitchInProgress(true);\n setStoredActiveWalletAddress(event.detail.address);\n // Reset the flag after a short delay to allow the connection to update\n setTimeout(() => {\n setIsWalletSwitchInProgress(false);\n }, 1000);\n };\n\n window.addEventListener(\n 'wallet_switched',\n handleWalletSwitch as EventListener,\n );\n return () => {\n window.removeEventListener(\n 'wallet_switched',\n handleWalletSwitch as EventListener,\n );\n };\n }, [isConnectedWithDappKit, isInAppBrowser]);\n\n // Always prioritize the stored active wallet from cache when switching\n // Use connected wallet when:\n // 1. No stored active wallet exists (new connection)\n // 2. Connected wallet is not in stored wallets list (new wallet after disconnect)\n // 3. A switch is NOT in progress AND connected wallet differs from stored (reconnection with different wallet)\n const storedWallets = getStoredWallets();\n const isConnectedWalletInStoredList = storedWallets.some(\n (w) =>\n w.address.toLowerCase() === connectedWalletAddress?.toLowerCase(),\n );\n\n // Always read the stored active wallet directly from storage to ensure consistency\n // This avoids race conditions with state updates\n const currentStoredActiveWallet =\n isConnectedWithDappKit && !isInAppBrowser ? getActiveWallet() : null;\n\n const effectiveConnectedWalletAddress =\n // If switch is in progress, always use stored active wallet\n isWalletSwitchInProgress && currentStoredActiveWallet\n ? currentStoredActiveWallet\n : // If stored active wallet exists and connected wallet is in stored list, use stored (switch scenario)\n currentStoredActiveWallet && isConnectedWalletInStoredList\n ? currentStoredActiveWallet\n : // Otherwise use connected wallet (new connection or reconnection with different wallet)\n connectedWalletAddress;\n\n // Get smart account\n const { data: smartAccount } = useSmartAccount(\n effectiveConnectedWalletAddress ?? '',\n );\n\n // TODO: here we will need to check if the owner of the wallet owns a smart account\n const activeAddress = isConnectedWithDappKit\n ? effectiveConnectedWalletAddress\n : smartAccount?.address;\n\n const activeAccountMetadata = useWalletMetadata(\n activeAddress ?? '',\n network.type,\n );\n\n const connectedMetadata = useWalletMetadata(\n effectiveConnectedWalletAddress ?? '',\n network.type,\n );\n const smartAccountMetadata = useWalletMetadata(\n smartAccount?.address ?? '',\n network.type,\n );\n\n const { setActiveWallet: setActiveWalletStorage } = useWalletStorage();\n\n // Track recently removed wallets to prevent them from being set as active again\n const recentlyRemovedWalletsRef = useRef<Set<string>>(new Set());\n\n // Listen for wallet removal events\n useEffect(() => {\n if (!isBrowser() || !isConnectedWithDappKit || isInAppBrowser) return;\n\n const handleWalletRemoved = (\n event: CustomEvent<{ address: string }>,\n ) => {\n // Track removed wallet for 5 seconds to prevent it from being set as active\n recentlyRemovedWalletsRef.current.add(\n event.detail.address.toLowerCase(),\n );\n setTimeout(() => {\n recentlyRemovedWalletsRef.current.delete(\n event.detail.address.toLowerCase(),\n );\n }, 5000);\n };\n\n window.addEventListener(\n 'wallet_removed',\n handleWalletRemoved as EventListener,\n );\n return () => {\n window.removeEventListener(\n 'wallet_removed',\n handleWalletRemoved as EventListener,\n );\n };\n }, [isConnectedWithDappKit, isInAppBrowser]);\n\n // Save/initialize wallet in storage when connected via dappkit and not in-app browser\n // Set the connected wallet as active when it's a new wallet or new connection\n useEffect(() => {\n if (\n isConnectedWithDappKit &&\n !isInAppBrowser &&\n connectedWalletAddress &&\n activeAccountMetadata &&\n !activeAccountMetadata.isLoading\n ) {\n // Don't save or set as active if this wallet was recently removed\n // This prevents re-adding wallets that the user just removed\n const wasRecentlyRemoved = recentlyRemovedWalletsRef.current.has(\n connectedWalletAddress.toLowerCase(),\n );\n if (wasRecentlyRemoved) {\n return;\n }\n\n // Check if this is a new wallet BEFORE saving (since saveWallet adds it to storage)\n const currentStoredWallets = getStoredWallets();\n const isNewWallet = !currentStoredWallets.some(\n (w) =>\n w.address.toLowerCase() ===\n connectedWalletAddress.toLowerCase(),\n );\n\n // First try to initialize (only saves if no wallets exist and sets as active)\n initializeCurrentWallet(connectedWalletAddress);\n // Always save/update the wallet (in case it already exists or is a new connection)\n saveWallet(connectedWalletAddress);\n\n // Check if this is a new connection or a switch\n // When switching, storedActiveWalletAddress is updated immediately via wallet_switched event\n // and isWalletSwitchInProgress is set to true\n // We should NOT override the stored active wallet when switching\n const isNewConnection = !storedActiveWalletAddress;\n const isSameAsStoredActive =\n storedActiveWalletAddress &&\n storedActiveWalletAddress.toLowerCase() ===\n connectedWalletAddress.toLowerCase();\n\n // Set as active if:\n // 1. It's a new wallet (not in stored wallets list) - always set as active for better UX, OR\n // 2. It's a new connection (no stored active wallet), OR\n // 3. The connected wallet matches the stored active wallet (same wallet, just ensuring it's saved), AND\n // 4. A wallet switch is NOT in progress (to prevent overriding user's selection during switch)\n if (\n (isNewWallet || isNewConnection || isSameAsStoredActive) &&\n !isWalletSwitchInProgress\n ) {\n setActiveWalletStorage(connectedWalletAddress);\n }\n }\n }, [\n isConnectedWithDappKit,\n isInAppBrowser,\n connectedWalletAddress,\n activeAccountMetadata?.domain,\n activeAccountMetadata?.image,\n activeAccountMetadata?.isLoading,\n initializeCurrentWallet,\n saveWallet,\n setActiveWalletStorage,\n storedActiveWalletAddress,\n getStoredWallets,\n ]);\n\n // Ensure the stored active wallet is saved when it changes\n // Metadata will be fetched dynamically when needed\n useEffect(() => {\n if (\n isConnectedWithDappKit &&\n !isInAppBrowser &&\n storedActiveWalletAddress &&\n storedActiveWalletAddress.toLowerCase() ===\n effectiveConnectedWalletAddress?.toLowerCase()\n ) {\n // Ensure the stored active wallet is saved\n saveWallet(storedActiveWalletAddress);\n }\n }, [\n isConnectedWithDappKit,\n isInAppBrowser,\n storedActiveWalletAddress,\n effectiveConnectedWalletAddress,\n saveWallet,\n ]);\n\n const account = activeAddress\n ? {\n address: activeAddress,\n domain: activeAccountMetadata.domain,\n image: activeAccountMetadata.image,\n isLoadingMetadata: activeAccountMetadata.isLoading,\n metadata: activeAccountMetadata.records,\n }\n : null;\n\n const connectedWallet = connectedWalletAddress\n ? {\n address: connectedWalletAddress,\n domain: connectedMetadata.domain,\n image: connectedMetadata.image,\n isLoadingMetadata: connectedMetadata.isLoading,\n metadata: connectedMetadata.records,\n }\n : null;\n\n // Get smart account version\n const { data: smartAccountVersion } = useGetAccountVersion(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n );\n\n const hasActiveSmartAccount =\n !!smartAccount?.address &&\n !!account?.address &&\n compareAddresses(smartAccount?.address, account?.address);\n\n // Modify the disconnect function to ensure state updates\n const disconnect = useCallback(async () => {\n try {\n // First set connection state to false\n setIsConnected(false);\n\n // Then perform disconnection logic\n if (isConnectedWithDappKit) {\n dappKitDisconnect();\n } else if (isConnectedWithSocialLogin) {\n await logout();\n } else if (isConnectedWithCrossApp) {\n await disconnectCrossApp();\n }\n\n clearConnectionCache();\n if (isBrowser()) {\n window.dispatchEvent(new Event('wallet_disconnected'));\n }\n } catch (error) {\n console.error('Error during disconnect:', error);\n }\n }, [\n isConnectedWithDappKit,\n dappKitDisconnect,\n isConnectedWithSocialLogin,\n logout,\n isConnectedWithCrossApp,\n disconnectCrossApp,\n clearConnectionCache,\n ]);\n\n return {\n account,\n smartAccount: {\n address: smartAccount?.address ?? '',\n domain: smartAccountMetadata.domain,\n image: smartAccountMetadata.image,\n isDeployed: smartAccount?.isDeployed ?? false,\n isActive: hasActiveSmartAccount,\n version: smartAccountVersion?.version ?? null,\n isLoadingMetadata: smartAccountMetadata.isLoading,\n metadata: smartAccountMetadata.records,\n },\n connectedWallet,\n privyUser: user,\n connection: {\n isLoading,\n isConnected,\n isConnectedWithSocialLogin,\n isConnectedWithDappKit,\n isConnectedWithCrossApp,\n isConnectedWithPrivy,\n isConnectedWithVeChain,\n source: connectionSource,\n isInAppBrowser,\n nodeUrl,\n delegatorUrl: feeDelegation?.delegatorUrl,\n chainId: chainId,\n network: network.type,\n },\n disconnect,\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';\nimport { useDAppKitWallet, useWallet } from '@/hooks';\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 } = useDAppKitWallet();\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';\nimport { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: ['xAppMetaData', xAppId],\n queryFn: async () => {\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: !!xAppId,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { convertUriToUrl } from '@/utils';\nimport { useVeChainKitConfig } from '@/providers';\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 { NFTMediaType } from '@/types';\nimport { useVeChainKitConfig } from '@/providers';\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';\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 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 {\n useThor,\n useWallet as useDAppKitWallet,\n} from '@vechain/dapp-kit-react';\nimport { TransactionMessage } from '@vechain/dapp-kit';\nimport { usePrivyWalletProvider, useVeChainKitConfig } from '@/providers';\nimport { TransactionStatus, TransactionStatusErrorType } from '@/types';\nimport { useGetNodeUrl, useTxReceipt, useWallet } from '@/hooks';\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 const thor = useThor();\n const { signer, requestTransaction } = useDAppKitWallet();\n const { connection } = useWallet();\n const { feeDelegation } = useVeChainKitConfig();\n const nodeUrl = useGetNodeUrl();\n const privyWalletProvider = usePrivyWalletProvider();\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 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 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 } 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) 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 { useCallback } from 'react';\nimport { useSendTransaction } from '@/hooks/thor/transactions/useSendTransaction';\nimport { useWallet } from '@/hooks';\nimport { 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 { 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 { 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 { 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 {\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 { 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 { SwapAggregator } from '@/types/swap';\nimport { NETWORK_TYPE } from '@/config/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 { SwapParams, SwapQuote } from '@/types/swap';\nimport { parseUnits, zeroAddress } from 'viem';\nimport { useThor } from '@vechain/dapp-kit-react';\nimport { useGetCustomTokenInfo } from '@/hooks/api/wallet/useGetCustomTokenInfo';\nimport { TokenWithValue } from '@/hooks';\nimport { useWallet } from '@/hooks/api/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 const thor = useThor();\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","import {\n Button,\n VStack,\n Text,\n HStack,\n PinInput,\n PinInputField,\n Icon,\n ModalFooter,\n ModalBody,\n ModalHeader,\n ModalCloseButton,\n Container,\n useToken,\n} from '@chakra-ui/react';\nimport { LuMail } from 'react-icons/lu';\nimport { BaseModal, StickyHeaderContainer } from '../common';\nimport { useEffect, useState } from 'react';\nimport { useCreateWallet, useLoginWithEmail } from '@privy-io/react-auth';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\n\ntype Props = {\n email: string;\n onResend: () => void;\n isLoading: boolean;\n isOpen: boolean;\n onClose: () => void;\n};\n\nexport const EmailCodeVerificationModal = ({\n email,\n onResend,\n isLoading,\n isOpen,\n onClose,\n}: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n \n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const [code, setCode] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n const { createWallet } = useCreateWallet();\n const { loginWithCode } = useLoginWithEmail({\n onComplete: async ({ isNewUser }) => {\n // When using initOAuth Privy does not create an embedded wallet automatically.\n // So we need to create a wallet manually.\n if (isNewUser) {\n await createWallet();\n }\n },\n });\n\n useEffect(() => {\n if (code.length === 6) {\n loginWithCode({ code })\n .then(() => {\n onClose();\n })\n .catch((error) => {\n setError(error.message);\n });\n }\n }, [code]);\n\n return (\n <BaseModal isOpen={isOpen} onClose={onClose} trapFocus={false}>\n <StickyHeaderContainer>\n <ModalHeader alignItems={'center'} display={'flex'} gap={2}>\n {t('Enter confirmation code')}\n </ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container maxW={'container.lg'}>\n <ModalBody>\n <VStack spacing={2}>\n <Icon\n as={LuMail}\n w=\"48px\"\n h=\"48px\"\n color={textSecondary}\n />\n\n <Text\n fontSize=\"xs\"\n color={textSecondary}\n textAlign=\"center\"\n >\n {t(\n 'Please check {{email}} for an email from privy.io and enter your code below.',\n {\n email,\n },\n )}\n </Text>\n <HStack spacing={2} justify=\"center\" mt={4}>\n <PinInput\n value={code}\n onChange={setCode}\n otp\n size=\"lg\"\n isInvalid={!!error}\n errorBorderColor=\"#ef4444\"\n >\n <PinInputField\n borderRadius=\"12px\"\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n backgroundColor={\n isDark ? 'transparent' : '#ffffff'\n }\n />\n <PinInputField\n borderRadius=\"12px\"\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n backgroundColor={\n isDark ? 'transparent' : '#ffffff'\n }\n />\n <PinInputField\n borderRadius=\"12px\"\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n backgroundColor={\n isDark ? 'transparent' : '#ffffff'\n }\n />\n <PinInputField\n borderRadius=\"12px\"\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n backgroundColor={\n isDark ? 'transparent' : '#ffffff'\n }\n />\n <PinInputField\n borderRadius=\"12px\"\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n backgroundColor={\n isDark ? 'transparent' : '#ffffff'\n }\n />\n <PinInputField\n borderRadius=\"12px\"\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n backgroundColor={\n isDark ? 'transparent' : '#ffffff'\n }\n />\n </PinInput>\n </HStack>\n {error && (\n <Text color=\"#ef4444\" fontSize=\"xs\">\n {error}\n </Text>\n )}\n </VStack>\n </ModalBody>\n <ModalFooter>\n <Text\n w=\"100%\"\n textAlign=\"center\"\n fontSize=\"14px\"\n color={isDark ? 'whiteAlpha.700' : 'gray.600'}\n >\n {t(\"Didn't get an email?\")}{' '}\n <Button\n variant=\"link\"\n color=\"blue.500\"\n fontSize=\"14px\"\n onClick={onResend}\n isLoading={isLoading}\n >\n {t('Resend code')}\n </Button>\n </Text>\n </ModalFooter>\n </Container>\n </BaseModal>\n );\n};\n","import {\n Button,\n GridItem,\n Icon,\n Input,\n InputGroup,\n InputLeftElement,\n useDisclosure,\n VStack,\n} from '@chakra-ui/react';\nimport { useLoginWithEmail } from '@privy-io/react-auth';\nimport { useState } from 'react';\nimport { LuMail } from 'react-icons/lu';\nimport { EmailCodeVerificationModal } from '../../EmailCodeVerificationModal/EmailCodeVerificationModal';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\n\nexport const EmailLoginButton = () => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n\n // Email login\n const [email, setEmail] = useState('');\n\n const { sendCode, state: emailState } = useLoginWithEmail({});\n\n const emailCodeVerificationModal = useDisclosure();\n\n const handleSendCode = async () => {\n await sendCode({ email });\n // onClose();\n emailCodeVerificationModal.onOpen();\n };\n\n return (\n <>\n <GridItem colSpan={4} w={'full'}>\n <VStack spacing={3} w=\"full\">\n <InputGroup size=\"lg\" w=\"full\">\n <InputLeftElement\n pointerEvents=\"none\"\n height=\"100%\"\n pl={4}\n >\n <Icon\n as={LuMail}\n color={\n isDark ? 'whiteAlpha.600' : 'blackAlpha.700'\n }\n w={'20px'}\n h={'20px'}\n />\n </InputLeftElement>\n <Input\n placeholder={t('your@email.com')}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n fontSize={'16px'}\n fontWeight={'400'}\n backgroundColor={isDark ? 'transparent' : '#ffffff'}\n border={`1px solid ${\n isDark ? '#ffffff0a' : '#ebebeb'\n }`}\n p={6}\n borderRadius={16}\n w={'full'}\n pl={12}\n />\n <Button\n aria-label=\"Send code\"\n position=\"absolute\"\n right={2}\n top=\"50%\"\n transform=\"translateY(-50%)\"\n zIndex={2}\n variant=\"ghost\"\n size=\"sm\"\n px={6}\n borderRadius=\"full\"\n isLoading={emailState.status === 'sending-code'}\n onClick={handleSendCode}\n >\n {t('Submit')}\n </Button>\n </InputGroup>\n </VStack>\n </GridItem>\n\n <EmailCodeVerificationModal\n isOpen={emailCodeVerificationModal.isOpen}\n onClose={emailCodeVerificationModal.onClose}\n onResend={() => sendCode({ email })}\n email={email}\n isLoading={emailState.status === 'sending-code'}\n />\n </>\n );\n};\n","import { GridItem } from '@chakra-ui/react';\nimport { FcGoogle } from 'react-icons/fc';\nimport { ConnectionButton } from '@/components';\nimport { useTranslation } from 'react-i18next';\nimport { useLoginWithOAuth } from '@/hooks';\n\ntype Props = {\n isDark: boolean;\n gridColumn?: number;\n};\n\nexport const LoginWithGoogleButton = ({ isDark, gridColumn }: Props) => {\n const { t } = useTranslation();\n const { initOAuth } = useLoginWithOAuth();\n\n return (\n <GridItem colSpan={gridColumn ?? 4} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={async () => {\n await initOAuth({\n provider: 'google',\n });\n }}\n icon={FcGoogle}\n text={t('Continue with Google')}\n />\n </GridItem>\n );\n};\n","import { GridItem } from '@chakra-ui/react';\nimport { LuGithub } from 'react-icons/lu';\nimport { ConnectionButton } from '@/components';\nimport { useTranslation } from 'react-i18next';\nimport { useLoginWithOAuth } from '@/hooks';\n\ntype Props = {\n isDark: boolean;\n gridColumn?: number;\n};\n\nexport const LoginWithGithubButton = ({ isDark, gridColumn }: Props) => {\n const { t } = useTranslation();\n const { initOAuth } = useLoginWithOAuth();\n\n return (\n <GridItem colSpan={gridColumn ?? 4} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={async () => {\n await initOAuth({\n provider: 'github',\n });\n }}\n icon={LuGithub}\n text={t('Continue with Github')}\n />\n </GridItem>\n );\n};\n","import { GridItem } from '@chakra-ui/react';\nimport { VechainLogoDark, VechainLogoLight } from '@/assets';\nimport { ConnectionButton, SocialIcons } from '@/components';\nimport { usePrivy } from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { IconType } from 'react-icons';\n\ntype Props = {\n isDark: boolean;\n gridColumn?: number;\n};\n\n/// This button is used to login with VeChain using Privy on\n/// platforms like VeBetterDAO and VeChain Kit Homepage.\n/// It is a very specific scenario.\nexport const VeChainWithPrivyLoginButton = ({ isDark, gridColumn }: Props) => {\n const { t } = useTranslation();\n const { login: viewMoreLogin } = usePrivy();\n\n return (\n <GridItem colSpan={gridColumn ? gridColumn : 4} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={viewMoreLogin}\n icon={\n isDark\n ? (VechainLogoLight as IconType)\n : (VechainLogoDark as IconType)\n }\n text={t('Use social login with VeChain')}\n variant={'loginWithVechain'}\n rightIcon={<SocialIcons />}\n />\n </GridItem>\n );\n};\n","import { GridItem } from '@chakra-ui/react';\nimport { VechainLogoDark, VechainLogoLight } from '@/assets';\nimport { ConnectionButton, SocialIcons } from '@/components';\nimport { useLoginWithVeChain } from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { IconType } from 'react-icons';\nimport { ConnectModalContentsTypes } from '../ConnectModal';\nimport React from 'react';\n\ntype Props = {\n isDark: boolean;\n gridColumn?: number;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n};\n\nexport const VeChainLoginButton = ({\n isDark,\n gridColumn,\n setCurrentContent,\n}: Props) => {\n const { t } = useTranslation();\n const { login: loginWithVeChain } = useLoginWithVeChain();\n\n const handleLoginWithVeChain = async () => {\n setCurrentContent({\n type: 'loading',\n props: {\n title: t('Connecting to VeChain'),\n loadingText: t(\n 'Please approve the request in the connection request window...',\n ),\n onTryAgain: handleLoginWithVeChain,\n },\n });\n try {\n await loginWithVeChain();\n } catch (error) {\n console.error(t('Login failed:'), error);\n setCurrentContent({\n type: 'error',\n props: {\n error:\n error instanceof Error\n ? error.message\n : t('Failed to connect with VeChain'),\n onTryAgain: handleLoginWithVeChain,\n },\n });\n }\n };\n\n return (\n <GridItem colSpan={gridColumn ? gridColumn : 4} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={handleLoginWithVeChain}\n icon={\n isDark\n ? (VechainLogoLight as IconType)\n : (VechainLogoDark as IconType)\n }\n text={t('Use social login with VeChain')}\n variant={'loginWithVechain'}\n rightIcon={<SocialIcons />}\n />\n </GridItem>\n );\n};\n","import { GridItem } from '@chakra-ui/react';\nimport { LuFingerprint } from 'react-icons/lu';\nimport { ConnectionButton } from '@/components';\nimport { useTranslation } from 'react-i18next';\nimport { useLoginWithPasskey } from '@/hooks';\nimport { ConnectModalContentsTypes } from '../ConnectModal';\nimport React from 'react';\n\ntype Props = {\n isDark: boolean;\n gridColumn?: number;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n};\n\nexport const PasskeyLoginButton = ({\n isDark,\n gridColumn,\n setCurrentContent,\n}: Props) => {\n const { t } = useTranslation();\n const { loginWithPasskey } = useLoginWithPasskey();\n\n const handleLoginWithPasskey = async () => {\n setCurrentContent({\n type: 'loading',\n props: {\n title: t('Connecting with Passkey'),\n loadingText: t('Please complete the passkey authentication...'),\n onTryAgain: handleLoginWithPasskey,\n },\n });\n try {\n await loginWithPasskey();\n } catch (error) {\n const errorMsg =\n error instanceof Error ? error.message.toLowerCase() : '';\n\n // Log specific error types for debugging\n if (errorMsg.includes('not found')) {\n console.error(error);\n }\n\n setCurrentContent({\n type: 'error',\n props: {\n error:\n error instanceof Error\n ? error.message\n : t('Failed to connect with Passkey'),\n onTryAgain: handleLoginWithPasskey,\n },\n });\n }\n };\n\n return (\n <GridItem colSpan={gridColumn} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={handleLoginWithPasskey}\n icon={LuFingerprint}\n text={gridColumn && gridColumn >= 2 ? t('Passkey') : undefined}\n />\n </GridItem>\n );\n};\n","import { GridItem, Icon } from '@chakra-ui/react';\nimport { useDAppKitWalletModal } from '@/hooks';\nimport { ConnectionButton } from '@/components';\nimport { useTranslation } from 'react-i18next';\nimport { LuArrowRight, LuWallet } from 'react-icons/lu';\nimport { useEffect } from 'react';\nimport { useWallet as useDappKitWallet } from '@vechain/dapp-kit-react';\nimport { VeWorldLogoDark, VeWorldLogoLight } from '@/assets';\nimport { IconType } from 'react-icons';\nimport { useVeChainKitConfig } from '@/providers';\n\ntype Props = {\n isDark: boolean;\n gridColumn?: number;\n};\n\nexport const DappKitButton = ({ isDark, gridColumn = 2 }: Props) => {\n const { t } = useTranslation();\n const { open: openDappKitModal, onConnectionStatusChange } =\n useDAppKitWalletModal();\n const { dappKit } = useVeChainKitConfig();\n const { source } = useDappKitWallet();\n\n // Determine the button text based on the source\n const buttonText = !dappKit?.allowedWallets?.includes('sync2')\n ? t('Connect with VeWorld wallet')\n : t('Connect wallet');\n\n useEffect(() => {\n const handleConnectionChange = (\n address: string | null,\n error?: Error,\n ) => {\n if (!address) {\n if (error?.message) {\n console.error(error?.message);\n }\n return { ...(source && { source }) };\n }\n // Wallet activation is now handled in useWallet.ts\n // When a wallet connects, it will automatically be set as active\n };\n onConnectionStatusChange(handleConnectionChange);\n }, [onConnectionStatusChange, source]);\n const handleDappKitClick = () => {\n openDappKitModal();\n };\n\n return (\n <GridItem colSpan={gridColumn ? gridColumn : 2} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={handleDappKitClick}\n icon={\n !dappKit?.allowedWallets?.includes('sync2')\n ? ((isDark\n ? VeWorldLogoLight\n : VeWorldLogoDark) as IconType)\n : (LuWallet as IconType)\n }\n iconWidth={'27px'}\n text={gridColumn >= 2 ? buttonText : undefined}\n rightIcon={\n (dappKit?.allowedWallets?.includes('sync2') && (\n <Icon as={LuArrowRight} />\n )) ||\n undefined\n }\n />\n </GridItem>\n );\n};\n","import { GridItem, Icon } from '@chakra-ui/react';\nimport { LuEllipsis, LuArrowRight } from 'react-icons/lu';\nimport { ConnectionButton } from '@/components';\nimport { useTranslation } from 'react-i18next';\n\ntype Props = {\n isDark: boolean;\n onViewMoreLogin: () => void;\n gridColumn?: number;\n};\n\nexport const PrivyButton = ({ isDark, onViewMoreLogin, gridColumn }: Props) => {\n const { t } = useTranslation();\n return (\n <GridItem colSpan={gridColumn} w={'full'}>\n <ConnectionButton\n isDark={isDark}\n onClick={onViewMoreLogin}\n icon={LuEllipsis}\n text={gridColumn && gridColumn >= 2 ? t('More') : undefined}\n rightIcon={<Icon as={LuArrowRight} />}\n />\n </GridItem>\n );\n};\n","import { Grid, Stack } from '@chakra-ui/react';\nimport { EmailLoginButton } from './EmailLoginButton';\nimport { LoginWithGoogleButton } from './LoginWithGoogleButton';\nimport { LoginWithGithubButton } from './LoginWithGithubButton';\nimport { VeChainWithPrivyLoginButton } from './VeChainWithPrivyLoginButton';\nimport { VeChainLoginButton } from './VeChainLoginButton';\nimport { PasskeyLoginButton } from './PasskeyLoginButton';\nimport { DappKitButton } from './DappKitButton';\nimport { PrivyButton } from './PrivyButton';\nimport { useLoginModalContent, usePrivy } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\nimport { ConnectModalContentsTypes } from '../ConnectModal';\nimport React from 'react';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n};\n\nexport const ConnectionOptionsStack = ({ setCurrentContent }: Props) => {\n const { loginMethods, darkMode: isDark } = useVeChainKitConfig();\n\n // View more login\n const { login: viewMoreLogin } = usePrivy();\n\n const {\n showGoogleLogin,\n showEmailLogin,\n showPasskey,\n showVeChainLogin,\n showDappKit,\n showMoreLogin,\n showGithubLogin,\n isOfficialVeChainApp,\n } = useLoginModalContent();\n\n return (\n <Stack spacing={4} w={'full'} align={'center'}>\n <Grid templateColumns=\"repeat(4, 1fr)\" gap={2} w={'full'}>\n {loginMethods?.map(({ method, gridColumn }) => {\n switch (method) {\n case 'email':\n return (\n showEmailLogin && (\n <EmailLoginButton key=\"email\" />\n )\n );\n case 'google':\n return (\n showGoogleLogin && (\n <LoginWithGoogleButton\n key=\"google\"\n isDark={isDark}\n gridColumn={gridColumn}\n />\n )\n );\n case 'github':\n return (\n showGithubLogin && (\n <LoginWithGithubButton\n key=\"github\"\n isDark={isDark}\n gridColumn={gridColumn}\n />\n )\n );\n case 'vechain':\n return (\n showVeChainLogin &&\n (isOfficialVeChainApp ? (\n <VeChainWithPrivyLoginButton\n key=\"vechain\"\n isDark={isDark}\n gridColumn={gridColumn}\n />\n ) : (\n <VeChainLoginButton\n key=\"vechain\"\n isDark={isDark}\n gridColumn={gridColumn}\n setCurrentContent={setCurrentContent}\n />\n ))\n );\n case 'passkey':\n return (\n showPasskey && (\n <PasskeyLoginButton\n key=\"passkey\"\n isDark={isDark}\n gridColumn={gridColumn}\n setCurrentContent={setCurrentContent}\n />\n )\n );\n case 'dappkit':\n return (\n showDappKit && (\n <DappKitButton\n key=\"dappkit\"\n isDark={isDark}\n gridColumn={gridColumn}\n />\n )\n );\n case 'more':\n return (\n showMoreLogin && (\n <PrivyButton\n key=\"more\"\n isDark={isDark}\n onViewMoreLogin={viewMoreLogin}\n gridColumn={gridColumn}\n />\n )\n );\n default:\n return null;\n }\n })}\n </Grid>\n </Stack>\n );\n};\n","import { Button } from '@chakra-ui/react';\nimport { ConnectModalContentsTypes } from '@/components';\nimport { useTranslation } from 'react-i18next';\nimport { PrivyAppInfo } from '@/types';\n\ntype Props = {\n isDark: boolean;\n appsInfo: PrivyAppInfo[];\n isLoading: boolean;\n gridColumn?: number;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n};\n\nexport const EcosystemButton = ({\n appsInfo,\n isLoading,\n setCurrentContent,\n}: Props) => {\n const { t } = useTranslation();\n\n return (\n <Button\n fontSize={'sm'}\n variant=\"link\"\n onClick={() =>\n setCurrentContent({\n type: 'ecosystem',\n props: { appsInfo, isLoading },\n })\n }\n >\n {t('Already have an x2earn app wallet?')}\n </Button>\n );\n};\n","import {\n HStack,\n Image,\n ModalBody,\n ModalCloseButton,\n ModalFooter,\n ModalHeader,\n Text,\n useToken,\n} from '@chakra-ui/react';\nimport { useVeChainKitConfig } from '@/providers';\nimport { ModalFAQButton, StickyHeaderContainer } from '@/components/common';\nimport { ConnectModalContentsTypes } from '../ConnectModal';\nimport React, { useEffect } from 'react';\nimport { useFetchAppInfo, useWallet } from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { ConnectionOptionsStack } from '../Components/ConnectionOptionsStack';\nimport { EcosystemButton } from '../Components/EcosystemButton';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n onClose: () => void;\n preventAutoClose?: boolean;\n};\n\nexport const MainContent = ({ setCurrentContent, onClose, preventAutoClose = false }: Props) => {\n const { t } = useTranslation();\n const { connection } = useWallet();\n\n const { loginModalUI, darkMode: isDark } = useVeChainKitConfig();\n const { loginMethods, privyEcosystemAppIDS } = useVeChainKitConfig();\n const { data: appsInfo, isLoading: isEcosystemAppsLoading } =\n useFetchAppInfo(privyEcosystemAppIDS);\n\n const textColor = useToken('colors', 'vechain-kit-text-secondary');\n\n const handleFAQClick = () => {\n setCurrentContent('faq');\n };\n\n const showEcosystemButton = loginMethods?.some(\n ({ method }) => method === 'ecosystem',\n );\n\n useEffect(() => {\n if (connection.isConnected && !preventAutoClose) {\n onClose();\n }\n }, [connection.isConnected, onClose, preventAutoClose]);\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalFAQButton onClick={handleFAQClick} />\n <ModalHeader>{t('Log in or sign up')}</ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n {loginModalUI?.logo && (\n <HStack justify={'center'}>\n <Image\n src={loginModalUI.logo || '/images/favicon.png'}\n maxW={'180px'}\n maxH={'90px'}\n m={8}\n alt=\"logo\"\n />\n </HStack>\n )}\n\n <ModalBody>\n {loginModalUI?.description && (\n <HStack\n spacing={4}\n w={'full'}\n justify={'center'}\n mb={'24px'}\n px={4}\n >\n <Text\n color={textColor}\n fontSize={'sm'}\n textAlign={'center'}\n >\n {loginModalUI?.description}\n </Text>\n </HStack>\n )}\n <ConnectionOptionsStack setCurrentContent={setCurrentContent} />\n </ModalBody>\n\n {showEcosystemButton ? (\n <ModalFooter>\n <HStack justify={'center'} w={'full'}>\n <EcosystemButton\n isDark={isDark}\n appsInfo={Object.values(appsInfo || {})}\n isLoading={isEcosystemAppsLoading}\n setCurrentContent={setCurrentContent}\n />\n </HStack>\n </ModalFooter>\n ) : (\n <ModalFooter pt={0} pb={'5px'} />\n )}\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Tag,\n ModalFooter,\n} from '@chakra-ui/react';\nimport {\n StickyHeaderContainer,\n ScrollToTopWrapper,\n WalletSwitchFeedback,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport {\n AccountSelector,\n BalanceSection,\n ModalBackButton,\n QuickActionsSection,\n} from '@/components';\nimport { Wallet } from '@/types';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useAccountModalOptions } from '@/hooks';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onClose: () => void;\n wallet: Wallet;\n switchFeedback?: { showFeedback: boolean };\n};\n\nexport const AccountMainContent = ({\n setCurrentContent,\n wallet,\n onClose,\n switchFeedback,\n}: Props) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const { isolatedView } = useAccountModalOptions();\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n {!isolatedView && (\n <ModalBackButton\n onClick={() => {\n setCurrentContent('profile');\n }}\n />\n )}\n <ModalHeader>\n {t('Wallet')}\n\n {network?.type !== 'main' && (\n <Tag\n size=\"xs\"\n colorScheme=\"orange\"\n fontSize={'2xs'}\n p={1}\n ml={1}\n textTransform={'uppercase'}\n >\n {`${network?.type}`}\n </Tag>\n )}\n </ModalHeader>\n\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack\n w={'full'}\n overflow={'hidden'}\n justifyContent={'flex-start'}\n spacing={8}\n >\n <WalletSwitchFeedback\n showFeedback={switchFeedback?.showFeedback}\n />\n <AccountSelector\n style={{ justifyContent: 'flex-start' }}\n onClick={() => {\n setCurrentContent('profile');\n }}\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n wallet={wallet}\n />\n\n <BalanceSection\n onAssetsClick={() => {\n setCurrentContent('assets');\n }}\n />\n\n <QuickActionsSection\n setCurrentContent={setCurrentContent}\n />\n </VStack>\n </ModalBody>\n <ModalFooter pt={0}></ModalFooter>\n </ScrollToTopWrapper>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Input,\n Text,\n InputGroup,\n InputLeftElement,\n Icon,\n ModalFooter,\n Container,\n useToken,\n} from '@chakra-ui/react';\nimport { LuSearch, LuSlash } from 'react-icons/lu';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes, AssetButton } from '@/components';\nimport { useWallet, useTokensWithValues, TokenWithValue } from '@/hooks';\nimport { useState, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useCurrency } from '@/hooks';\nimport { SupportedCurrency } from '@/utils/currencyUtils';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onSelectToken: (token: TokenWithValue) => void;\n onBack: () => void;\n /**\n * If true, shows all tokens (not just tokens with balance) and sorts owned tokens first\n */\n showAllTokens?: boolean;\n};\n\nexport const SelectTokenContent = ({\n onSelectToken,\n onBack,\n showAllTokens = false,\n}: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { currentCurrency } = useCurrency();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const { account } = useWallet();\n const { tokensWithBalance, sortedTokens } = useTokensWithValues({\n address: account?.address ?? '',\n });\n const [searchQuery, setSearchQuery] = useState('');\n\n // Get the appropriate token list based on showAllTokens prop\n const availableTokens = useMemo(() => {\n if (showAllTokens) {\n // Show all tokens, sorted with owned tokens first (by value), then unowned\n const ownedTokens = sortedTokens.filter(\n (token) => Number(token.balance) > 0,\n );\n const unownedTokens = sortedTokens.filter(\n (token) => Number(token.balance) === 0,\n );\n\n // Owned tokens are already sorted by value (highest first)\n // Unowned tokens are sorted alphabetically\n const sortedUnowned = [...unownedTokens].sort((a, b) =>\n a.symbol.localeCompare(b.symbol),\n );\n\n return [...ownedTokens, ...sortedUnowned];\n }\n return tokensWithBalance;\n }, [showAllTokens, sortedTokens, tokensWithBalance]);\n\n // Filter tokens\n const filteredTokens = availableTokens.filter(({ symbol }) =>\n symbol.toLowerCase().includes(searchQuery.toLowerCase()),\n );\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Select Token')}</ModalHeader>\n <ModalBackButton onClick={onBack} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container h={['540px', 'auto']} p={0}>\n <ModalBody>\n <VStack spacing={4} align=\"stretch\">\n <InputGroup size=\"lg\">\n <Input\n placeholder=\"Search token\"\n bg={\n isDark\n ? 'vechain-kit-overlay'\n : 'vechain-kit-card'\n }\n borderRadius=\"xl\"\n height=\"56px\"\n pl={12}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n data-testid=\"search-token-input\"\n />\n <InputLeftElement h=\"56px\" w=\"56px\" pl={4}>\n <LuSearch color={textTertiary} />\n </InputLeftElement>\n </InputGroup>\n\n <Text\n fontSize=\"lg\"\n fontWeight=\"semibold\"\n color={textPrimary}\n mt={4}\n >\n {showAllTokens ? t('All tokens') : t('Your tokens')}\n </Text>\n\n {filteredTokens.length === 0 ? (\n <VStack spacing={2} py={8}>\n <Icon\n as={LuSlash}\n boxSize={12}\n color={textTertiary}\n />\n <Text fontSize=\"lg\" color={textPrimary}>\n {t('No tokens found')}\n </Text>\n <Text fontSize=\"md\" color={textSecondary}>\n {t('Try searching with a different term')}\n </Text>\n </VStack>\n ) : (\n <VStack spacing={2} align=\"stretch\">\n {filteredTokens.map((token) => (\n <AssetButton\n key={token.address}\n symbol={token.symbol}\n amount={Number(token.balance)}\n currencyValue={token.valueInCurrency}\n currentCurrency={\n currentCurrency as SupportedCurrency\n }\n onClick={() => onSelectToken(token)}\n />\n ))}\n </VStack>\n )}\n </VStack>\n </ModalBody>\n </Container>\n <ModalFooter pt={0} />\n </>\n );\n};\n","import { useModal } from '@/providers/ModalProvider';\n\nexport const useAccountModalOptions = () => {\n const { isolatedView, closeAccountModal } = useModal();\n\n return {\n isolatedView,\n closeAccountModal,\n };\n};\n","import React from 'react';\nimport {\n ModalBody,\n ModalHeader,\n VStack,\n Input,\n Button,\n Text,\n Box,\n HStack,\n Icon,\n ModalFooter,\n Image,\n FormControl,\n useToken,\n ModalCloseButton,\n} from '@chakra-ui/react';\nimport { useState, useEffect, useMemo, useRef } from 'react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components';\nimport { AccountModalContentTypes } from '../../Types';\nimport { LuChevronDown } from 'react-icons/lu';\nimport { SelectTokenContent } from './SelectTokenContent';\nimport { parseEther } from 'ethers';\nimport { TOKEN_LOGOS, TOKEN_LOGO_COMPONENTS } from '@/utils';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useForm } from 'react-hook-form';\nimport {\n useVechainDomain,\n TokenWithValue,\n useTokensWithValues,\n useWallet,\n} from '@/hooks';\nimport { useCurrency, useTokenPrices } from '@/hooks';\nimport {\n formatCompactCurrency,\n SupportedCurrency,\n convertToSelectedCurrency,\n} from '@/utils/currencyUtils';\nimport { ens_normalize } from '@adraffy/ens-normalize';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\nexport type SendTokenContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n preselectedToken?: TokenWithValue;\n initialAmount?: string;\n initialToAddressOrDomain?: string;\n onBack?: () => void;\n};\n\n// Add form values type\ntype FormValues = {\n amount: string;\n toAddressOrDomain: string;\n};\n\nexport const SendTokenContent = ({\n setCurrentContent,\n preselectedToken,\n initialAmount = '',\n initialToAddressOrDomain = '',\n onBack: parentOnBack = () => setCurrentContent('main'),\n}: SendTokenContentProps) => {\n const { t } = useTranslation();\n const { darkMode: isDark, feeDelegation } = useVeChainKitConfig();\n const { currentCurrency } = useCurrency();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const errorColor = useToken('colors', 'vechain-kit-error');\n const cardBg = useToken('colors', 'vechain-kit-card');\n\n const { exchangeRates } = useTokenPrices();\n const { account } = useWallet();\n const { isolatedView } = useAccountModalOptions();\n const { tokensWithBalance } = useTokensWithValues({\n address: account?.address ?? '',\n });\n\n const [selectedToken, setSelectedToken] = useState<TokenWithValue | null>(\n preselectedToken ?? tokensWithBalance[0] ?? null,\n );\n const [isSelectingToken, setIsSelectingToken] = useState(false);\n\n // Set first token with balance as default when tokens load\n useEffect(() => {\n if (\n !preselectedToken &&\n !selectedToken &&\n tokensWithBalance.length > 0\n ) {\n setSelectedToken(tokensWithBalance[0]);\n }\n }, [tokensWithBalance, preselectedToken, selectedToken]);\n\n // Form setup with validation rules\n const {\n register,\n watch,\n setValue,\n setError,\n formState: { errors, isValid },\n handleSubmit,\n } = useForm<FormValues>({\n defaultValues: {\n amount: initialAmount,\n toAddressOrDomain: initialToAddressOrDomain,\n },\n mode: 'onChange',\n });\n\n // Watch form values\n const { toAddressOrDomain, amount } = watch();\n\n // Track previous token to detect changes\n const prevTokenRef = useRef<TokenWithValue | null>(selectedToken);\n\n // Reset amount when token changes\n useEffect(() => {\n if (\n prevTokenRef.current &&\n selectedToken &&\n prevTokenRef.current.address !== selectedToken.address\n ) {\n setValue('amount', '');\n }\n prevTokenRef.current = selectedToken;\n }, [selectedToken, setValue]);\n\n const formattedValue = useMemo(() => {\n if (selectedToken) {\n return formatCompactCurrency(\n convertToSelectedCurrency(\n Number(amount) * selectedToken.priceUsd,\n currentCurrency as SupportedCurrency,\n exchangeRates,\n ),\n { currency: currentCurrency as SupportedCurrency },\n );\n }\n return '';\n }, [amount, selectedToken, currentCurrency, exchangeRates]);\n\n const { data: resolvedDomainData, isLoading } =\n useVechainDomain(toAddressOrDomain);\n\n const handleSetMaxAmount = () => {\n if (selectedToken) {\n setValue('amount', selectedToken.balance);\n }\n };\n\n const handleBack = () => {\n parentOnBack();\n };\n\n const onSubmit = async (data: FormValues) => {\n if (!selectedToken) return;\n\n // Validation:\n // - Address is valid\n // - There is no domain attached to the address or (if it is attached) the returned domain is the primary domain\n const isValidReceiver =\n resolvedDomainData?.isValidAddressOrDomain &&\n (!resolvedDomainData?.domain ||\n (resolvedDomainData?.domain &&\n resolvedDomainData?.isPrimaryDomain));\n\n if (!isValidReceiver) {\n setError('toAddressOrDomain', {\n type: 'manual',\n message: t('Invalid address or domain'),\n });\n return;\n }\n\n // Validate amount\n if (selectedToken) {\n const numericAmount = parseEther(data.amount);\n\n // Enforce minimum for B3TR (precise wei comparison)\n const minB3tr = feeDelegation?.b3trTransfers?.minAmountInEther;\n if (\n selectedToken.symbol === 'B3TR' &&\n typeof minB3tr === 'number' &&\n minB3tr > 0\n ) {\n try {\n const minWei = parseEther(String(minB3tr));\n if (numericAmount < minWei) {\n setError('amount', {\n type: 'manual',\n message: t(\n 'Minimum {{symbol}} transfer is {{min}}',\n {\n symbol: selectedToken.symbol,\n min: minB3tr,\n },\n ),\n });\n return;\n }\n } catch {\n // ignore parse error and continue\n }\n }\n\n if (numericAmount > parseEther(selectedToken.balance)) {\n setError('amount', {\n type: 'manual',\n message: t(`Insufficient {{symbol}} balance`, {\n symbol: selectedToken.symbol,\n }),\n });\n return;\n }\n }\n setCurrentContent({\n type: 'send-token-summary',\n props: {\n toAddressOrDomain: data.toAddressOrDomain,\n resolvedDomain: resolvedDomainData?.domain,\n resolvedAddress: resolvedDomainData?.address,\n amount: data.amount,\n selectedToken,\n formattedTotalAmount: formattedValue,\n setCurrentContent,\n },\n });\n };\n\n if (isSelectingToken) {\n return (\n <SelectTokenContent\n setCurrentContent={setCurrentContent}\n onSelectToken={(token) => {\n setSelectedToken(token);\n setIsSelectingToken(false);\n }}\n onBack={() => {\n setIsSelectingToken(false);\n }}\n />\n );\n }\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Send')}</ModalHeader>\n {!isolatedView && <ModalBackButton onClick={handleBack} />}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={2} align=\"stretch\" position=\"relative\">\n <HStack justify=\"space-between\">\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n color={textPrimary}\n >\n {t('Amount')}\n </Text>\n\n <Text\n cursor=\"pointer\"\n _hover={{\n color: textSecondary,\n textDecoration: 'underline',\n }}\n onClick={handleSetMaxAmount}\n noOfLines={1}\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textSecondary}\n >\n {t('Balance')}:{' '}\n {Number(selectedToken?.balance ?? 0).toLocaleString(\n undefined,\n {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n },\n )}\n </Text>\n </HStack>\n\n <Box p={4} borderRadius=\"2xl\" bg={cardBg}>\n <VStack align=\"stretch\" spacing={2}>\n <FormControl isInvalid={!!errors.amount}>\n <HStack justify=\"space-between\">\n <Input\n {...register('amount', {\n required: t('Amount is required'),\n pattern: {\n value: /^\\d*\\.?\\d*$/,\n message: t(\n 'Please enter a valid number',\n ),\n },\n validate: (value) => {\n if (!value) return true;\n const numericValue =\n parseFloat(value);\n if (isNaN(numericValue)) {\n return t(\n 'Please enter a valid number',\n );\n }\n\n // Enforce minimum amount for B3TR (in ether units)\n const minB3tr =\n feeDelegation?.b3trTransfers\n ?.minAmountInEther;\n if (\n selectedToken?.symbol ===\n 'B3TR' &&\n typeof minB3tr ===\n 'number' &&\n minB3tr > 0 &&\n numericValue < minB3tr\n ) {\n return t(\n 'Minimum {{symbol}} transfer is {{min}}',\n {\n symbol: selectedToken.symbol,\n min: minB3tr,\n },\n );\n }\n\n return true;\n },\n })}\n onChange={(e) => {\n const trimmed =\n e.target.value.trim();\n e.target.value = trimmed;\n setValue('amount', trimmed, {\n shouldValidate: true,\n });\n }}\n placeholder=\"0\"\n variant=\"unstyled\"\n fontSize=\"4xl\"\n fontWeight=\"bold\"\n data-testid=\"tx-amount-input\"\n type=\"number\"\n inputMode=\"decimal\"\n color={textPrimary}\n />\n\n {selectedToken ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n }}\n onClick={() =>\n setIsSelectingToken(true)\n }\n leftIcon={\n TOKEN_LOGO_COMPONENTS[\n selectedToken.symbol\n ] ? (\n React.cloneElement(\n TOKEN_LOGO_COMPONENTS[\n selectedToken.symbol\n ],\n {\n boxSize: '20px',\n borderRadius:\n 'full',\n },\n )\n ) : (\n <Image\n src={\n TOKEN_LOGOS[\n selectedToken\n .symbol\n ]\n }\n alt={`${selectedToken.symbol} logo`}\n boxSize=\"20px\"\n borderRadius=\"full\"\n fallback={\n <Box\n boxSize=\"20px\"\n borderRadius=\"full\"\n bg=\"whiteAlpha.200\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Text\n fontSize=\"8px\"\n fontWeight=\"bold\"\n color={\n textPrimary\n }\n >\n {selectedToken.symbol.slice(\n 0,\n 3,\n )}\n </Text>\n </Box>\n }\n />\n )\n }\n >\n {selectedToken.symbol}\n\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n color: textTertiary,\n }}\n onClick={() =>\n setIsSelectingToken(true)\n }\n >\n {t('Select token')}\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n )}\n </HStack>\n {selectedToken && (\n <HStack\n spacing={1}\n fontSize=\"sm\"\n justifyContent={'space-between'}\n color={textSecondary}\n >\n <Text color={textSecondary}>\n ≈ {formattedValue}\n </Text>\n </HStack>\n )}\n {errors.amount && (\n <Text\n color=\"#ef4444\"\n fontSize=\"sm\"\n mt={1}\n data-testid=\"amount-error-msg\"\n >\n {errors.amount.message}\n </Text>\n )}\n </FormControl>\n </VStack>\n </Box>\n\n <HStack justify=\"space-between\" mt={2}>\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n color={textPrimary}\n >\n {t('To')}\n </Text>\n </HStack>\n <Box borderRadius=\"2xl\" bg={cardBg}>\n <VStack align=\"stretch\" spacing={2} p={4} width=\"100%\">\n <FormControl isInvalid={!!errors.toAddressOrDomain}>\n <Input\n {...register('toAddressOrDomain', {\n required: t('Address is required'),\n })}\n onChange={(e) => {\n const trimmed = e.target.value.trim();\n // If the input contains a dot, treat it as a domain name and normalize it\n const normalizedValue =\n trimmed.includes('.')\n ? ens_normalize(trimmed)\n : trimmed;\n e.target.value = normalizedValue;\n setValue(\n 'toAddressOrDomain',\n normalizedValue,\n {\n shouldValidate: true,\n },\n );\n }}\n placeholder={t(\n 'Type the receiver address or domain',\n )}\n _placeholder={{\n fontSize: 'md',\n fontWeight: 'normal',\n }}\n fontSize=\"lg\"\n fontWeight=\"bold\"\n color={textPrimary}\n variant=\"unstyled\"\n data-testid=\"tx-address-input\"\n />\n {errors.toAddressOrDomain && (\n <Text\n color={errorColor}\n fontSize=\"sm\"\n data-testid=\"address-error-msg\"\n >\n {errors.toAddressOrDomain.message}\n </Text>\n )}\n </FormControl>\n </VStack>\n </Box>\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <Button\n variant=\"vechainKitPrimary\"\n isDisabled={!selectedToken || !isValid}\n isLoading={isLoading}\n onClick={handleSubmit(onSubmit)}\n data-testid=\"send-button\"\n >\n {selectedToken ? t('Send') : t('Select Token')}\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import React, { useMemo } from 'react';\nimport {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n HStack,\n ModalFooter,\n useToken,\n Box,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n StickyHeaderContainer,\n AddressDisplayCard,\n TransactionButtonAndStatus,\n GasFeeSummary,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { getPicassoImage } from '@/utils';\nimport {\n useTransferERC20,\n useTransferVET,\n useUpgradeRequired,\n useUpgradeSmartAccountModal,\n useWallet,\n TokenWithValue,\n useGasTokenSelection,\n useGenericDelegatorFeeEstimation,\n} from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useGetAvatarOfAddress } from '@/hooks/api/vetDomains';\nimport { GasTokenType } from '@/types/gasToken';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\nexport type SendTokenSummaryContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n toAddressOrDomain: string;\n resolvedDomain?: string;\n resolvedAddress?: string;\n amount: string;\n selectedToken: TokenWithValue;\n formattedTotalAmount: string;\n};\n\nexport const SendTokenSummaryContent = ({\n setCurrentContent,\n toAddressOrDomain,\n resolvedDomain,\n resolvedAddress,\n amount,\n selectedToken,\n formattedTotalAmount,\n}: SendTokenSummaryContentProps) => {\n const { t } = useTranslation();\n const { account, connection, connectedWallet } = useWallet();\n const { data: avatar } = useGetAvatarOfAddress(resolvedAddress ?? '');\n const { network, feeDelegation } = useVeChainKitConfig();\n const { preferences } = useGasTokenSelection();\n const { isolatedView, closeAccountModal } = useAccountModalOptions();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const { data: upgradeRequired } = useUpgradeRequired(\n account?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n const { open: openUpgradeSmartAccountModal } =\n useUpgradeSmartAccountModal();\n // Get the final image URL\n const toImageSrc = useMemo(() => {\n if (avatar) {\n return avatar;\n }\n return getPicassoImage(resolvedAddress || toAddressOrDomain);\n }, [avatar, network.type, resolvedAddress, toAddressOrDomain]);\n\n const handleSend = async () => {\n if (upgradeRequired) {\n openUpgradeSmartAccountModal();\n return;\n }\n\n try {\n if (selectedToken.symbol === 'VET') {\n await transferVET();\n } else {\n await transferERC20();\n }\n } catch (error) {\n console.error(t('Transaction failed:'), error);\n }\n };\n\n const handleSuccess = React.useCallback(\n (txId: string) => {\n setCurrentContent({\n type: 'successful-operation',\n props: {\n setCurrentContent,\n txId,\n title: t('Transaction successful'),\n onDone: () => {\n if (isolatedView) {\n closeAccountModal();\n } else {\n setCurrentContent('main');\n }\n },\n showSocialButtons: true,\n },\n });\n },\n [setCurrentContent, t, isolatedView, closeAccountModal],\n );\n\n const {\n sendTransaction: transferERC20,\n txReceipt: transferERC20Receipt,\n error: transferERC20Error,\n isWaitingForWalletConfirmation:\n transferERC20WaitingForWalletConfirmation,\n isTransactionPending: transferERC20Pending,\n clauses: erc20Clauses,\n } = useTransferERC20({\n fromAddress: account?.address ?? '',\n receiverAddress: resolvedAddress || toAddressOrDomain,\n amount,\n tokenAddress: selectedToken.address,\n tokenName: selectedToken.symbol,\n onError: (error) => {\n handleError(error ?? '');\n },\n });\n\n const {\n sendTransaction: transferVET,\n txReceipt: transferVETReceipt,\n error: transferVETError,\n isWaitingForWalletConfirmation: transferVETWaitingForWalletConfirmation,\n isTransactionPending: transferVETPending,\n clauses: vetClauses,\n } = useTransferVET({\n fromAddress: account?.address ?? '',\n receiverAddress: resolvedAddress || toAddressOrDomain,\n amount,\n onError: (error) => {\n handleError(error ?? '');\n },\n });\n\n const getTxReceipt = React.useCallback(() => {\n return selectedToken.symbol === 'VET'\n ? transferVETReceipt\n : transferERC20Receipt;\n }, [selectedToken.symbol, transferVETReceipt, transferERC20Receipt]);\n\n const isTxWaitingConfirmation =\n transferERC20WaitingForWalletConfirmation ||\n transferVETWaitingForWalletConfirmation;\n const isSubmitting =\n isTxWaitingConfirmation || transferERC20Pending || transferVETPending;\n\n // Track if we've already shown success to prevent duplicate calls\n const [hasShownSuccess, setHasShownSuccess] = React.useState(false);\n\n // Handle successful transaction via useEffect to avoid synchronous state updates\n React.useEffect(() => {\n const receipt = getTxReceipt();\n\n // Guard clauses\n if (!receipt) return;\n if (receipt.reverted) return;\n if (hasShownSuccess) return;\n if (isSubmitting) return;\n\n const txId = receipt.meta.txID;\n if (!txId) return;\n\n setHasShownSuccess(true);\n handleSuccess(txId);\n }, [getTxReceipt, hasShownSuccess, isSubmitting, handleSuccess]);\n\n // Reset the flag when starting a new transaction\n React.useEffect(() => {\n if (isSubmitting) {\n setHasShownSuccess(false);\n }\n }, [isSubmitting]);\n\n const handleBack = () => {\n setCurrentContent({\n type: 'send-token',\n props: {\n setCurrentContent,\n preselectedToken: selectedToken,\n initialAmount: amount,\n initialToAddressOrDomain: toAddressOrDomain,\n },\n });\n };\n\n const handleError = (error: string) => {\n console.error('Transaction failed:', error);\n };\n\n const [selectedGasToken, setSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n // Track the user's manual selection to show it during loading (before estimation completes)\n const [userSelectedGasToken, setUserSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n\n const shouldEstimateGas =\n preferences.availableGasTokens.length > 0 &&\n (connection.isConnectedWithPrivy ||\n connection.isConnectedWithVeChain) &&\n !feeDelegation?.delegatorUrl;\n const {\n data: gasEstimation,\n isLoading: gasEstimationLoading,\n error: gasEstimationError,\n refetch: refetchGasEstimation,\n } = useGenericDelegatorFeeEstimation({\n clauses: selectedToken.symbol === 'VET' ? vetClauses : erc20Clauses,\n tokens: selectedGasToken\n ? [selectedGasToken]\n : preferences.availableGasTokens, // Use selected token or all available\n sendingAmount: amount,\n sendingTokenSymbol: selectedToken.symbol,\n enabled: shouldEstimateGas && !!feeDelegation?.genericDelegatorUrl,\n });\n const usedGasToken = gasEstimation?.usedToken;\n const disableConfirmButtonDuringEstimation =\n (gasEstimationLoading || !gasEstimation) &&\n connection.isConnectedWithPrivy &&\n !feeDelegation?.delegatorUrl;\n\n const handleGasTokenChange = React.useCallback(\n (token: GasTokenType) => {\n setSelectedGasToken(token);\n setUserSelectedGasToken(token); // Track user's choice\n // Refetch will be triggered automatically by the query key change\n setTimeout(() => refetchGasEstimation(), 100);\n },\n [refetchGasEstimation],\n );\n\n // hasEnoughBalance is now determined by the hook itself\n const hasEnoughBalance = !!usedGasToken && !gasEstimationError;\n\n // Auto-fallback: if the selected token cannot cover fees (estimation error),\n // clear selection to re-estimate across all available tokens\n // Keep userSelectedGasToken to show during loading, but actual result will show the token that succeeds\n React.useEffect(() => {\n if (gasEstimationError && selectedGasToken) {\n setSelectedGasToken(null);\n }\n }, [gasEstimationError, selectedGasToken]);\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>Send</ModalHeader>\n <ModalBackButton\n isDisabled={isSubmitting}\n onClick={handleBack}\n />\n <ModalCloseButton isDisabled={isSubmitting} />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"stretch\" w=\"full\">\n {/* From/To Card */}\n\n <VStack spacing={4} w=\"full\">\n <Box w=\"full\">\n <Text fontSize=\"sm\" mb={2} color={textSecondary}>\n {t('From')}\n </Text>\n <AddressDisplayCard\n address={account?.address ?? ''}\n domain={account?.domain}\n imageSrc={account?.image ?? ''}\n imageAlt=\"From account\"\n balance={Number(selectedToken.balance)}\n tokenAddress={selectedToken.address}\n />\n </Box>\n\n <Box w=\"full\">\n <Text fontSize=\"sm\" mb={2} color={textSecondary}>\n {t('To')}\n </Text>\n <AddressDisplayCard\n address={resolvedAddress || toAddressOrDomain}\n domain={resolvedDomain}\n imageSrc={toImageSrc ?? ''}\n imageAlt=\"To account\"\n tokenAddress={selectedToken.address}\n />\n </Box>\n\n {connection.isConnectedWithPrivy && (\n <GasFeeSummary\n estimation={gasEstimation}\n isLoading={gasEstimationLoading}\n isLoadingTransaction={isSubmitting}\n onTokenChange={handleGasTokenChange}\n clauses={\n selectedToken.symbol === 'VET'\n ? vetClauses\n : erc20Clauses\n }\n userSelectedToken={userSelectedGasToken}\n />\n )}\n\n <VStack\n spacing={0}\n w=\"full\"\n justifyContent=\"flex-start\"\n >\n <Text\n fontSize=\"sm\"\n fontWeight=\"light\"\n textAlign=\"left\"\n w=\"full\"\n color={textSecondary}\n >\n {t('Amount')}\n </Text>\n <HStack justifyContent=\"flex-start\" w=\"full\">\n <Text\n fontSize=\"xl\"\n fontWeight=\"semibold\"\n textAlign=\"left\"\n data-testid=\"send-summary-amount\"\n color={textPrimary}\n >\n {Number(amount).toLocaleString(undefined, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })}{' '}\n {selectedToken.symbol}\n </Text>\n <Text color={textSecondary}>\n ≈ {formattedTotalAmount}\n </Text>\n </HStack>\n </VStack>\n </VStack>\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <TransactionButtonAndStatus\n transactionError={\n selectedToken.symbol === 'VET'\n ? transferVETError\n : transferERC20Error\n }\n isSubmitting={isSubmitting}\n isTxWaitingConfirmation={isTxWaitingConfirmation}\n onConfirm={handleSend}\n transactionPendingText={t('Sending...')}\n txReceipt={getTxReceipt()}\n buttonText={t('Confirm')}\n isDisabled={\n isSubmitting || disableConfirmButtonDuringEstimation\n }\n gasEstimationError={gasEstimationError}\n hasEnoughGasBalance={hasEnoughBalance}\n isLoadingGasEstimation={gasEstimationLoading}\n showGasEstimationError={\n !feeDelegation?.delegatorUrl &&\n connection.isConnectedWithPrivy\n }\n context=\"send\"\n />\n </ModalFooter>\n </>\n );\n};\n","import {\n Container,\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n ModalFooter,\n useToken,\n} from '@chakra-ui/react';\nimport { QRCode } from 'react-qrcode-logo';\nimport {\n ModalBackButton,\n StickyHeaderContainer,\n AddressDisplay,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useWallet } from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const ReceiveTokenContent = ({ setCurrentContent }: Props) => {\n const { t } = useTranslation();\n const { account } = useWallet();\n const { isolatedView } = useAccountModalOptions();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Receive')}</ModalHeader>\n {!isolatedView && (\n <ModalBackButton\n onClick={() => setCurrentContent('main')}\n />\n )}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container maxW={'container.lg'}>\n <ModalBody>\n <VStack spacing={4} align=\"center\" w=\"full\">\n <QRCode\n value={account?.address ?? ''}\n size={200}\n removeQrCodeBehindLogo={true}\n eyeRadius={4}\n logoPaddingStyle={'circle'}\n style={{\n borderRadius: '16px',\n }}\n />\n\n <AddressDisplay wallet={account} style={{ w: '85%' }} />\n\n <Text\n fontSize=\"sm\"\n textAlign=\"center\"\n color={textPrimary}\n >\n {t('Copy your address or scan this QR code')}\n </Text>\n\n <Text\n fontSize=\"xs\"\n textAlign=\"center\"\n color={textSecondary}\n >\n {t('This address only supports VeChain assets.')}\n </Text>\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </Container>\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n HStack,\n Text,\n Container,\n Box,\n Badge,\n Collapse,\n Icon,\n Image,\n Tooltip,\n ModalFooter,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { SwapQuote } from '@/types/swap';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { formatEther } from 'viem';\nimport { LuChevronDown, LuChevronUp } from 'react-icons/lu';\nimport { formatCompactCurrency, SupportedCurrency, convertToSelectedCurrency } from '@/utils/currencyUtils';\nimport { useCurrency, useTokensWithValues, useWallet } from '@/hooks';\nimport { useTokenPrices } from '@/hooks';\nimport { useState, useMemo } from 'react';\nimport { TOKEN_LOGO_COMPONENTS, TOKEN_LOGOS, compareAddresses } from '@/utils';\nimport React from 'react';\n\ntype Props = {\n quotes: SwapQuote[];\n selectedQuote: SwapQuote | null;\n toTokenAddress: string | null;\n onSelectQuote: (quote: SwapQuote) => void;\n onBack: () => void;\n};\n\nexport const SelectQuoteContent = ({\n quotes,\n selectedQuote,\n toTokenAddress,\n onSelectQuote,\n onBack,\n}: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { currentCurrency } = useCurrency();\n const { account } = useWallet();\n const { exchangeRates, prices } = useTokenPrices();\n const { tokens } = useTokensWithValues({ address: account?.address ?? '' });\n const [showUnavailable, setShowUnavailable] = useState(false);\n\n // Get toToken symbol from address\n const toToken = useMemo(() => {\n if (!toTokenAddress) return null;\n // Use compareAddresses for proper address comparison\n return tokens.find(t => compareAddresses(t.address, toTokenAddress)) || null;\n }, [toTokenAddress, tokens]);\n\n\n // Separate available and unavailable quotes\n const availableQuotes = quotes.filter(q => !q.reverted);\n const unavailableQuotes = quotes.filter(q => q.reverted);\n\n // Find the best quote (highest output amount among available)\n const bestQuote = useMemo(() => {\n if (availableQuotes.length === 0) return null;\n return availableQuotes.reduce((best, current) => {\n const bestOutput = BigInt(best.outputAmount || '0');\n const currentOutput = BigInt(current.outputAmount || '0');\n return currentOutput > bestOutput ? current : best;\n });\n }, [availableQuotes]);\n\n // Calculate USD value for each quote\n const quotesWithValues = useMemo(() => {\n const toTokenPriceUsd = toTokenAddress ? (prices[toTokenAddress] || 0) : 0;\n\n return availableQuotes.map((quote) => {\n const outputAmountFormatted = formatEther(BigInt(quote.outputAmount || '0'));\n const valueUsd = Number(outputAmountFormatted) * toTokenPriceUsd;\n const valueInCurrency = convertToSelectedCurrency(\n valueUsd,\n currentCurrency as SupportedCurrency,\n exchangeRates,\n );\n const isBest = bestQuote && quote.aggregatorName === bestQuote.aggregatorName;\n\n // Calculate percentage difference from best\n let percentageDiff = 0;\n if (bestQuote && !isBest) {\n const bestOutput = BigInt(bestQuote.outputAmount || '0');\n const currentOutput = BigInt(quote.outputAmount || '0');\n const diff = Number(currentOutput - bestOutput);\n percentageDiff = (diff / Number(bestOutput)) * 100;\n }\n\n return {\n ...quote,\n outputAmountFormatted,\n valueUsd,\n valueInCurrency,\n isBest,\n percentageDiff,\n };\n }).sort((a, b) => {\n // Sort by output amount (descending)\n const aOutput = BigInt(a.outputAmount || '0');\n const bOutput = BigInt(b.outputAmount || '0');\n return Number(bOutput - aOutput);\n });\n }, [availableQuotes, toTokenAddress, prices, currentCurrency, exchangeRates, bestQuote]);\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Found following rates')}</ModalHeader>\n <ModalBackButton onClick={onBack} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container h={['540px', 'auto']} p={0}>\n <ModalBody>\n <VStack spacing={6} align=\"stretch\">\n {/* Available Quotes */}\n {quotesWithValues.length > 0 && (\n <VStack spacing={2} align=\"stretch\">\n {quotesWithValues.map((quoteWithValue) => {\n const isSelected = selectedQuote?.aggregatorName === quoteWithValue.aggregatorName;\n\n return (\n <Box\n key={quoteWithValue.aggregatorName}\n p={2.5}\n borderRadius=\"xl\"\n bg={isDark ? '#00000038' : 'gray.50'}\n borderWidth={1}\n borderColor={\n isSelected\n ? 'blue.500'\n : isDark\n ? 'whiteAlpha.200'\n : 'gray.200'\n }\n cursor=\"pointer\"\n onClick={() => onSelectQuote(quoteWithValue)}\n _hover={{\n borderColor: isSelected ? 'blue.500' : (isDark ? 'whiteAlpha.400' : 'gray.300'),\n }}\n position=\"relative\"\n >\n {/* Badge tag on top left */}\n {(quoteWithValue.isBest || (!quoteWithValue.isBest && quoteWithValue.percentageDiff < 0)) && (\n <Box position=\"absolute\" top={-1} left={0} zIndex={1}>\n {quoteWithValue.isBest ? (\n <Badge\n colorScheme=\"purple\"\n borderRadius=\"sm\"\n fontSize=\"2xs\"\n px={1.5}\n py={0.5}\n borderTopLeftRadius=\"xl\"\n borderBottomRightRadius=\"md\"\n >\n {t('Best')}\n </Badge>\n ) : (\n <Badge\n colorScheme=\"red\"\n borderRadius=\"xs\"\n fontSize=\"2xs\"\n px={1.5}\n py={0.5}\n borderTopLeftRadius=\"xl\"\n borderBottomRightRadius=\"md\"\n >\n {quoteWithValue.percentageDiff.toFixed(2)}%\n </Badge>\n )}\n </Box>\n )}\n\n <VStack align=\"stretch\" spacing={1.5} marginTop={4}>\n {/* Aggregator name/icon and token amount in same line */}\n <HStack justify=\"space-between\" align=\"center\">\n <HStack spacing={1.5} align=\"center\">\n {quoteWithValue.aggregator.getIcon('20px')}\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n >\n {quoteWithValue.aggregatorName}\n </Text>\n </HStack>\n <HStack align=\"center\" spacing={1.5}>\n {toToken && (\n <>\n {TOKEN_LOGO_COMPONENTS[toToken.symbol] ? (\n React.cloneElement(\n TOKEN_LOGO_COMPONENTS[toToken.symbol],\n {\n boxSize: '24px',\n borderRadius: 'full',\n }\n )\n ) : TOKEN_LOGOS[toToken.symbol] ? (\n <Image\n src={TOKEN_LOGOS[toToken.symbol]}\n alt={`${toToken.symbol} logo`}\n boxSize=\"24px\"\n borderRadius=\"full\"\n />\n ) : null}\n <Tooltip\n label={Number(quoteWithValue.outputAmountFormatted).toLocaleString(undefined, { maximumFractionDigits: 18 })}\n hasArrow\n placement=\"top\"\n >\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n textAlign=\"right\"\n whiteSpace=\"nowrap\"\n >\n {Number(quoteWithValue.outputAmountFormatted).toLocaleString(undefined, {\n minimumFractionDigits: 4,\n })}\n {' '}{toToken.symbol}\n </Text>\n </Tooltip>\n </>\n )}\n </HStack>\n </HStack>\n\n {/* Gas and fiat value in same line underneath */}\n <HStack justify=\"space-between\" align=\"center\">\n <Text\n fontSize=\"xs\"\n color={isDark ? 'whiteAlpha.500' : 'blackAlpha.500'}\n >\n {quoteWithValue.gasCostVTHO && quoteWithValue.gasCostVTHO > 0\n ? `Gas: ${quoteWithValue.gasCostVTHO.toLocaleString(undefined, {\n maximumFractionDigits: 2,\n })} VTHO`\n : ''}\n </Text>\n {quoteWithValue.valueUsd > 0 && (\n <Text\n fontSize=\"xs\"\n color={isDark ? 'whiteAlpha.600' : 'blackAlpha.600'}\n textAlign=\"right\"\n whiteSpace=\"nowrap\"\n >\n ≈ {formatCompactCurrency(\n quoteWithValue.valueInCurrency,\n { currency: currentCurrency as SupportedCurrency },\n )}\n </Text>\n )}\n </HStack>\n </VStack>\n </Box>\n );\n })}\n </VStack>\n )}\n\n {/* Unavailable Quotes */}\n {unavailableQuotes.length > 0 && (\n <Box>\n <HStack\n justify=\"space-between\"\n cursor=\"pointer\"\n onClick={() => setShowUnavailable(!showUnavailable)}\n py={2}\n >\n <Text\n fontSize=\"sm\"\n color={isDark ? 'whiteAlpha.600' : 'blackAlpha.600'}\n >\n {unavailableQuotes.length} {t('rate')}{unavailableQuotes.length !== 1 ? 's' : ''} {t('unavailable')}\n </Text>\n <Icon\n as={showUnavailable ? LuChevronUp : LuChevronDown}\n boxSize={4}\n color={isDark ? 'whiteAlpha.600' : 'blackAlpha.600'}\n />\n </HStack>\n <Collapse in={showUnavailable} animateOpacity>\n <VStack spacing={2} align=\"stretch\" pt={2}>\n {unavailableQuotes.map((quote) => (\n <Box\n key={quote.aggregatorName}\n p={2}\n borderRadius=\"xl\"\n bg={isDark ? '#00000038' : 'gray.50'}\n opacity={0.6}\n >\n <HStack justify=\"space-between\">\n <HStack spacing={2} align=\"center\">\n {quote.aggregator.getIcon('20px')}\n <Text\n fontSize=\"md\"\n fontWeight=\"medium\"\n >\n {quote.aggregatorName}\n </Text>\n </HStack>\n <Text\n fontSize=\"xs\"\n color={isDark ? 'whiteAlpha.500' : 'blackAlpha.500'}\n >\n {t('Unable to fetch the price')}\n </Text>\n </HStack>\n </Box>\n ))}\n </VStack>\n </Collapse>\n </Box>\n )}\n\n {quotesWithValues.length === 0 && unavailableQuotes.length === 0 && (\n <VStack\n spacing={2}\n py={8}\n color={isDark ? 'whiteAlpha.600' : 'blackAlpha.600'}\n >\n <Text fontSize=\"lg\">\n {t('No quotes available')}\n </Text>\n </VStack>\n )}\n </VStack>\n </ModalBody>\n </Container>\n <ModalFooter />\n </>\n );\n};\n\n","import { decodeEventLog, zeroAddress } from 'viem';\nimport { IERC20__factory } from '@vechain/vechain-contract-types';\nimport type { TransactionReceipt, Event, Transfer } from '@vechain/sdk-network';\n\n/**\n * Check if address is native VET token\n */\nconst isVET = (address: string): boolean => {\n return address === '0x' || address === zeroAddress || !address;\n};\n\n/**\n * Extract swap amounts from transaction receipt by parsing Transfer events\n * @param receipt Transaction receipt containing events\n * @param userAddress User's wallet address\n * @param fromTokenAddress Address of the token being swapped from\n * @param toTokenAddress Address of the token being swapped to\n * @returns Object containing formatted amounts and symbols, or null if not found\n */\nexport const extractSwapAmounts = (\n receipt: TransactionReceipt,\n userAddress: string,\n fromTokenAddress: string,\n toTokenAddress: string,\n): {\n fromAmount: bigint;\n toAmount: bigint;\n} | null => {\n if (!receipt || !userAddress || !fromTokenAddress || !toTokenAddress) {\n return null;\n }\n\n const userAddressLower = userAddress.toLowerCase();\n const fromTokenAddressLower = fromTokenAddress.toLowerCase();\n const toTokenAddressLower = toTokenAddress.toLowerCase();\n const isFromTokenVET = isVET(fromTokenAddress);\n const isToTokenVET = isVET(toTokenAddress);\n\n // Get all events and transfers from receipt outputs\n const allEvents: Event[] = [];\n const allTransfers: Transfer[] = [];\n\n if (receipt.outputs && Array.isArray(receipt.outputs)) {\n for (const output of receipt.outputs) {\n // Events can be direct array or nested - handle both cases\n if (output.events && Array.isArray(output.events)) {\n allEvents.push(...output.events);\n }\n // Collect native VET transfers\n if (output.transfers && Array.isArray(output.transfers)) {\n allTransfers.push(...output.transfers);\n }\n }\n }\n\n // Get ERC20 ABI for decoding (only needed if we have ERC20 tokens)\n const ERC20Interface = IERC20__factory.createInterface();\n const transferEventAbi = ERC20Interface.getEvent('Transfer');\n const transferEventTopicHash = transferEventAbi?.topicHash.toLowerCase();\n\n // Filter for Transfer events (only needed for ERC20 tokens)\n const transferEvents = allEvents.filter((event) => {\n // Check if topic[0] matches Transfer event signature\n return (\n event.topics &&\n event.topics.length > 0 &&\n event.topics[0]?.toString().toLowerCase() === transferEventTopicHash\n );\n });\n\n // Decode transfer events and find relevant ones\n let fromAmount: bigint | null = null;\n let toAmount: bigint | null = null;\n\n // Handle native VET transfers from transfers array\n if (isFromTokenVET) {\n // Find VET transfer FROM the user\n for (const transfer of allTransfers) {\n if (\n transfer.sender?.toLowerCase() === userAddressLower &&\n transfer.amount &&\n transfer.amount !== '0x0' &&\n transfer.amount !== '0x'\n ) {\n const amount = BigInt(transfer.amount);\n if (amount > 0n) {\n fromAmount = amount;\n break; // Take the first matching transfer\n }\n }\n }\n }\n\n if (isToTokenVET) {\n // Find VET transfer TO the user\n for (const transfer of allTransfers) {\n if (\n transfer.recipient?.toLowerCase() === userAddressLower &&\n transfer.amount &&\n transfer.amount !== '0x0' &&\n transfer.amount !== '0x'\n ) {\n const amount = BigInt(transfer.amount);\n if (amount > 0n) {\n toAmount = amount;\n break; // Take the first matching transfer\n }\n }\n }\n }\n\n // Handle ERC20 token transfers from Transfer events (only if we have ERC20 tokens)\n if (transferEvents.length > 0) {\n for (const event of transferEvents) {\n try {\n const decoded = decodeEventLog({\n abi: [transferEventAbi],\n data: event.data.toString() as `0x${string}`,\n topics: event.topics.map((t: any) => t.toString()) as [\n `0x${string}`,\n ...`0x${string}`[],\n ],\n });\n\n // Type guard for Transfer event args\n if (\n !decoded.args ||\n !('from' in decoded.args) ||\n !('to' in decoded.args) ||\n !('value' in decoded.args)\n ) {\n continue;\n }\n\n const from = (\n decoded.args as {\n from: `0x${string}`;\n to: `0x${string}`;\n value: bigint;\n }\n ).from\n ?.toString()\n .toLowerCase();\n const to = (\n decoded.args as {\n from: `0x${string}`;\n to: `0x${string}`;\n value: bigint;\n }\n ).to\n ?.toString()\n .toLowerCase();\n const value = (\n decoded.args as {\n from: `0x${string}`;\n to: `0x${string}`;\n value: bigint;\n }\n ).value as bigint;\n\n // Get contract address from event\n // Event type from TransactionReceipt has address as string\n const eventContractAddress = event.address.toLowerCase();\n\n // Check if this is a transfer FROM the user for the fromToken (skip if already found from VET transfers)\n if (\n !isFromTokenVET &&\n from === userAddressLower &&\n eventContractAddress &&\n eventContractAddress === fromTokenAddressLower &&\n value > 0n &&\n fromAmount === null\n ) {\n fromAmount = value;\n }\n\n // Check if this is a transfer TO the user for the toToken (skip if already found from VET transfers)\n if (\n !isToTokenVET &&\n to === userAddressLower &&\n eventContractAddress &&\n eventContractAddress === toTokenAddressLower &&\n value > 0n &&\n toAmount === null\n ) {\n toAmount = value;\n }\n } catch (error) {\n // Skip events that can't be decoded\n console.warn('Failed to decode transfer event:', error);\n continue;\n }\n }\n }\n\n return {\n fromAmount: fromAmount ?? 0n,\n toAmount: toAmount ?? 0n,\n };\n};\n","import React, { useState, useMemo, useCallback } from 'react';\nimport {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n HStack,\n Text,\n ModalFooter,\n Button,\n Icon,\n Box,\n Input,\n InputGroup,\n InputRightElement,\n Image,\n Collapse,\n useToken,\n} from '@chakra-ui/react';\nimport {\n GasFeeSummary,\n ModalBackButton,\n StickyHeaderContainer,\n TransactionButtonAndStatus,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { LuArrowDown, LuArrowUp, LuChevronDown } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport {\n useWallet,\n useTokensWithValues,\n TokenWithValue,\n useSwapQuotes,\n useSwapTransaction,\n useCurrency,\n useGasTokenSelection,\n useGenericDelegatorFeeEstimation,\n} from '@/hooks';\nimport { SelectQuoteContent } from './SelectQuoteContent';\nimport { SwapQuote } from '@/types/swap';\nimport { useVeChainKitConfig } from '@/providers';\nimport { TOKEN_LOGOS, TOKEN_LOGO_COMPONENTS } from '@/utils';\nimport { formatUnits, parseUnits } from 'viem';\nimport { getConfig } from '@/config';\nimport { compareAddresses } from '@/utils';\nimport { SelectTokenContent } from '../SendToken/SelectTokenContent';\nimport { formatCompactCurrency } from '@/utils/currencyUtils';\nimport {\n convertToSelectedCurrency,\n SupportedCurrency,\n} from '@/utils/currencyUtils';\nimport { useTokenPrices } from '@/hooks';\nimport { GasTokenType } from '@/types/gasToken';\nimport { TransactionClause } from '@vechain/sdk-core';\nimport { extractSwapAmounts } from '@/utils/swap/extractSwapAmounts';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n fromTokenAddress?: string;\n toTokenAddress?: string;\n};\n\ntype SwapStep =\n | 'main'\n | 'select-from-token'\n | 'select-to-token'\n | 'select-quote';\n\nexport const SwapTokenContent = ({\n setCurrentContent,\n fromTokenAddress,\n toTokenAddress,\n}: Props) => {\n const { t } = useTranslation();\n const { account, connection } = useWallet();\n const { currentCurrency } = useCurrency();\n const { network, feeDelegation, darkMode: isDark } = useVeChainKitConfig();\n const { isolatedView, closeAccountModal } = useAccountModalOptions();\n\n const cardBg = useToken('colors', 'vechain-kit-card');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const primaryButtonBg = useToken('colors', 'vechain-kit-button-primary-bg');\n const primaryButtonColor = useToken(\n 'colors',\n 'vechain-kit-button-primary-color',\n );\n\n const { preferences } = useGasTokenSelection();\n const { sortedTokens } = useTokensWithValues({\n address: account?.address ?? '',\n });\n\n const [step, setStep] = useState<SwapStep>('main');\n const [fromToken, setFromToken] = useState<TokenWithValue | null>(null);\n const [toToken, setToToken] = useState<TokenWithValue | null>(null);\n const [amount, setAmount] = useState('');\n const [showMore, setShowMore] = useState(false);\n const [slippageTolerance, setSlippageTolerance] = useState(1);\n const [customSlippageValue, setCustomSlippageValue] = useState('1');\n const [selectedQuote, setSelectedQuote] = useState<SwapQuote | null>(null);\n const [selectedGasToken, setSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n const [userSelectedGasToken, setUserSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n const [swapClauses, setSwapClauses] = React.useState<TransactionClause[]>(\n [],\n );\n\n // Prices and FX to compute fiat values for entered and output amounts\n const { prices, exchangeRates } = useTokenPrices();\n\n // Determine if we're in auto mode (1% default) or custom mode\n const isAutoMode = slippageTolerance === 1;\n\n // Sync customSlippageValue with slippageTolerance\n React.useEffect(() => {\n if (slippageTolerance === 1) {\n setCustomSlippageValue('1');\n } else if (slippageTolerance === 0.5) {\n setCustomSlippageValue('0.5');\n } else if (slippageTolerance === 3) {\n setCustomSlippageValue('3');\n } else {\n setCustomSlippageValue(slippageTolerance.toString());\n }\n }, [slippageTolerance]);\n\n // Set initial tokens from provided addresses if present, otherwise default VET -> B3TR\n React.useEffect(() => {\n if (sortedTokens.length === 0) return;\n\n // Prefer provided addresses\n if ((fromTokenAddress || toTokenAddress) && (!fromToken || !toToken)) {\n if (fromTokenAddress && !fromToken) {\n const match = sortedTokens.find((t) =>\n compareAddresses(t.address, fromTokenAddress),\n );\n if (match) setFromToken(match);\n }\n if (toTokenAddress && !toToken) {\n const match = sortedTokens.find((t) =>\n compareAddresses(t.address, toTokenAddress),\n );\n if (match) setToToken(match);\n }\n return;\n }\n\n if (!fromToken && !toToken) {\n // Find VET token\n const vetToken = sortedTokens.find((t) => t.symbol === 'VET');\n if (vetToken) {\n setFromToken(vetToken);\n }\n\n // Find B3TR token: first try by symbol, then by address from config\n let b3trToken = sortedTokens.find((t) => t.symbol === 'B3TR');\n\n // If not found by symbol, try finding by address from config\n if (!b3trToken) {\n try {\n const config = getConfig(network.type);\n const b3trAddress = config.b3trContractAddress;\n if (b3trAddress) {\n b3trToken = sortedTokens.find((t) =>\n compareAddresses(t.address, b3trAddress),\n );\n }\n } catch (error) {\n console.warn(\n 'Failed to get B3TR address from config:',\n error,\n );\n }\n }\n\n if (b3trToken) {\n setToToken(b3trToken);\n }\n }\n }, [\n sortedTokens,\n fromToken,\n toToken,\n fromTokenAddress,\n toTokenAddress,\n network.type,\n ]);\n\n // Clear selected quote when quote parameters change\n // This ensures that when amount/token changes, we use the new best quote\n // instead of a stale manually selected quote\n React.useEffect(() => {\n setSelectedQuote(null);\n }, [fromToken?.address, toToken?.address, amount]);\n\n // Unified quotes: get best and full list\n const {\n bestQuote,\n quotes: allQuotes,\n isLoading: isLoadingQuote,\n from,\n to,\n } = useSwapQuotes(\n fromToken,\n toToken,\n amount,\n account?.address ?? '',\n slippageTolerance,\n !!fromToken && !!toToken && Number(amount) > 0,\n );\n\n // Convert amount to raw format for quote (now that we know decimals)\n const amountInRaw = useMemo(() => {\n if (!amount || Number(amount) <= 0 || !from) return 0n;\n try {\n return parseUnits(amount, from.decimals);\n } catch {\n return 0n;\n }\n }, [amount, from?.decimals]);\n\n // Use selected quote if available, otherwise use best quote\n const quote = selectedQuote || bestQuote;\n\n // Format output amount for display\n const outputAmount = useMemo(() => {\n if (!quote?.outputAmount || !to) return '0';\n try {\n // Convert from raw format to human-readable\n return formatUnits(quote.outputAmount, to.decimals);\n } catch {\n return '0';\n }\n }, [quote, to?.decimals]);\n\n // Fiat value for the entered input amount (from side)\n const fromAmountFiatValue = useMemo(() => {\n if (!fromToken || !amount) return 0;\n const priceUsd = prices[fromToken.address] || 0;\n const valueUsd = Number(amount) * priceUsd;\n return convertToSelectedCurrency(\n valueUsd,\n currentCurrency as SupportedCurrency,\n exchangeRates,\n );\n }, [fromToken?.address, amount, prices, currentCurrency, exchangeRates]);\n\n // Fiat value for the quoted output amount (to side)\n const toAmountFiatValue = useMemo(() => {\n if (!toToken || !outputAmount) return 0;\n const priceUsd = prices[toToken.address] || 0;\n const valueUsd = Number(outputAmount) * priceUsd;\n return convertToSelectedCurrency(\n valueUsd,\n currentCurrency as SupportedCurrency,\n exchangeRates,\n );\n }, [\n toToken?.address,\n outputAmount,\n prices,\n currentCurrency,\n exchangeRates,\n ]);\n\n // Simulate swap to get gas estimate\n const swapParams = useMemo(() => {\n if (!fromToken || !toToken || !account?.address || amountInRaw === 0n) {\n return null;\n }\n return {\n fromTokenAddress: fromToken.address,\n toTokenAddress: toToken.address,\n amountIn: amountInRaw.toString(),\n userAddress: account.address,\n slippageTolerance,\n };\n }, [fromToken, toToken, account?.address, amountInRaw, slippageTolerance]);\n\n // Use gas cost from quote if available, otherwise from simulation hook\n const gasCostVTHO = quote?.gasCostVTHO ?? 0;\n\n // Build swap clauses for gas estimation (async operation)\n React.useEffect(() => {\n const buildClauses = async () => {\n if (!quote || !swapParams || !quote.aggregator) {\n setSwapClauses([]);\n return;\n }\n\n try {\n const clauses = await quote.aggregator.buildSwapTransaction(\n swapParams,\n quote,\n );\n setSwapClauses(clauses);\n } catch (error) {\n console.error(\n 'Failed to build swap clauses for gas estimation:',\n error,\n );\n setSwapClauses([]);\n }\n };\n\n buildClauses();\n }, [quote, swapParams]);\n\n // Gas estimation for social login wallets with generic delegator\n const shouldEstimateGas =\n preferences.availableGasTokens.length > 0 &&\n (connection.isConnectedWithPrivy ||\n connection.isConnectedWithVeChain) &&\n !feeDelegation?.delegatorUrl;\n\n const {\n data: gasEstimation,\n isLoading: gasEstimationLoading,\n error: gasEstimationError,\n refetch: refetchGasEstimation,\n } = useGenericDelegatorFeeEstimation({\n clauses: swapClauses,\n tokens: selectedGasToken\n ? [selectedGasToken]\n : preferences.availableGasTokens,\n sendingAmount: amount,\n sendingTokenSymbol: fromToken?.symbol ?? '',\n enabled:\n shouldEstimateGas &&\n !!feeDelegation?.genericDelegatorUrl &&\n swapClauses.length > 0,\n });\n\n const usedGasToken = gasEstimation?.usedToken;\n const disableConfirmButtonDuringEstimation =\n (gasEstimationLoading || !gasEstimation) &&\n connection.isConnectedWithPrivy &&\n !feeDelegation?.delegatorUrl;\n\n const handleGasTokenChange = React.useCallback(\n (token: GasTokenType) => {\n setSelectedGasToken(token);\n setUserSelectedGasToken(token);\n setTimeout(() => refetchGasEstimation(), 100);\n },\n [refetchGasEstimation],\n );\n\n // hasEnoughBalance is now determined by the hook itself\n const hasEnoughBalance = !!usedGasToken && !gasEstimationError;\n\n // Auto-fallback: if the selected token cannot cover fees (estimation error),\n // clear selection to re-estimate across all available tokens\n React.useEffect(() => {\n if (gasEstimationError && selectedGasToken) {\n setSelectedGasToken(null);\n }\n }, [gasEstimationError, selectedGasToken]);\n\n // Swap transaction execution\n const {\n executeSwap,\n isTransactionPending,\n isWaitingForWalletConfirmation,\n txReceipt,\n status,\n error: txError,\n } = useSwapTransaction(swapParams, quote);\n\n const handleSwapSuccess = useCallback(() => {\n const txId = txReceipt?.meta.txID ?? '';\n // Extract swap amounts from receipt transfer events\n const swapTitle = t('Swap successful', {\n defaultValue: 'Swap successful',\n });\n let swapDescription: string | undefined;\n\n if (txReceipt && fromToken && toToken && account?.address) {\n const swapAmounts = extractSwapAmounts(\n txReceipt,\n account.address,\n fromToken.address,\n toToken.address,\n );\n\n if (swapAmounts && from && to) {\n try {\n // Format amounts using token decimals from useSwapQuotes\n const fromDecimals = from.decimals;\n const toDecimals = to.decimals;\n const fromAmountFormatted = formatUnits(\n swapAmounts.fromAmount,\n fromDecimals,\n );\n const toAmountFormatted = formatUnits(\n swapAmounts.toAmount,\n toDecimals,\n );\n\n // Format numbers for display (remove unnecessary trailing zeros)\n const formatAmount = (value: string) => {\n const num = Number(value);\n if (num >= 1000) {\n return num.toLocaleString(undefined, {\n maximumFractionDigits: 2,\n });\n }\n return num.toLocaleString(undefined, {\n maximumFractionDigits: 6,\n minimumFractionDigits: 0,\n });\n };\n\n swapDescription = t(\n 'You successfully swapped {fromAmount} {fromSymbol} for {toAmount} {toSymbol}',\n {\n fromAmount: formatAmount(fromAmountFormatted),\n fromSymbol: fromToken.symbol,\n toAmount: formatAmount(toAmountFormatted),\n toSymbol: toToken.symbol,\n defaultValue: `You successfully swapped ${formatAmount(\n fromAmountFormatted,\n )} ${fromToken.symbol} for ${formatAmount(\n toAmountFormatted,\n )} ${toToken.symbol}`,\n },\n );\n } catch (error) {\n console.warn('Failed to format swap amounts:', error);\n }\n }\n }\n\n // Fallback to basic description if extraction failed\n if (!swapDescription && fromToken && toToken) {\n swapDescription = t(\n 'You successfully swapped {fromToken} for {toToken}',\n {\n fromToken: fromToken.symbol,\n toToken: toToken.symbol,\n defaultValue: `You successfully swapped ${fromToken.symbol} for ${toToken.symbol}`,\n },\n );\n }\n\n setCurrentContent({\n type: 'successful-operation',\n props: {\n setCurrentContent,\n txId,\n title: swapTitle,\n description: swapDescription,\n onDone: () => {\n if (isolatedView) {\n closeAccountModal();\n } else {\n setCurrentContent('main');\n }\n },\n showSocialButtons: true,\n },\n });\n }, [\n fromToken,\n toToken,\n amount,\n quote,\n txReceipt,\n account?.address,\n setCurrentContent,\n t,\n isolatedView,\n closeAccountModal,\n ]);\n\n const handleSwapError = useCallback(\n (error: Error | string) => {\n const errorMessage =\n typeof error === 'string' ? error : error.message;\n console.error('Swap failed:', errorMessage);\n },\n [fromToken, toToken, amount],\n );\n\n // Track if we've already shown success/error to prevent duplicate dialogs\n const [hasShownResult, setHasShownResult] = React.useState(false);\n\n // Handle transaction status changes to show success dialogs\n // Errors are shown inline via TransactionButtonAndStatus component\n React.useEffect(() => {\n // Reset the flag when transaction status changes to ready (new transaction)\n if (status === 'ready') {\n setHasShownResult(false);\n return;\n }\n\n // Only show dialog once per transaction\n if (hasShownResult) {\n return;\n }\n\n // Only show success modal, errors are handled inline\n if (status === 'success' && txReceipt && !txReceipt.reverted) {\n setHasShownResult(true);\n handleSwapSuccess();\n } else if (status === 'error' && txError) {\n // Track error for analytics but don't show modal\n const errorMessage =\n (txError as any)?.reason ||\n (txError as any)?.message ||\n String(txError);\n handleSwapError(errorMessage);\n } else if (txReceipt?.reverted) {\n // Track reverted transaction for analytics but don't show modal\n handleSwapError('Transaction reverted');\n }\n }, [\n status,\n txReceipt,\n txError,\n handleSwapSuccess,\n handleSwapError,\n hasShownResult,\n ]);\n\n // Token selection handlers\n const handleSelectFromToken = useCallback(\n (token: TokenWithValue) => {\n setFromToken(token);\n\n // Default to B3TR if VET is selected as from token\n if (token.symbol === 'VET' && !toToken) {\n // Try finding B3TR by symbol first\n let b3trToken = sortedTokens.find((t) => t.symbol === 'B3TR');\n\n // If not found by symbol, try finding by address from config\n if (!b3trToken) {\n try {\n const config = getConfig(network.type);\n const b3trAddress = config.b3trContractAddress;\n if (b3trAddress) {\n b3trToken = sortedTokens.find((t) =>\n compareAddresses(t.address, b3trAddress),\n );\n }\n } catch (error) {\n console.warn(\n 'Failed to get B3TR address from config:',\n error,\n );\n }\n }\n\n if (b3trToken) {\n setToToken(b3trToken);\n }\n }\n\n setStep('main');\n },\n [toToken, sortedTokens, network.type],\n );\n\n const handleSelectToToken = useCallback((token: TokenWithValue) => {\n setToToken(token);\n setStep('main');\n }, []);\n\n // Amount input handlers\n const handleAmountChange = useCallback((value: string) => {\n // Allow only numbers and decimal point\n const regex = /^\\d*\\.?\\d*$/;\n if (regex.test(value) || value === '') {\n setAmount(value);\n }\n }, []);\n\n const handleSetMaxAmount = useCallback(() => {\n if (fromToken) {\n setAmount(fromToken.balance);\n }\n }, [fromToken]);\n\n // Get token display info\n const getTokenDisplay = (token: TokenWithValue | null) => {\n if (!token) return null;\n const logoComponent = TOKEN_LOGO_COMPONENTS[token.symbol];\n const logoUrl = TOKEN_LOGOS[token.symbol];\n return {\n symbol: token.symbol,\n logoComponent,\n logoUrl,\n balance: token.balance,\n value: token.valueInCurrency,\n };\n };\n\n const fromTokenDisplay = getTokenDisplay(fromToken);\n const toTokenDisplay = getTokenDisplay(toToken);\n\n // Render token selection screen\n if (step === 'select-from-token') {\n return (\n <SelectTokenContent\n setCurrentContent={setCurrentContent}\n onSelectToken={handleSelectFromToken}\n onBack={() => setStep('main')}\n showAllTokens={false}\n />\n );\n }\n\n if (step === 'select-quote') {\n return (\n <SelectQuoteContent\n quotes={allQuotes}\n selectedQuote={quote}\n toTokenAddress={toToken?.address ?? null}\n onSelectQuote={(selected) => {\n setSelectedQuote(selected);\n setStep('main');\n }}\n onBack={() => setStep('main')}\n />\n );\n }\n\n if (step === 'select-to-token') {\n return (\n <SelectTokenContent\n setCurrentContent={setCurrentContent}\n onSelectToken={handleSelectToToken}\n onBack={() => setStep('main')}\n showAllTokens={true}\n />\n );\n }\n\n // Render main swap interface\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Swap')}</ModalHeader>\n {!isolatedView && (\n <ModalBackButton\n onClick={() => setCurrentContent('main')}\n isDisabled={\n isTransactionPending ||\n isWaitingForWalletConfirmation\n }\n />\n )}\n <ModalCloseButton\n isDisabled={\n isTransactionPending || isWaitingForWalletConfirmation\n }\n />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={2} align=\"stretch\" w=\"full\">\n {/* From Section */}\n <HStack justify=\"space-between\">\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n color={textPrimary}\n >\n {t('From')}\n </Text>\n\n {fromTokenDisplay && (\n <Text\n cursor=\"pointer\"\n _hover={{\n color: textSecondary,\n textDecoration: 'underline',\n }}\n onClick={handleSetMaxAmount}\n noOfLines={1}\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textSecondary}\n >\n {t('Balance')}:{' '}\n {Number(\n fromTokenDisplay.balance ?? 0,\n ).toLocaleString(undefined, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })}\n </Text>\n )}\n </HStack>\n <Box p={4} borderRadius=\"2xl\" bg={cardBg}>\n <VStack align=\"stretch\" spacing={2}>\n <HStack justify=\"space-between\">\n <Input\n placeholder=\"0\"\n value={amount}\n onChange={(e) =>\n handleAmountChange(e.target.value)\n }\n fontSize=\"4xl\"\n fontWeight=\"bold\"\n variant=\"unstyled\"\n data-testid=\"swap-amount-input\"\n type=\"number\"\n inputMode=\"decimal\"\n color={\n fromTokenDisplay &&\n amount &&\n Number(amount) >\n Number(fromTokenDisplay.balance)\n ? 'red.500'\n : textPrimary\n }\n />\n {fromTokenDisplay ? (\n <Button\n onClick={() =>\n setStep('select-from-token')\n }\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n }}\n leftIcon={\n fromTokenDisplay.logoComponent ? (\n React.cloneElement(\n fromTokenDisplay.logoComponent,\n {\n boxSize: '20px',\n borderRadius: 'full',\n },\n )\n ) : fromTokenDisplay.logoUrl ? (\n <Image\n src={\n fromTokenDisplay.logoUrl\n }\n alt={`${fromTokenDisplay.symbol} logo`}\n boxSize=\"20px\"\n borderRadius=\"full\"\n fallback={\n <Box\n boxSize=\"20px\"\n borderRadius=\"full\"\n bg=\"whiteAlpha.200\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Text\n fontSize=\"8px\"\n fontWeight=\"bold\"\n color={\n textPrimary\n }\n >\n {fromTokenDisplay.symbol.slice(\n 0,\n 3,\n )}\n </Text>\n </Box>\n }\n />\n ) : undefined\n }\n >\n {fromTokenDisplay.symbol}\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n ) : (\n <Button\n onClick={() =>\n setStep('select-from-token')\n }\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n color: textTertiary,\n }}\n >\n {t('Select token')}\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n )}\n </HStack>\n\n <HStack\n spacing={1}\n fontSize=\"sm\"\n justifyContent={'space-between'}\n color={textSecondary}\n >\n <HStack spacing={2} alignItems=\"center\">\n <Text color={textSecondary}>\n ≈{' '}\n {formatCompactCurrency(\n fromAmountFiatValue ?? 0,\n {\n currency: currentCurrency,\n },\n )}\n </Text>\n </HStack>\n </HStack>\n </VStack>\n </Box>\n\n {/* To Section */}\n <HStack justify=\"space-between\" mt={4}>\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n color={textPrimary}\n >\n {t('To')}\n </Text>\n </HStack>\n <Box borderRadius=\"2xl\" bg={cardBg} p={4}>\n <VStack align=\"stretch\" spacing={2} width=\"100%\">\n <HStack justify=\"space-between\" alignItems=\"center\">\n <Input\n value={Number(outputAmount).toLocaleString(\n undefined,\n {\n maximumFractionDigits:\n Number(outputAmount) > 10000\n ? 0\n : 2,\n },\n )}\n readOnly\n variant=\"unstyled\"\n fontSize=\"4xl\"\n fontWeight=\"bold\"\n data-testid=\"swap-output-amount\"\n color={textPrimary}\n />\n {toTokenDisplay ? (\n <Button\n onClick={() =>\n setStep('select-to-token')\n }\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n }}\n leftIcon={\n toTokenDisplay.logoComponent ? (\n React.cloneElement(\n toTokenDisplay.logoComponent,\n {\n boxSize: '20px',\n borderRadius: 'full',\n },\n )\n ) : toTokenDisplay.logoUrl ? (\n <Image\n src={toTokenDisplay.logoUrl}\n alt={`${toTokenDisplay.symbol} logo`}\n boxSize=\"20px\"\n borderRadius=\"full\"\n fallback={\n <Box\n boxSize=\"20px\"\n borderRadius=\"full\"\n bg=\"whiteAlpha.200\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Text\n fontSize=\"8px\"\n fontWeight=\"bold\"\n color={\n textPrimary\n }\n >\n {toTokenDisplay.symbol.slice(\n 0,\n 3,\n )}\n </Text>\n </Box>\n }\n />\n ) : undefined\n }\n >\n {toTokenDisplay.symbol}\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n ) : (\n <Button\n onClick={() =>\n setStep('select-to-token')\n }\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n color: textTertiary,\n }}\n >\n {t('Select token')}\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n )}\n </HStack>\n\n <HStack\n spacing={1}\n fontSize=\"sm\"\n justifyContent={'space-between'}\n color={textSecondary}\n >\n <HStack spacing={2} alignItems=\"center\">\n <Text color={textSecondary}>\n ≈{' '}\n {formatCompactCurrency(\n toAmountFiatValue ?? 0,\n {\n currency: currentCurrency,\n },\n )}\n </Text>\n </HStack>\n\n {toTokenDisplay && (\n <Text\n noOfLines={1}\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textSecondary}\n >\n {t('Balance')}:{' '}\n {Number(\n toTokenDisplay.balance ?? 0,\n ).toLocaleString(undefined, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })}\n </Text>\n )}\n </HStack>\n </VStack>\n </Box>\n\n {/* Show More Section */}\n <Collapse in={showMore && !!quote} animateOpacity>\n <VStack\n spacing={1}\n align=\"stretch\"\n p={4}\n borderRadius=\"2xl\"\n bg={cardBg}\n >\n {/* Source */}\n {quote && (\n <HStack justify=\"space-between\">\n <Text fontSize=\"xs\" color={textSecondary}>\n {t('Source')}:\n </Text>\n <Button\n variant=\"outline\"\n size=\"xs\"\n borderRadius=\"full\"\n px={3}\n h=\"auto\"\n py={1}\n cursor=\"pointer\"\n onClick={() => setStep('select-quote')}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n }}\n leftIcon={quote.aggregator?.getIcon(\n '12px',\n )}\n >\n <Text fontSize=\"xs\" color={textPrimary}>\n {quote.aggregatorName}\n </Text>\n </Button>\n </HStack>\n )}\n\n {/* Slippage */}\n <VStack align=\"stretch\" spacing={2}>\n <HStack justify=\"space-between\">\n <Text fontSize=\"xs\" color={textSecondary}>\n {t('Slippage tolerance')}:\n </Text>\n <Text\n fontSize=\"xs\"\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {slippageTolerance}%\n </Text>\n </HStack>\n\n {/* Slippage Configuration */}\n <VStack spacing={3} align=\"stretch\" pt={2}>\n <HStack spacing={2}>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setSlippageTolerance(1);\n }}\n flex=\"0 0 auto\"\n minW=\"60px\"\n borderRadius=\"md\"\n fontSize=\"xs\"\n bg={\n isAutoMode\n ? primaryButtonBg\n : 'transparent'\n }\n color={\n isAutoMode\n ? primaryButtonColor\n : textSecondary\n }\n borderColor={\n isAutoMode\n ? primaryButtonBg\n : textSecondary\n }\n _hover={{\n bg: isAutoMode\n ? primaryButtonBg\n : isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n opacity: isAutoMode ? 0.8 : 1,\n }}\n >\n Auto\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setSlippageTolerance(0.5);\n }}\n flex=\"0 0 auto\"\n minW=\"60px\"\n borderRadius=\"md\"\n fontSize=\"xs\"\n bg={\n slippageTolerance === 0.5\n ? primaryButtonBg\n : 'transparent'\n }\n color={\n slippageTolerance === 0.5\n ? primaryButtonColor\n : textSecondary\n }\n borderColor={\n slippageTolerance === 0.5\n ? primaryButtonBg\n : textSecondary\n }\n _hover={{\n bg:\n slippageTolerance === 0.5\n ? primaryButtonBg\n : isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n opacity:\n slippageTolerance === 0.5\n ? 0.8\n : 1,\n }}\n >\n 0.5%\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n setSlippageTolerance(3);\n }}\n flex=\"0 0 auto\"\n minW=\"60px\"\n borderRadius=\"md\"\n fontSize=\"xs\"\n bg={\n slippageTolerance === 3\n ? primaryButtonBg\n : 'transparent'\n }\n color={\n slippageTolerance === 3\n ? primaryButtonColor\n : textSecondary\n }\n borderColor={\n slippageTolerance === 3\n ? primaryButtonBg\n : textSecondary\n }\n _hover={{\n bg:\n slippageTolerance === 3\n ? primaryButtonBg\n : isDark\n ? 'whiteAlpha.300'\n : 'blackAlpha.300',\n opacity:\n slippageTolerance === 3\n ? 0.8\n : 1,\n }}\n >\n 3%\n </Button>\n <InputGroup size=\"sm\" flex={1}>\n <Input\n value={customSlippageValue}\n onChange={(e) => {\n const value =\n e.target.value;\n // Allow numbers and decimal point\n if (\n /^\\d*\\.?\\d*$/.test(\n value,\n ) ||\n value === ''\n ) {\n setCustomSlippageValue(\n value,\n );\n if (value !== '') {\n const numValue =\n parseFloat(\n value,\n );\n if (\n !isNaN(\n numValue,\n ) &&\n numValue >= 0 &&\n numValue <= 100\n ) {\n setSlippageTolerance(\n numValue,\n );\n }\n } else {\n // Reset to default when cleared\n setSlippageTolerance(\n 1,\n );\n }\n }\n }}\n placeholder=\"1\"\n borderRadius=\"md\"\n textAlign=\"right\"\n pr={8}\n fontSize=\"xs\"\n color={textPrimary}\n />\n <InputRightElement\n width=\"2rem\"\n pointerEvents=\"none\"\n >\n <Text\n fontSize=\"2xs\"\n color={textSecondary}\n >\n %\n </Text>\n </InputRightElement>\n </InputGroup>\n </HStack>\n </VStack>\n </VStack>\n\n {/* Gas Fee */}\n <HStack justify=\"space-between\">\n <Text fontSize=\"xs\" color={textSecondary}>\n {t('Fee')}:\n </Text>\n <Text\n fontSize=\"xs\"\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {gasCostVTHO > 0\n ? `${gasCostVTHO.toLocaleString(\n undefined,\n {\n maximumFractionDigits: 2,\n },\n )} VTHO`\n : '-'}\n </Text>\n </HStack>\n </VStack>\n </Collapse>\n\n {/* Show More Toggle - Always reserve space */}\n {quote && (\n <Box\n minH=\"24px\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Button\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => setShowMore(!showMore)}\n rightIcon={\n <Icon\n color={textTertiary}\n _hover={{\n color: textSecondary,\n }}\n as={showMore ? LuArrowUp : LuArrowDown}\n />\n }\n fontSize=\"xs\"\n fontWeight=\"light\"\n color={textTertiary}\n _hover={{\n color: textSecondary,\n }}\n >\n {showMore\n ? t('Hide')\n : t('Show Advanced Options')}\n </Button>\n </Box>\n )}\n\n {swapClauses.length > 0 &&\n connection.isConnectedWithPrivy && (\n <GasFeeSummary\n estimation={gasEstimation}\n isLoading={gasEstimationLoading}\n isLoadingTransaction={isTransactionPending}\n onTokenChange={handleGasTokenChange}\n clauses={swapClauses}\n userSelectedToken={userSelectedGasToken}\n />\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <TransactionButtonAndStatus\n buttonText={\n isLoadingQuote ? t('Loading quote...') : t('Swap')\n }\n onConfirm={executeSwap}\n isSubmitting={isTransactionPending}\n isTxWaitingConfirmation={isWaitingForWalletConfirmation}\n transactionPendingText={t('Swapping...')}\n txReceipt={txReceipt}\n transactionError={txError}\n onError={(errorMessage) => {\n // Track error for analytics when displayed inline\n handleSwapError(errorMessage);\n }}\n isDisabled={\n !fromToken ||\n !toToken ||\n !amount ||\n Number(amount) <= 0 ||\n isLoadingQuote ||\n !quote ||\n quote?.reverted === true ||\n Boolean(\n fromTokenDisplay &&\n amount &&\n Number(amount) >\n Number(fromTokenDisplay.balance),\n ) ||\n disableConfirmButtonDuringEstimation\n }\n gasEstimationError={gasEstimationError}\n hasEnoughGasBalance={hasEnoughBalance}\n isLoadingGasEstimation={gasEstimationLoading}\n showGasEstimationError={\n !feeDelegation?.delegatorUrl &&\n connection.isConnectedWithPrivy\n }\n context=\"transaction\"\n />\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Button,\n Icon,\n ModalFooter,\n useToken,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { LuSquareUser } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\nexport type ChooseNameContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onBack?: () => void;\n initialContentSource?: AccountModalContentTypes;\n};\n\nexport const ChooseNameContent = ({\n setCurrentContent,\n onBack = () => setCurrentContent('settings'),\n initialContentSource = 'settings',\n}: ChooseNameContentProps) => {\n const { t } = useTranslation();\n\n const { isolatedView } = useAccountModalOptions();\n\n const textColor = useToken('colors', 'vechain-kit-text-primary');\n const secondaryTextColor = useToken('colors', 'vechain-kit-text-secondary');\n\n const handleBack = () => {\n onBack();\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader data-testid=\"modal-title\">\n {t('Choose your account name')}\n </ModalHeader>\n {!isolatedView && <ModalBackButton onClick={handleBack} />}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"center\" py={8}>\n <Icon\n as={LuSquareUser}\n boxSize={16}\n color={secondaryTextColor}\n />\n <VStack spacing={2}>\n <Text\n fontSize=\"lg\"\n fontWeight=\"500\"\n textAlign=\"center\"\n color={textColor}\n >\n {t('Finally say goodbye to 0x addresses')}\n </Text>\n <Text\n fontSize=\"md\"\n color={secondaryTextColor}\n textAlign=\"center\"\n px={4}\n >\n {t(\n 'Name your account to make it easier to exchange assets',\n )}\n </Text>\n </VStack>\n </VStack>\n </ModalBody>\n <ModalFooter>\n <Button\n variant=\"vechainKitPrimary\"\n onClick={() =>\n setCurrentContent({\n type: 'choose-name-search',\n props: {\n name: '',\n setCurrentContent: setCurrentContent,\n initialContentSource,\n },\n })\n }\n data-testid=\"choose-name-button\"\n >\n {t('Choose name')}\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import {\n Accordion,\n AccordionItem,\n AccordionButton,\n AccordionPanel,\n Box,\n Text,\n Icon,\n List,\n ListItem,\n Tag,\n HStack,\n VStack,\n useToken,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { LuChevronDown, LuChevronUp, LuTrash2 } from 'react-icons/lu';\nimport { useWallet } from '@/hooks';\nimport { useWalletMetadata } from '@/hooks/api/wallet/useWalletMetadata';\nimport { AccountAvatar } from '@/components/common';\nimport { getPicassoImage, humanDomain } from '@/utils';\n\ntype ExistingDomainsListProps = {\n domains: { name: string }[];\n onDomainSelect: (domain: string) => void;\n onUnsetDomain: () => void;\n isLoading?: boolean;\n};\n\nconst DomainListItem = ({\n domain,\n isCurrentDomain,\n onSelect,\n}: {\n domain: { name: string };\n isCurrentDomain: boolean;\n onSelect: (name: string) => void;\n}) => {\n const { connection } = useWallet();\n const { t } = useTranslation();\n const metadata = useWalletMetadata(domain.name, connection.network);\n\n const cardBg = useToken('colors', 'vechain-kit-card');\n const cardBgHover = useToken('colors', 'vechain-kit-card-hover');\n const borderColor = useToken('colors', 'vechain-kit-border');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const buttonBg = useToken('colors', 'vechain-kit-card');\n\n return (\n <ListItem\n key={domain.name}\n p={4}\n bg={cardBg}\n borderRadius=\"xl\"\n cursor={isCurrentDomain ? 'default' : 'pointer'}\n opacity={isCurrentDomain ? 0.7 : 1}\n border={`1px solid ${borderColor}`}\n _hover={{\n bg: isCurrentDomain ? cardBgHover : cardBg,\n borderColor: borderColor,\n }}\n onClick={() => !isCurrentDomain && onSelect(domain.name)}\n transition=\"all 0.2s\"\n >\n <HStack spacing={3} align=\"center\">\n <AccountAvatar\n props={{\n width: '40px',\n height: '40px',\n src: metadata.image ?? getPicassoImage(domain.name),\n alt: domain.name,\n }}\n />\n\n <VStack align=\"start\" spacing={0} flex={1}>\n <Text color={textPrimary} fontSize=\"md\" fontWeight=\"500\">\n {humanDomain(domain.name, 24, 0)}\n </Text>\n {isCurrentDomain && (\n <Text fontSize=\"sm\" color={textSecondary}>\n {t('Current domain')}\n </Text>\n )}\n </VStack>\n\n {isCurrentDomain && (\n <Tag\n size=\"sm\"\n bg={buttonBg}\n color={textPrimary}\n px={3}\n py={1}\n borderRadius=\"full\"\n >\n {t('Current')}\n </Tag>\n )}\n </HStack>\n </ListItem>\n );\n};\n\nconst UnsetDomainListItem = ({ onUnset }: { onUnset: () => void }) => {\n const cardBg = useToken('colors', 'vechain-kit-card');\n const cardBgHover = useToken('colors', 'vechain-kit-card-hover');\n const borderColor = useToken('colors', 'vechain-kit-border');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const errorColor = useToken('colors', 'vechain-kit-error');\n\n const { t } = useTranslation();\n\n return (\n <ListItem\n key={'unset-domain-list-item'}\n p={4}\n bg={cardBg}\n borderRadius=\"xl\"\n cursor={'pointer'}\n opacity={1}\n border={`1px solid ${borderColor}`}\n _hover={{\n bg: cardBgHover,\n borderColor: borderColor,\n color: 'red.400',\n }}\n onClick={onUnset}\n transition=\"all 0.2s\"\n role=\"button\"\n aria-label={t('Unset current domain')}\n >\n <HStack spacing={3} align=\"center\">\n <Box\n width=\"40px\"\n height=\"40px\"\n borderRadius=\"full\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n bg={cardBg}\n >\n <Icon as={LuTrash2} fontSize=\"18px\" color={errorColor} />\n </Box>\n <VStack align=\"start\" spacing={0} flex={1}>\n <Text color={textPrimary} fontSize=\"md\" fontWeight=\"500\">\n {t('Unset current domain')}\n </Text>\n <Text fontSize=\"sm\" color={textSecondary}>\n {t('Remove your current domain name')}\n </Text>\n </VStack>\n </HStack>\n </ListItem>\n );\n};\n\nexport const ExistingDomainsList = ({\n domains,\n onDomainSelect,\n onUnsetDomain,\n isLoading,\n}: ExistingDomainsListProps) => {\n const { t } = useTranslation();\n const { account } = useWallet();\n\n const cardBg = useToken('colors', 'vechain-kit-card');\n const cardBgHover = useToken('colors', 'vechain-kit-card-hover');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n // avoid flickering after loading by returning null, so if no domains are found, it will not show the accordion\n if (domains.length === 0 || isLoading) {\n return null;\n }\n\n return (\n <Accordion allowToggle>\n <AccordionItem border=\"none\">\n {({ isExpanded }) => (\n <>\n <AccordionButton\n bg={cardBg}\n borderRadius=\"xl\"\n _hover={{\n bg: cardBgHover,\n }}\n opacity={isLoading ? 0.7 : 1}\n transition=\"all 0.2s\"\n disabled={isLoading}\n >\n <Box flex=\"1\" textAlign=\"left\" py={2}>\n <Text fontWeight=\"500\" color={textPrimary}>\n {isLoading\n ? t('Loading your domains...')\n : `${t('Your existing domains')} (${\n domains.length\n })`}\n </Text>\n </Box>\n <Icon\n as={isExpanded ? LuChevronUp : LuChevronDown}\n fontSize=\"20px\"\n color={textSecondary}\n />\n </AccordionButton>\n <AccordionPanel pb={4} pt={2}>\n <List spacing={2}>\n {domains.map((domain) => (\n <DomainListItem\n key={domain.name}\n domain={domain}\n isCurrentDomain={\n domain.name === account?.domain\n }\n onSelect={onDomainSelect}\n />\n ))}\n {account?.domain && (\n <UnsetDomainListItem\n onUnset={onUnsetDomain}\n />\n )}\n </List>\n </AccordionPanel>\n </>\n )}\n </AccordionItem>\n </Accordion>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Input,\n InputGroup,\n Box,\n Button,\n ModalFooter,\n InputRightElement,\n useToken,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useState, useEffect } from 'react';\nimport {\n useEnsRecordExists,\n useWallet,\n useVechainDomain,\n useIsDomainProtected,\n useGetDomainsOfAddress,\n} from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { ExistingDomainsList } from './Components/ExistingDomainsList';\nimport { ens_normalize } from '@adraffy/ens-normalize';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\nexport type ChooseNameSearchContentProps = {\n name: string;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n initialContentSource?: AccountModalContentTypes;\n};\n\nexport const ChooseNameSearchContent = ({\n name: initialName,\n setCurrentContent,\n initialContentSource = 'settings',\n}: ChooseNameSearchContentProps) => {\n const { t } = useTranslation();\n const { account } = useWallet();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { isolatedView } = useAccountModalOptions();\n const [name, setName] = useState(ens_normalize(initialName));\n const [error, setError] = useState<string | null>(null);\n const [isOwnDomain, setIsOwnDomain] = useState(false);\n const [isAvailable, setIsAvailable] = useState(false);\n const [hasInteracted, setHasInteracted] = useState(false);\n\n const errorColor = useToken('colors', 'vechain-kit-error');\n const successColor = useToken('colors', 'vechain-kit-success');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const { data: ensRecordExists, isLoading: isEnsCheckLoading } =\n useEnsRecordExists(name);\n const { data: domainInfo, isLoading: isDomainInfoLoading } =\n useVechainDomain(`${name}.veworld.vet`);\n const { data: isProtected, isLoading: isProtectedLoading } =\n useIsDomainProtected(name);\n\n const {\n data: vetDomainsOfAddress,\n isLoading: isVetDomainsOfAddressLoading,\n } = useGetDomainsOfAddress(account?.address, '');\n\n const isFetchingDomainInfo =\n isEnsCheckLoading || isDomainInfoLoading || isProtectedLoading;\n\n useEffect(() => {\n if (!hasInteracted) return;\n\n // Add validation for special characters, spaces, and periods\n const hasSpecialChars = /[^a-zA-Z0-9-]|\\s/.test(name);\n\n if (name.length < 3) {\n setError(t('Name must be at least 3 characters long'));\n setIsAvailable(false);\n setIsOwnDomain(false);\n } else if (hasSpecialChars) {\n setError(t('Only letters, numbers, and hyphens are allowed'));\n setIsAvailable(false);\n setIsOwnDomain(false);\n } else if (isProtected) {\n setError(t('This domain is protected'));\n setIsAvailable(false);\n setIsOwnDomain(false);\n } else if (ensRecordExists) {\n // Check if the domain belongs to the current user\n const isOwnDomain =\n domainInfo?.address?.toLowerCase() ===\n account?.address?.toLowerCase();\n\n if (isOwnDomain) {\n setError(null);\n setIsAvailable(true);\n setIsOwnDomain(true);\n } else {\n setError(t('This domain is already taken'));\n setIsAvailable(false);\n setIsOwnDomain(false);\n }\n } else if (!isEnsCheckLoading) {\n setError(null);\n setIsAvailable(true);\n setIsOwnDomain(false);\n }\n }, [\n name,\n hasInteracted,\n ensRecordExists,\n isEnsCheckLoading,\n domainInfo,\n account?.address,\n isProtected,\n isAvailable,\n isFetchingDomainInfo,\n ]);\n\n const handleContinue = () => {\n if (isAvailable && !error) {\n setCurrentContent({\n type: 'choose-name-summary',\n props: {\n fullDomain: name + '.veworld.vet',\n isOwnDomain,\n setCurrentContent,\n initialContentSource,\n },\n });\n }\n };\n\n const handleDomainSelect = (selectedDomain: string) => {\n // Extract the domain type and base name\n const parts = selectedDomain.split('.');\n const domainType = parts.length > 2 ? `${parts[1]}.${parts[2]}` : 'vet';\n\n setCurrentContent({\n type: 'choose-name-summary',\n props: {\n fullDomain: selectedDomain,\n domainType: domainType,\n isOwnDomain: true,\n setCurrentContent,\n initialContentSource,\n },\n });\n };\n\n const handleUnsetDomain = () => {\n setCurrentContent({\n type: 'choose-name-summary',\n props: {\n fullDomain: '',\n domainType: '',\n isOwnDomain: false,\n isUnsetting: true,\n setCurrentContent,\n initialContentSource,\n },\n });\n };\n\n const handleBack = () => {\n setCurrentContent(initialContentSource);\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader data-testid=\"modal-title\">\n {t('Choose Name')}\n </ModalHeader>\n {!isolatedView && <ModalBackButton onClick={handleBack} />}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={4} align=\"stretch\">\n <ExistingDomainsList\n domains={vetDomainsOfAddress?.domains || []}\n onDomainSelect={handleDomainSelect}\n onUnsetDomain={handleUnsetDomain}\n isLoading={isVetDomainsOfAddressLoading}\n />\n\n <InputGroup size=\"lg\">\n <Input\n placeholder={t('Enter your name')}\n value={name}\n onChange={(e) => {\n setName(ens_normalize(e.target.value));\n if (!hasInteracted) setHasInteracted(true);\n }}\n paddingRight=\"120px\"\n fontSize=\"lg\"\n height=\"60px\"\n bg={isDark ? '#00000038' : 'white'}\n border={`1px solid ${\n isDark ? '#ffffff29' : '#ebebeb'\n }`}\n _hover={{\n border: `1px solid ${\n isDark ? '#ffffff40' : '#e0e0e0'\n }`,\n }}\n _focus={{\n border: `1px solid ${\n isDark ? '#ffffff60' : '#d0d0d0'\n }`,\n boxShadow: 'none',\n }}\n isInvalid={!!error}\n data-testid=\"domain-input\"\n />\n <InputRightElement\n width=\"auto\"\n paddingRight=\"12px\"\n h={'full'}\n >\n <Box mr={4} fontSize=\"sm\" color={textSecondary}>\n .veworld.vet\n </Box>\n </InputRightElement>\n </InputGroup>\n\n {error && hasInteracted && (\n <Text\n color={errorColor}\n fontSize=\"sm\"\n data-testid=\"domain-availability-status\"\n >\n {error}\n </Text>\n )}\n\n {!error && hasInteracted && name.length >= 3 && (\n <Text\n fontSize=\"sm\"\n color={isAvailable ? successColor : errorColor}\n fontWeight=\"500\"\n data-testid=\"domain-availability-status\"\n >\n {isOwnDomain\n ? t('YOU OWN THIS')\n : isAvailable\n ? t('AVAILABLE')\n : t('UNAVAILABLE')}\n </Text>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <Button\n variant=\"vechainKitPrimary\"\n isDisabled={\n !isAvailable ||\n !!error ||\n isProtected ||\n isFetchingDomainInfo\n }\n isLoading={isFetchingDomainInfo}\n onClick={handleContinue}\n loadingText={t('Checking...')}\n data-testid=\"continue-button\"\n >\n {t('Continue')}\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import React from 'react';\nimport {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n ModalFooter,\n Text,\n useToken,\n Icon,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n StickyHeaderContainer,\n TransactionButtonAndStatus,\n GasFeeSummary,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useClaimVeWorldSubdomain } from '@/hooks/api/vetDomains/useClaimVeWorldSubdomain';\nimport { useClaimVetDomain } from '@/hooks/api/vetDomains/useClaimVetDomain';\nimport { useUnsetDomain } from '@/hooks/api/vetDomains/useUnsetDomain';\nimport { useTranslation } from 'react-i18next';\nimport {\n useUpgradeRequired,\n useUpgradeSmartAccountModal,\n useWallet,\n useGasTokenSelection,\n useGenericDelegatorFeeEstimation,\n} from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\nimport { GasTokenType } from '@/types/gasToken';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\nimport { LuSquareUser } from 'react-icons/lu';\n\nexport type ChooseNameSummaryContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n fullDomain: string;\n domainType?: string;\n isOwnDomain: boolean;\n isUnsetting?: boolean;\n initialContentSource?: AccountModalContentTypes;\n};\n\nexport const ChooseNameSummaryContent = ({\n setCurrentContent,\n fullDomain,\n domainType = 'veworld.vet',\n isOwnDomain,\n isUnsetting = false,\n initialContentSource = 'settings',\n}: ChooseNameSummaryContentProps) => {\n const { t } = useTranslation();\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const { isolatedView, closeAccountModal } = useAccountModalOptions();\n const { account, connectedWallet, connection } = useWallet();\n const { data: upgradeRequired } = useUpgradeRequired(\n account?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n const { open: openUpgradeSmartAccountModal } =\n useUpgradeSmartAccountModal();\n\n const { preferences } = useGasTokenSelection();\n const { feeDelegation } = useVeChainKitConfig();\n\n const handleError = (error: string) => {\n console.error('Transaction failed:', error);\n };\n\n // Use the unset domain hook if we're unsetting\n const unsetDomainHook = useUnsetDomain({\n onSuccess: () => handleSuccess(),\n });\n\n // If not unsetting, determine if this is a .veworld.vet subdomain or a primary .vet domain\n const isVeWorldSubdomain = domainType.endsWith('veworld.vet');\n\n // Use the appropriate claim hook based on domain type (only when not unsetting)\n const veWorldSubdomainHook = useClaimVeWorldSubdomain({\n subdomain: fullDomain.split('.veworld.vet')[0],\n domain: domainType,\n alreadyOwned: isOwnDomain,\n onSuccess: () => handleSuccess(),\n });\n\n const vetDomainHook = useClaimVetDomain({\n domain: !isUnsetting && !isVeWorldSubdomain ? fullDomain : '',\n alreadyOwned: isOwnDomain,\n onSuccess: () => handleSuccess(),\n });\n\n // Use the appropriate hook based on action and domain type\n const {\n sendTransaction,\n txReceipt,\n error: txError,\n isWaitingForWalletConfirmation,\n isTransactionPending,\n clauses,\n } = isUnsetting\n ? unsetDomainHook\n : isVeWorldSubdomain\n ? veWorldSubdomainHook\n : vetDomainHook;\n\n const handleSuccess = () => {\n setCurrentContent({\n type: 'successful-operation',\n props: {\n setCurrentContent,\n txId: txReceipt?.meta.txID,\n title: isUnsetting ? t('Domain unset') : t('Domain set'),\n description: isUnsetting\n ? t('Your domain has been unset successfully.')\n : t(`Your address has been successfully set to {{name}}`, {\n name: fullDomain,\n }),\n onDone: () => {\n if (isolatedView) {\n closeAccountModal();\n } else {\n setCurrentContent(initialContentSource);\n }\n },\n },\n });\n };\n\n const handleConfirm = async () => {\n if (upgradeRequired) {\n openUpgradeSmartAccountModal();\n return;\n }\n\n try {\n await sendTransaction();\n } catch (error) {\n console.error('Transaction failed:', error);\n }\n };\n\n const handleRetry = () => {\n handleConfirm();\n };\n\n const handleBack = () => {\n setCurrentContent({\n type: 'choose-name-search',\n props: {\n setCurrentContent,\n name: fullDomain,\n initialContentSource,\n },\n });\n };\n\n const [selectedGasToken, setSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n // Track the user's manual selection to show it during loading (before estimation completes)\n const [userSelectedGasToken, setUserSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n\n const shouldEstimateGas =\n preferences.availableGasTokens.length > 0 &&\n (connection.isConnectedWithPrivy ||\n connection.isConnectedWithVeChain) &&\n !feeDelegation?.delegatorUrl;\n const {\n data: gasEstimation,\n isLoading: gasEstimationLoading,\n error: gasEstimationError,\n refetch: refetchGasEstimation,\n } = useGenericDelegatorFeeEstimation({\n clauses: clauses(),\n tokens: selectedGasToken\n ? [selectedGasToken]\n : preferences.availableGasTokens, // Use selected token or all available\n enabled: shouldEstimateGas && !!feeDelegation?.genericDelegatorUrl,\n });\n const usedGasToken = gasEstimation?.usedToken;\n const disableConfirmButtonDuringEstimation =\n (gasEstimationLoading || !gasEstimation) &&\n connection.isConnectedWithPrivy &&\n !feeDelegation?.delegatorUrl;\n\n const handleGasTokenChange = React.useCallback(\n (token: GasTokenType) => {\n setSelectedGasToken(token);\n setUserSelectedGasToken(token); // Track user's choice\n setTimeout(() => refetchGasEstimation(), 100);\n },\n [refetchGasEstimation],\n );\n\n // hasEnoughBalance is now determined by the hook itself\n const hasEnoughBalance = !!usedGasToken && !gasEstimationError;\n\n // Auto-fallback: if the selected token cannot cover fees (estimation error),\n // clear selection to re-estimate across all available tokens\n // Keep userSelectedGasToken to show during loading, but actual result will show the token that succeeds\n React.useEffect(() => {\n if (gasEstimationError && selectedGasToken) {\n setSelectedGasToken(null);\n }\n }, [gasEstimationError, selectedGasToken]);\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader data-testid=\"confirm-domain\">\n {isUnsetting\n ? t('Confirm Unset Domain')\n : t('Confirm Name')}\n </ModalHeader>\n <ModalBackButton\n onClick={handleBack}\n isDisabled={isTransactionPending}\n />\n <ModalCloseButton isDisabled={isTransactionPending} />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"center\" mt={10}>\n <Icon\n as={LuSquareUser}\n color={textPrimary}\n fontSize={'60px'}\n opacity={0.5}\n />\n <Text fontSize=\"md\" textAlign=\"center\" color={textPrimary}>\n {isUnsetting\n ? t(\n 'By confirming, your current domain will be unset',\n )\n : t(\n 'By confirming, your address will be set to {{domain}}',\n {\n domain: fullDomain,\n },\n )}\n </Text>\n </VStack>\n {!isUnsetting && (\n <VStack spacing={4} align=\"stretch\" mt={6}>\n <Text\n fontSize=\"xl\"\n fontWeight=\"bold\"\n color={textPrimary}\n textAlign=\"center\"\n data-testid=\"preconfirm-domain-val\"\n >\n {fullDomain}\n </Text>\n </VStack>\n )}\n {connection.isConnectedWithPrivy && (\n <GasFeeSummary\n estimation={gasEstimation}\n isLoading={gasEstimationLoading}\n isLoadingTransaction={isTransactionPending}\n onTokenChange={handleGasTokenChange}\n clauses={clauses() as any}\n userSelectedToken={userSelectedGasToken}\n />\n )}\n </ModalBody>\n\n <ModalFooter gap={4} w=\"full\">\n <TransactionButtonAndStatus\n transactionError={txError}\n isSubmitting={isTransactionPending}\n isTxWaitingConfirmation={isWaitingForWalletConfirmation}\n onConfirm={handleConfirm}\n onRetry={handleRetry}\n transactionPendingText={\n isUnsetting\n ? t('Unsetting current domain...')\n : t('Claiming name...')\n }\n txReceipt={txReceipt}\n buttonText={t('Confirm')}\n isDisabled={\n isTransactionPending ||\n disableConfirmButtonDuringEstimation\n }\n onError={handleError}\n gasEstimationError={gasEstimationError}\n hasEnoughGasBalance={hasEnoughBalance}\n isLoadingGasEstimation={gasEstimationLoading}\n showGasEstimationError={\n !feeDelegation?.delegatorUrl &&\n connection.isConnectedWithPrivy\n }\n context=\"domain\"\n />\n </ModalFooter>\n </>\n );\n};\n","import {\n Accordion,\n AccordionItem,\n AccordionButton,\n AccordionPanel,\n Box,\n Text,\n Icon,\n VStack,\n InputGroup,\n Input,\n InputLeftElement,\n useToken,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { LuChevronDown, LuChevronUp, LuSearch, LuSlash } from 'react-icons/lu';\nimport { useState } from 'react';\n\ninterface FAQItem {\n question: string;\n answer: string;\n}\n\nexport const FAQAccordion = () => {\n const { t } = useTranslation();\n const [searchQuery, setSearchQuery] = useState('');\n\n // Use semantic tokens for colors\n const inputBg = useToken('colors', 'vechain-kit-card');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const accordionBg = useToken('colors', 'vechain-kit-card');\n const accordionBgHover = useToken('colors', 'vechain-kit-card-elevated');\n\n const faqItems: FAQItem[] = [\n {\n question: t('What is VeChain?'),\n answer: t(\n 'VeChain, headquartered in San Marino, Europe, is a pioneering blockchain ecosystem and creator of VeChainThor, a world-class smart contract platform driving real-world blockchain adoption. Founded in 2015 by Sunny Lu, VeChain has consistently worked to deliver a transparent, efficient, scalable, and adaptable blockchain solution.',\n ),\n },\n {\n question: t('What is a wallet?'),\n answer: t(\n 'A wallet is your gateway to the VeChain blockchain. It stores your private keys and allows you to securely manage your digital assets, send and receive tokens, and interact with decentralized applications. Think of it as your digital bank account for blockchain transactions.',\n ),\n },\n {\n question: t('What is a Smart Account?'),\n answer: t(\n 'A Smart Account is a smart contract wallet that provides enhanced security and functionality. It allows for features like social recovery, transaction batching, and more.',\n ),\n },\n {\n question: t('How is my wallet secured?'),\n answer: t(\n 'Your wallet security depends on how you access it. With self-custody options like the VeWorld extension, mobile app, or hardware wallet, you have complete control over your private keys. This extension itself has no access to your private keys. When logging in with social accounts or VeChain, your wallet is created and secured by Privy and managed by VeChain, providing an easier onboarding experience while maintaining security.',\n ),\n },\n {\n question: t('How do I backup my wallet?'),\n answer: t(\n \"Backing up your wallet is crucial as you are the only one with access to your private keys. If something goes wrong, having your private key is the only way to recover your assets. How to backup depends on how you access your wallet: If using VeWorld, the backup option is available within the app. For social login users, you can find backup options in the Wallet section. If you're connected through VeChain or another ecosystem app, you'll need to visit the original website, log in, and access the Wallet section from there.\",\n ),\n },\n {\n question: t('What is a network?'),\n answer: t(\n \"A network in blockchain refers to the environment where transactions take place. VeChain has two main networks: Mainnet (the live network where real transactions occur) and Testnet (a testing environment for developers). The network you're connected to is displayed at the top of this modal.\",\n ),\n },\n {\n question: t('What is a domain name?'),\n answer: t(\n 'A domain name is a sort of nickname for your wallet address. It allows you to easily identify your wallet and interact with dApps using a human-readable name. For example, if your wallet address is 0x1234567890, your nickname could be \"alice.vechain\".',\n ),\n },\n {\n question: t('What is Privy?'),\n answer: t(\n 'Privy builds user onboarding and embedded wallet infrastructure to enable better products built on crypto rails. This means embedding asset control within applications themselves to enable users, businesses or machines to use digital assets through seamless product experiences.',\n ),\n },\n {\n question: t('What is VeBetterDAO?'),\n answer: t(\n 'VeBetterDAO is a decentralized organization on VeChain blockchain focused on sustainability. Members participate in the governance of the DAO using B3TR tokens for rewards and VOT3 for voting in proposals and weekly token allocation rounds.',\n ),\n },\n {\n question: t('What is an x2earn application?'),\n answer: t(\n 'An X2Earn application in VeBetterDAO is a sustainable app that rewards users with B3TR tokens for eco-friendly actions. These apps must distribute B3TR, link user wallets, and provide proof of sustainable actions. They join VeBetterDAO through endorsement and participate in weekly token allocation rounds.',\n ),\n },\n {\n question: t('What is B3TR?'),\n answer: t(\n 'B3TR is the incentive token of VeBetterDAO, built on VechainThor blockchain. It has a capped supply of 1 billion tokens, emitted weekly over 12 years. B3TR is used for rewards, governance, and backing VOT3 tokens 1:1. It supports sustainability applications and DAO treasury management.',\n ),\n },\n {\n question: t('What is VET?'),\n answer: t(\n 'VET is the primary cryptocurrency of the VeChain network. It represents value and ownership in the VeChain ecosystem, similar to how stocks represent ownership in a company. Holding VET automatically generates VTHO, which is needed to pay for transactions on the network.',\n ),\n },\n {\n question: t('What is VTHO?'),\n answer: t(\n \"VTHO (VeThor) is the energy or 'gas' token of the VeChain network. It's used to pay for transaction fees when interacting with the blockchain. VTHO is automatically generated by holding VET tokens, creating a two-token system that helps maintain network stability and manage transaction costs.\",\n ),\n },\n {\n question: t('How do I send tokens?'),\n answer: t(\n \"You can send tokens by clicking the send icon in the Quick Actions section. Enter the recipient's address or VeChain domain name, select the token, and specify the amount you want to send.\",\n ),\n },\n {\n question: t('What is fee delegation?'),\n answer: t(\n \"Fee delegation is a unique feature of VeChain that allows someone else (a delegator) to pay for your transaction fees. While many dApps and service providers act as delegators to make it easier for new users to get started, some transactions may still require you to pay fees using your own VTHO. Fees are necessary to prevent network spam and compensate the nodes that process and validate transactions on the blockchain. When paying fees yourself, you'll be able to select VTHO from your assets to cover the transaction cost.\",\n ),\n },\n ];\n\n // Filter FAQ items based on search query\n const filteredFaqItems = faqItems.filter(\n (item) =>\n item.question.toLowerCase().includes(searchQuery.toLowerCase()) ||\n (typeof item.answer === 'string' &&\n item.answer.toLowerCase().includes(searchQuery.toLowerCase())),\n );\n\n return (\n <VStack spacing={4} align=\"stretch\">\n <InputGroup size=\"lg\">\n <Input\n placeholder={t('Search FAQ')}\n bg={inputBg}\n borderRadius=\"xl\"\n height=\"56px\"\n pl={12}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n />\n <InputLeftElement h=\"56px\" w=\"56px\" pl={4}>\n <LuSearch color={textTertiary} />\n </InputLeftElement>\n </InputGroup>\n\n {filteredFaqItems.length === 0 ? (\n <VStack spacing={2} py={8} color={textSecondary}>\n <Icon as={LuSlash} boxSize={12} opacity={0.5} />\n <Text fontSize=\"lg\">{t('No questions found')}</Text>\n <Text fontSize=\"md\">\n {t('Try searching with a different term')}\n </Text>\n </VStack>\n ) : (\n <Accordion allowMultiple>\n {filteredFaqItems.map((item, index) => (\n <AccordionItem key={index} border=\"none\" mb={2}>\n {({ isExpanded }) => (\n <>\n <AccordionButton\n bg={accordionBg}\n borderRadius=\"xl\"\n color={textSecondary}\n _hover={{\n bg: accordionBgHover,\n }}\n >\n <Box flex=\"1\" textAlign=\"left\" py={2}>\n <Text fontWeight=\"500\" color={textSecondary}>\n {item.question}\n </Text>\n </Box>\n <Icon\n as={\n isExpanded\n ? LuChevronUp\n : LuChevronDown\n }\n fontSize=\"20px\"\n opacity={0.5}\n />\n </AccordionButton>\n <AccordionPanel pb={4}>\n <Text fontSize=\"sm\" color={textSecondary} opacity={0.8}>\n {item.answer}\n </Text>\n </AccordionPanel>\n </>\n )}\n </AccordionItem>\n ))}\n </Accordion>\n )}\n </VStack>\n );\n};\n","import {\n Button,\n Link,\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Icon,\n Select,\n ModalFooter,\n useToken,\n} from '@chakra-ui/react';\nimport { LuExternalLink } from 'react-icons/lu';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { FAQAccordion } from './FAQAccordion';\nimport { useTranslation } from 'react-i18next';\nimport { supportedLanguages, languageNames } from '../../../../../i18n';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\nimport { VECHAIN_KIT_DOCS_BASE_URL } from '@/constants';\n\nexport type FAQContentProps = {\n onGoBack: () => void;\n showLanguageSelector?: boolean;\n};\n\nexport const FAQContent = ({\n onGoBack,\n showLanguageSelector = true,\n}: FAQContentProps) => {\n const { i18n, t } = useTranslation();\n const { isolatedView } = useAccountModalOptions();\n\n // Use semantic tokens for colors\n const selectBg = useToken('colors', 'vechain-kit-card');\n const selectBorder = useToken('colors', 'vechain-kit-border');\n const selectBorderHover = useToken('colors', 'vechain-kit-border-hover');\n\n const handleLanguageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n i18n.changeLanguage(e.target.value);\n };\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Help')}</ModalHeader>\n {!isolatedView && <ModalBackButton onClick={onGoBack} />}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack spacing={6} align=\"stretch\">\n {showLanguageSelector && (\n <Select\n borderRadius={'md'}\n size=\"sm\"\n width=\"auto\"\n value={i18n.language}\n onChange={handleLanguageChange}\n bg={selectBg}\n borderColor={selectBorder}\n _hover={{\n borderColor: selectBorderHover,\n }}\n >\n {supportedLanguages.map((lang) => (\n <option key={lang} value={lang}>\n {\n languageNames[\n lang as keyof typeof languageNames\n ]\n }\n </option>\n ))}\n </Select>\n )}\n\n <Button\n as={Link}\n href={VECHAIN_KIT_DOCS_BASE_URL}\n isExternal\n variant=\"vechainKitSecondary\"\n rightIcon={<Icon as={LuExternalLink} />}\n >\n {t('For developers')}\n </Button>\n\n <FAQAccordion />\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n};\n","import {\n Button,\n Box,\n HStack,\n VStack,\n Text,\n Icon,\n Image,\n Tag,\n} from '@chakra-ui/react';\nimport { ElementType } from 'react';\nimport { humanAddress, humanDomain } from '@/utils';\nimport { useTranslation } from 'react-i18next';\nimport { Wallet } from '@/types';\nimport { useVeChainKitConfig } from '@/providers';\n\ninterface AccountDetailsButtonProps {\n title: string;\n wallet: Wallet;\n onClick: () => void;\n leftIcon?: ElementType;\n rightIcon?: ElementType;\n leftImage?: string;\n backgroundColor?: string;\n border?: string;\n isActive?: boolean;\n}\n\nexport const AccountDetailsButton = ({\n leftIcon,\n rightIcon,\n title,\n wallet,\n onClick,\n leftImage,\n isActive = false,\n}: AccountDetailsButtonProps) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n\n return (\n <Button\n w={'full'}\n minH={'70px'}\n h={'fit-content'}\n py={4}\n onClick={onClick}\n backgroundColor={isDark ? 'transparent' : 'transparent'}\n border={`1px solid ${isDark ? '#ffffff29' : '#ebebeb'}`}\n >\n <HStack w={'full'} justify={'space-between'}>\n <Box minW={'40px'} justifyContent={'center'}>\n {leftImage ? (\n <Image\n justifySelf={'center'}\n src={leftImage}\n w={'28px'}\n alt=\"left-image\"\n />\n ) : (\n <Icon as={leftIcon} fontSize={'28px'} />\n )}\n </Box>\n <VStack textAlign={'left'} w={'full'} flex={1}>\n <HStack\n w={'full'}\n spacing={2}\n justifyContent={'flex-start'}\n >\n <Text fontSize={'sm'} fontWeight={'400'}>\n {title}\n </Text>\n </HStack>\n <Text\n fontSize={'sm'}\n fontWeight={'500'}\n opacity={0.5}\n overflowWrap={'break-word'}\n wordBreak={'break-word'}\n whiteSpace={'normal'}\n w={'full'}\n >\n {wallet?.domain\n ? humanDomain(wallet?.domain ?? '', 18, 0)\n : humanAddress(wallet?.address ?? '', 6, 4)}\n </Text>\n </VStack>\n <VStack minW={'40px'} justifyContent={'flex-end'}>\n <HStack justifyContent={'flex-end'} minW={'40px'}>\n {isActive && (\n <Tag size={'sm'} colorScheme={'green'}>\n {t('Active')}\n </Tag>\n )}\n <Icon as={rightIcon} fontSize={'20px'} opacity={0.5} />\n </HStack>\n </VStack>\n </HStack>\n </Button>\n );\n};\n","import {\n Button,\n Box,\n HStack,\n VStack,\n Text,\n Icon,\n Image,\n Tag,\n ButtonProps,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { IconType } from 'react-icons';\n\ntype ActionButtonProps = {\n title: string;\n description?: string;\n onClick: () => void;\n leftIcon?: IconType;\n rightIcon?: IconType;\n leftImage?: string;\n backgroundColor?: string;\n border?: string;\n hide?: boolean;\n _hover?: object;\n showComingSoon?: boolean;\n isDisabled?: boolean;\n stacked?: boolean;\n isLoading?: boolean;\n loadingText?: string;\n style?: ButtonProps;\n extraContent?: React.ReactNode;\n dataTestId?: string;\n variant?: string;\n};\n\nexport const ActionButton = ({\n leftIcon,\n rightIcon,\n title,\n onClick,\n leftImage,\n hide = false,\n showComingSoon = false,\n backgroundColor,\n _hover,\n isDisabled = false,\n stacked = false,\n isLoading,\n loadingText,\n style,\n extraContent,\n dataTestId,\n variant = 'actionButton',\n}: ActionButtonProps) => {\n const { t } = useTranslation();\n \n // Map actionButton to vechainKitSecondary for consistency\n // Maintain backward compatibility by allowing override\n const standardVariant = variant === 'actionButton' ? 'vechainKitSecondary' : variant;\n \n return (\n <Button\n variant={standardVariant}\n py={stacked ? 0 : 2}\n minHeight=\"50px\"\n height=\"fit-content\"\n p={0}\n onClick={onClick}\n display={hide ? 'none' : 'flex'}\n isDisabled={showComingSoon || isDisabled}\n isLoading={isLoading}\n loadingText={loadingText}\n bgColor={backgroundColor}\n _hover={_hover}\n data-testid={dataTestId}\n {...style}\n >\n <HStack w={'full'} justify={'space-between'} alignItems={'center'}>\n <Box minW={'40px'} h={'20px'}>\n {leftImage ? (\n <Image\n src={leftImage}\n w={'30px'}\n h={'30px'}\n borderRadius={'full'}\n alt=\"left-image\"\n alignSelf={'end'}\n objectFit=\"cover\"\n />\n ) : (\n <Icon\n as={leftIcon}\n fontSize={'20px'}\n h={'full'}\n alignContent={'center'}\n />\n )}\n </Box>\n <VStack\n textAlign={'left'}\n w={'full'}\n flex={1}\n justifyContent={'flex-start'}\n alignItems={'flex-start'}\n >\n <HStack justify={'flex-start'} alignItems={'baseline'}>\n <Text fontSize={'sm'} fontWeight={'400'}>\n {title}\n </Text>\n {showComingSoon && (\n <Tag size=\"sm\" colorScheme=\"red\">\n {t('Coming Soon!')}\n </Tag>\n )}\n {extraContent}\n </HStack>\n\n {/* <Text\n fontSize={'xs'}\n fontWeight={'400'}\n opacity={0.5}\n overflowWrap={'break-word'}\n wordBreak={'break-word'}\n whiteSpace={'normal'}\n w={'full'}\n pr={rightIcon ? '0px' : '10px'}\n >\n {description}\n </Text> */}\n </VStack>\n\n {rightIcon && (\n <VStack minW={'40px'} justifyContent={'flex-end'}>\n <Icon as={rightIcon} fontSize={'20px'} opacity={0.5} />\n </VStack>\n )}\n </HStack>\n </Button>\n );\n};\n","'use client';\n\nimport {\n Text,\n Icon,\n HStack,\n Button,\n StackProps,\n IconButton,\n} from '@chakra-ui/react';\nimport { humanAddress, humanDomain } from '../../../utils';\nimport { copyToClipboard } from '@/utils/ssrUtils';\nimport { Wallet } from '@/types';\nimport {\n LuChevronRight,\n LuCheck,\n LuCopy,\n LuArrowLeftRight,\n} from 'react-icons/lu';\nimport { AccountAvatar } from '@/components/common';\nimport { useState } from 'react';\nimport { AccountModalContentTypes } from '../Types/Types';\nimport { useTranslation } from 'react-i18next';\nimport { useWallet, useSwitchWallet, useDAppKitWallet } from '@/hooks';\n\ntype Props = {\n wallet: Wallet;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n size?: string;\n onClick?: () => void;\n onClose: () => void;\n mt?: number;\n style?: StackProps;\n};\n\nexport const AccountSelector = ({\n wallet,\n setCurrentContent,\n size = 'md',\n onClick,\n onClose,\n mt,\n style,\n}: Props) => {\n const { t } = useTranslation();\n const { connection } = useWallet();\n const { switchWallet, isSwitching, isInAppBrowser } = useSwitchWallet();\n const { isSwitchWalletEnabled } = useDAppKitWallet();\n\n const [copied, setCopied] = useState(false);\n\n const handleCopyToClipboard = async () => {\n const success = await copyToClipboard(\n wallet?.domain ?? wallet?.address ?? '',\n );\n if (success) {\n setCopied(true);\n setTimeout(() => {\n setCopied(false);\n }, 2000);\n }\n };\n\n const handleSwitchWallet = () => {\n if (isInAppBrowser) {\n switchWallet();\n } else {\n // Desktop: navigate to select wallet screen\n setCurrentContent?.({\n type: 'select-wallet',\n props: {\n setCurrentContent: setCurrentContent!,\n onClose,\n returnTo: 'main',\n onLogoutSuccess: onClose,\n },\n });\n }\n };\n\n return (\n <HStack\n mt={mt}\n w={'full'}\n {...style}\n justifyContent={'flex-start'}\n alignItems={'center'}\n >\n <Button\n w=\"full\"\n h={12}\n aria-label=\"Wallet\"\n onClick={onClick}\n variant=\"vechainKitSecondary\"\n p={3}\n data-testid=\"profile-button\"\n >\n <HStack\n spacing={2}\n align=\"center\"\n justifyContent={'space-between'}\n w={'full'}\n >\n <HStack spacing={2} justifyContent={'flex-start'}>\n <AccountAvatar\n wallet={wallet}\n props={{ width: 7, height: 7 }}\n />\n <Text fontSize={size} fontWeight=\"500\">\n {copied\n ? t('Copied!')\n : humanDomain(wallet?.domain ?? '', 22, 0) ||\n humanAddress(wallet?.address ?? '', 6, 4)}\n </Text>\n </HStack>\n\n <Icon\n boxSize={5}\n as={LuChevronRight}\n cursor=\"pointer\"\n opacity={0.5}\n />\n </HStack>\n </Button>\n\n {(connection.isInAppBrowser && isSwitchWalletEnabled) ||\n (!connection.isInAppBrowser &&\n connection.isConnectedWithDappKit) ? (\n <IconButton\n aria-label=\"Switch wallet\"\n icon={<Icon as={LuArrowLeftRight} />}\n onClick={handleSwitchWallet}\n w=\"60px\"\n h={12}\n variant=\"vechainKitSecondary\"\n p={3}\n isLoading={isSwitching}\n isDisabled={isSwitching}\n data-testid=\"switch-wallet-button\"\n />\n ) : (\n <IconButton\n aria-label=\"Copy address\"\n icon={<Icon as={copied ? LuCheck : LuCopy} />}\n onClick={handleCopyToClipboard}\n w=\"60px\"\n h={12}\n variant=\"vechainKitSecondary\"\n p={3}\n />\n )}\n\n {/* <IconButton\n aria-label=\"Logout\"\n icon={<Icon as={LuLogOut} />}\n onClick={() =>\n setCurrentContent({\n type: 'disconnect-confirm',\n props: {\n onDisconnect: handleLogout,\n onBack: () => setCurrentContent('main'),\n },\n })\n }\n variant=\"ghost\"\n size=\"sm\"\n opacity={0.5}\n _hover={{ opacity: 0.8 }}\n colorScheme=\"red\"\n /> */}\n </HStack>\n );\n};\n","import {\n HStack,\n Text,\n Circle,\n Image,\n StackProps,\n useToken,\n} from '@chakra-ui/react';\nimport { useTokensWithValues } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\nimport { TOKEN_LOGOS, TOKEN_LOGO_COMPONENTS } from '@/utils';\nimport { useTranslation } from 'react-i18next';\nimport React from 'react';\n\ntype AssetIconsProps = {\n address: string;\n maxIcons?: number;\n iconSize?: number;\n ml?: number;\n style?: StackProps;\n iconsGap?: number;\n rightIcon?: React.ReactNode;\n showNoAssetsWarning?: boolean;\n onClick?: () => void;\n};\n\nexport const AssetIcons = ({\n address,\n maxIcons = 3,\n iconSize = 20,\n ml = 0,\n style,\n iconsGap = 0,\n rightIcon,\n showNoAssetsWarning = false,\n onClick,\n}: AssetIconsProps) => {\n const { t } = useTranslation();\n const { tokensWithBalance } = useTokensWithValues({ address });\n const { darkMode } = useVeChainKitConfig();\n const secondaryTextColor = useToken('colors', 'vechain-kit-text-secondary');\n const marginLeft = iconsGap < 1 ? `-${iconSize / 2}px` : `${iconsGap}px`;\n\n const tokensToShow = tokensWithBalance.slice(0, maxIcons);\n const remainingTokens = tokensWithBalance.length - maxIcons;\n\n if (!address) return null;\n if (tokensWithBalance.length === 0 && !showNoAssetsWarning) return null;\n\n return (\n <HStack spacing={0} ml={ml} {...style} onClick={onClick}>\n <HStack spacing={0}>\n {tokensToShow.map((token, index) => (\n <Circle\n key={token.symbol}\n ml={index > 0 ? marginLeft : '0'}\n zIndex={index}\n size={`${iconSize}px`}\n borderRadius=\"full\"\n bg={darkMode ? 'gray.100' : 'gray.600'}\n border=\"2px solid #00000024\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n {TOKEN_LOGO_COMPONENTS[token.symbol] ? (\n React.cloneElement(\n TOKEN_LOGO_COMPONENTS[token.symbol],\n {\n width: `${iconSize * 0.8}px`,\n height: `${iconSize * 0.8}px`,\n rounded: 'full',\n },\n )\n ) : TOKEN_LOGOS[token.symbol] ? (\n <Image\n src={TOKEN_LOGOS[token.symbol]}\n alt={`${token.symbol} logo`}\n width={`${iconSize * 0.8}px`}\n height={`${iconSize * 0.8}px`}\n rounded=\"full\"\n />\n ) : (\n <Text\n fontSize={`${iconSize * 0.4}px`}\n fontWeight=\"bold\"\n color={darkMode ? 'black' : 'white'}\n >\n {token.symbol.slice(0, 3)}\n </Text>\n )}\n </Circle>\n ))}\n {remainingTokens > 0 && (\n <Circle\n ml={marginLeft}\n zIndex={tokensToShow.length}\n size={`${iconSize}px`}\n borderRadius=\"full\"\n bg={darkMode ? 'gray.100' : 'gray.700'}\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n border=\"2px solid\"\n >\n <Text\n fontSize={`${iconSize * 0.4}px`}\n fontWeight=\"bold\"\n color={darkMode ? 'black' : 'white'}\n >\n +{remainingTokens}\n </Text>\n </Circle>\n )}\n\n {tokensWithBalance.length === 0 && showNoAssetsWarning && (\n <Text\n fontSize={'sm'}\n color={secondaryTextColor}\n fontWeight=\"700\"\n >\n {t('No assets')}\n </Text>\n )}\n </HStack>\n\n {rightIcon}\n </HStack>\n );\n};\n","import {\n Heading,\n VStack,\n HStack,\n Icon,\n IconButton,\n Button,\n useToken,\n} from '@chakra-ui/react';\nimport { useRefreshBalances, useWallet, useTotalBalance, LocalStorageKey, useLocalStorage } from '@/hooks';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { LuRefreshCw } from 'react-icons/lu';\nimport { AssetIcons } from '@/components/WalletButton/AssetIcons';\nimport { LuChevronRight } from 'react-icons/lu';\nimport { GoEye, GoEyeClosed } from 'react-icons/go';\n\nexport const BalanceSection = ({\n mb,\n mt,\n onAssetsClick,\n}: {\n mb?: number;\n mt?: number;\n onAssetsClick?: () => void;\n}) => {\n const { t } = useTranslation();\n const { account } = useWallet();\n const { formattedBalance, isLoading } = useTotalBalance({\n address: account?.address ?? '',\n });\n\n const { refresh } = useRefreshBalances();\n const [isRefreshing, setIsRefreshing] = useState(false);\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const handleRefresh = async () => {\n setIsRefreshing(true);\n await refresh();\n setTimeout(() => {\n setIsRefreshing(false);\n }, 1500);\n };\n const [showAssets, setShowAssets] = useLocalStorage(LocalStorageKey.SHOW_ASSETS, true);\n\n return (\n <VStack w=\"full\" justifyContent={'start'} spacing={1} mt={mt} mb={mb}>\n <HStack\n w={'full'}\n justifyContent={'space-between'}\n alignItems={'center'}\n spacing={0}\n role=\"group\"\n >\n <Heading\n size={'xs'}\n fontWeight={'800'}\n color={textSecondary}\n textTransform={'uppercase'}\n letterSpacing={1.2}\n ml={'5px'}\n >\n {t('Assets')}\n </Heading>\n\n <HStack\n spacing={0}\n alignItems=\"center\"\n >\n <IconButton\n aria-label=\"Refresh balances\"\n variant=\"ghost\"\n size=\"sm\"\n opacity={0.5}\n _hover={{ opacity: 0.8 }}\n onClick={handleRefresh}\n icon={<Icon as={LuRefreshCw} boxSize={4} />}\n isLoading={isLoading || isRefreshing}\n sx={{\n '& > span.chakra-button__spinner': {\n width: '16px',\n height: '16px',\n position: 'absolute',\n },\n }}\n />\n <IconButton\n aria-label=\"Show/hide assets\"\n variant=\"ghost\"\n size=\"sm\"\n opacity={0.5}\n _hover={{ opacity: 0.8 }}\n onClick={() => setShowAssets(!showAssets)}\n icon={<Icon as={showAssets ? GoEye : GoEyeClosed} boxSize={4} />}\n />\n </HStack>\n </HStack>\n\n <Button\n onClick={onAssetsClick}\n h=\"fit-content\"\n variant=\"vechainKitSecondary\"\n >\n <VStack\n spacing={2}\n w=\"full\"\n justifyContent=\"flex-start\"\n alignItems=\"flex-start\"\n mt={4}\n mb={4}\n >\n <Heading size={'2xl'} fontWeight={'700'}>\n { showAssets ? formattedBalance : formattedBalance[0] + '*'.repeat(formattedBalance.slice(1).length) }\n </Heading>\n\n <HStack\n w={'full'}\n justifyContent={'flex-start'}\n data-testid=\"all-assets-button\"\n mt={2}\n >\n <AssetIcons\n style={{\n width: '100%',\n justifyContent: 'space-between',\n }}\n maxIcons={10}\n iconSize={26}\n iconsGap={3}\n address={account?.address ?? ''}\n showNoAssetsWarning={true}\n rightIcon={\n <Icon\n as={LuChevronRight}\n boxSize={5}\n opacity={0.5}\n marginLeft={2}\n />\n }\n />\n </HStack>\n </VStack>\n </Button>\n </VStack>\n );\n};\n","import {\n Grid,\n Icon,\n IconButton,\n VStack,\n Text,\n HStack,\n Box,\n} from '@chakra-ui/react';\nimport { AccountModalContentTypes } from '../Types';\nimport { useUpgradeRequired, useWallet, useTotalBalance } from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport {\n LuArrowDownToLine,\n LuArrowLeftRight,\n LuArrowUpFromLine,\n} from 'react-icons/lu';\n\ntype Props = {\n mt?: number;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\ntype QuickAction = {\n icon: React.ElementType;\n label: string;\n onClick: (setCurrentContent: Props['setCurrentContent']) => void;\n isDisabled?: (hasAnyBalance: boolean) => boolean;\n};\n\nconst QUICK_ACTIONS: QuickAction[] = [\n {\n icon: LuArrowUpFromLine,\n label: 'Send',\n onClick: (setCurrentContent) =>\n setCurrentContent({\n type: 'send-token',\n props: {\n setCurrentContent,\n },\n }),\n isDisabled: (hasAnyBalance) => !hasAnyBalance,\n },\n {\n icon: LuArrowLeftRight,\n label: 'Swap',\n onClick: (setCurrentContent) => {\n setCurrentContent('swap-token');\n },\n isDisabled: (hasAnyBalance) => !hasAnyBalance,\n },\n {\n icon: LuArrowDownToLine,\n label: 'Receive',\n onClick: (setCurrentContent) => {\n setCurrentContent('receive-token');\n },\n },\n];\n\nconst QuickActionButton = ({\n icon,\n label,\n onClick,\n isDisabled,\n showRedDot,\n}: {\n icon: React.ElementType;\n label: string;\n onClick: () => void;\n isDisabled?: boolean;\n showRedDot?: boolean;\n}) => {\n const { t } = useTranslation();\n\n return (\n <IconButton\n variant=\"vechainKitSecondary\"\n h=\"80px\"\n w=\"full\"\n aria-label={label}\n isDisabled={isDisabled}\n p={3}\n icon={\n <VStack spacing={4}>\n <Icon as={icon} boxSize={5} opacity={0.9} />\n\n <HStack p={0} alignItems={'baseline'} spacing={1}>\n <Text\n fontSize=\"sm\"\n fontWeight=\"600\"\n data-testid={`${label.toLowerCase()}-button-label`}\n >\n {t(label, label)}\n </Text>\n {showRedDot && (\n <Box\n minWidth=\"8px\"\n height=\"8px\"\n bg=\"red.500\"\n borderRadius=\"full\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n />\n )}\n </HStack>\n </VStack>\n }\n onClick={onClick}\n />\n );\n};\n\nexport const QuickActionsSection = ({ mt, setCurrentContent }: Props) => {\n const { account, smartAccount, connectedWallet, connection } = useWallet();\n const { hasAnyBalance } = useTotalBalance({\n address: account?.address ?? '',\n });\n\n const { data: upgradeRequired } = useUpgradeRequired(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n\n const showRedDot = connection.isConnectedWithPrivy && upgradeRequired;\n\n return (\n <Grid templateColumns=\"repeat(3, 1fr)\" gap={2} w=\"full\" mt={mt}>\n {QUICK_ACTIONS.map((action) => (\n <QuickActionButton\n key={action.label}\n icon={action.icon}\n label={action.label}\n onClick={() => action.onClick(setCurrentContent)}\n isDisabled={action.isDisabled?.(hasAnyBalance)}\n showRedDot={showRedDot && action.label === 'Settings'}\n />\n ))}\n </Grid>\n );\n};\n","import {\n Card,\n CardBody,\n HStack,\n VStack,\n Text,\n useToken,\n Tag,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { AccountModalContentTypes } from '../../Types';\n\ntype FeatureAnnouncementCardProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\nexport const FeatureAnnouncementCard = ({\n setCurrentContent,\n}: FeatureAnnouncementCardProps) => {\n const { t } = useTranslation();\n // const { closeAnnouncement } = useFeatureAnnouncement();\n\n const titleColor = useToken('colors', 'vechain-kit-text-primary');\n const descriptionColor = useToken('colors', 'vechain-kit-text-secondary');\n\n const handleOnClick = () => {\n setCurrentContent({\n type: 'choose-name',\n props: {\n setCurrentContent,\n onBack: () => setCurrentContent('profile'),\n initialContentSource: 'profile',\n },\n });\n // closeAnnouncement();\n };\n\n // We always show the announcement card for now\n // if (!isVisible) return null;\n\n return (\n <Card\n w=\"full\"\n variant={'featureAnnouncement'}\n overflow=\"hidden\"\n onClick={handleOnClick}\n cursor=\"pointer\"\n _hover={{ opacity: 0.8 }}\n >\n <CardBody p={4}>\n <HStack justify=\"space-between\" align=\"flex-start\" spacing={3}>\n <VStack align=\"flex-start\" spacing={1}>\n <HStack spacing={2}>\n <Text\n fontSize=\"sm\"\n fontWeight=\"400\"\n color={titleColor}\n >\n {t('Claim your vet domain!')}\n </Text>\n <Tag size=\"sm\" colorScheme=\"red\">\n {t('New')}\n </Tag>\n </HStack>\n <Text fontSize=\"xs\" color={descriptionColor}>\n {t(\n 'Say goodbye to 0x addresses, claim your .veworld.vet subdomain now for free!',\n )}\n </Text>\n </VStack>\n </HStack>\n </CardBody>\n </Card>\n );\n};\n","import { Alert, AlertIcon, Text, VStack, HStack } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\n\nexport const ExchangeWarningAlert = () => {\n const { t } = useTranslation();\n\n return (\n <Alert status=\"warning\" fontSize={'xs'} borderRadius={'xl'} p={2}>\n <VStack spacing={1} align=\"stretch\" w=\"full\">\n <HStack spacing={2} align=\"flex-start\">\n <AlertIcon boxSize={4} mt={'10px'} />\n <Text w=\"full\">\n {t(\n 'Sending to OceanX or other exchanges may result in loss of funds.',\n )}\n </Text>\n </HStack>\n </VStack>\n </Alert>\n );\n};\n","import { Alert, AlertIcon, Text, VStack, HStack } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\n\nexport const DomainRequiredAlert = () => {\n const { t } = useTranslation();\n\n return (\n <Alert status=\"warning\" fontSize={'xs'} borderRadius={'xl'} p={2}>\n <VStack spacing={1} align=\"stretch\" w=\"full\">\n <HStack spacing={2} align=\"flex-start\">\n <AlertIcon boxSize={4} mt={'10px'} />\n <Text w=\"full\">\n {t(\n 'A .vet domain is required to customize your profile. Choose an account name to get started.',\n )}\n </Text>\n </HStack>\n </VStack>\n </Alert>\n );\n};\n","import {\n Card,\n CardHeader,\n CardBody,\n CardFooter,\n HStack,\n Text,\n Icon,\n Button,\n VStack,\n Center,\n Box,\n} from '@chakra-ui/react';\nimport { LuExternalLink, LuUserCog, LuShieldCheck } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { useCrossAppConnectionCache } from '@/hooks';\nimport { VEBETTERDAO_GOVERNANCE_BASE_URL } from '@/constants';\n\nexport const CrossAppConnectionSecurityCard = () => {\n const { t } = useTranslation();\n\n const { getConnectionCache } = useCrossAppConnectionCache();\n\n const connectionCache = getConnectionCache();\n\n return (\n <Card variant=\"vechainKitBase\" w=\"full\">\n <CardHeader p={4} pl={6} borderBottomWidth=\"1px\">\n <Text fontWeight=\"medium\" opacity={0.8}>\n {t('Security preferences')}\n </Text>\n\n <Text fontSize=\"xs\" mt={1} opacity={0.7}>\n {t(\n 'For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.',\n {\n appName:\n connectionCache?.ecosystemApp.name ??\n 'origin app',\n },\n )}\n </Text>\n </CardHeader>\n\n <CardBody borderRadius={'none'}>\n <VStack spacing={3} align=\"stretch\">\n <HStack spacing={3} align=\"center\">\n <Center\n w={'fit-content'}\n h={'fit-content'}\n p={2}\n borderRadius=\"full\"\n bg=\"blackAlpha.100\"\n flexShrink={0}\n >\n <Icon as={LuUserCog} />\n </Center>\n <Box flex={1}>\n <Text\n fontSize=\"sm\"\n fontWeight=\"medium\"\n lineHeight=\"shorter\"\n >\n {t('Login methods')}\n </Text>\n <Text\n fontSize=\"xs\"\n opacity={0.7}\n lineHeight=\"shorter\"\n >\n {t('Manage your login methods and passkeys')}\n </Text>\n </Box>\n </HStack>\n\n <HStack spacing={3} align=\"center\">\n <Center\n w={'fit-content'}\n h={'fit-content'}\n p={2}\n borderRadius=\"full\"\n bg=\"blackAlpha.100\"\n flexShrink={0}\n >\n <Icon as={LuShieldCheck} />\n </Center>\n <Box flex={1}>\n <Text\n fontSize=\"sm\"\n fontWeight=\"medium\"\n lineHeight=\"shorter\"\n >\n {t('Security settings')}\n </Text>\n <Text\n fontSize=\"xs\"\n opacity={0.7}\n lineHeight=\"shorter\"\n >\n {t(\n 'Backup your wallet, configure MFA and set recovery options',\n )}\n </Text>\n </Box>\n </HStack>\n </VStack>\n </CardBody>\n\n <CardFooter>\n <Button\n variant=\"vechainKitSecondary\"\n w=\"full\"\n onClick={() => {\n window.open(\n connectionCache?.ecosystemApp.website ??\n VEBETTERDAO_GOVERNANCE_BASE_URL,\n '_blank',\n );\n }}\n >\n {t('Manage on {{appName}}', {\n appName:\n connectionCache?.ecosystemApp.name ?? 'origin app',\n })}\n <Icon as={LuExternalLink} ml={2} />\n </Button>\n </CardFooter>\n </Card>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Button,\n Box,\n ModalFooter,\n Icon,\n Input,\n Textarea,\n FormControl,\n FormLabel,\n useToken,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useWallet } from '@/hooks';\nimport { LuChevronRight, LuCamera, LuSquareUser } from 'react-icons/lu';\nimport { ActionButton } from '../../../Components';\nimport { useSingleImageUpload } from '@/hooks/api/ipfs';\nimport { useRef, useState, useEffect, useMemo } from 'react';\nimport { uploadBlobToIPFS } from '@/utils/ipfs';\nimport { AccountAvatar } from '@/components/common';\nimport { DomainRequiredAlert } from '../../../Components/Alerts';\nimport { AccountModalContentTypes } from '../../../Types';\nimport { useForm } from 'react-hook-form';\n\n// Update FormValues type to include validation\ntype FormValues = {\n displayName: string;\n description: string;\n};\n\nexport type AccountCustomizationContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n initialContentSource?: AccountModalContentTypes;\n};\n\nexport const CustomizationContent = ({\n setCurrentContent,\n initialContentSource = 'profile',\n}: AccountCustomizationContentProps) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const { account } = useWallet();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const errorColor = useToken('colors', 'vechain-kit-error');\n const cardBg = useToken('colors', 'vechain-kit-card');\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const coverInputRef = useRef<HTMLInputElement>(null);\n const [isUploading, setIsUploading] = useState(false);\n const { onUpload } = useSingleImageUpload({\n compressImage: true,\n });\n\n const [previewImageUrl, setPreviewImageUrl] = useState<string | null>(null);\n const [avatarIpfsHash, setAvatarIpfsHash] = useState<string | null>(null);\n const hasDomain = !!account?.domain;\n\n // Add these state variables for initial values\n const [initialAvatarHash, setInitialAvatarHash] = useState<string | null>(\n null,\n );\n const [initialDisplayName, setInitialDisplayName] = useState('');\n const [initialDescription, setInitialDescription] = useState('');\n\n // Update form initialization with validation rules\n const {\n register,\n watch,\n formState: { errors, isValid },\n } = useForm<FormValues>({\n defaultValues: {\n displayName: account?.metadata?.display || '',\n description: account?.metadata?.description || '',\n },\n mode: 'onChange',\n });\n\n // Update effect to reset image when domain changes\n useEffect(() => {\n if (account?.metadata) {\n const metadata = account.metadata;\n setInitialDisplayName(metadata.display || '');\n setInitialDescription(metadata.description || '');\n setInitialAvatarHash(\n account.image ? account.image.replace('ipfs://', '') : null,\n );\n\n // Only set the preview URL if it hasn't been set yet\n setPreviewImageUrl((prev) => prev ?? account.image ?? null);\n }\n }, [account, network.type]);\n\n // Watch all form values for changes\n const formValues = watch();\n\n const handleImageUpload = async (\n event: React.ChangeEvent<HTMLInputElement>,\n ) => {\n const file = event.target.files?.[0];\n if (!file) return;\n\n try {\n setIsUploading(true);\n\n // Clear the previous preview URL first\n if (previewImageUrl) {\n URL.revokeObjectURL(previewImageUrl);\n }\n\n // Create temporary preview URL\n const newPreviewUrl = URL.createObjectURL(file);\n setPreviewImageUrl(newPreviewUrl);\n\n const uploadedImage = await onUpload(file);\n if (!uploadedImage) throw new Error('Failed to compress image');\n\n const ipfsHash = await uploadBlobToIPFS(\n uploadedImage.file,\n file.name,\n network.type,\n );\n setAvatarIpfsHash(ipfsHash);\n } catch (error) {\n console.error('Error uploading image:', error);\n setPreviewImageUrl(null);\n } finally {\n setIsUploading(false);\n }\n };\n\n // This cleanup effect is important for memory management in the browser. Here's why:\n // When you create a URL using URL.createObjectURL() (which happens in the handleImageUpload function),\n // the browser creates a unique URL that points to the file/blob in memory.\n // This URL remains valid and the object remains in memory until explicitly revoked.\n // If you don't revoke these URLs, you can create memory leaks,\n // especially if users upload multiple images or the component remounts frequently.\n useEffect(() => {\n return () => {\n if (previewImageUrl) {\n URL.revokeObjectURL(previewImageUrl);\n }\n };\n }, [previewImageUrl]);\n\n // Update getChangedValues to use form values\n const getChangedValues = () => {\n const changes: {\n avatarIpfsHash?: string;\n displayName?: string;\n description?: string;\n } = {};\n\n if (avatarIpfsHash !== initialAvatarHash && avatarIpfsHash)\n changes.avatarIpfsHash = avatarIpfsHash;\n if (formValues.displayName !== initialDisplayName)\n changes.displayName = formValues.displayName;\n if (formValues.description !== initialDescription)\n changes.description = formValues.description;\n return changes;\n };\n\n // Add this function to check if there are any changes\n const hasChanges = useMemo(() => {\n const changes = getChangedValues();\n return Object.keys(changes).length > 0;\n }, [getChangedValues]);\n\n const handleSaveChanges = () => {\n setCurrentContent({\n type: 'account-customization-summary',\n props: {\n setCurrentContent,\n changes: getChangedValues(),\n onDoneRedirectContent: initialContentSource,\n },\n });\n };\n\n const handleBack = () => {\n setCurrentContent(initialContentSource);\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader data-testid=\"modal-title\">\n {t('Customization')}\n </ModalHeader>\n <ModalBackButton onClick={handleBack} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <Box\n cursor={hasDomain ? 'pointer' : 'default'}\n pt={2}\n display=\"flex\"\n justifyContent=\"center\"\n position=\"relative\"\n onClick={() => hasDomain && fileInputRef.current?.click()}\n >\n <AccountAvatar\n wallet={account}\n props={{\n width: '100px',\n height: '100px',\n boxShadow: '0px 0px 3px 2px #00000024',\n src: previewImageUrl ?? undefined,\n }}\n />\n {hasDomain && (\n <Icon\n as={LuCamera}\n position=\"absolute\"\n top=\"80px\"\n left=\"60%\"\n bg={cardBg}\n color={textPrimary}\n p=\"1\"\n borderRadius=\"full\"\n boxSize=\"6\"\n />\n )}\n {isUploading && (\n <Box\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n backgroundColor=\"rgba(0, 0, 0, 0.5)\"\n position=\"absolute\"\n transform=\"translateX(0%)\"\n width=\"100px\"\n height=\"100px\"\n borderRadius=\"full\"\n zIndex={10}\n >\n <Text fontSize=\"xs\" color=\"white\">\n {isUploading ? 'Uploading...' : 'Processing...'}\n </Text>\n </Box>\n )}\n </Box>\n\n <VStack spacing={6} mt={4}>\n {!hasDomain && <DomainRequiredAlert />}\n\n <ActionButton\n title={account?.domain ?? t('Choose account name')}\n description={t(\n 'Choose a unique .vet domain name for your account.',\n )}\n onClick={() => {\n if (account?.domain) {\n setCurrentContent({\n type: 'choose-name-search',\n props: {\n name: '',\n setCurrentContent,\n initialContentSource: {\n type: 'account-customization',\n props: {\n setCurrentContent,\n },\n },\n },\n });\n } else {\n setCurrentContent({\n type: 'choose-name',\n props: {\n setCurrentContent,\n initialContentSource: {\n type: 'account-customization',\n props: {\n setCurrentContent,\n },\n },\n onBack: () =>\n setCurrentContent({\n type: 'account-customization',\n props: {\n setCurrentContent,\n },\n }),\n },\n });\n }\n }}\n leftIcon={LuSquareUser}\n rightIcon={LuChevronRight}\n dataTestId=\"set-domain-name-button\"\n />\n\n <FormControl\n isDisabled={!hasDomain}\n isInvalid={!!errors.displayName}\n >\n <FormLabel\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {t('Display Name')}\n </FormLabel>\n <Input\n {...register('displayName', {\n maxLength: {\n value: 25,\n message: t(\n 'Display name must be less than 25 characters',\n ),\n },\n })}\n placeholder={\n !hasDomain\n ? t('Set a domain first')\n : t('Enter your display name')\n }\n fontWeight=\"medium\"\n color={textPrimary}\n data-testid=\"display-name-input\"\n />\n {errors.displayName && (\n <Text\n color={errorColor}\n fontSize=\"sm\"\n mt={1}\n fontWeight=\"medium\"\n >\n {errors.displayName.message}\n </Text>\n )}\n </FormControl>\n\n <FormControl\n isDisabled={!hasDomain}\n isInvalid={!!errors.description}\n >\n <FormLabel\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {t('Description')}\n </FormLabel>\n <Textarea\n {...register('description', {\n maxLength: {\n value: 100,\n message: t(\n 'Description must be less than 100 characters',\n ),\n },\n })}\n placeholder={t('Eg: DevRel @ ENS Labs')}\n fontWeight=\"medium\"\n color={textPrimary}\n data-testid=\"description-input\"\n minH=\"50px\"\n />\n {errors.description && (\n <Text\n color={errorColor}\n mt={1}\n fontSize=\"sm\"\n fontWeight=\"medium\"\n >\n {errors.description.message}\n </Text>\n )}\n </FormControl>\n </VStack>\n\n <input\n type=\"file\"\n ref={fileInputRef}\n hidden\n accept=\"image/*\"\n onChange={async (event) => await handleImageUpload(event)}\n />\n <input\n type=\"file\"\n ref={coverInputRef}\n hidden\n accept=\"image/*\"\n onChange={async (event) => {\n /* Add cover upload handler */\n event.preventDefault();\n }}\n />\n </ModalBody>\n\n <ModalFooter w=\"full\">\n <Button\n variant=\"vechainKitPrimary\"\n onClick={handleSaveChanges}\n isDisabled={!hasDomain || !hasChanges || !isValid}\n isLoading={isUploading}\n loadingText={t('Preparing changes...')}\n data-testid=\"save-changes-button\"\n >\n {t('Save Changes')}\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import React, { useMemo } from 'react';\nimport {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n ModalFooter,\n Icon,\n useToken,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n StickyHeaderContainer,\n TransactionButtonAndStatus,\n GasFeeSummary,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport {\n useWallet,\n useUpgradeRequired,\n useUpgradeSmartAccountModal,\n getAvatarQueryKey,\n getAvatarOfAddressQueryKey,\n getTextRecordsQueryKey,\n useGasTokenSelection,\n useGenericDelegatorFeeEstimation,\n} from '@/hooks';\nimport { useUpdateTextRecord } from '@/hooks';\nimport { useForm } from 'react-hook-form';\nimport { useGetResolverAddress } from '@/hooks/api/vetDomains/useGetResolverAddress';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { convertUriToUrl } from '@/utils';\nimport { GasTokenType } from '@/types/gasToken';\nimport { LuFileText } from 'react-icons/lu';\n\nexport type CustomizationSummaryContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n changes: {\n avatarIpfsHash?: string | null;\n displayName?: string;\n description?: string;\n twitter?: string;\n website?: string;\n email?: string;\n };\n onDoneRedirectContent: AccountModalContentTypes;\n};\n\ntype FormValues = {\n avatarIpfsHash?: string;\n displayName?: string;\n description?: string;\n twitter?: string;\n website?: string;\n email?: string;\n};\n\nexport const CustomizationSummaryContent = ({\n setCurrentContent,\n changes,\n onDoneRedirectContent,\n}: CustomizationSummaryContentProps) => {\n const { t } = useTranslation();\n const { darkMode: isDark, network, feeDelegation } = useVeChainKitConfig();\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const { account, connectedWallet, connection } = useWallet();\n const { preferences } = useGasTokenSelection();\n\n const { data: upgradeRequired } = useUpgradeRequired(\n account?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n const { open: openUpgradeSmartAccountModal } =\n useUpgradeSmartAccountModal();\n\n const { handleSubmit } = useForm<FormValues>({\n defaultValues: {\n ...changes,\n avatarIpfsHash: changes.avatarIpfsHash ?? undefined,\n },\n });\n\n const domain = account?.domain ?? '';\n\n // Pre-fetch the resolver address\n const { data: resolverAddress } = useGetResolverAddress(domain);\n\n const queryClient = useQueryClient();\n\n const {\n sendTransaction: updateTextRecord,\n txReceipt,\n error: txError,\n isWaitingForWalletConfirmation,\n isTransactionPending,\n clauses: getClauses,\n } = useUpdateTextRecord({\n resolverAddress, // Pass the pre-fetched resolver address\n signerAccountAddress: account?.address ?? '',\n onSuccess: async () => {\n try {\n await refresh();\n } catch (error) {\n console.error('Error refreshing data:', error);\n }\n },\n onError: (error) => {\n console.error('Error updating text record:', error);\n },\n });\n\n // Track if we've already shown success to prevent duplicate calls\n const [hasShownSuccess, setHasShownSuccess] = React.useState(false);\n\n // Handle successful transaction via useEffect to avoid synchronous state updates\n React.useEffect(() => {\n // Guard clauses\n if (!txReceipt) return;\n if (txReceipt.reverted) return;\n if (hasShownSuccess) return;\n if (isTransactionPending) return;\n\n const txId = txReceipt.meta.txID;\n if (!txId) return;\n\n setHasShownSuccess(true);\n setCurrentContent({\n type: 'successful-operation',\n props: {\n setCurrentContent,\n txId,\n title: t('Profile Updated'),\n description: t('Your changes have been saved successfully.'),\n onDone: () => {\n setCurrentContent(onDoneRedirectContent);\n },\n },\n });\n }, [\n txReceipt,\n hasShownSuccess,\n isTransactionPending,\n setCurrentContent,\n t,\n onDoneRedirectContent,\n ]);\n\n // Reset the flag when starting a new transaction\n React.useEffect(() => {\n if (isTransactionPending) {\n setHasShownSuccess(false);\n }\n }, [isTransactionPending]);\n\n // Build the text record updates immediately\n const textRecordUpdates = useMemo(() => {\n const domain = account?.domain ?? '';\n const CHANGES_TO_TEXT_RECORDS = {\n displayName: 'display',\n description: 'description',\n twitter: 'com.x',\n website: 'url',\n email: 'email',\n avatarIpfsHash: 'avatar',\n } as const;\n\n return Object.entries(changes)\n .filter(\n (entry): entry is [string, string] =>\n entry[1] !== undefined && entry[1] !== null,\n )\n .map(([key, value]) => ({\n domain,\n key: CHANGES_TO_TEXT_RECORDS[key as keyof FormValues],\n value: key === 'avatarIpfsHash' ? `ipfs://${value}` : value,\n }));\n }, [changes, account?.domain]);\n\n // Build clauses synchronously only if resolver address is available\n const clauses = useMemo(() => {\n try {\n // Don't build clauses until we have a resolver address\n if (\n !resolverAddress ||\n textRecordUpdates.length === 0 ||\n !getClauses\n ) {\n return [];\n }\n return getClauses(textRecordUpdates);\n } catch (error) {\n console.error('Error building clauses:', error);\n return [];\n }\n }, [textRecordUpdates, getClauses, resolverAddress]);\n\n // Gas estimation\n const [selectedGasToken, setSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n // Track the user's manual selection to show it during loading (before estimation completes)\n const [userSelectedGasToken, setUserSelectedGasToken] =\n React.useState<GasTokenType | null>(null);\n\n const shouldEstimateGas =\n preferences.availableGasTokens.length > 0 &&\n (connection.isConnectedWithPrivy ||\n connection.isConnectedWithVeChain) &&\n !feeDelegation?.delegatorUrl;\n const {\n data: gasEstimation,\n isLoading: gasEstimationLoading,\n error: gasEstimationError,\n refetch: refetchGasEstimation,\n } = useGenericDelegatorFeeEstimation({\n clauses: clauses,\n tokens: selectedGasToken\n ? [selectedGasToken]\n : preferences.availableGasTokens, // Use selected token or all available\n enabled: shouldEstimateGas && !!feeDelegation?.genericDelegatorUrl,\n });\n const usedGasToken = gasEstimation?.usedToken;\n const disableConfirmButtonDuringEstimation =\n (gasEstimationLoading || !gasEstimation) &&\n connection.isConnectedWithPrivy &&\n !feeDelegation?.delegatorUrl;\n\n const handleGasTokenChange = React.useCallback(\n (token: GasTokenType) => {\n setSelectedGasToken(token);\n setUserSelectedGasToken(token); // Track user's choice\n setTimeout(() => refetchGasEstimation(), 100);\n },\n [refetchGasEstimation],\n );\n\n // hasEnoughBalance is now determined by the hook itself\n const hasEnoughBalance = !!usedGasToken && !gasEstimationError;\n\n // Auto-fallback: if the selected token cannot cover fees (estimation error),\n // clear selection to re-estimate across all available tokens\n // Keep userSelectedGasToken to show during loading, but actual result will show the token that succeeds\n React.useEffect(() => {\n if (gasEstimationError && selectedGasToken) {\n setSelectedGasToken(null);\n }\n }, [gasEstimationError, selectedGasToken]);\n\n const onSubmit = async () => {\n if (upgradeRequired) {\n openUpgradeSmartAccountModal();\n return;\n }\n\n try {\n if (textRecordUpdates.length > 0) {\n await updateTextRecord(textRecordUpdates);\n }\n } catch (error) {\n console.error('Error saving changes:', error);\n }\n };\n\n const renderField = (label: string, value: string) => {\n if (!value?.trim()) return null;\n return (\n <VStack align=\"flex-start\" w=\"full\" spacing={1}>\n <Text\n fontSize=\"sm\"\n color={isDark ? 'whiteAlpha.600' : 'blackAlpha.600'}\n >\n {label}\n </Text>\n <Text fontSize=\"md\">{value}</Text>\n </VStack>\n );\n };\n\n const handleRetry = () => {\n handleSubmit(onSubmit)();\n };\n\n const handleBack = () => {\n setCurrentContent({\n type: 'account-customization',\n props: {\n setCurrentContent,\n },\n });\n };\n\n const refresh = async () => {\n // only update avatar data if it's being changed\n if (changes.avatarIpfsHash) {\n queryClient.setQueryData(\n getAvatarQueryKey(domain, network.type),\n convertUriToUrl(\n 'ipfs://' + changes.avatarIpfsHash,\n network.type,\n ),\n );\n\n queryClient.setQueryData(\n getAvatarOfAddressQueryKey(account?.address ?? ''),\n convertUriToUrl(\n 'ipfs://' + changes.avatarIpfsHash,\n network.type,\n ),\n );\n }\n\n // still refresh text records since they might have other changes\n await queryClient.invalidateQueries({\n queryKey: getTextRecordsQueryKey(domain, network.type),\n });\n\n await queryClient.refetchQueries({\n queryKey: getTextRecordsQueryKey(domain, network.type),\n });\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Confirm Changes')}</ModalHeader>\n <ModalBackButton\n isDisabled={isTransactionPending}\n onClick={handleBack}\n />\n <ModalCloseButton isDisabled={isTransactionPending} />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"center\" mt={10}>\n <Icon\n as={LuFileText}\n color={textPrimary}\n fontSize={'60px'}\n opacity={0.5}\n />\n <Text fontSize=\"md\" textAlign=\"center\" color={textPrimary}>\n {t(\n 'By confirming, the following details attached to your name ({{domain}}) will be updated',\n {\n domain,\n },\n )}\n </Text>\n </VStack>\n <VStack spacing={4} align=\"stretch\" mt={6}>\n {changes.avatarIpfsHash && (\n <VStack align=\"flex-start\" w=\"full\" spacing={1}>\n <Text\n fontSize=\"sm\"\n color={\n isDark ? 'whiteAlpha.600' : 'blackAlpha.600'\n }\n >\n {t('Profile Image')}\n </Text>\n <Text fontSize=\"md\">{t('New image selected')}</Text>\n </VStack>\n )}\n\n {changes.displayName &&\n renderField(t('Display Name'), changes.displayName)}\n {changes.description &&\n renderField(t('Description'), changes.description)}\n {changes.twitter &&\n renderField(t('Twitter'), changes.twitter)}\n {changes.website &&\n renderField(t('Website'), changes.website)}\n {changes.email && renderField(t('Email'), changes.email)}\n </VStack>\n {connection.isConnectedWithPrivy && (\n <GasFeeSummary\n estimation={gasEstimation}\n isLoading={gasEstimationLoading}\n isLoadingTransaction={isTransactionPending}\n onTokenChange={handleGasTokenChange}\n clauses={clauses as any}\n userSelectedToken={userSelectedGasToken}\n />\n )}\n </ModalBody>\n\n <ModalFooter gap={4} w=\"full\">\n <TransactionButtonAndStatus\n transactionError={txError}\n isSubmitting={isTransactionPending}\n isTxWaitingConfirmation={isWaitingForWalletConfirmation}\n onConfirm={handleSubmit(onSubmit)}\n onRetry={handleRetry}\n transactionPendingText={t('Saving changes...')}\n txReceipt={txReceipt}\n buttonText={t('Confirm')}\n isDisabled={\n isTransactionPending ||\n disableConfirmButtonDuringEstimation\n }\n gasEstimationError={gasEstimationError}\n hasEnoughGasBalance={hasEnoughBalance}\n isLoadingGasEstimation={gasEstimationLoading}\n showGasEstimationError={\n !feeDelegation?.delegatorUrl &&\n connection.isConnectedWithPrivy\n }\n context=\"customization\"\n />\n </ModalFooter>\n </>\n );\n};\n","import {\n Box,\n HStack,\n Icon,\n Link,\n Text,\n useToken,\n VStack,\n} from '@chakra-ui/react';\nimport { AccountAvatar, AddressDisplay } from '@/components/common';\nimport { useWalletMetadata } from '@/hooks';\nimport { LuMail, LuGlobe, LuPencil } from 'react-icons/lu';\nimport { FaXTwitter } from 'react-icons/fa6';\nimport { getPicassoImage } from '@/utils';\nimport { useVeChainKitConfig } from '@/providers';\nimport { AccountModalContentTypes } from '@/components/AccountModal/Types';\n\nexport type ProfileCardProps = {\n address: string;\n onEditClick?: () => void;\n onLogout?: () => void;\n showHeader?: boolean;\n showLinks?: boolean;\n showDescription?: boolean;\n showDisplayName?: boolean;\n showEdit?: boolean;\n setCurrentContent?: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const ProfileCard = ({\n address,\n showHeader = true,\n showLinks = true,\n showDescription = true,\n showDisplayName = true,\n setCurrentContent,\n onLogout,\n}: ProfileCardProps) => {\n const { network } = useVeChainKitConfig();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const cardBg = useToken('colors', 'vechain-kit-card');\n\n const metadata = useWalletMetadata(address, network.type);\n\n const headerImageSvg = getPicassoImage(address);\n\n const hasLinks =\n metadata?.records?.url ||\n metadata?.records?.['com.x'] ||\n metadata?.records?.email;\n\n const safeHttpUrl = (raw: string): string | null => {\n try {\n const u = new URL(raw);\n return u.protocol === 'http:' || u.protocol === 'https:'\n ? u.toString()\n : null;\n } catch {\n return null;\n }\n };\n\n return (\n <VStack spacing={0} w=\"full\">\n <Box\n p={0}\n backgroundSize=\"100% !important\"\n backgroundPosition=\"center\"\n position=\"relative\"\n // h=\"80px\"\n background={\n showHeader ? `no-repeat url('${headerImageSvg}')` : 'none'\n }\n w=\"100%\"\n borderRadius=\"14px 14px 0 0\"\n />\n <Box\n position=\"relative\"\n display=\"inline-block\"\n cursor={setCurrentContent ? 'pointer' : 'default'}\n onClick={\n setCurrentContent\n ? () => {\n setCurrentContent({\n type: 'account-customization',\n props: {\n setCurrentContent,\n initialContentSource: 'profile',\n },\n });\n }\n : undefined\n }\n >\n <AccountAvatar\n wallet={{\n address,\n domain: metadata?.domain,\n image: metadata?.image,\n isLoadingMetadata: metadata?.isLoading,\n metadata: metadata?.records,\n }}\n props={{\n width: '120px',\n height: '120px',\n // boxShadow: '0px 0px 3px 2px #00000024',\n }}\n />\n {setCurrentContent && (\n <Icon\n as={LuPencil}\n position=\"absolute\"\n bottom=\"0\"\n right=\"0\"\n bg={cardBg}\n color={textPrimary}\n p=\"1\"\n borderRadius=\"full\"\n boxSize=\"6\"\n border=\"2px solid\"\n borderColor={cardBg}\n />\n )}\n </Box>\n\n <VStack w={'full'} spacing={2}>\n {showDisplayName && metadata?.records?.display && (\n <Text\n fontSize=\"xl\"\n color={textPrimary}\n fontWeight=\"bold\"\n w=\"full\"\n textAlign=\"center\"\n mt={2}\n data-testid=\"display-name-val\"\n >\n {metadata?.records?.display}\n </Text>\n )}\n\n {showDescription && metadata?.records?.description && (\n <Text\n fontSize=\"sm\"\n color={textSecondary}\n w=\"full\"\n textAlign=\"center\"\n data-testid=\"description-val\"\n >\n {metadata?.records?.description}\n </Text>\n )}\n\n {showLinks && hasLinks && (\n <HStack w={'full'} justify={'center'} spacing={5} mt={4}>\n {metadata?.records?.email && (\n <Link\n href={`mailto:${metadata?.records?.email}`}\n target=\"_blank\"\n data-testid=\"mail-link\"\n >\n <Icon as={LuMail} color={textPrimary} />\n </Link>\n )}\n {metadata?.records?.url && (\n <Link\n href={\n safeHttpUrl(metadata.records.url) ??\n undefined\n }\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid=\"website-link\"\n >\n <Icon as={LuGlobe} color={textPrimary} />\n </Link>\n )}\n {metadata?.records?.['com.x'] && (\n <Link\n href={`https://x.com/${encodeURIComponent(\n String(metadata.records['com.x']),\n )}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid=\"twitter-link\"\n >\n <Icon as={FaXTwitter} color={textPrimary} />\n </Link>\n )}\n </HStack>\n )}\n\n <AddressDisplay\n onLogout={onLogout}\n wallet={{\n address,\n domain: metadata?.domain,\n image: metadata?.image,\n isLoadingMetadata: metadata?.isLoading,\n metadata: metadata?.records,\n }}\n style={{ mt: 4 }}\n setCurrentContent={setCurrentContent}\n />\n </VStack>\n </VStack>\n );\n};\n","import { useUpgradeRequired, useWallet } from '@/hooks';\nimport { IconButton, IconButtonProps, Box, Icon } from '@chakra-ui/react';\nimport { useEffect, useState } from 'react';\nimport { LuSettings2 } from 'react-icons/lu';\n\ntype ModalSettingsButtonProps = {\n onClick: () => void;\n} & Partial<IconButtonProps>;\n\nexport const ModalSettingsButton = ({\n onClick,\n ...props\n}: ModalSettingsButtonProps) => {\n const { smartAccount, connectedWallet, connection } = useWallet();\n const [isFirstVisit, setIsFirstVisit] = useState(false);\n\n useEffect(() => {\n const hasVisited = localStorage.getItem('app-first-visit');\n setIsFirstVisit(!hasVisited);\n }, []);\n\n const { data: upgradeRequired } = useUpgradeRequired(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n const showRedDot = connection.isConnectedWithPrivy && upgradeRequired;\n\n const handleOnClick = () => {\n if (isFirstVisit) {\n localStorage.setItem('app-first-visit', 'true');\n setIsFirstVisit(false);\n }\n\n onClick();\n };\n\n return (\n <IconButton\n aria-label=\"Settings\"\n size=\"sm\"\n variant=\"vechainKitHeaderIconButtons\"\n position=\"absolute\"\n left=\"10px\"\n top=\"8px\"\n lineHeight={'0'}\n onClick={handleOnClick}\n icon={\n <Box position=\"relative\">\n <Icon as={LuSettings2} fontSize={'18px'} />\n {showRedDot && (\n <Box\n position=\"absolute\"\n top=\"-1px\"\n right=\"-1px\"\n minWidth=\"8px\"\n height=\"8px\"\n bg=\"red.500\"\n borderRadius=\"full\"\n />\n )}\n </Box>\n }\n {...props}\n />\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n ModalFooter,\n VStack,\n HStack,\n Button,\n Icon,\n Text,\n} from '@chakra-ui/react';\nimport {\n useSwitchWallet,\n useWallet,\n useDAppKitWallet,\n useTotalBalance,\n LocalStorageKey,\n useLocalStorage,\n} from '@/hooks';\nimport { FeatureAnnouncementCard } from '@/components';\nimport { ProfileCard } from './Components/ProfileCard/ProfileCard';\nimport {\n StickyHeaderContainer,\n WalletSwitchFeedback,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { LuArrowLeftRight, LuLogOut, LuWalletCards } from 'react-icons/lu';\nimport { ModalSettingsButton } from '@/components/common/ModalSettingsButton';\nimport { AssetIcons } from '@/components/WalletButton/AssetIcons';\n\nexport type ProfileContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onLogoutSuccess: () => void;\n switchFeedback?: { showFeedback: boolean };\n};\n\nexport const ProfileContent = ({\n setCurrentContent,\n onLogoutSuccess,\n switchFeedback,\n}: ProfileContentProps) => {\n const { t } = useTranslation();\n const { account, disconnect, connection } = useWallet();\n const { switchWallet, isSwitching, isInAppBrowser } = useSwitchWallet();\n const { isSwitchWalletEnabled } = useDAppKitWallet();\n const { hasAnyBalance, formattedBalance } = useTotalBalance({\n address: account?.address,\n });\n const [showAssets] = useLocalStorage(LocalStorageKey.SHOW_ASSETS, true);\n\n const handleSwitchWallet = () => {\n if (isInAppBrowser) {\n switchWallet();\n } else {\n // Desktop: navigate to select wallet screen\n setCurrentContent({\n type: 'select-wallet',\n props: {\n setCurrentContent,\n onClose: () => {},\n returnTo: 'profile',\n onLogoutSuccess,\n },\n });\n }\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader data-testid=\"modal-title\">\n {t('Profile')}\n </ModalHeader>\n\n <ModalSettingsButton\n onClick={() => {\n setCurrentContent('settings');\n }}\n data-testid=\"settings-button\"\n />\n\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack w={'full'} spacing={6}>\n <WalletSwitchFeedback\n showFeedback={switchFeedback?.showFeedback}\n />\n {!account?.domain && (\n <FeatureAnnouncementCard\n setCurrentContent={setCurrentContent}\n />\n )}\n\n <ProfileCard\n onEditClick={() => {\n setCurrentContent({\n type: 'account-customization',\n props: {\n setCurrentContent,\n initialContentSource: 'profile',\n },\n });\n }}\n address={account?.address ?? ''}\n showHeader={false}\n setCurrentContent={setCurrentContent}\n onLogout={() => {\n disconnect();\n onLogoutSuccess?.();\n }}\n />\n </VStack>\n </ModalBody>\n <ModalFooter w=\"full\">\n <HStack w=\"full\" justify=\"space-between\" spacing={4} mt={4}>\n <Button\n size=\"md\"\n width=\"full\"\n height=\"40px\"\n variant=\"vechainKitSecondary\"\n leftIcon={\n hasAnyBalance ? undefined : (\n <Icon as={LuWalletCards} />\n )\n }\n onClick={() => setCurrentContent('main')}\n data-testid=\"wallet-button\"\n >\n {hasAnyBalance ? (\n <HStack spacing={2} w=\"full\" justify=\"center\">\n <AssetIcons\n address={account?.address ?? ''}\n maxIcons={2}\n />\n <Text fontWeight=\"600\">\n {showAssets\n ? formattedBalance\n : formattedBalance[0] +\n '*'.repeat(formattedBalance.slice(1).length)}\n </Text>\n </HStack>\n ) : (\n t('Wallet')\n )}\n </Button>\n\n {/* In VeWorld mobile we call switchWallet\n on the desktop we call setCurrentContent to select-wallet\n otherwise we show logout button\n */}\n {(connection.isInAppBrowser && isSwitchWalletEnabled) ||\n (!connection.isInAppBrowser &&\n connection.isConnectedWithDappKit) ? (\n <Button\n size=\"md\"\n width=\"full\"\n height=\"40px\"\n variant=\"vechainKitSecondary\"\n leftIcon={<Icon as={LuArrowLeftRight} />}\n colorScheme=\"red\"\n onClick={async () => {\n handleSwitchWallet();\n }}\n isLoading={isSwitching}\n isDisabled={isSwitching}\n data-testid=\"switch-wallet-button\"\n >\n {t('Switch')}\n </Button>\n ) : (\n <Button\n size=\"md\"\n width=\"full\"\n height=\"40px\"\n variant=\"vechainKitSecondary\"\n leftIcon={<Icon as={LuLogOut} />}\n colorScheme=\"red\"\n onClick={() =>\n setCurrentContent({\n type: 'disconnect-confirm',\n props: {\n onDisconnect: () => {\n disconnect();\n onLogoutSuccess?.();\n },\n onBack: () =>\n setCurrentContent?.('profile'),\n },\n })\n }\n data-testid=\"logout-button\"\n >\n {t('Logout')}\n </Button>\n )}\n </HStack>\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalHeader,\n ModalBody,\n ModalFooter,\n Text,\n VStack,\n Alert,\n AlertIcon,\n AlertTitle,\n AlertDescription,\n Box,\n ModalCloseButton,\n Button,\n HStack,\n Circle,\n Image,\n Heading,\n Icon,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport {\n ModalBackButton,\n StickyHeaderContainer,\n TransactionButtonAndStatus,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useUpgradeRequired, useUpgradeSmartAccount, useWallet } from '@/hooks';\nimport { LuArrowRight } from 'react-icons/lu';\n\nexport type UpgradeSmartAccountContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n handleClose?: () => void;\n initialContent?: AccountModalContentTypes;\n};\n\nexport const UpgradeSmartAccountContent = ({\n setCurrentContent,\n handleClose,\n initialContent = 'settings',\n}: UpgradeSmartAccountContentProps) => {\n const { t } = useTranslation();\n const { smartAccount, connectedWallet } = useWallet();\n const { data: upgradeRequired } = useUpgradeRequired(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n\n // Set up the upgrade transaction\n const {\n sendTransaction: upgradeSmartAccount,\n isTransactionPending,\n isWaitingForWalletConfirmation,\n error: upgradeError,\n txReceipt,\n } = useUpgradeSmartAccount({\n smartAccountAddress: smartAccount?.address ?? '',\n targetVersion: 3,\n onSuccess: () => {\n setCurrentContent({\n type: 'successful-operation',\n props: {\n setCurrentContent,\n txId: txReceipt?.meta.txID,\n title: t('Upgrade Successful!'),\n description: t(\n 'Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.',\n ),\n onDone: () => {\n if (handleClose) {\n handleClose();\n } else {\n setCurrentContent(initialContent);\n }\n },\n showSocialButtons: false,\n },\n });\n },\n onError: () => {\n console.error('Error upgrading Smart Account');\n },\n });\n\n // Handle the upgrade process\n const handleUpgrade = async () => {\n try {\n await upgradeSmartAccount();\n } catch (err) {\n console.error('Failed to upgrade Smart Account:', err);\n }\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Account upgrade required')}</ModalHeader>\n <ModalBackButton\n onClick={() => {\n setCurrentContent(initialContent);\n }}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={10} align=\"stretch\">\n <Text fontSize=\"sm\" textAlign=\"center\">\n {upgradeRequired\n ? t(\n 'Your smart account needs to be upgraded to the latest version (v3).',\n )\n : t(\n 'Your smart account is already upgraded to this version.',\n )}\n </Text>\n\n <HStack\n align=\"center\"\n justifyContent=\"space-evenly\"\n rounded=\"md\"\n >\n <Box position=\"relative\" display=\"inline-block\">\n <Circle size=\"60px\" bg=\"gray.200\">\n <Image\n borderRadius=\"full\"\n src={smartAccount?.image}\n alt={t('Profile Picture')}\n w=\"100%\"\n h=\"100%\"\n objectFit=\"cover\"\n />\n </Circle>\n\n <Heading\n position=\"absolute\"\n top=\"-5\"\n right=\"-5\"\n color=\"#D23F63\"\n fontSize=\"28px\"\n >\n {`v1`}\n </Heading>\n </Box>\n\n <Icon as={LuArrowRight} color=\"#3DBA67\" />\n\n <Box position=\"relative\" display=\"inline-block\">\n <Circle size=\"60px\" bg=\"gray.200\">\n <Image\n borderRadius=\"full\"\n src={smartAccount?.image}\n alt={t('Profile Picture')}\n w=\"100%\"\n h=\"100%\"\n objectFit=\"cover\"\n />\n </Circle>\n <Heading\n position=\"absolute\"\n top=\"-5\"\n right=\"-5\"\n color=\"#3DBA67\"\n fontSize=\"28px\"\n >\n {`v3`}\n </Heading>\n </Box>\n </HStack>\n\n <Alert status=\"info\" borderRadius=\"md\">\n <AlertIcon />\n <Box>\n <AlertTitle fontSize=\"sm\">\n {t('Benefits of this upgrade:')}\n </AlertTitle>\n <AlertDescription fontSize=\"xs\">\n <VStack align=\"start\" spacing={0} mt={1}>\n <Text fontSize=\"xs\" lineHeight=\"1.2\">\n • {t('Improved security features')}\n </Text>\n <Text fontSize=\"xs\">\n • {t('Better transaction handling')}\n </Text>\n <Text fontSize=\"xs\">\n •{' '}\n {t('Enhanced compatibility with dApps')}\n </Text>\n <Text fontSize=\"xs\">\n •{' '}\n {t('Reduced gas costs for operations')}\n </Text>\n </VStack>\n </AlertDescription>\n </Box>\n </Alert>\n </VStack>\n </ModalBody>\n\n <ModalFooter justifyContent=\"center\">\n <VStack spacing={3} w=\"full\">\n <TransactionButtonAndStatus\n buttonText={\n upgradeRequired\n ? t('Upgrade account')\n : t('Account already upgraded')\n }\n onConfirm={handleUpgrade}\n isTxWaitingConfirmation={isWaitingForWalletConfirmation}\n isSubmitting={isTransactionPending}\n transactionPendingText={t('Upgrading...')}\n txReceipt={txReceipt}\n transactionError={upgradeError}\n isDisabled={!upgradeRequired}\n />\n\n <Button\n mt={2}\n variant={'link'}\n onClick={() => {\n if (handleClose) {\n handleClose();\n } else {\n setCurrentContent(initialContent);\n }\n }}\n isDisabled={isTransactionPending}\n >\n {upgradeRequired\n ? t('Close and do this later')\n : t('Close')}\n </Button>\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import {\n Button,\n Container,\n Icon,\n Input,\n InputGroup,\n InputLeftElement,\n ModalBody,\n ModalCloseButton,\n ModalFooter,\n ModalHeader,\n VStack,\n useToken,\n} from '@chakra-ui/react';\nimport { useWallet, useTokensWithValues, TokenWithValue } from '@/hooks';\nimport {\n AssetButton,\n ModalBackButton,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useTranslation } from 'react-i18next';\nimport { LuPencil } from 'react-icons/lu';\nimport { AccountModalContentTypes } from '../../Types';\nimport { LuSearch } from 'react-icons/lu';\nimport { useState } from 'react';\nimport { useCurrency } from '@/hooks';\nimport { SupportedCurrency } from '@/utils/currencyUtils';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\nexport type AssetsContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const AssetsContent = ({ setCurrentContent }: AssetsContentProps) => {\n const { account } = useWallet();\n const { sortedTokens } = useTokensWithValues({ address: account?.address });\n const { allowCustomTokens, darkMode } = useVeChainKitConfig();\n const { currentCurrency } = useCurrency();\n \n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const { t } = useTranslation();\n const { isolatedView } = useAccountModalOptions();\n const [searchQuery, setSearchQuery] = useState('');\n\n const handleTokenSelect = (token: TokenWithValue) => {\n setCurrentContent({\n type: 'send-token',\n props: {\n setCurrentContent,\n preselectedToken: token,\n onBack: () => setCurrentContent('assets'),\n },\n });\n };\n\n // Filter tokens by search query\n const filteredTokens = sortedTokens.filter(({ symbol }) =>\n symbol.toLowerCase().includes(searchQuery.toLowerCase()),\n );\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Assets')}</ModalHeader>\n {!isolatedView && (\n <ModalBackButton\n onClick={() => setCurrentContent('main')}\n />\n )}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container h={['540px', 'auto']} p={0}>\n <ModalBody>\n <InputGroup size=\"lg\">\n <Input\n placeholder=\"Search token\"\n bg={darkMode ? '#00000038' : 'gray.50'}\n borderRadius=\"xl\"\n height=\"56px\"\n pl={12}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n data-testid=\"search-token-input\"\n />\n <InputLeftElement h=\"56px\" w=\"56px\" pl={4}>\n <LuSearch\n color={textTertiary}\n />\n </InputLeftElement>\n </InputGroup>\n\n <VStack spacing={2} align=\"stretch\" mt={2}>\n {filteredTokens.map((token) => {\n const hasBalance = Number(token.balance) > 0;\n\n return (\n <AssetButton\n key={token.address}\n symbol={token.symbol}\n amount={Number(token.balance)}\n currencyValue={token.valueInCurrency}\n currentCurrency={\n currentCurrency as SupportedCurrency\n }\n onClick={() => handleTokenSelect(token)}\n isDisabled={!hasBalance}\n />\n );\n })}\n </VStack>\n </ModalBody>\n <ModalFooter>\n {allowCustomTokens && (\n <Button\n variant=\"vechainKitSecondary\"\n leftIcon={<Icon as={LuPencil} boxSize={4} />}\n onClick={() =>\n setCurrentContent('add-custom-token')\n }\n >\n {t('Manage Custom Tokens')}\n </Button>\n )}\n </ModalFooter>\n </Container>\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Input,\n Button,\n Text,\n Box,\n HStack,\n ModalFooter,\n FormControl,\n FormLabel,\n Image,\n useToken,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { useForm } from 'react-hook-form';\nimport { useCustomTokens } from '@/hooks/api/wallet/useCustomTokens';\nimport { humanAddress, TOKEN_LOGOS } from '@/utils';\nimport { LuTrash2 } from 'react-icons/lu';\n\nexport type ManageCustomTokenContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\n// Add form values type\ntype FormValues = {\n newTokenAddress: string;\n};\n\nexport const ManageCustomTokenContent = ({\n setCurrentContent,\n}: ManageCustomTokenContentProps) => {\n const { t } = useTranslation();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const backgroundCard = useToken('colors', 'vechain-kit-card');\n const backgroundOverlay = useToken('colors', 'vechain-kit-overlay');\n\n const {\n addToken,\n removeToken,\n isTokenIncluded,\n isDefaultToken,\n customTokens,\n } = useCustomTokens();\n\n // Form setup with validation rules\n const {\n register,\n setError,\n setValue,\n formState: { errors, isValid },\n handleSubmit,\n } = useForm<FormValues>({\n defaultValues: {\n newTokenAddress: '',\n },\n mode: 'onChange',\n });\n\n const onSubmit = async (data: FormValues) => {\n if (!data.newTokenAddress) return;\n\n if (\n isTokenIncluded(data.newTokenAddress) ||\n isDefaultToken(data.newTokenAddress)\n ) {\n return setError('newTokenAddress', {\n type: 'manual',\n message: t('Token already added'),\n });\n }\n\n try {\n await addToken(data.newTokenAddress);\n setValue('newTokenAddress', ''); // Clear the input after successful addition\n } catch (error) {\n console.error('Error adding token 2:', error);\n setError('newTokenAddress', {\n type: 'manual',\n message: t('Invalid token address'),\n });\n }\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Manage Custom Tokens')}</ModalHeader>\n <ModalBackButton onClick={() => setCurrentContent('assets')} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={4} align=\"stretch\" position=\"relative\">\n {/* Input Section */}\n <Box p={6} borderRadius=\"xl\" bg={backgroundCard}>\n <VStack align=\"stretch\" spacing={2}>\n <FormControl isInvalid={!!errors.newTokenAddress}>\n <FormLabel\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {t('Token Contract Address')}\n </FormLabel>\n <Input\n {...register('newTokenAddress', {\n required: t('Address is required'),\n pattern: {\n value: /^0x[a-fA-F0-9]{40}$/,\n message: t(\n 'Please enter a valid contract address',\n ),\n },\n validate: (value) =>\n /^0x[a-fA-F0-9]{40}$/.test(value) ||\n t('Invalid contract address'),\n })}\n onChange={(e) => {\n const trimmed = e.target.value.trim();\n e.target.value = trimmed;\n setValue('newTokenAddress', trimmed, {\n shouldValidate: true,\n });\n }}\n placeholder=\"0x...\"\n variant=\"outline\"\n fontSize=\"md\"\n fontWeight=\"medium\"\n />\n {errors.newTokenAddress && (\n <Text color=\"#ef4444\" fontSize=\"sm\">\n {errors.newTokenAddress.message}\n </Text>\n )}\n </FormControl>\n </VStack>\n </Box>\n\n {/* Existing Tokens List */}\n {customTokens.length > 0 && (\n <Box p={4} borderRadius=\"xl\" bg={backgroundOverlay}>\n <Text fontSize=\"sm\" fontWeight=\"medium\" mb={2}>\n {t('Existing Custom Tokens')}\n </Text>\n <VStack align=\"stretch\" spacing={2}>\n {customTokens.map((token) => (\n <HStack\n key={token.address}\n justify=\"space-between\"\n fontSize=\"sm\"\n p={2}\n borderRadius=\"md\"\n bg={backgroundCard}\n >\n <HStack>\n <Image\n src={TOKEN_LOGOS[token?.symbol]}\n alt={`${token.symbol} logo`}\n boxSize=\"20px\"\n borderRadius=\"full\"\n fallback={\n <Box\n boxSize=\"20px\"\n borderRadius=\"full\"\n bg=\"whiteAlpha.200\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Text\n fontSize=\"8px\"\n fontWeight=\"bold\"\n color={textPrimary}\n >\n {token.symbol?.slice(\n 0,\n 3,\n )}\n </Text>\n </Box>\n }\n />\n <Text\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {token.symbol ?? 'Unknown'}\n </Text>\n </HStack>\n <Text color={textSecondary}>\n {humanAddress(\n token.address ?? '',\n 4,\n 4,\n )}\n </Text>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n color={textPrimary}\n borderRadius=\"md\"\n p={2}\n onClick={() =>\n removeToken(token.address)\n }\n >\n <LuTrash2\n size={16}\n color={textPrimary}\n />\n </Button>\n </HStack>\n ))}\n </VStack>\n </Box>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <Button\n variant=\"vechainKitPrimary\"\n isDisabled={!isValid}\n onClick={handleSubmit(onSubmit)}\n >\n {t('Add Token')}\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import {\n Container,\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n ModalFooter,\n Button,\n Icon,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { LuExternalLink } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { VechainEnergy } from '@/assets';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\nimport { VECHAIN_ENERGY_SWAP_BASE_URL } from '@/constants';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const BridgeContent = ({ setCurrentContent }: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { isolatedView } = useAccountModalOptions();\n\n const handleLaunchVeChainEnergy = () => {\n window.open(VECHAIN_ENERGY_SWAP_BASE_URL, '_blank');\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Bridge')}</ModalHeader>\n {!isolatedView && (\n <ModalBackButton onClick={() => setCurrentContent('main')} />\n )}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container maxW={'container.lg'}>\n <ModalBody>\n <VStack spacing={6} align=\"center\" w=\"full\">\n <VechainEnergy isDark={isDark} borderRadius={'xl'} />\n\n <Text fontSize=\"sm\" textAlign=\"center\">\n {t(\n 'Exchange your digital assets between VeChain and other blockchain networks easily and securely. Swaps are executed through partners that leverage both decentralized and centralized exchanges to convert tokens.',\n )}\n </Text>\n </VStack>\n </ModalBody>\n </Container>\n\n <ModalFooter>\n <Button\n variant=\"vechainKitSecondary\"\n onClick={handleLaunchVeChainEnergy}\n >\n {t('Launch vechain.energy')}\n <Icon as={LuExternalLink} ml={2} />\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Button,\n ModalFooter,\n Text,\n Icon,\n HStack,\n useColorModeValue,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { CURRENCY, CURRENCY_SYMBOLS } from '@/types';\nimport { useCurrency } from '@/hooks';\nimport { LuCheck } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { useEffect } from 'react';\nimport { setLocalStorageItem } from '@/utils/ssrUtils';\n\nexport type ChangeCurrencyContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const ChangeCurrencyContent = ({\n setCurrentContent,\n}: ChangeCurrencyContentProps) => {\n const { t } = useTranslation();\n const { currentCurrency, changeCurrency, allCurrencies } = useCurrency();\n const selectedBg = useColorModeValue(\n 'rgba(0, 0, 0, 0.1)',\n 'rgba(255, 255, 255, 0.05)',\n );\n\n useEffect(() => {\n // Ensure we mark the currency settings as visited when this component mounts\n setLocalStorageItem('settings-currency-visited', 'true');\n }, []);\n\n const renderCurrencyButton = (currency: CURRENCY) => {\n const isSelected = currentCurrency === currency;\n return (\n <Button\n key={currency}\n w=\"full\"\n variant=\"ghost\"\n justifyContent=\"space-between\"\n onClick={() => changeCurrency(currency)}\n py={6}\n px={4}\n bg={isSelected ? selectedBg : undefined}\n >\n <HStack spacing={3}>\n <Text fontSize=\"xl\">{CURRENCY_SYMBOLS[currency]}</Text>\n <Text>{currency.toUpperCase()}</Text>\n </HStack>\n {isSelected && (\n <Icon as={LuCheck} boxSize={5} color=\"blue.500\" />\n )}\n </Button>\n );\n };\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Select currency')}</ModalHeader>\n <ModalBackButton\n onClick={() => setCurrentContent('settings')}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n <ModalBody w={'full'}>\n <VStack\n justify={'center'}\n spacing={3}\n align=\"flex-start\"\n w={'full'}\n >\n {allCurrencies.map((cur) => renderCurrencyButton(cur))}\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n VStack,\n ModalFooter,\n ModalHeader,\n Text,\n Button,\n Icon,\n useColorModeValue,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { languageNames, supportedLanguages } from '../../../../../i18n';\nimport { LuCheck } from 'react-icons/lu';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const LanguageSettingsContent = ({ setCurrentContent }: Props) => {\n const { t, i18n } = useTranslation();\n const selectedBg = useColorModeValue(\n 'rgba(0, 0, 0, 0.1)',\n 'rgba(255, 255, 255, 0.05)',\n );\n\n const handleLanguageChange = (lang: string) => {\n i18n.changeLanguage(lang);\n };\n\n const renderLanguageButton = (lang: string) => {\n const isSelected = i18n.language === lang;\n return (\n <Button\n key={lang}\n w=\"full\"\n variant=\"ghost\"\n justifyContent=\"space-between\"\n onClick={() => handleLanguageChange(lang)}\n py={6}\n px={4}\n bg={isSelected ? selectedBg : undefined}\n >\n <Text>{languageNames[lang as keyof typeof languageNames]}</Text>\n {isSelected && (\n <Icon as={LuCheck} boxSize={5} color=\"blue.500\" />\n )}\n </Button>\n );\n };\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Select language')}</ModalHeader>\n\n <ModalBackButton\n onClick={() => setCurrentContent('settings')}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack\n justify={'center'}\n spacing={3}\n align=\"flex-start\"\n w={'full'}\n >\n {supportedLanguages.map((lang: string) =>\n renderLanguageButton(lang),\n )}\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n};\n","import { useState, useRef } from 'react';\nimport {\n Box,\n HStack,\n VStack,\n Text,\n Switch,\n Icon,\n useToken,\n} from '@chakra-ui/react';\nimport { LuGripVertical } from 'react-icons/lu';\nimport { GasTokenType } from '@/types/gasToken';\nimport { SUPPORTED_GAS_TOKENS } from '@/utils/constants';\nimport { useVeChainKitConfig } from '@/providers';\n\ninterface DragListProps {\n tokens: GasTokenType[];\n excludedTokens: GasTokenType[];\n onReorder: (newOrder: GasTokenType[]) => void;\n onToggleExclusion: (token: GasTokenType) => void;\n}\n\ninterface TokenItemProps {\n token: GasTokenType;\n index: number;\n isExcluded: boolean;\n onToggleExclusion: (token: GasTokenType) => void;\n onDragStart: (index: number) => void;\n onDragOver: (index: number) => void;\n onDrop: (index: number) => void;\n onTouchStart: (index: number, event: React.TouchEvent) => void;\n onTouchMove: (event: React.TouchEvent) => void;\n onTouchEnd: () => void;\n isDragging: boolean;\n isDraggedOver: boolean;\n}\n\nconst TokenPriorityItem = ({\n token,\n index,\n isExcluded,\n onToggleExclusion,\n onDragStart,\n onDragOver,\n onDrop,\n onTouchStart,\n onTouchMove,\n onTouchEnd,\n isDragging,\n isDraggedOver,\n}: TokenItemProps) => {\n const tokenInfo = SUPPORTED_GAS_TOKENS[token];\n const { darkMode: isDark } = useVeChainKitConfig();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const cardBg = useToken('colors', 'vechain-kit-card');\n\n return (\n <Box\n bg={isDark ? '#ffffff0a' : 'blackAlpha.50'}\n borderRadius=\"md\"\n border=\"1px\"\n borderColor={\n isDragging\n ? isDark\n ? 'blue.500'\n : 'blue.300'\n : isDraggedOver\n ? isDark\n ? 'blue.400'\n : 'blue.200'\n : cardBg\n }\n p={3}\n mb={2}\n opacity={isDragging ? 0.5 : isExcluded ? 0.5 : 1}\n cursor=\"move\"\n transition=\"background-color 0.2s ease, border-color 0.2s ease\"\n draggable\n onDragStart={() => onDragStart(index)}\n onDragOver={(e) => {\n e.preventDefault();\n onDragOver(index);\n }}\n onDrop={() => onDrop(index)}\n onTouchStart={(e) => onTouchStart(index, e)}\n onTouchMove={onTouchMove}\n onTouchEnd={onTouchEnd}\n _hover={{\n backgroundColor: isDark ? '#ffffff12' : 'blackAlpha.200',\n }}\n >\n <HStack justify=\"space-between\">\n <HStack opacity={isExcluded ? 0.5 : 1}>\n <Box\n cursor=\"grab\"\n _active={{ cursor: 'grabbing' }}\n pointerEvents=\"none\"\n >\n <Icon as={LuGripVertical} color={textSecondary} />\n </Box>\n <VStack align=\"start\" spacing={0}>\n <Text fontWeight=\"medium\" color={textPrimary}>\n {tokenInfo.name}\n </Text>\n <Text fontSize=\"sm\" color={textSecondary}>\n {tokenInfo.description}\n </Text>\n </VStack>\n </HStack>\n <Switch\n isChecked={!isExcluded}\n onChange={() => onToggleExclusion(token)}\n colorScheme=\"blue\"\n size=\"sm\"\n />\n </HStack>\n </Box>\n );\n};\n\nexport const GasTokenDragList = ({\n tokens,\n excludedTokens,\n onReorder,\n onToggleExclusion,\n}: DragListProps) => {\n const [draggedIndex, setDraggedIndex] = useState<number | null>(null);\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);\n const itemRefs = useRef<(HTMLDivElement | null)[]>([]);\n const touchStartY = useRef<number>(0);\n\n const handleDragStart = (index: number) => {\n setDraggedIndex(index);\n };\n\n const handleDragOver = (index: number) => {\n setDragOverIndex(index);\n };\n\n const handleDrop = (dropIndex: number) => {\n if (draggedIndex === null || draggedIndex === dropIndex) {\n setDraggedIndex(null);\n setDragOverIndex(null);\n return;\n }\n\n const newOrder = [...tokens];\n const draggedToken = newOrder[draggedIndex];\n newOrder.splice(draggedIndex, 1);\n newOrder.splice(dropIndex, 0, draggedToken);\n\n onReorder(newOrder);\n setDraggedIndex(null);\n setDragOverIndex(null);\n };\n\n // Touch event handlers for mobile support\n const handleTouchStart = (index: number, event: React.TouchEvent) => {\n touchStartY.current = event.touches[0].clientY;\n setDraggedIndex(index);\n };\n\n const handleTouchMove = (event: React.TouchEvent) => {\n if (draggedIndex === null) return;\n\n const touch = event.touches[0];\n const currentY = touch.clientY;\n\n // Find which item is under the current touch position\n for (let i = 0; i < itemRefs.current.length; i++) {\n const element = itemRefs.current[i];\n if (!element) continue;\n\n const rect = element.getBoundingClientRect();\n if (currentY >= rect.top && currentY <= rect.bottom) {\n setDragOverIndex(i);\n break;\n }\n }\n };\n\n const handleTouchEnd = () => {\n if (\n draggedIndex !== null &&\n dragOverIndex !== null &&\n draggedIndex !== dragOverIndex\n ) {\n const newOrder = [...tokens];\n const draggedToken = newOrder[draggedIndex];\n newOrder.splice(draggedIndex, 1);\n newOrder.splice(dragOverIndex, 0, draggedToken);\n onReorder(newOrder);\n }\n\n setDraggedIndex(null);\n setDragOverIndex(null);\n touchStartY.current = 0;\n };\n\n return (\n <Box w=\"full\">\n {tokens.map((token, index) => (\n <Box\n key={token}\n ref={(el) => {\n itemRefs.current[index] = el;\n }}\n >\n <TokenPriorityItem\n token={token}\n index={index}\n isExcluded={excludedTokens.includes(token)}\n onToggleExclusion={onToggleExclusion}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n isDragging={draggedIndex === index}\n isDraggedOver={dragOverIndex === index}\n />\n </Box>\n ))}\n </Box>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n VStack,\n ModalHeader,\n Text,\n Alert,\n AlertIcon,\n AlertDescription,\n useToken,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useGasTokenSelection } from '@/hooks';\nimport { GasTokenType } from '@/types/gasToken';\nimport { GasTokenDragList } from './GasTokenDragList';\nimport { useCallback } from 'react';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const GasTokenSettingsContent = ({ setCurrentContent }: Props) => {\n const { t } = useTranslation();\n const { preferences, reorderTokenPriority, toggleTokenExclusion } =\n useGasTokenSelection();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const handleReorder = useCallback(\n (newOrder: GasTokenType[]) => {\n reorderTokenPriority(newOrder);\n },\n [reorderTokenPriority],\n );\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Gas Token Preferences')}</ModalHeader>\n <ModalBackButton\n onClick={() => setCurrentContent('settings')}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w=\"full\">\n <VStack\n justify=\"center\"\n spacing={6}\n align=\"flex-start\"\n w=\"full\"\n >\n <VStack w=\"full\" justifyContent=\"center\" spacing={3} mb={3}>\n <Text\n fontSize=\"sm\"\n color={textSecondary}\n textAlign=\"center\"\n >\n {t(\n 'Choose which tokens to use for transaction fees when the app is not covering them.',\n )}\n </Text>\n </VStack>\n\n {/* Warning when all tokens are disabled */}\n {preferences.availableGasTokens.length === 0 && (\n <Alert status=\"warning\" borderRadius=\"md\">\n <AlertIcon />\n <AlertDescription\n fontSize=\"sm\"\n color={textSecondary}\n >\n {t(\n 'You must enable at least one token to perform transactions. Without any enabled tokens, you will not be able to pay for gas fees.' as any,\n )}\n </AlertDescription>\n </Alert>\n )}\n\n {/* Token Priority List */}\n <VStack w=\"full\" align=\"start\" spacing={3}>\n <Text\n fontSize=\"md\"\n fontWeight=\"semibold\"\n color={textPrimary}\n >\n {t('Token Priority Order')}\n </Text>\n <Text fontSize=\"sm\" color={textSecondary}>\n {t(\n 'Drag to reorder. The system will automatically use the highest priority token with sufficient balance.',\n )}\n </Text>\n\n <GasTokenDragList\n tokens={preferences.tokenPriority}\n excludedTokens={preferences.excludedTokens}\n onReorder={handleReorder}\n onToggleExclusion={toggleTokenExclusion}\n />\n </VStack>\n </VStack>\n </ModalBody>\n </ScrollToTopWrapper>\n );\n};\n","import {\n ModalBody,\n VStack,\n ModalFooter,\n ModalHeader,\n Box,\n ModalCloseButton,\n Text,\n useToken,\n} from '@chakra-ui/react';\nimport {\n useMfaEnrollment,\n usePrivy,\n useUpgradeRequired,\n useWallet,\n} from '@/hooks';\nimport {\n LuChevronRight,\n LuCircleHelp,\n LuShield,\n LuLogOut,\n LuDollarSign,\n LuLanguages,\n LuFuel,\n LuLayoutGrid,\n LuUserCog,\n LuKey,\n LuShieldCheck,\n LuSettings2,\n LuFingerprint,\n} from 'react-icons/lu';\nimport { ActionButton } from '@/components';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { LuUnlink } from 'react-icons/lu';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\nimport { useVeChainKitConfig } from '@/providers';\n\nexport type SettingsContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onLogoutSuccess: () => void;\n};\n\nexport const SettingsContent = ({\n setCurrentContent,\n onLogoutSuccess,\n}: SettingsContentProps) => {\n const { t } = useTranslation();\n const { isolatedView } = useAccountModalOptions();\n\n const { exportWallet, linkPasskey } = usePrivy();\n const { showMfaEnrollmentModal } = useMfaEnrollment();\n\n const { feeDelegation } = useVeChainKitConfig();\n\n const { connection, disconnect, smartAccount, connectedWallet } =\n useWallet();\n\n const { data: upgradeRequired } = useUpgradeRequired(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n\n const handleUpgradeSmartAccountClick = () => {\n setCurrentContent({\n type: 'upgrade-smart-account',\n props: {\n setCurrentContent,\n initialContent: 'settings',\n },\n });\n };\n\n const handleConnectionDetails = () => {\n setCurrentContent('connection-details');\n };\n\n const handleLogout = () => {\n disconnect();\n onLogoutSuccess();\n };\n\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const handleCurrencyClick = () => {\n setCurrentContent('change-currency');\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Settings')}</ModalHeader>\n\n {!isolatedView && (\n <ModalBackButton\n onClick={() => setCurrentContent('profile')}\n />\n )}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack w={'full'} spacing={2}>\n <Text\n fontSize={'sm'}\n fontWeight={'bold'}\n color={textSecondary}\n textAlign={'left'}\n w={'full'}\n >\n {t('General')}\n </Text>\n\n <ActionButton\n title={t('Currency')}\n onClick={handleCurrencyClick}\n leftIcon={LuDollarSign}\n rightIcon={LuChevronRight}\n />\n\n <ActionButton\n title={t('Language')}\n onClick={() => {\n setCurrentContent('change-language');\n }}\n leftIcon={LuLanguages}\n rightIcon={LuChevronRight}\n />\n\n {connection.isConnectedWithPrivy &&\n !feeDelegation?.delegatorUrl && (\n <ActionButton\n title={t('Gas Token Preferences')}\n onClick={() => {\n setCurrentContent('gas-token-settings');\n }}\n leftIcon={LuFuel}\n rightIcon={LuChevronRight}\n />\n )}\n\n <ActionButton\n title={t('Terms and Policies')}\n onClick={() => {\n setCurrentContent({\n type: 'terms-and-privacy',\n props: {\n onGoBack: () =>\n setCurrentContent('settings'),\n },\n });\n }}\n leftIcon={LuShield}\n rightIcon={LuChevronRight}\n />\n\n <ActionButton\n title={t('Logout')}\n onClick={() =>\n setCurrentContent({\n type: 'disconnect-confirm',\n props: {\n onDisconnect: handleLogout,\n onBack: () => setCurrentContent('settings'),\n },\n })\n }\n leftIcon={LuLogOut}\n />\n </VStack>\n\n {upgradeRequired && (\n <VStack w={'full'} spacing={2} mt={4}>\n <ActionButton\n title={t('Upgrade Smart Account to V3')}\n description={t(\n 'A new version is available for your account',\n )}\n onClick={handleUpgradeSmartAccountClick}\n leftIcon={LuSettings2}\n extraContent={\n <Box\n minWidth=\"8px\"\n height=\"8px\"\n bg=\"red.500\"\n borderRadius=\"full\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n ml={2}\n />\n }\n />\n </VStack>\n )}\n\n {connection.isConnectedWithSocialLogin && (\n <VStack w={'full'} spacing={2} mt={4}>\n <Text\n fontSize={'sm'}\n fontWeight={'bold'}\n color={textSecondary}\n textAlign={'left'}\n w={'full'}\n >\n {t('Access and security')}\n </Text>\n <ActionButton\n title={t('Passkey')}\n onClick={() => linkPasskey()}\n leftIcon={LuFingerprint}\n />\n\n <ActionButton\n title={t('Backup')}\n onClick={() => {\n exportWallet();\n }}\n leftIcon={LuKey}\n />\n\n <ActionButton\n title={t('Manage MFA')}\n onClick={() => {\n showMfaEnrollmentModal();\n }}\n leftIcon={LuShieldCheck}\n />\n\n <ActionButton\n title={t('Login methods')}\n onClick={() => {\n setCurrentContent('privy-linked-accounts');\n }}\n leftIcon={LuUserCog}\n rightIcon={LuChevronRight}\n />\n </VStack>\n )}\n\n <VStack w={'full'} spacing={2} mt={4}>\n <Text\n fontSize={'sm'}\n fontWeight={'bold'}\n color={textSecondary}\n textAlign={'left'}\n w={'full'}\n >\n {t('Help')}\n </Text>\n\n <ActionButton\n title={t('Connection details')}\n onClick={handleConnectionDetails}\n leftIcon={LuUnlink}\n rightIcon={LuChevronRight}\n />\n\n <ActionButton\n title={t('Explore ecosystem')}\n onClick={() => setCurrentContent('ecosystem')}\n leftIcon={LuLayoutGrid}\n rightIcon={LuChevronRight}\n />\n\n <ActionButton\n title={t('Frequently asked questions')}\n onClick={() =>\n setCurrentContent({\n type: 'faq',\n props: {\n onGoBack: () =>\n setCurrentContent('settings'),\n showLanguageSelector: false,\n },\n })\n }\n leftIcon={LuCircleHelp}\n rightIcon={LuChevronRight}\n />\n </VStack>\n </ModalBody>\n <ModalFooter p={0} />\n </>\n );\n};\n","import { VStack, Icon, Text, useToken } from '@chakra-ui/react';\nimport { ElementType } from 'react';\n\ntype Props = {\n title: string;\n description?: string;\n icon: ElementType;\n};\n\nexport const EmptyContent = ({ title, description, icon }: Props) => {\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n\n return (\n <VStack spacing={6} align=\"center\" py={8}>\n <Icon as={icon} boxSize={16} color={textSecondary} />\n <VStack spacing={2}>\n <Text\n fontSize=\"lg\"\n fontWeight=\"500\"\n textAlign=\"center\"\n color={textPrimary}\n >\n {title}\n </Text>\n <Text\n fontSize=\"md\"\n color={textSecondary}\n textAlign=\"center\"\n px={4}\n >\n {description}\n </Text>\n </VStack>\n </VStack>\n );\n};\n","export const formatDate = (timestamp: number, locale: string = 'en-US') => {\n //Return intl (Eg. Sep 15)\n\n return new Intl.DateTimeFormat(locale, {\n month: 'short',\n day: 'numeric',\n }).format(new Date(timestamp));\n};\n","import {\n LegalDocumentAgreement,\n LegalDocumentSource,\n LegalDocumentType,\n} from '@/types';\nimport { formatDate } from '@/utils/dateUtils';\nimport { HStack, Tag, Text, useToken } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\n\nexport const AcceptedPolicyItem = ({\n document,\n}: {\n document: LegalDocumentAgreement;\n}) => {\n const { t } = useTranslation();\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const isVechainKitTerms =\n document.documentSource === LegalDocumentSource.VECHAIN_KIT &&\n document.documentType === LegalDocumentType.TERMS;\n return (\n <HStack>\n <Tag size=\"sm\" borderRadius=\"full\" color={textSecondary}>\n v{document.version}\n </Tag>\n <Text\n fontSize=\"xs\"\n cursor=\"pointer\"\n color={textSecondary}\n onClick={() => {\n window.open(document.url, '_blank');\n }}\n _hover={{\n textDecoration: 'underline',\n }}\n >\n {isVechainKitTerms\n ? t(\"'{{policyName}}' on connect\", {\n policyName:\n document.displayName ?? t('Vechain Kit Policy'),\n })\n : t(\"'{{policyName}}' on {{date}}\", {\n policyName: document.displayName ?? t('Policy'),\n date: formatDate(document.timestamp),\n })}\n </Text>\n </HStack>\n );\n};\n","import {\n AccordionButton,\n AccordionItem,\n AccordionPanel,\n Button,\n HStack,\n Icon,\n Text,\n useToken,\n VStack,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { LuChevronDown, LuChevronUp, LuCheck } from 'react-icons/lu';\n\nimport { EnrichedLegalDocument, LegalDocumentAgreement } from '@/types';\nimport { formatDate } from '@/utils/dateUtils';\nimport { AcceptedPolicyItem } from './AcceptedPolicyItem';\n\ntype PolicyAccordionProps = {\n title: string;\n description: string;\n documents: LegalDocumentAgreement[];\n bg: string;\n hoverBg: string;\n currentPolicy?: EnrichedLegalDocument | undefined;\n};\n\nexport const PolicyAccordion = ({\n title,\n description,\n documents,\n bg,\n hoverBg,\n currentPolicy,\n}: PolicyAccordionProps) => {\n const { t } = useTranslation();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const hasDocuments = documents?.length > 0;\n\n const currentPolicyAgreement = documents?.find(\n (document) => document.id === currentPolicy?.id,\n );\n\n if (!hasDocuments) return null;\n\n return (\n <AccordionItem border=\"none\" mb={3}>\n {({ isExpanded }) => (\n <>\n <AccordionButton\n bg={bg}\n borderRadius=\"xl\"\n _hover={{\n bg: hoverBg,\n }}\n >\n <VStack w=\"full\" align=\"flex-start\" textAlign=\"left\">\n <Text fontWeight=\"700\" color={textPrimary}>\n {title}\n </Text>\n <Text fontSize=\"xs\" color={textSecondary}>\n {description}\n </Text>\n </VStack>\n <Icon\n as={isExpanded ? LuChevronUp : LuChevronDown}\n fontSize=\"20px\"\n color={textSecondary}\n />\n </AccordionButton>\n <AccordionPanel pb={4} pt={3}>\n <VStack align=\"stretch\" spacing={4}>\n {currentPolicyAgreement?.id ? (\n <HStack w=\"full\">\n <Icon as={LuCheck} color={textPrimary} />\n <Text fontSize=\"xs\" color={textSecondary}>\n {t(\n 'You accepted current policy on {{date}}',\n {\n date: formatDate(\n currentPolicyAgreement.timestamp,\n ),\n },\n )}\n </Text>\n </HStack>\n ) : null}\n\n <HStack w=\"full\" textAlign=\"left\">\n <Text\n fontSize=\"xs\"\n fontWeight=\"bold\"\n color={textSecondary}\n >\n {t('All policies you have accepted')}\n </Text>\n </HStack>\n\n <HStack w=\"full\" gap={2}>\n <VStack align=\"stretch\" spacing={2}>\n {documents.map((document) => (\n <AcceptedPolicyItem\n key={document.id}\n document={document}\n />\n ))}\n </VStack>\n </HStack>\n\n {currentPolicy && (\n <Button\n variant=\"outline\"\n size=\"xs\"\n alignSelf=\"flex-end\"\n onClick={() => {\n window.open(\n currentPolicy.url,\n '_blank',\n );\n }}\n >\n {t('View Current Policy')}\n </Button>\n )}\n </VStack>\n </AccordionPanel>\n </>\n )}\n </AccordionItem>\n );\n};\n","import { EmptyContent } from '@/components/common/EmptyContent';\nimport { useWallet } from '@/hooks';\nimport { useLegalDocuments, useVeChainKitConfig } from '@/providers';\nimport {\n LegalDocumentAgreement,\n LegalDocumentSource,\n LegalDocumentType,\n} from '@/types';\nimport { compareAddresses, VECHAIN_KIT_TERMS_CONFIG } from '@/utils';\nimport { Accordion, VStack } from '@chakra-ui/react';\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { LuGavel } from 'react-icons/lu';\n\nimport { PolicyAccordion } from './PolicyAccordion';\n\nexport const TermsAndPrivacyAccordion = () => {\n const { account } = useWallet();\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { agreements, documents } = useLegalDocuments();\n\n const agreementsByDocumentType = useMemo(() => {\n const userAgreements = agreements?.filter((agreement) =>\n compareAddresses(agreement.walletAddress, account?.address),\n );\n const vechainKitDefaultTerms: LegalDocumentAgreement = {\n id: 'vechain-kit-terms',\n ...VECHAIN_KIT_TERMS_CONFIG,\n documentType: LegalDocumentType.TERMS,\n documentSource: LegalDocumentSource.VECHAIN_KIT,\n walletAddress: account?.address ?? '',\n timestamp: new Date().getTime(),\n };\n\n const userAgreementsWithVechainKitTerms = [\n vechainKitDefaultTerms,\n ...userAgreements,\n ];\n\n return userAgreementsWithVechainKitTerms?.reduce((acc, agreement) => {\n acc[agreement.documentType] = [\n ...(acc[agreement.documentType] || []),\n agreement,\n ];\n return acc;\n }, {} as Record<LegalDocumentType, LegalDocumentAgreement[]>);\n }, [agreements, account?.address]);\n\n const latestDocumentsByType = useMemo(() => {\n return documents.reduce((acc, document) => {\n const docType = document.documentType;\n if (!acc[docType] || document.version > acc[docType].version) {\n acc[docType] = document;\n }\n return acc;\n }, {} as Record<LegalDocumentType, (typeof documents)[0]>);\n }, [documents]);\n\n const hasAgreements = useMemo(() => {\n return Object.values(agreementsByDocumentType).some(\n (agreements) => agreements.length > 0,\n );\n }, [agreementsByDocumentType]);\n\n const accordionBg = isDark ? 'whiteAlpha.50' : 'blackAlpha.50';\n const accordionHoverBg = isDark ? 'whiteAlpha.100' : 'blackAlpha.100';\n\n const defaultOpenIndices = useMemo(() => {\n const indices: number[] = [];\n\n if (agreementsByDocumentType[LegalDocumentType.TERMS]?.length > 0) {\n indices.push(0);\n }\n if (agreementsByDocumentType[LegalDocumentType.PRIVACY]?.length > 0) {\n indices.push(1);\n }\n if (agreementsByDocumentType[LegalDocumentType.COOKIES]?.length > 0) {\n indices.push(2);\n }\n\n return indices;\n }, [agreementsByDocumentType]);\n\n if (!hasAgreements) {\n return (\n <EmptyContent\n title={t('No policies accepted')}\n description={t(\n 'When you have accepted a policy, it will appear here',\n )}\n icon={LuGavel}\n />\n );\n }\n\n return (\n <VStack spacing={4} align=\"stretch\">\n <Accordion allowMultiple defaultIndex={defaultOpenIndices}>\n <PolicyAccordion\n title={t('Terms and Conditions')}\n description={t(\n 'Legal agreement between you, Vechain Kit and the current app, outlining the rules for using wallet services.',\n )}\n documents={\n agreementsByDocumentType[LegalDocumentType.TERMS]\n }\n bg={accordionBg}\n hoverBg={accordionHoverBg}\n currentPolicy={\n latestDocumentsByType[LegalDocumentType.TERMS]\n }\n />\n\n <PolicyAccordion\n title={t('Privacy Policy')}\n description={t(\n 'Privacy policy outlining the data collection and processing practices.',\n )}\n documents={\n agreementsByDocumentType[LegalDocumentType.PRIVACY]\n }\n bg={accordionBg}\n hoverBg={accordionHoverBg}\n currentPolicy={\n latestDocumentsByType[LegalDocumentType.PRIVACY]\n }\n />\n\n <PolicyAccordion\n title={t('Cookie Policy')}\n description={t(\n 'Cookie policy outlining the use of cookies and tracking technologies.',\n )}\n documents={\n agreementsByDocumentType[LegalDocumentType.COOKIES]\n }\n bg={accordionBg}\n hoverBg={accordionHoverBg}\n currentPolicy={\n latestDocumentsByType[LegalDocumentType.COOKIES]\n }\n />\n </Accordion>\n </VStack>\n );\n};\n","import {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport {\n ModalBody,\n ModalCloseButton,\n ModalFooter,\n ModalHeader,\n VStack,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\n\nimport { TermsAndPrivacyAccordion } from './TermsAndPrivacyAccordion';\n\nexport type TermsAndPrivacyContentProps = {\n onGoBack: () => void;\n};\n\nexport const TermsAndPrivacyContent = ({\n onGoBack,\n}: TermsAndPrivacyContentProps) => {\n const { t } = useTranslation();\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Terms and Policies')}</ModalHeader>\n <ModalBackButton onClick={onGoBack} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack spacing={6} align=\"stretch\">\n <TermsAndPrivacyAccordion />\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Button,\n Text,\n useToken,\n Icon,\n ModalFooter,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { LuLogOut } from 'react-icons/lu';\n\nexport type DisconnectConfirmContentProps = {\n onDisconnect: () => void;\n onBack: () => void;\n onClose?: () => void;\n text?: string;\n showCloseButton?: boolean;\n};\n\nexport const DisconnectConfirmContent = ({\n onDisconnect,\n onBack,\n onClose,\n showCloseButton = true,\n text,\n}: DisconnectConfirmContentProps) => {\n const { t } = useTranslation();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textTitle =\n text ?? t('Are you sure you want to disconnect your wallet?');\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Logout')}</ModalHeader>\n <ModalBackButton onClick={onBack} />\n {showCloseButton ? (\n <ModalCloseButton onClick={onClose} />\n ) : null}\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"center\" mt={10}>\n <Icon\n as={LuLogOut}\n color={'#ef4444'}\n fontSize={'60px'}\n opacity={0.5}\n />\n <Text fontSize=\"md\" textAlign=\"center\" color={textPrimary}>\n {textTitle}\n </Text>\n </VStack>\n </ModalBody>\n <ModalFooter w=\"full\" mt={4}>\n <VStack spacing={3} w=\"full\">\n <Button\n onClick={onDisconnect}\n data-testid=\"disconnect-button\"\n variant=\"vechainKitLogout\"\n >\n {t('Confirm')}\n </Button>\n <Button\n variant=\"vechainKitSecondary\"\n onClick={onBack}\n data-testid=\"cancel-logout-button\"\n >\n {t('Cancel')}\n </Button>\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import {\n Card,\n CardBody,\n HStack,\n VStack,\n Text,\n IconButton,\n Icon,\n useToken,\n Box,\n} from '@chakra-ui/react';\nimport { AccountAvatar } from '@/components/common';\nimport { humanAddress, humanDomain } from '@/utils';\nimport { useTotalBalance, useWalletMetadata } from '@/hooks';\nimport { StoredWallet } from '@/hooks/api/wallet/useWalletStorage';\nimport { LuTrash2, LuCheck } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\n\ntype Props = {\n wallet: StoredWallet;\n isActive: boolean;\n onSelect: () => void;\n onRemove: () => void;\n showRemove?: boolean;\n};\n\nexport const WalletCard = ({\n wallet,\n isActive,\n onSelect,\n onRemove,\n showRemove = true,\n}: Props) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const { formattedBalance, isLoading: isLoadingBalance } = useTotalBalance({\n address: wallet.address,\n });\n const {\n domain,\n image,\n isLoading: isLoadingMetadata,\n } = useWalletMetadata(wallet.address, network.type);\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const borderColor = useToken('colors', 'vechain-kit-border');\n\n const isLoading = isLoadingBalance || isLoadingMetadata;\n\n return (\n <Card\n variant=\"vechainKitWalletCard\"\n onClick={onSelect}\n borderWidth={isActive ? '2px' : '1px'}\n borderColor={isActive ? 'vechain-kit-primary' : borderColor}\n _hover={{\n borderColor: isActive\n ? 'vechain-kit-primary'\n : 'vechain-kit-text-secondary',\n }}\n >\n <CardBody p={4}>\n <HStack spacing={3} w=\"full\" justifyContent=\"space-between\">\n <HStack spacing={3} flex={1} minW={0}>\n <AccountAvatar\n wallet={{\n address: wallet.address,\n domain: domain ?? undefined,\n image: image ?? undefined,\n isLoadingMetadata,\n }}\n props={{ width: 10, height: 10 }}\n />\n <VStack\n spacing={0}\n alignItems=\"flex-start\"\n flex={1}\n minW={0}\n >\n <Text\n fontSize=\"sm\"\n fontWeight=\"medium\"\n color={textPrimary}\n noOfLines={1}\n >\n {domain\n ? humanDomain(domain, 22, 0)\n : humanAddress(wallet.address, 6, 4)}\n </Text>\n <Text\n fontSize=\"xs\"\n color={textSecondary}\n noOfLines={1}\n >\n {isLoading ? t('Loading...') : formattedBalance}\n </Text>\n </VStack>\n </HStack>\n {isActive && (\n <Box>\n <Icon\n as={LuCheck}\n boxSize={5}\n color=\"vechain-kit-primary\"\n />\n </Box>\n )}\n {showRemove && !isActive && (\n <IconButton\n aria-label={t('Remove wallet')}\n icon={<Icon as={LuTrash2} />}\n variant=\"vechainKitSecondary\"\n height=\"30px\"\n w=\"30px\"\n borderRadius=\"5px\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n />\n )}\n </HStack>\n </CardBody>\n </Card>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Button,\n Heading,\n useToken,\n ModalFooter,\n} from '@chakra-ui/react';\nimport { StickyHeaderContainer, ModalBackButton } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { WalletCard } from './Components/WalletCard';\nimport {\n useSwitchWallet,\n useWallet,\n useRefreshBalances,\n useDAppKitWallet,\n useDAppKitWalletModal,\n} from '@/hooks';\nimport { useWalletStorage } from '@/hooks/api/wallet/useWalletStorage';\nimport { useAccountModalOptions } from '@/hooks';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { StoredWallet } from '@/hooks/api/wallet/useWalletStorage';\nimport { LuLogOut, LuPlus } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { simpleHash } from '@/utils';\n\nconst hashWallets = (wallets: StoredWallet[]): string => {\n const addresses = wallets\n .map((w) => w.address.toLowerCase())\n .sort()\n .join('|');\n return simpleHash(addresses);\n};\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n onClose: () => void;\n returnTo?: 'main' | 'profile';\n onLogoutSuccess?: () => void;\n};\n\nexport const SelectWalletContent = ({\n setCurrentContent,\n returnTo = 'main',\n onLogoutSuccess: _onLogoutSuccess,\n}: Props) => {\n const { t } = useTranslation();\n const { isolatedView } = useAccountModalOptions();\n const { account, disconnect } = useWallet();\n const { disconnect: dappKitDisconnect } = useDAppKitWallet();\n const { open: openDappKitModal } = useDAppKitWalletModal();\n const { getStoredWallets, setActiveWallet, removeWallet } =\n useSwitchWallet();\n const { saveWallet } = useWalletStorage();\n const { refresh } = useRefreshBalances();\n\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const [wallets, setWallets] = useState(getStoredWallets());\n const walletsHashRef = useRef(hashWallets(getStoredWallets()));\n\n // Function to refresh wallets list\n const refreshWallets = useCallback(() => {\n const updatedWallets = getStoredWallets();\n setWallets(updatedWallets);\n walletsHashRef.current = hashWallets(updatedWallets);\n }, [getStoredWallets]);\n\n // Refresh wallets list when account changes (new wallet connected) or when wallets are updated\n useEffect(() => {\n refreshWallets();\n }, [refreshWallets, account?.address]);\n\n // Listen for wallet switch events to refresh the list\n useEffect(() => {\n const handleWalletSwitch = () => {\n // Small delay to ensure storage is updated\n setTimeout(() => {\n refreshWallets();\n }, 100);\n };\n\n if (typeof window !== 'undefined') {\n window.addEventListener('wallet_switched', handleWalletSwitch);\n return () => {\n window.removeEventListener(\n 'wallet_switched',\n handleWalletSwitch,\n );\n };\n }\n }, [refreshWallets]);\n\n // Poll for wallet changes when modal is open to catch new wallets being added\n // This ensures we catch wallets added via dappkit modal even if account doesn't change immediately\n useEffect(() => {\n const interval = setInterval(() => {\n const currentWallets = getStoredWallets();\n const currentHash = hashWallets(currentWallets);\n\n // If wallet hash changed, refresh\n if (currentHash !== walletsHashRef.current) {\n refreshWallets();\n }\n }, 200); // Check every 200ms\n\n return () => clearInterval(interval);\n }, [getStoredWallets, refreshWallets]);\n\n // Always use the stored active wallet from cache\n // This is the wallet the user has selected as active\n const activeWalletAddress = useMemo(() => {\n const storedActive = wallets.find((w) => w.isActive);\n // Use stored active wallet if it exists\n if (storedActive) {\n return storedActive.address;\n }\n // Fallback to account address if no stored active wallet (new connection)\n return account?.address ?? null;\n }, [wallets, account?.address]);\n\n const activeWallet = useMemo(() => {\n return wallets.find(\n (w) =>\n w.address.toLowerCase() === activeWalletAddress?.toLowerCase(),\n );\n }, [wallets, activeWalletAddress]);\n\n const otherWallets = useMemo(() => {\n return wallets.filter(\n (w) =>\n w.address.toLowerCase() !== activeWalletAddress?.toLowerCase(),\n );\n }, [wallets, activeWalletAddress]);\n\n const handleWalletSelect = useCallback(\n (address: string) => {\n if (address.toLowerCase() === activeWalletAddress?.toLowerCase()) {\n return;\n }\n\n // Ensure the wallet that was previously active is saved\n // Metadata will be fetched dynamically when needed\n if (activeWallet) {\n saveWallet(activeWallet.address);\n }\n\n setActiveWallet(address);\n\n // Refresh wallets list immediately after switch\n setTimeout(() => {\n refreshWallets();\n }, 50);\n // Refresh balances after switching\n refresh();\n\n // Close modal and go back to the screen we came from\n // Pass feedback flag through content props\n setCurrentContent({\n type: returnTo,\n props: {\n switchFeedback: {\n showFeedback: true,\n },\n },\n });\n },\n [\n activeWalletAddress,\n activeWallet,\n account,\n setActiveWallet,\n refresh,\n setCurrentContent,\n refreshWallets,\n saveWallet,\n ],\n );\n\n const handleRemoveWallet = useCallback(\n (wallet: StoredWallet) => {\n const isActiveWallet =\n wallet.address.toLowerCase() ===\n activeWalletAddress?.toLowerCase();\n const remainingWallets = wallets.filter(\n (w) => w.address.toLowerCase() !== wallet.address.toLowerCase(),\n );\n\n // Navigate to remove wallet confirmation screen\n setCurrentContent({\n type: 'remove-wallet-confirm',\n props: {\n walletAddress: wallet.address,\n walletDomain: null, // Domain will be fetched dynamically in RemoveWalletConfirmContent\n onConfirm: async () => {\n // If removing the active wallet and there are other wallets, switch to the first one\n if (isActiveWallet && remainingWallets.length > 0) {\n const nextActiveWallet = remainingWallets[0];\n setActiveWallet(nextActiveWallet.address);\n } else if (\n isActiveWallet &&\n remainingWallets.length === 0\n ) {\n // If removing the last wallet, disconnect\n try {\n await dappKitDisconnect();\n } catch (error) {\n console.error('Error disconnecting:', error);\n }\n }\n\n removeWallet(wallet.address);\n\n // Refresh wallets list after removal\n setTimeout(() => {\n refreshWallets();\n }, 50);\n\n // If no wallets remain, close the modal\n if (remainingWallets.length === 0) {\n if (_onLogoutSuccess) {\n _onLogoutSuccess();\n }\n return;\n }\n\n // Go back to select wallet screen\n setCurrentContent({\n type: 'select-wallet',\n props: {\n setCurrentContent,\n onClose: () => {},\n returnTo,\n onLogoutSuccess: _onLogoutSuccess,\n },\n });\n },\n onBack: () => {\n setCurrentContent({\n type: 'select-wallet',\n props: {\n setCurrentContent,\n onClose: () => {},\n returnTo,\n onLogoutSuccess: _onLogoutSuccess,\n },\n });\n },\n },\n });\n },\n [\n removeWallet,\n refreshWallets,\n setCurrentContent,\n returnTo,\n _onLogoutSuccess,\n activeWalletAddress,\n wallets,\n setActiveWallet,\n dappKitDisconnect,\n ],\n );\n\n const handleAddNewWallet = useCallback(() => {\n openDappKitModal();\n }, [openDappKitModal]);\n\n const handleLogout = () => {\n disconnect();\n _onLogoutSuccess?.();\n };\n\n return (\n <>\n <StickyHeaderContainer>\n {!isolatedView && (\n <ModalBackButton\n onClick={() => {\n setCurrentContent(returnTo);\n }}\n />\n )}\n <ModalHeader>{t('Select Wallet')}</ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack w={'full'} spacing={4}>\n {activeWallet && (\n <VStack w={'full'} spacing={2} alignItems=\"flex-start\">\n <Heading size=\"sm\" color={textSecondary}>\n {t('Active Wallet')}\n </Heading>\n <WalletCard\n wallet={activeWallet}\n isActive={true}\n onSelect={() => {}}\n onRemove={() =>\n handleRemoveWallet(activeWallet)\n }\n showRemove={wallets.length > 1}\n />\n </VStack>\n )}\n\n {otherWallets.length > 0 && (\n <VStack w={'full'} spacing={2} alignItems=\"flex-start\">\n <Heading size=\"sm\" color={textSecondary}>\n {t('Other Wallets')}\n </Heading>\n {otherWallets.map((wallet) => (\n <WalletCard\n key={wallet.address}\n wallet={wallet}\n isActive={false}\n onSelect={() =>\n handleWalletSelect(wallet.address)\n }\n onRemove={() => handleRemoveWallet(wallet)}\n showRemove={true}\n />\n ))}\n </VStack>\n )}\n </VStack>\n </ModalBody>\n <ModalFooter w=\"full\">\n <VStack w=\"full\" spacing={2}>\n <Button\n w=\"full\"\n leftIcon={<LuPlus />}\n variant=\"vechainKitSecondary\"\n onClick={handleAddNewWallet}\n >\n {t('Add New Wallet')}\n </Button>\n <Button\n w=\"full\"\n leftIcon={<LuLogOut />}\n variant=\"vechainKitLogout\"\n onClick={() =>\n setCurrentContent({\n type: 'disconnect-confirm',\n props: {\n onDisconnect: handleLogout,\n onBack: () =>\n setCurrentContent({\n type: 'select-wallet',\n props: {\n setCurrentContent,\n onClose: () => {},\n returnTo: returnTo,\n onLogoutSuccess:\n _onLogoutSuccess,\n },\n }),\n },\n })\n }\n >\n {t('Logout')}\n </Button>\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Button,\n Text,\n useToken,\n Icon,\n ModalFooter,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { LuTrash2 } from 'react-icons/lu';\nimport { humanAddress, humanDomain } from '@/utils';\nimport { useWalletMetadata } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\n\nexport type RemoveWalletConfirmContentProps = {\n walletAddress: string;\n walletDomain: string | null; // Kept for backward compatibility but will be fetched dynamically\n onConfirm: () => void;\n onBack: () => void;\n onClose?: () => void;\n};\n\nexport const RemoveWalletConfirmContent = ({\n walletAddress,\n walletDomain: _walletDomain,\n onConfirm,\n onBack,\n onClose,\n}: RemoveWalletConfirmContentProps) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const { domain } = useWalletMetadata(walletAddress, network.type);\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n\n const displayName = domain\n ? humanDomain(domain, 20, 0)\n : humanAddress(walletAddress, 6, 4);\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Remove')}</ModalHeader>\n <ModalBackButton onClick={onBack} />\n {onClose && <ModalCloseButton onClick={onClose} />}\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"center\" mt={10}>\n <Icon\n as={LuTrash2}\n color={'#ef4444'}\n fontSize={'60px'}\n opacity={0.5}\n />\n <Text fontSize=\"md\" textAlign=\"center\" color={textPrimary}>\n {t('Are you sure you want to remove this wallet?')}\n </Text>\n <Text\n fontSize=\"sm\"\n textAlign=\"center\"\n color=\"vechain-kit-text-secondary\"\n fontWeight=\"600\"\n >\n {displayName}\n </Text>\n <Text\n fontSize=\"sm\"\n textAlign=\"center\"\n color=\"vechain-kit-text-secondary\"\n >\n {humanAddress(walletAddress, 8, 7)}\n </Text>\n </VStack>\n </ModalBody>\n <ModalFooter w=\"full\" mt={4}>\n <VStack spacing={3} w=\"full\">\n <Button\n onClick={onConfirm}\n data-testid=\"remove-wallet-button\"\n variant=\"vechainKitLogout\"\n >\n {t('Remove')}\n </Button>\n <Button\n variant=\"vechainKitSecondary\"\n onClick={onBack}\n data-testid=\"cancel-remove-button\"\n >\n {t('Cancel')}\n </Button>\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import { getConfig } from '@/config';\nimport {\n useFetchAppInfo,\n useWallet,\n useFetchPrivyStatus,\n useGetAccountVersion,\n} from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\nimport {\n VStack,\n Text,\n Spinner,\n HStack,\n useToken,\n useClipboard,\n Icon,\n Divider,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { CrossAppConnectionCache } from '@/types';\nimport { useWallet as useWalletDappKit } from '@vechain/dapp-kit-react';\nimport packageJson from '../../../../../../package.json';\nimport { humanAddress } from '@/utils';\nimport { LuCheck, LuCopy } from 'react-icons/lu';\n\n// Get DAppKit version from package.json (this is the version constraint, not the installed version)\nconst dappKitVersion =\n packageJson.dependencies?.['@vechain/dapp-kit-react'] ||\n packageJson.peerDependencies?.['@vechain/dapp-kit-react'] ||\n 'unknown';\n\n// Get Privy version from package.json\nconst privyVersion =\n packageJson.dependencies?.['@privy-io/react-auth'] || 'unknown';\n\ntype Props = {\n connectionCache?: CrossAppConnectionCache;\n};\n\nexport const ConnectionCard = ({ connectionCache }: Props) => {\n const { t } = useTranslation();\n const { connection, smartAccount, connectedWallet } = useWallet();\n const { source: sourceDappKit } = useWalletDappKit();\n const { privy, network } = useVeChainKitConfig();\n\n const privyAppId = privy?.appId;\n const { data: appInfo, isLoading: isPrivyLoading } = useFetchAppInfo(\n privyAppId ? privyAppId : [],\n );\n\n const { onCopy, hasCopied } = useClipboard('');\n\n const { data: privyStatus, isLoading: isPrivyStatusLoading } =\n useFetchPrivyStatus();\n\n const { data: accountVersion, isLoading: isAccountVersionLoading } =\n useGetAccountVersion(\n smartAccount.address ?? '',\n connectedWallet?.address ?? '',\n );\n\n const cardBg = useToken('colors', 'vechain-kit-card');\n const textColorSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n\n const getConnectionName = (): string | null => {\n if (\n connection.isConnectedWithCrossApp &&\n connectionCache?.ecosystemApp\n ) {\n return connectionCache.ecosystemApp.name;\n }\n if (connection.isConnectedWithSocialLogin && appInfo) {\n const first = Object.values(appInfo)[0];\n return first?.name ?? null;\n }\n if (connection.isConnectedWithDappKit && sourceDappKit) {\n return sourceDappKit;\n }\n return null;\n };\n\n const connectionName = getConnectionName();\n const isLoading = connection.isConnectedWithSocialLogin && isPrivyLoading;\n\n const InfoRow = ({\n label,\n value,\n isLoading: isLoadingRow = false,\n href,\n }: {\n label: string;\n value: string | number;\n isLoading?: boolean;\n href?: string;\n }) => (\n <HStack w=\"full\" justifyContent=\"space-between\">\n <Text fontSize=\"sm\" color={textPrimary}>\n {label}:\n </Text>\n <Text\n fontSize=\"sm\"\n as={href ? 'a' : undefined}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ textDecoration: href ? 'underline' : 'none' }}\n color={textColorSecondary}\n >\n {isLoadingRow ? 'Loading...' : value}\n </Text>\n </HStack>\n );\n\n if (isLoading) {\n return (\n <VStack\n w=\"full\"\n h=\"full\"\n justify=\"center\"\n align=\"center\"\n minH=\"200px\"\n borderRadius={'xl'}\n bg={cardBg}\n >\n <Spinner />\n </VStack>\n );\n }\n\n if (!connectionName) {\n return null;\n }\n\n return (\n <VStack\n p={4}\n bg={cardBg}\n borderRadius={'xl'}\n spacing={4}\n w=\"full\"\n justifyContent=\"space-between\"\n >\n <InfoRow label={t('Logged in with')} value={connectionName} />\n\n {connection.isConnectedWithCrossApp &&\n connectionCache?.timestamp && (\n <InfoRow\n label={t('At')}\n value={new Date(\n connectionCache.timestamp,\n ).toLocaleString()}\n />\n )}\n\n <InfoRow\n label={t('Connection Type')}\n value={connection.source.type}\n isLoading={connection.isLoading}\n />\n\n <Divider />\n\n <InfoRow label={t('Network')} value={network.type} />\n <InfoRow\n label={t('Node URL')}\n value={network.nodeUrl || getConfig(network.type).nodeUrl}\n />\n\n {connection.isConnectedWithPrivy && <Divider />}\n\n {connection.isConnectedWithPrivy && (\n <HStack w=\"full\" justifyContent=\"space-between\">\n <Text fontSize=\"sm\" color={textPrimary}>\n {t('Embedded wallet')}:\n </Text>\n\n <HStack>\n <Text fontSize=\"sm\" color={textColorSecondary}>\n {connectedWallet?.address\n ? humanAddress(connectedWallet.address, 8, 7)\n : '-'}\n </Text>\n\n <Icon\n color={textColorSecondary}\n onClick={() => {\n if (connectedWallet?.address)\n onCopy(connectedWallet.address);\n }}\n opacity={connectedWallet?.address ? 1 : 0.4}\n pointerEvents={\n connectedWallet?.address ? 'auto' : 'none'\n }\n cursor=\"pointer\"\n as={hasCopied ? LuCheck : LuCopy}\n />\n </HStack>\n </HStack>\n )}\n\n {connection.isConnectedWithPrivy ? (\n <>\n <InfoRow\n label={t('Smart Account')}\n value={`v${accountVersion?.version ?? ''} ${\n accountVersion?.isDeployed ? '' : '(not deployed)'\n }`}\n isLoading={isAccountVersionLoading}\n />\n <InfoRow\n label={t('Privy Status')}\n value={privyStatus || ''}\n isLoading={isPrivyStatusLoading}\n />\n </>\n ) : (\n smartAccount.isDeployed && (\n <InfoRow\n label={t('Smart Account')}\n value={`v${accountVersion?.version ?? ''}`}\n isLoading={isAccountVersionLoading}\n />\n )\n )}\n\n <Divider />\n\n <InfoRow\n label={t('VeChain Kit')}\n value={packageJson.version}\n href={`https://github.com/vechain/vechain-kit/releases/tag/${packageJson.version}`}\n />\n\n <InfoRow label={'DAppKit'} value={dappKitVersion} />\n\n <InfoRow label={'Privy'} value={privyVersion} />\n </VStack>\n );\n};\n","import { PrivyLogo, VechainLogo } from '@/assets';\nimport { useCrossAppConnectionCache, useWallet } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\nimport { HStack, Icon, Image, Text, VStack, useToken } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { LuMinus } from 'react-icons/lu';\n\nexport const WalletSecuredBy = () => {\n const { connection } = useWallet();\n const { t } = useTranslation();\n const { privy, darkMode: isDark } = useVeChainKitConfig();\n const { getConnectionCache } = useCrossAppConnectionCache();\n\n const connectionCache = getConnectionCache();\n const cardBg = useToken('colors', 'vechain-kit-card');\n\n if (!connection.isConnectedWithPrivy) {\n return null;\n }\n\n return (\n <VStack\n w={'full'}\n align=\"stretch\"\n textAlign={'center'}\n mt={5}\n p={3}\n borderRadius=\"lg\"\n bg={cardBg}\n shadow=\"sm\"\n >\n <Text fontSize={'xs'} fontWeight={'800'}>\n {t('Wallet secured by')}\n </Text>\n <HStack justify={'center'}>\n <PrivyLogo isDark={isDark} w={'50px'} />\n <Icon as={LuMinus} ml={3} />\n\n {connection.isConnectedWithVeChain ? (\n <VechainLogo\n isDark={isDark}\n w={'80px'}\n h={'auto'}\n mb={'3px'}\n />\n ) : (\n connection.isConnectedWithCrossApp &&\n connectionCache && (\n <Image\n src={connectionCache.ecosystemApp.logoUrl}\n alt={connectionCache.ecosystemApp.name}\n maxW=\"40px\"\n borderRadius=\"md\"\n />\n )\n )}\n\n {connection.isConnectedWithSocialLogin &&\n !connection.isConnectedWithVeChain && (\n <Image\n src={privy?.appearance.logo}\n alt={privy?.appearance.logo}\n maxW=\"40px\"\n borderRadius=\"md\"\n />\n )}\n </HStack>\n </VStack>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalFooter,\n ModalHeader,\n} from '@chakra-ui/react';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { useCrossAppConnectionCache } from '@/hooks';\nimport { ConnectionCard, WalletSecuredBy } from './Components';\n\ntype Props = {\n onGoBack: () => void;\n};\n\nexport const ConnectionDetailsContent = ({ onGoBack }: Props) => {\n const { t } = useTranslation();\n const { getConnectionCache } = useCrossAppConnectionCache();\n\n const connectionCache = getConnectionCache() ?? undefined;\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Connection Details')}</ModalHeader>\n\n <ModalBackButton\n onClick={() => {\n onGoBack();\n }}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <ConnectionCard connectionCache={connectionCache} />\n <WalletSecuredBy />\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n};\n","import { LinkedAccountWithMetadata, usePrivy } from '@privy-io/react-auth';\nimport {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Button,\n Flex,\n Text,\n Icon,\n ModalFooter,\n useToken,\n} from '@chakra-ui/react';\nimport { FcGoogle } from 'react-icons/fc';\nimport { SiFarcaster } from 'react-icons/si';\nimport {\n FaSpotify,\n FaApple,\n FaInstagram,\n FaTiktok,\n FaLinkedin,\n FaTelegram,\n FaDiscord,\n} from 'react-icons/fa';\nimport {\n LuMail,\n LuWallet,\n LuPhone,\n LuGithub,\n LuPlus,\n LuFingerprint,\n} from 'react-icons/lu';\nimport { FaXTwitter } from 'react-icons/fa6';\nimport { ActionButton } from '@/components';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { useState, useMemo } from 'react';\nimport { useVeChainKitConfig } from '@/providers';\nimport { humanAddress } from '@/utils';\n\ntype ConfirmUnlinkProps = {\n accountType: string;\n accountDescription: string;\n isLoading: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst ConfirmUnlink = ({\n accountType,\n accountDescription,\n isLoading,\n onConfirm,\n onCancel,\n}: ConfirmUnlinkProps) => {\n const { t } = useTranslation();\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n\n return (\n <VStack spacing={6} align=\"stretch\">\n <Text fontSize=\"md\" textAlign=\"center\" color={textPrimary}>\n {t(\n 'Are you sure you want to unlink {{accountType}} as a login method linked to {{accountDescription}}?',\n {\n accountType,\n accountDescription,\n },\n )}\n </Text>\n\n <VStack spacing={3} w=\"full\">\n <Button\n height=\"60px\"\n colorScheme=\"red\"\n w=\"full\"\n onClick={onConfirm}\n isLoading={isLoading}\n >\n {t('Remove Login Method')}\n </Button>\n <Button\n isLoading={isLoading}\n height=\"60px\"\n w=\"full\"\n onClick={onCancel}\n >\n {t('Cancel')}\n </Button>\n </VStack>\n </VStack>\n );\n};\n\ntype PrivyLinkedAccountsProps = {\n onBack: () => void;\n};\n\nexport const PrivyLinkedAccounts = ({ onBack }: PrivyLinkedAccountsProps) => {\n const { t } = useTranslation();\n const { privy, dappKit } = useVeChainKitConfig();\n const [unlinkingAccount, setUnlinkingAccount] = useState<any>(null);\n const [showLinkOptions, setShowLinkOptions] = useState(false);\n const [showFullText, setShowFullText] = useState(false);\n const [isLoadingUnlink, setIsLoadingUnlink] = useState(false);\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const {\n user,\n linkEmail,\n linkGoogle,\n linkTwitter,\n linkPhone,\n linkSpotify,\n linkApple,\n linkInstagram,\n linkTiktok,\n linkGithub,\n linkLinkedIn,\n linkTelegram,\n linkFarcaster,\n linkPasskey,\n linkDiscord,\n unlinkEmail,\n unlinkGoogle,\n unlinkApple,\n unlinkSpotify,\n unlinkInstagram,\n unlinkTiktok,\n unlinkGithub,\n unlinkLinkedIn,\n unlinkTelegram,\n unlinkFarcaster,\n unlinkPhone,\n unlinkPasskey,\n unlinkDiscord,\n linkWallet,\n } = usePrivy();\n\n const canLinkWallets = useMemo(() => {\n const privyWallets =\n privy?.loginMethods?.filter((method) =>\n [\n 'rabby_wallet',\n 'coinbase_wallet',\n 'rainbow',\n 'phantom',\n 'metamask',\n ].includes(method),\n ) ?? [];\n\n const dappKitWallets = dappKit?.allowedWallets ?? [];\n\n return privyWallets.length > 0 || dappKitWallets.length > 0;\n }, [privy?.loginMethods, dappKit?.allowedWallets]);\n\n const getAccountIcon = (type: string) => {\n switch (type) {\n case 'google_oauth':\n return FcGoogle;\n case 'email':\n return LuMail;\n case 'passkey':\n return LuFingerprint;\n case 'wallet':\n return LuWallet;\n case 'twitter_oauth':\n return FaXTwitter;\n case 'phone':\n return LuPhone;\n case 'spotify_oauth':\n return FaSpotify;\n case 'apple_oauth':\n return FaApple;\n case 'instagram_oauth':\n return FaInstagram;\n case 'tiktok_oauth':\n return FaTiktok;\n case 'github_oauth':\n return LuGithub;\n case 'linkedin_oauth':\n return FaLinkedin;\n case 'telegram':\n return FaTelegram;\n case 'farcaster':\n return SiFarcaster;\n case 'discord_oauth':\n return FaDiscord;\n default:\n return undefined;\n }\n };\n\n const canUnlink = () => {\n // the embedded wallet is always in this list, so we need to exclude it\n const linkedAccountsExcludingWallet = user?.linkedAccounts?.filter(\n (account) =>\n account.type !== 'wallet' ||\n (account.type === 'wallet' &&\n account.connectorType !== 'embedded'),\n );\n return (\n linkedAccountsExcludingWallet &&\n linkedAccountsExcludingWallet?.length > 1\n );\n };\n\n const handleUnlink = async (account: any) => {\n if (!canUnlink()) return;\n\n setIsLoadingUnlink(true);\n\n try {\n switch (account.type) {\n case 'google_oauth':\n await unlinkGoogle(account.subject);\n break;\n case 'email':\n await unlinkEmail(account.address);\n break;\n case 'passkey':\n await unlinkPasskey(account.subject);\n break;\n case 'phone':\n await unlinkPhone(account.number);\n break;\n case 'spotify_oauth':\n await unlinkSpotify(account.subject);\n break;\n case 'apple_oauth':\n await unlinkApple(account.subject);\n break;\n case 'instagram_oauth':\n await unlinkInstagram(account.subject);\n break;\n case 'tiktok_oauth':\n await unlinkTiktok(account.subject);\n break;\n case 'github_oauth':\n await unlinkGithub(account.subject);\n break;\n case 'linkedin_oauth':\n await unlinkLinkedIn(account.subject);\n break;\n case 'telegram':\n await unlinkTelegram(account.subject);\n break;\n case 'farcaster':\n await unlinkFarcaster(account.subject);\n break;\n case 'discord_oauth':\n await unlinkDiscord(account.subject);\n break;\n default:\n break;\n }\n } catch (error) {\n console.error(error);\n } finally {\n setIsLoadingUnlink(false);\n setUnlinkingAccount(null);\n }\n };\n\n const getAccountDescription = (account: LinkedAccountWithMetadata) => {\n switch (account.type) {\n case 'google_oauth':\n return account.email;\n case 'email':\n return account.address;\n case 'passkey':\n return `${account.authenticatorName} - ${account.createdWithBrowser}`;\n case 'phone':\n return account.number;\n case 'wallet':\n return `${humanAddress(account.address)} - ${\n account.walletClientType\n }`;\n default:\n return '';\n }\n };\n\n const linkedAccountTypes =\n user?.linkedAccounts?.map((account) => account.type) || [];\n const availableLoginMethods = privy?.loginMethods || [];\n\n const canLinkGoogle =\n !linkedAccountTypes.includes('google_oauth') &&\n availableLoginMethods.includes('google');\n const canLinkEmail =\n !linkedAccountTypes.includes('email') &&\n availableLoginMethods.includes('email');\n const canLinkTwitter =\n !linkedAccountTypes.includes('twitter_oauth') &&\n availableLoginMethods.includes('twitter');\n const canLinkSms =\n !linkedAccountTypes.includes('phone') &&\n availableLoginMethods.includes('sms');\n const canLinkSpotify =\n !linkedAccountTypes.includes('spotify_oauth') &&\n availableLoginMethods.includes('spotify');\n const canLinkApple =\n !linkedAccountTypes.includes('apple_oauth') &&\n availableLoginMethods.includes('apple');\n const canLinkInstagram =\n !linkedAccountTypes.includes('instagram_oauth') &&\n availableLoginMethods.includes('instagram');\n const canLinkTiktok =\n !linkedAccountTypes.includes('tiktok_oauth') &&\n availableLoginMethods.includes('tiktok');\n const canLinkGithub =\n !linkedAccountTypes.includes('github_oauth') &&\n availableLoginMethods.includes('github');\n const canLinkLinkedin =\n !linkedAccountTypes.includes('linkedin_oauth') &&\n availableLoginMethods.includes('linkedin');\n const canLinkTelegram =\n !linkedAccountTypes.includes('telegram') &&\n availableLoginMethods.includes('telegram');\n const canLinkFarcaster =\n !linkedAccountTypes.includes('farcaster') &&\n availableLoginMethods.includes('farcaster');\n const canLinkDiscord =\n !linkedAccountTypes.includes('discord_oauth') &&\n availableLoginMethods.includes('discord');\n\n if (showLinkOptions) {\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>\n {t('Select Additional Login Method')}\n </ModalHeader>\n <ModalBackButton\n onClick={() => setShowLinkOptions(false)}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n <ModalBody w=\"full\">\n <VStack spacing={3} align=\"stretch\" w=\"full\">\n <ActionButton\n title={t('Set up Passkey')}\n description={t(\n 'Set up a passkey for easier access',\n )}\n onClick={() => linkPasskey()}\n leftIcon={LuFingerprint}\n />\n\n {canLinkGoogle && (\n <ActionButton\n title={t('Link Google Account')}\n description={t(\n 'Connect your Google account for easier access',\n )}\n onClick={() => linkGoogle()}\n leftIcon={FcGoogle}\n />\n )}\n {canLinkEmail && (\n <ActionButton\n title={t('Link Email Account')}\n description={t(\n 'Connect your email for easier access',\n )}\n onClick={() => linkEmail()}\n leftIcon={LuMail}\n stacked={true}\n />\n )}\n {canLinkTwitter && (\n <ActionButton\n title={t('Link Twitter Account')}\n description={t(\n 'Connect your Twitter account for easier access',\n )}\n onClick={() => linkTwitter()}\n leftIcon={FaXTwitter}\n />\n )}\n {canLinkSms && (\n <ActionButton\n title={t('Link Phone Number')}\n description={t(\n 'Connect your phone number for easier access',\n )}\n onClick={() => linkPhone()}\n leftIcon={LuPhone}\n />\n )}\n {canLinkSpotify && (\n <ActionButton\n title={t('Link Spotify Account')}\n description={t(\n 'Connect your Spotify account for easier access',\n )}\n onClick={() => linkSpotify()}\n leftIcon={FaSpotify}\n />\n )}\n {canLinkApple && (\n <ActionButton\n title={t('Link Apple Account')}\n description={t(\n 'Connect your Apple account for easier access',\n )}\n onClick={() => linkApple()}\n leftIcon={FaApple}\n />\n )}\n {canLinkInstagram && (\n <ActionButton\n title={t('Link Instagram Account')}\n description={t(\n 'Connect your Instagram account for easier access',\n )}\n onClick={() => linkInstagram()}\n leftIcon={FaInstagram}\n />\n )}\n {canLinkTiktok && (\n <ActionButton\n title={t('Link Tiktok Account')}\n description={t(\n 'Connect your Tiktok account for easier access',\n )}\n onClick={() => linkTiktok()}\n leftIcon={FaTiktok}\n />\n )}\n {canLinkGithub && (\n <ActionButton\n title={t('Link Github Account')}\n description={t(\n 'Connect your Github account for easier access',\n )}\n onClick={() => linkGithub()}\n leftIcon={LuGithub}\n />\n )}\n {canLinkLinkedin && (\n <ActionButton\n title={t('Link LinkedIn Account')}\n description={t(\n 'Connect your LinkedIn account for easier access',\n )}\n onClick={() => linkLinkedIn()}\n leftIcon={FaLinkedin}\n />\n )}\n {canLinkTelegram && (\n <ActionButton\n title={t('Link Telegram Account')}\n description={t(\n 'Connect your Telegram account for easier access',\n )}\n onClick={() => linkTelegram()}\n leftIcon={FaTelegram}\n />\n )}\n {canLinkFarcaster && (\n <ActionButton\n title={t('Link Farcaster Account')}\n description={t(\n 'Connect your Farcaster account for easier access',\n )}\n onClick={() => linkFarcaster()}\n leftIcon={SiFarcaster}\n />\n )}\n {canLinkDiscord && (\n <ActionButton\n title={t('Link Discord Account')}\n description={t(\n 'Connect your Discord account for easier access',\n )}\n onClick={() => linkDiscord()}\n leftIcon={FaDiscord}\n />\n )}\n {canLinkWallets && (\n <ActionButton\n title={t('Link External Wallet')}\n description={t(\n 'Connect an external wallet for easier access',\n )}\n onClick={() => linkWallet()}\n leftIcon={LuWallet}\n />\n )}\n {!canLinkGoogle &&\n !canLinkEmail &&\n !canLinkTwitter &&\n !canLinkSms &&\n !canLinkSpotify &&\n !canLinkApple &&\n !canLinkInstagram &&\n !canLinkTiktok &&\n !canLinkGithub &&\n !canLinkLinkedin &&\n !canLinkTelegram &&\n !canLinkFarcaster &&\n !canLinkDiscord && (\n <Text\n fontSize=\"sm\"\n textAlign=\"center\"\n opacity={0.7}\n >\n {t(\n 'No additional accounts available to link',\n )}\n </Text>\n )}\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n }\n\n if (unlinkingAccount) {\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Remove Login Method')}</ModalHeader>\n <ModalBackButton\n onClick={() => setUnlinkingAccount(null)}\n />\n <ModalCloseButton />\n </StickyHeaderContainer>\n <ModalBody>\n <ConfirmUnlink\n accountType={unlinkingAccount.type}\n accountDescription={getAccountDescription(\n unlinkingAccount,\n )}\n isLoading={isLoadingUnlink}\n onConfirm={() => handleUnlink(unlinkingAccount)}\n onCancel={() => setUnlinkingAccount(null)}\n />\n </ModalBody>\n <ModalFooter pt={0} />\n </ScrollToTopWrapper>\n );\n }\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n <ModalHeader>{t('Login methods')}</ModalHeader>\n <ModalBackButton onClick={onBack} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody w={'full'}>\n <VStack\n spacing={3}\n align=\"center\"\n w={'full'}\n justify={'center'}\n >\n <VStack\n spacing={1}\n justify={'flex-start'}\n alignItems=\"flex-start\"\n mb={5}\n textAlign=\"left\"\n w={'full'}\n >\n <Text fontSize=\"sm\" color={textSecondary}>\n {t(\n 'These accounts are linked to your embedded wallet and can be used to login to your wallet and access your private key.',\n )}\n </Text>\n {showFullText && (\n <Text fontSize=\"sm\" color={textSecondary}>\n {t(\n 'Adding more linked accounts increases security against loss of access, but also introduces additional potential attack vectors. For enhanced security, we recommend enabling MFA.',\n )}\n </Text>\n )}\n <Button\n variant=\"link\"\n mt={0}\n size=\"sm\"\n onClick={() => setShowFullText(!showFullText)}\n color={textPrimary}\n >\n {t(showFullText ? 'Show Less' : 'Read More')}\n </Button>\n </VStack>\n\n {user?.linkedAccounts\n ?.filter(\n (account) =>\n account.type !== 'wallet' ||\n (account.type === 'wallet' &&\n account.connectorType !== 'embedded'),\n )\n .map((account) => (\n <Flex\n key={account.type}\n p={4}\n borderWidth=\"1px\"\n borderRadius=\"md\"\n align=\"center\"\n justify=\"space-between\"\n w={'full'}\n >\n <Flex align=\"center\" gap={3}>\n <Icon\n as={getAccountIcon(account.type)}\n color={textPrimary}\n />\n <VStack align=\"start\" spacing={0}>\n <Text\n fontWeight=\"500\"\n color={textPrimary}\n >\n {account.type === 'google_oauth'\n ? t('Google')\n : account.type === 'email'\n ? t('Email')\n : account.type === 'passkey'\n ? t('Passkey')\n : account.type ===\n 'twitter_oauth'\n ? t('Twitter')\n : account.type === 'phone'\n ? t('Phone Number')\n : account.type ===\n 'spotify_oauth'\n ? t('Spotify')\n : account.type === 'apple_oauth'\n ? t('Apple')\n : account.type ===\n 'instagram_oauth'\n ? t('Instagram')\n : account.type ===\n 'tiktok_oauth'\n ? t('Tiktok')\n : account.type ===\n 'github_oauth'\n ? t('Github')\n : account.type ===\n 'linkedin_oauth'\n ? t('LinkedIn')\n : account.type === 'telegram'\n ? t('Telegram')\n : account.type === 'farcaster'\n ? t('Farcaster')\n : account.type ===\n 'discord_oauth'\n ? t('Discord')\n : t('Wallet')}\n </Text>\n <Text\n fontSize=\"sm\"\n color={textSecondary}\n >\n {getAccountDescription(account)}\n </Text>\n </VStack>\n </Flex>\n\n <Button\n size=\"sm\"\n variant=\"ghost\"\n colorScheme=\"red\"\n isDisabled={!canUnlink()}\n onClick={() => {\n if (account.type === 'passkey') {\n linkPasskey();\n } else {\n setUnlinkingAccount(account);\n }\n }}\n >\n {t('Remove')}\n </Button>\n </Flex>\n ))}\n </VStack>\n </ModalBody>\n <ModalFooter w={'full'}>\n <Button\n w=\"full\"\n variant=\"vechainKitPrimary\"\n onClick={() => setShowLinkOptions(true)}\n leftIcon={<Icon as={LuPlus} />}\n isDisabled={\n !canLinkGoogle &&\n !canLinkEmail &&\n !canLinkTwitter &&\n !canLinkSms &&\n !canLinkSpotify &&\n !canLinkApple &&\n !canLinkInstagram &&\n !canLinkTiktok &&\n !canLinkGithub &&\n !canLinkLinkedin &&\n !canLinkTelegram &&\n !canLinkFarcaster &&\n !canLinkDiscord\n }\n >\n {t('Add Login Method')}\n </Button>\n </ModalFooter>\n </ScrollToTopWrapper>\n );\n};\n","import { useEffect } from 'react';\nimport {\n useWallet,\n useNotifications,\n useUpgradeRequiredForAccount,\n} from '@/hooks';\nimport { useTranslation } from 'react-i18next';\n\nexport const DEFAULT_NOTIFICATIONS = [\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\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","import { useCallback, useEffect } from 'react';\nimport { useWallet } from '@/hooks';\nimport { Notification } from './types';\nimport { DEFAULT_NOTIFICATIONS } from './useNotificationAlerts';\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 { useTranslation } from 'react-i18next';\nimport { EmptyContent } from '@/components/common/EmptyContent';\nimport { LuBell, LuArchive } from 'react-icons/lu';\n\ntype Props = {\n showArchived: boolean;\n};\n\nexport const EmptyNotifications = ({ showArchived }: Props) => {\n const { t } = useTranslation();\n\n return (\n <EmptyContent\n title={\n showArchived\n ? t('No archived notifications')\n : t('No notifications')\n }\n description={\n showArchived\n ? t('Cleared notifications will appear here')\n : t('When you have notifications, they will appear here')\n }\n icon={showArchived ? LuArchive : LuBell}\n />\n );\n};\n","import {\n Alert,\n AlertIcon,\n Box,\n AlertDescription,\n IconButton,\n AlertTitle,\n} from '@chakra-ui/react';\nimport { LuCircleX } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { Notification } from '@/hooks/notifications/types';\n\ntype Props = {\n notification: Notification;\n isArchiveView: boolean;\n onMarkAsRead: (id: string) => void;\n};\n\nexport const NotificationItem = ({\n notification,\n isArchiveView,\n onMarkAsRead,\n}: Props) => {\n const { t } = useTranslation();\n\n const handleDismiss = () => {\n onMarkAsRead(notification.id);\n };\n\n if (notification.isRead && !isArchiveView) {\n return null;\n }\n\n return (\n <Alert\n key={notification.id}\n status={notification.status}\n variant=\"subtle\"\n borderRadius={'lg'}\n pr={8}\n position=\"relative\"\n opacity={notification.isRead ? 0.7 : 1}\n cursor=\"pointer\"\n _hover={{ opacity: 0.8 }}\n data-testid=\"notification-item\"\n >\n <AlertIcon boxSize={'16px'} />\n <Box>\n <AlertTitle fontSize={'sm'} data-testid=\"notification-title\">\n {/* @ts-ignore */}\n {t(notification.title)}\n </AlertTitle>\n <AlertDescription fontSize={'xs'} lineHeight={'1.2'} data-testid=\"notification-text\">\n {/* @ts-ignore */}\n {t(notification.description)}\n </AlertDescription>\n </Box>\n {!isArchiveView && !notification.isRead && (\n <IconButton\n position=\"absolute\"\n right={1}\n top={1}\n size=\"sm\"\n variant=\"ghost\"\n icon={<LuCircleX />}\n onClick={(e) => {\n e.stopPropagation();\n handleDismiss();\n }}\n aria-label=\"Mark as read and archive\"\n data-testid=\"remove-notification-button\"\n />\n )}\n </Alert>\n );\n};\n","import {\n Container,\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Icon,\n ModalFooter,\n Button,\n HStack,\n} from '@chakra-ui/react';\nimport { LuBell, LuArchive } from 'react-icons/lu';\nimport {\n ModalBackButton,\n ScrollToTopWrapper,\n StickyHeaderContainer,\n} from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { useNotifications } from '@/hooks/notifications';\nimport { useState } from 'react';\nimport { EmptyNotifications } from './Components/EmptyNotifications';\nimport { NotificationItem } from './Components/NotificationItem';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const NotificationsContent = ({ setCurrentContent }: Props) => {\n const { t } = useTranslation();\n const { isolatedView } = useAccountModalOptions();\n const {\n getNotifications,\n getArchivedNotifications,\n clearAllNotifications,\n markAsRead,\n } = useNotifications();\n const [isArchiveView, setIsArchiveView] = useState(false);\n const [notifications, setNotifications] = useState(getNotifications());\n const [archivedNotifications, setArchivedNotifications] = useState(\n getArchivedNotifications(),\n );\n\n const handleClearAll = () => {\n clearAllNotifications();\n setArchivedNotifications([...archivedNotifications, ...notifications]);\n setNotifications([]);\n };\n\n const handleMarkAsRead = (id: string) => {\n markAsRead(id);\n const notificationToArchive = notifications.find((n) => n.id === id);\n setNotifications(notifications.filter((n) => n.id !== id));\n if (notificationToArchive) {\n setArchivedNotifications([\n { ...notificationToArchive, isRead: true },\n ...archivedNotifications,\n ]);\n }\n };\n\n const handleToggleView = () => {\n setIsArchiveView(!isArchiveView);\n };\n\n const currentNotifications = isArchiveView\n ? archivedNotifications\n : notifications;\n\n // Sort notifications by date in descending order (newest first)\n const sortedNotifications = [...currentNotifications].sort((a, b) => {\n // Welcome notification always first\n if (a.id === 'welcome') return -1;\n if (b.id === 'welcome') return 1;\n\n // Smart account second\n if (a.id === 'smart-account') return -1;\n if (b.id === 'smart-account') return 1;\n\n // Multiclause third\n if (a.id === 'multiclause') return -1;\n if (b.id === 'multiclause') return 1;\n\n // All other notifications sorted by timestamp\n return b.timestamp - a.timestamp;\n });\n\n return (\n <ScrollToTopWrapper>\n <StickyHeaderContainer>\n {!isolatedView && (\n <ModalBackButton onClick={() => setCurrentContent('main')} />\n )}\n <ModalHeader data-testid=\"modal-title\">\n {isArchiveView\n ? t('Archived Notifications')\n : t('Notifications')}\n </ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <Container h={['540px', 'auto']} p={0}>\n <ModalBody>\n <VStack spacing={4} align=\"stretch\" w=\"full\">\n <HStack justify=\"space-between\">\n <Button\n variant=\"ghost\"\n leftIcon={\n <Icon\n as={isArchiveView ? LuBell : LuArchive}\n />\n }\n size=\"sm\"\n onClick={handleToggleView}\n data-testid=\"toggle-view-button\"\n >\n {isArchiveView ? t('Current') : t('Archived')}\n </Button>\n {!isArchiveView && notifications.length > 0 && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClearAll}\n data-testid=\"clear-all-button\"\n >\n {t('Clear all')}\n </Button>\n )}\n </HStack>\n\n {currentNotifications.length === 0 ? (\n <EmptyNotifications showArchived={isArchiveView} />\n ) : (\n <VStack spacing={3}>\n {sortedNotifications.map((notification) => (\n <NotificationItem\n key={notification.id}\n notification={notification}\n isArchiveView={isArchiveView}\n onMarkAsRead={handleMarkAsRead}\n />\n ))}\n </VStack>\n )}\n </VStack>\n </ModalBody>\n <ModalFooter pt={0} />\n </Container>\n </ScrollToTopWrapper>\n );\n};\n","import { Tag, TagProps } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\n\nexport type AllowedCategories =\n | 'defi'\n | 'games'\n | 'collectibles'\n | 'marketplaces'\n | 'utilities'\n | 'vebetter';\n\ntype CategoryProps = {\n category: AllowedCategories;\n} & Omit<TagProps, 'category'>;\n\nconst getCategoryColor = (category: AllowedCategories): string => {\n switch (category) {\n case 'defi':\n return 'blue';\n case 'games':\n return 'green';\n case 'collectibles':\n return 'purple';\n case 'marketplaces':\n return 'orange';\n case 'utilities':\n return 'cyan';\n default:\n return 'gray';\n }\n};\n\nexport const CategoryLabel = ({ category, ...props }: CategoryProps) => {\n const { t } = useTranslation();\n\n const categoryKey = category.toLowerCase() as AllowedCategories;\n const color = getCategoryColor(categoryKey);\n\n return (\n <Tag\n size=\"sm\"\n colorScheme={color}\n borderRadius=\"full\"\n px={2}\n {...props}\n >\n {t(categoryKey)}\n </Tag>\n );\n};\n","import { Card, CardBody, Image, Text, VStack, Box } from '@chakra-ui/react';\nimport { notFoundImage } from '@/utils';\nimport { CategoryLabel, AllowedCategories } from './CategoryLabel';\n\nexport type SharedAppCardProps = {\n name?: string;\n imageUrl: string;\n linkUrl: string;\n category?: AllowedCategories;\n logoComponent?: JSX.Element;\n onClick: () => void;\n size?: 'sm' | 'md';\n};\n\nexport const SharedAppCard = ({\n name,\n imageUrl,\n logoComponent,\n category,\n onClick,\n size = 'md',\n}: SharedAppCardProps) => {\n return (\n <Card\n variant=\"vechainKitAppCard\"\n _hover={{ opacity: 0.8 }}\n cursor=\"pointer\"\n onClick={onClick}\n position=\"relative\"\n >\n {category && (\n <Box position=\"absolute\" top=\"2\" right=\"2\" zIndex=\"1\">\n <CategoryLabel category={category} />\n </Box>\n )}\n <CardBody p={size === 'sm' ? 2 : 4} alignItems=\"center\">\n <VStack spacing={2} h=\"100%\" justifyContent=\"space-between\">\n {logoComponent\n ? logoComponent\n : imageUrl && (\n <Image\n src={imageUrl}\n fallbackSrc={notFoundImage}\n alt={name}\n height=\"90px\"\n objectFit=\"contain\"\n rounded=\"full\"\n />\n )}\n {name && (\n <Text\n fontWeight=\"medium\"\n wordBreak=\"break-word\"\n noOfLines={1}\n textAlign=\"center\"\n w=\"full\"\n >\n {name}\n </Text>\n )}\n </VStack>\n </CardBody>\n </Card>\n );\n};\n","import { useIpfsImage, useXAppMetadata, XApp } from '@/hooks';\nimport { SharedAppCard } from './SharedAppCard';\nimport { AccountModalContentTypes } from '@/components/AccountModal/Types';\nimport { Skeleton } from '@chakra-ui/react';\nimport { CategoryFilter } from './CategoryFilterSection';\n\ntype Props = {\n xApp: XApp;\n selectedCategory?: CategoryFilter;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const AppComponent = ({\n xApp,\n setCurrentContent,\n selectedCategory,\n}: Props) => {\n const { data: appMetadata, isLoading: appMetadataLoading } =\n useXAppMetadata(xApp.id);\n const { data: logo, isLoading: isLogoLoading } = useIpfsImage(\n appMetadata?.logo,\n );\n\n const handleAppClick = () => {\n if (appMetadata?.name) {\n setCurrentContent({\n type: 'app-overview',\n props: {\n name: appMetadata.name,\n image: logo?.image ?? '',\n url: appMetadata?.external_url ?? '',\n description: appMetadata?.description ?? '',\n category: 'vebetter',\n selectedCategory,\n setCurrentContent,\n },\n });\n }\n };\n\n return (\n <Skeleton\n isLoaded={!appMetadataLoading && !isLogoLoading}\n borderRadius=\"md\"\n height=\"100%\"\n >\n <SharedAppCard\n name={appMetadata?.name ?? ''}\n imageUrl={logo?.image ?? ''}\n linkUrl={appMetadata?.external_url ?? ''}\n category=\"vebetter\"\n onClick={handleAppClick}\n />\n </Skeleton>\n );\n};\n","import { AccountModalContentTypes } from '@/components/AccountModal/Types';\nimport { SharedAppCard } from './SharedAppCard';\nimport { CategoryFilter } from './CategoryFilterSection';\nimport { AllowedCategories } from './CategoryLabel';\n\ntype Props = {\n name: string;\n image: string;\n url: string;\n description: string;\n category?: AllowedCategories;\n logoComponent?: JSX.Element;\n selectedCategory?: CategoryFilter;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const CustomAppComponent = ({\n name,\n image,\n url,\n description,\n category,\n logoComponent,\n selectedCategory,\n setCurrentContent,\n}: Props) => {\n const handleAppClick = () => {\n setCurrentContent({\n type: 'app-overview',\n props: {\n name,\n image,\n url,\n description,\n category,\n logoComponent,\n selectedCategory,\n setCurrentContent,\n },\n });\n };\n\n return (\n <SharedAppCard\n name={name}\n imageUrl={image}\n linkUrl={url}\n category={category}\n onClick={handleAppClick}\n {...(logoComponent && { logoComponent })}\n />\n );\n};\n","import {\n Card,\n CardBody,\n Grid,\n GridItem,\n Image,\n Text,\n VStack,\n} from '@chakra-ui/react';\nimport { useEcosystemShortcuts } from '@/hooks';\nimport { AccountModalContentTypes } from '@/components/AccountModal/Types';\nimport { useTranslation } from 'react-i18next';\nimport { notFoundImage } from '@/utils';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\nexport const ShortcutsSection = ({}: Props) => {\n const { t } = useTranslation();\n const { shortcuts } = useEcosystemShortcuts();\n\n if (shortcuts.length === 0) return null;\n\n return (\n <VStack w=\"full\" align=\"flex-start\" spacing={2}>\n <Text fontSize=\"sm\" fontWeight=\"500\">\n {t('Shortcuts')}\n </Text>\n <Grid templateColumns=\"repeat(4, 1fr)\" gap={2} w=\"full\">\n {shortcuts.map((shortcut) => (\n <GridItem key={shortcut.url}>\n <Card\n _hover={{ opacity: 0.8 }}\n cursor=\"pointer\"\n onClick={() => window.open(shortcut.url, '_blank')}\n >\n <CardBody p={2} alignItems=\"center\">\n <Image\n src={shortcut.image}\n fallbackSrc={notFoundImage}\n alt={shortcut.name}\n objectFit=\"contain\"\n rounded=\"full\"\n />\n </CardBody>\n </Card>\n </GridItem>\n ))}\n </Grid>\n </VStack>\n );\n};\n","import { Box, Tag, Text, Wrap, WrapItem } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { CategoryLabel, AllowedCategories } from './CategoryLabel';\n\nexport type CategoryFilter = string | null;\n\ntype CategoryFilterSectionProps = {\n selectedCategory: CategoryFilter;\n onCategoryChange: (category: CategoryFilter) => void;\n categories: AllowedCategories[];\n darkMode: boolean;\n};\n\nexport const CategoryFilterSection = ({\n selectedCategory,\n onCategoryChange,\n categories,\n darkMode,\n}: CategoryFilterSectionProps) => {\n const { t } = useTranslation();\n\n return (\n <Box width=\"full\" mb={4}>\n <Text fontSize=\"sm\" fontWeight=\"500\" mb={2}>\n {t('Filter by category')}\n </Text>\n <Wrap spacing={2}>\n <WrapItem>\n <Tag\n size=\"md\"\n borderRadius=\"full\"\n variant={\n selectedCategory === null ? 'solid' : 'outline'\n }\n colorScheme={darkMode ? 'gray' : 'blackAlpha'}\n cursor=\"pointer\"\n onClick={() => onCategoryChange(null)}\n >\n {t('All')}\n </Tag>\n </WrapItem>\n\n {categories.map((category) => (\n <WrapItem key={category}>\n <CategoryLabel\n category={category}\n size=\"md\"\n variant={\n selectedCategory === category\n ? 'solid'\n : 'outline'\n }\n cursor=\"pointer\"\n onClick={() => onCategoryChange(category)}\n />\n </WrapItem>\n ))}\n </Wrap>\n </Box>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Input,\n InputGroup,\n InputLeftElement,\n Grid,\n GridItem,\n ModalFooter,\n Text,\n Spinner,\n Center,\n useToken,\n} from '@chakra-ui/react';\nimport { LuSearch } from 'react-icons/lu';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport React, { useState, useMemo, useEffect } from 'react';\nimport {\n useCurrentAllocationsRoundId,\n useEcosystemShortcuts,\n useMostVotedAppsInRound,\n XAppMetadata,\n} from '@/hooks';\nimport { useAppHubApps, AppHubApp } from '@/hooks';\nimport { AppComponent } from './Components/AppComponent';\nimport { CustomAppComponent } from './Components/CustomAppComponent';\nimport { ShortcutsSection } from './Components/ShortcutsSection';\nimport {\n CategoryFilterSection,\n CategoryFilter,\n} from './Components/CategoryFilterSection';\nimport { AllowedCategories } from './Components/CategoryLabel';\nimport { useAccountModalOptions } from '@/hooks/modals/useAccountModalOptions';\nimport {\n VEBETTERDAO_GOVERNANCE_BASE_URL,\n VET_DOMAINS_BASE_URL,\n COINMARKETCAP_STATIC_BASE_URL,\n} from '@/constants';\n\nexport type EcosystemWithCategoryProps = {\n selectedCategory: CategoryFilter;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n};\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n selectedCategory?: CategoryFilter;\n};\n\n// Mock data - Replace with real data from your API\nconst DEFAULT_APPS: XAppMetadata[] = [\n {\n name: 'VeBetterDAO',\n description: 'Engage, earn and prosper by doing sustainable actions.',\n external_url: VEBETTERDAO_GOVERNANCE_BASE_URL,\n logo: new URL(\n '/static/img/coins/64x64/33509.png',\n COINMARKETCAP_STATIC_BASE_URL,\n ).toString(),\n banner: new URL(\n '/static/img/icons/vbd.png',\n COINMARKETCAP_STATIC_BASE_URL,\n ).toString(),\n screenshots: [],\n social_urls: [],\n app_urls: [],\n tweets: [],\n ve_world: {\n banner: new URL(\n '/static/img/icons/vbd.png',\n COINMARKETCAP_STATIC_BASE_URL,\n ).toString(),\n },\n categories: [],\n },\n {\n name: 'vet.domains',\n description:\n '.vet.domains provides a unique and unchangeable identity for Vechain users by linking information to their wallet addresses. It becomes easier for people to use the blockchain by replacing complicated wallet addresses with easy-to-remember names.',\n external_url: VET_DOMAINS_BASE_URL,\n logo: new URL(\n '/assets/walletconnect.png',\n VET_DOMAINS_BASE_URL,\n ).toString(),\n banner: new URL(\n '/assets/walletconnect.png',\n VET_DOMAINS_BASE_URL,\n ).toString(),\n screenshots: [],\n social_urls: [],\n app_urls: [],\n tweets: [],\n ve_world: {\n banner: new URL(\n '/assets/walletconnect.png',\n VET_DOMAINS_BASE_URL,\n ).toString(),\n },\n categories: [],\n },\n];\n\nexport const ExploreEcosystemContent = ({\n setCurrentContent,\n selectedCategory,\n}: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark, network } = useVeChainKitConfig();\n const { isolatedView } = useAccountModalOptions();\n\n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const [searchQuery, setSearchQuery] = useState('');\n\n // Initialize currentCategory with selectedCategory or null\n const [currentCategory, setCurrentCategory] = useState<CategoryFilter>(\n selectedCategory || null,\n );\n\n // Update currentCategory when selectedCategory changes\n useEffect(() => {\n if (selectedCategory !== undefined) {\n setCurrentCategory(selectedCategory);\n }\n }, [selectedCategory]);\n\n const { data: currentRoundId } = useCurrentAllocationsRoundId();\n const { data: vbdApps } = useMostVotedAppsInRound(\n currentRoundId ? (parseInt(currentRoundId) - 1).toString() : '1',\n );\n const {\n data: appHubApps,\n isLoading: appHubLoading,\n error: appHubError,\n } = useAppHubApps();\n\n // Extract unique categories from app hub apps and add VeBetter category\n const categories = useMemo(() => {\n const categorySet = new Set<AllowedCategories>();\n\n // Add VeBetter category if there are VBD apps and we're on mainnet\n if (network.type === 'main' && vbdApps && vbdApps.length > 0) {\n categorySet.add('vebetter');\n }\n\n // Add categories from app hub\n if (appHubApps) {\n appHubApps.forEach((app) => {\n if (app.category) {\n categorySet.add(app.category);\n }\n });\n }\n\n return Array.from(categorySet).sort();\n }, [appHubApps, vbdApps, network.type]);\n\n // Only show VBD apps if we're on mainnet\n const isMainnet = network.type === 'main';\n\n // Filter VeBetterDAO apps based on search query\n const filteredVbdApps = isMainnet\n ? vbdApps.filter((dapp) =>\n dapp.app.name.toLowerCase().includes(searchQuery.toLowerCase()),\n )\n : [];\n\n // Filter default apps based on search query\n const filteredDefaultApps = DEFAULT_APPS.filter((dapp) =>\n dapp.name.toLowerCase().includes(searchQuery.toLowerCase()),\n );\n\n // Filter App Hub apps based on search query and selected category\n const filteredAppHubApps =\n appHubApps?.filter(\n (app: AppHubApp) =>\n // Text search filter\n (app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n app.description\n .toLowerCase()\n .includes(searchQuery.toLowerCase()) ||\n app.tags.some((tag: string) =>\n tag.toLowerCase().includes(searchQuery.toLowerCase()),\n )) &&\n // Category filter\n (currentCategory === null || app.category === currentCategory),\n ) || [];\n\n // Determine which apps to display based on category filter\n const shouldShowDefaultApps = currentCategory === null;\n const shouldShowVbdApps =\n currentCategory === null || currentCategory === 'vebetter';\n\n const { shortcuts } = useEcosystemShortcuts();\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchQuery(e.target.value);\n };\n\n const handleCategoryChange = (category: CategoryFilter) => {\n setCurrentCategory(category);\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Ecosystem')}</ModalHeader>\n {!isolatedView && (\n <ModalBackButton\n onClick={() => setCurrentContent('settings')}\n />\n )}\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody overflowY=\"auto\" minH=\"300px\">\n <VStack spacing={6} w=\"full\">\n <ShortcutsSection setCurrentContent={setCurrentContent} />\n\n {shortcuts.length > 0 && (\n <Text\n fontSize=\"sm\"\n fontWeight=\"500\"\n w=\"full\"\n textAlign=\"left\"\n >\n {t('All apps')}\n </Text>\n )}\n <InputGroup size=\"lg\">\n <Input\n placeholder={t('Search Apps')}\n value={searchQuery}\n onChange={handleSearchChange}\n bg={isDark ? '#00000038' : 'gray.50'}\n borderRadius=\"xl\"\n height=\"56px\"\n pl={12}\n />\n <InputLeftElement h=\"56px\" w=\"56px\" pl={4}>\n <LuSearch color={textTertiary} />\n </InputLeftElement>\n </InputGroup>\n\n {/* Category filter section */}\n {categories.length > 0 && (\n <CategoryFilterSection\n selectedCategory={currentCategory}\n onCategoryChange={handleCategoryChange}\n categories={categories}\n darkMode={isDark}\n />\n )}\n\n <Grid templateColumns=\"repeat(2, 1fr)\" gap={4} w=\"full\">\n {/* Default Apps */}\n {shouldShowDefaultApps &&\n filteredDefaultApps.length > 0 && (\n <>\n {filteredDefaultApps.map((dapp) => (\n <GridItem key={dapp.name}>\n <CustomAppComponent\n name={dapp.name}\n image={dapp.logo}\n url={dapp.external_url}\n setCurrentContent={\n setCurrentContent\n }\n description={dapp.description}\n selectedCategory={\n currentCategory\n }\n />\n </GridItem>\n ))}\n </>\n )}\n\n {/* VeBetterDAO Apps */}\n {shouldShowVbdApps && filteredVbdApps.length > 0 && (\n <>\n {filteredVbdApps.map((dapp) => (\n <GridItem key={dapp.id}>\n <AppComponent\n xApp={dapp.app}\n setCurrentContent={\n setCurrentContent\n }\n selectedCategory={currentCategory}\n />\n </GridItem>\n ))}\n </>\n )}\n\n {/* App Hub Apps */}\n {appHubLoading ? (\n <GridItem colSpan={2}>\n <Center py={4}>\n <Spinner />\n </Center>\n </GridItem>\n ) : appHubError ? (\n <GridItem colSpan={2}>\n <Text color=\"red.500\" textAlign=\"center\">\n {t('Failed to load App Hub apps')}\n </Text>\n </GridItem>\n ) : filteredAppHubApps.length > 0 ? (\n filteredAppHubApps.map((app: AppHubApp) => (\n <GridItem key={app.id}>\n <CustomAppComponent\n name={app.name}\n image={app.logo}\n url={app.url}\n setCurrentContent={setCurrentContent}\n description={app.description}\n category={app.category}\n selectedCategory={currentCategory}\n />\n </GridItem>\n ))\n ) : (\n currentCategory &&\n !shouldShowVbdApps && (\n <GridItem colSpan={2}>\n <Center py={4}>\n <Text>\n {t(\n 'No apps found in this category',\n )}\n </Text>\n </Center>\n </GridItem>\n )\n )}\n </Grid>\n </VStack>\n </ModalBody>\n\n <ModalFooter pt={0} />\n </>\n );\n};\n","import { Button, Icon } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { LuBookmark, LuBookmarkCheck } from 'react-icons/lu';\nimport { useEcosystemShortcuts } from '@/hooks';\n\ntype Props = {\n name: string;\n image: string;\n url: string;\n description?: string;\n};\n\nexport const ShortcutButton = ({ name, image, url, description }: Props) => {\n const { t } = useTranslation();\n const { isShortcut, addShortcut, removeShortcut } = useEcosystemShortcuts();\n const hasShortcut = isShortcut(url);\n\n const handleShortcutClick = () => {\n if (hasShortcut) {\n removeShortcut(url);\n } else {\n addShortcut({ name, image, url, description });\n }\n };\n\n return (\n <Button\n px={4}\n width=\"full\"\n height=\"45px\"\n variant=\"vechainKitSecondary\"\n borderRadius=\"xl\"\n onClick={handleShortcutClick}\n leftIcon={<Icon as={hasShortcut ? LuBookmarkCheck : LuBookmark} />}\n >\n {hasShortcut ? t('Remove from shortcuts') : t('Add to shortcuts')}\n </Button>\n );\n};\n","import {\n Button,\n Icon,\n Image,\n ModalBody,\n ModalCloseButton,\n ModalFooter,\n ModalHeader,\n Text,\n VStack,\n Flex,\n HStack,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { LuExternalLink } from 'react-icons/lu';\nimport { ShortcutButton } from './Components/ShortcutButton';\nimport { CategoryLabel, AllowedCategories } from './Components/CategoryLabel';\nimport { CategoryFilter } from './Components/CategoryFilterSection';\n\nexport type AppOverviewContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n name: string;\n image: string;\n url: string;\n description: string;\n category?: AllowedCategories;\n selectedCategory?: CategoryFilter;\n logoComponent?: JSX.Element;\n};\n\nexport const AppOverviewContent = ({\n setCurrentContent,\n name,\n image,\n url,\n description,\n category,\n selectedCategory,\n logoComponent,\n}: AppOverviewContentProps) => {\n const { t } = useTranslation();\n\n const handleLaunchApp = () => {\n window.open(url, '_blank');\n };\n\n const handleBackClick = () => {\n if (selectedCategory) {\n setCurrentContent({\n type: 'ecosystem-with-category',\n props: {\n selectedCategory,\n setCurrentContent,\n },\n });\n } else {\n setCurrentContent('ecosystem');\n }\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{name}</ModalHeader>\n <ModalBackButton onClick={handleBackClick} />\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={6} align=\"center\" w=\"full\">\n <Flex direction=\"column\" align=\"center\">\n {logoComponent ? (\n logoComponent\n ) : (\n <Image\n src={image}\n alt={name}\n w={'200px'}\n h={'200px'}\n objectFit=\"contain\"\n borderRadius={'xl'}\n />\n )}\n\n {category && (\n <HStack mt={2}>\n <CategoryLabel category={category} />\n </HStack>\n )}\n </Flex>\n\n <Text fontSize=\"sm\" textAlign=\"center\">\n {description}\n </Text>\n\n <Text fontSize=\"sm\" textAlign=\"center\">\n {t(\n 'Click below to access {{ name }} and explore its features.',\n { name },\n )}\n </Text>\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <VStack w=\"full\" spacing={4}>\n <Button\n variant=\"vechainKitSecondary\"\n onClick={handleLaunchApp}\n >\n {t('Launch {{name}}', { name })}\n <Icon as={LuExternalLink} ml={2} />\n </Button>\n\n <ShortcutButton\n name={name}\n image={image}\n url={url}\n description={description}\n />\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import { Box, HStack, Link } from '@chakra-ui/react';\nimport { motion } from 'framer-motion';\nimport { FaTelegramPlane, FaWhatsapp } from 'react-icons/fa';\nimport { FaXTwitter } from 'react-icons/fa6';\nimport React from 'react';\nimport { useVeChainKitConfig } from '@/providers';\nimport { TELEGRAM_BASE_URL, TWITTER_BASE_URL, WHATSAPP_BASE_URL } from '@/constants';\n\n// bouncing circle button animation provider\nconst BouncingAnimation = ({ children }: { children: React.ReactNode }) => (\n <motion.div\n whileHover={{ scale: 1.1 }}\n transition={{\n duration: 0.5,\n ease: 'easeInOut',\n repeat: Infinity,\n repeatDelay:\n (crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32) * 5,\n }}\n animate={{\n y: [0, -2, 0],\n rotate: [0, 10, -10, 0],\n }}\n >\n {children}\n </motion.div>\n);\n\ntype Props = {\n description: string;\n url?: string;\n facebookHashtag?: string;\n};\n\nexport const ShareButtons = ({ description }: Props) => {\n const { darkMode: isDark } = useVeChainKitConfig();\n\n // `description` is treated as raw text; use URLSearchParams so values are encoded.\n const twitterUrl = new URL('intent/tweet', TWITTER_BASE_URL);\n twitterUrl.searchParams.set('text', description);\n\n const telegramUrl = new URL('share/url', TELEGRAM_BASE_URL);\n telegramUrl.searchParams.set('url', description);\n\n const whatsappUrl = new URL('', WHATSAPP_BASE_URL);\n whatsappUrl.searchParams.set('text', description);\n\n return (\n <HStack gap={2}>\n <BouncingAnimation>\n <Link href={twitterUrl.toString()} isExternal>\n <Box\n bg={isDark ? 'blackAlpha.700' : 'lightgrey'}\n p={2}\n borderRadius={'full'}\n >\n <FaXTwitter size={22} />\n </Box>\n </Link>\n </BouncingAnimation>\n <BouncingAnimation>\n <Link href={telegramUrl.toString()} isExternal>\n <Box bg={'#30abec'} p={2} borderRadius={'full'}>\n <FaTelegramPlane color=\"white\" size={22} />\n </Box>\n </Link>\n </BouncingAnimation>\n <BouncingAnimation>\n <Link href={whatsappUrl.toString()} isExternal>\n <Box bg={'#01cb37'} p={2} borderRadius={'full'}>\n <FaWhatsapp size={22} color=\"white\" />\n </Box>\n </Link>\n </BouncingAnimation>\n </HStack>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Button,\n ModalFooter,\n Icon,\n Link,\n HStack,\n Spinner,\n useToken,\n} from '@chakra-ui/react';\nimport { ReactNode, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getConfig } from '@/config';\nimport {\n LuExternalLink,\n LuCircleCheck,\n LuCircleAlert,\n LuRefreshCw,\n} from 'react-icons/lu';\nimport { ShareButtons } from './Components/ShareButtons';\nimport { StickyHeaderContainer } from '../common';\nimport { TransactionModalProps } from './TransactionModal';\n\ntype StatusConfig = {\n title: ReactNode;\n icon: ReactNode;\n description: string;\n};\n\nexport const TransactionModalContent = ({\n status,\n uiConfig,\n onTryAgain,\n txReceipt,\n txError,\n onClose,\n}: Omit<TransactionModalProps, 'isOpen'>) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n\n const errorColor = useToken('colors', 'vechain-kit-error');\n const successColor = useToken('colors', 'vechain-kit-success');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const errorMessage = useMemo(() => {\n if (!txError) return null;\n return (\n (txError as any).reason ||\n t('Something went wrong. Please try again.')\n );\n }, [txError, t]);\n\n const getStatusConfig = (): StatusConfig => {\n // overwrite status to avoid flickering\n const isSendingTransaction = status === 'waitingConfirmation';\n if (isSendingTransaction) {\n status = 'pending';\n }\n switch (status) {\n case 'pending':\n return {\n title:\n uiConfig?.title ??\n (isSendingTransaction\n ? t('Sending Transaction...')\n : t('Waiting for confirmation')),\n icon: uiConfig?.loadingIcon ?? (\n <Spinner\n size=\"xl\"\n data-testid=\"pending-spinner-modal\"\n />\n ),\n description: isSendingTransaction\n ? t(\n 'Transaction is being processed, it can take up to 15 seconds.',\n )\n : uiConfig?.description ??\n t('Please confirm the transaction in your wallet.'),\n };\n case 'error':\n return {\n title: t('Something went wrong'),\n icon: uiConfig?.errorIcon ?? (\n <Icon\n as={LuCircleAlert}\n color={errorColor}\n fontSize=\"100px\"\n data-testid=\"error-icon-modal\"\n />\n ),\n description:\n errorMessage ?? t('An unexpected error occurred.'),\n };\n case 'success':\n return {\n title: t('Transaction successful!'),\n icon: uiConfig?.successIcon ?? (\n <Icon\n as={LuCircleCheck}\n color={successColor}\n fontSize=\"100px\"\n data-testid=\"success-icon-modal\"\n />\n ),\n description: '',\n };\n case 'ready':\n return {\n title: uiConfig?.title ?? t('Confirm transaction'),\n icon: null,\n description:\n uiConfig?.description ??\n t(\n 'Confirm the transaction in your wallet to complete it.',\n ),\n };\n default:\n return {\n title: '',\n icon: null,\n description: '',\n };\n }\n };\n\n const statusConfig = getStatusConfig();\n const socialDescription = `${getConfig(network.type).explorerUrl}/${\n txReceipt?.meta.txID\n }`;\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{statusConfig.title}</ModalHeader>\n <ModalCloseButton\n isDisabled={status === 'pending' && !uiConfig?.isClosable}\n />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack align=\"center\" p={6} spacing={3}>\n {statusConfig.icon}\n\n {status === 'success' && uiConfig?.showShareOnSocials && (\n <VStack mt={2} spacing={3}>\n <Text\n fontSize=\"sm\"\n fontWeight={'bold'}\n color={textSecondary}\n >\n {t('Share on')}\n </Text>\n <ShareButtons description={socialDescription} />\n </VStack>\n )}\n\n {statusConfig.description && (\n <Text\n fontSize={status === 'ready' ? 'md' : 'sm'}\n textAlign=\"center\"\n color={\n status === 'error' ? errorColor : textPrimary\n }\n mt={5}\n style={{\n lineBreak: 'anywhere',\n }}\n >\n {statusConfig.description}\n </Text>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter justifyContent=\"center\">\n <VStack width=\"full\" spacing={4}>\n {status === 'error' && !!onTryAgain && (\n <Button\n variant=\"vechainKitPrimary\"\n onClick={onTryAgain}\n width=\"full\"\n >\n <Icon mr={2} as={LuRefreshCw} />\n {t('Try again')}\n </Button>\n )}\n\n {status === 'ready' && (\n <Button\n onClick={onTryAgain}\n variant=\"vechainKitPrimary\"\n width=\"full\"\n >\n {t('Confirm')}\n </Button>\n )}\n\n {(status === 'success' ||\n status === 'error' ||\n status === 'ready') && (\n <Button onClick={onClose} variant=\"ghost\" width=\"full\">\n {t('Close')}\n </Button>\n )}\n\n {uiConfig?.showExplorerButton && txReceipt?.meta.txID && (\n <Link\n href={`${getConfig(network.type).explorerUrl}/${\n txReceipt?.meta.txID\n }`}\n isExternal\n opacity={0.5}\n fontSize=\"14px\"\n textDecoration=\"underline\"\n >\n <HStack\n spacing={1}\n alignItems=\"center\"\n w=\"full\"\n justifyContent=\"center\"\n >\n <Text color={textSecondary}>\n {t('View transaction on the explorer')}\n </Text>\n <Icon\n size=\"sm\"\n as={LuExternalLink}\n color={textSecondary}\n />\n </HStack>\n </Link>\n )}\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import { ReactNode } from 'react';\nimport { BaseModal } from '../common/BaseModal';\nimport { TransactionModalContent } from './TransactionModalContent';\nimport { TransactionStatus, TransactionStatusErrorType } from '@/types';\nimport { TransactionReceipt } from '@vechain/sdk-network';\nimport { useVeChainKitConfig, VechainKitThemeProvider } from '@/providers';\nexport type TransactionModalProps = {\n isOpen: boolean;\n onClose: () => void;\n onTryAgain: () => void;\n status: TransactionStatus;\n txReceipt: TransactionReceipt | null;\n txError?: Error | TransactionStatusErrorType;\n uiConfig?: {\n isClosable?: boolean;\n showShareOnSocials?: boolean;\n showExplorerButton?: boolean;\n loadingIcon?: ReactNode;\n successIcon?: ReactNode;\n errorIcon?: ReactNode;\n title?: ReactNode;\n description?: string;\n showSocialButtons?: boolean;\n };\n};\n\nexport const TransactionModal = ({\n isOpen,\n onClose,\n status,\n uiConfig,\n txReceipt,\n txError,\n onTryAgain,\n}: TransactionModalProps) => {\n const { darkMode, theme } = useVeChainKitConfig();\n\n // avoid deep nesting and unnecessary rendering\n if (!isOpen) return null;\n\n return (\n <VechainKitThemeProvider darkMode={darkMode} theme={theme}>\n <BaseModal\n isOpen={isOpen}\n onClose={onClose}\n allowExternalFocus={true}\n blockScrollOnMount={true}\n closeOnOverlayClick={\n status !== 'pending' && uiConfig?.isClosable\n }\n >\n <TransactionModalContent\n status={status}\n onTryAgain={onTryAgain}\n uiConfig={uiConfig}\n txReceipt={txReceipt}\n onClose={onClose}\n txError={txError}\n />\n </BaseModal>\n </VechainKitThemeProvider>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Button,\n ModalFooter,\n Icon,\n Link,\n HStack,\n useToken,\n} from '@chakra-ui/react';\nimport { StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getConfig } from '@/config';\nimport { LuExternalLink, LuCircleCheck } from 'react-icons/lu';\nimport { ShareButtons } from '@/components/TransactionModal';\n\nexport type SuccessfulOperationContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n txId?: string;\n title: string;\n description?: string;\n onDone: () => void;\n showSocialButtons?: boolean;\n};\n\nexport const SuccessfulOperationContent = ({\n txId,\n title,\n description,\n onDone,\n showSocialButtons = false,\n}: SuccessfulOperationContentProps) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const explorerUrl = getConfig(network.type).explorerUrl;\n const socialDescription = `${explorerUrl}/${txId}`;\n\n const successColor = useToken('colors', 'vechain-kit-success');\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{title}</ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack align={'center'} p={6} spacing={3}>\n <Icon\n as={LuCircleCheck}\n fontSize={'100px'}\n color={successColor}\n data-testid=\"success-icon\"\n />\n\n {description && (\n <Text\n fontSize=\"sm\"\n textAlign=\"center\"\n color={textPrimary}\n >\n {description}\n </Text>\n )}\n\n {showSocialButtons && txId && (\n <VStack mt={2} spacing={3}>\n <Text\n fontSize=\"sm\"\n fontWeight={'bold'}\n color={textSecondary}\n >\n {t('Share on')}\n </Text>\n <ShareButtons description={socialDescription} />\n </VStack>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter justifyContent={'center'}>\n <VStack width=\"full\" spacing={4}>\n <Button\n onClick={onDone}\n variant=\"vechainKitSecondary\"\n width=\"full\"\n >\n {t('Done')}\n </Button>\n\n {txId && (\n <Link\n href={`${explorerUrl}/${txId}`}\n isExternal\n opacity={0.5}\n fontSize={'14px'}\n textDecoration={'underline'}\n >\n <HStack\n spacing={1}\n alignItems={'center'}\n w={'full'}\n justifyContent={'center'}\n >\n <Text color={textSecondary}>\n {t('View transaction on the explorer')}\n </Text>\n <Icon size={16} as={LuExternalLink} />\n </HStack>\n </Link>\n )}\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Button,\n ModalFooter,\n Icon,\n Link,\n HStack,\n} from '@chakra-ui/react';\nimport { StickyHeaderContainer } from '@/components/common';\nimport { AccountModalContentTypes } from '../../Types';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getConfig } from '@/config';\nimport { LuExternalLink, LuCircleAlert } from 'react-icons/lu';\n\nexport type FailedOperationContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n txId?: string;\n title: string;\n description?: string;\n onDone: () => void;\n};\n\nexport const FailedOperationContent = ({\n txId,\n title,\n description,\n onDone,\n}: FailedOperationContentProps) => {\n const { t } = useTranslation();\n const { network, darkMode } = useVeChainKitConfig();\n const explorerUrl = getConfig(network.type).explorerUrl;\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{title}</ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack align={'center'} p={6} spacing={3}>\n <Icon\n as={LuCircleAlert}\n fontSize={'100px'}\n color={darkMode ? 'red.400' : 'red.500'}\n data-testid=\"error-icon\"\n />\n\n {description && (\n <Text fontSize=\"sm\" textAlign=\"center\">\n {description}\n </Text>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter justifyContent={'center'}>\n <VStack width=\"full\" spacing={4}>\n <Button\n onClick={onDone}\n variant=\"vechainKitSecondary\"\n width=\"full\"\n >\n {t('Done')}\n </Button>\n\n {txId && (\n <Link\n href={`${explorerUrl}/${txId}`}\n isExternal\n opacity={0.5}\n fontSize={'14px'}\n textDecoration={'underline'}\n >\n <HStack\n spacing={1}\n alignItems={'center'}\n w={'full'}\n justifyContent={'center'}\n >\n <Text>\n {t('View transaction on the explorer')}\n </Text>\n <Icon size={16} as={LuExternalLink} />\n </HStack>\n </Link>\n )}\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","'use client';\n\nimport { useWallet } from '@/hooks';\nimport { BaseModal } from '@/components/common';\nimport {\n AccountMainContent,\n SettingsContent,\n SendTokenContent,\n SendTokenSummaryContent,\n ReceiveTokenContent,\n SwapTokenContent,\n ChooseNameContent,\n ChooseNameSearchContent,\n ChooseNameSummaryContent,\n FAQContent,\n ProfileContent,\n AssetsContent,\n LanguageSettingsContent,\n TermsAndPrivacyContent,\n GasTokenSettingsContent,\n SelectWalletContent,\n RemoveWalletConfirmContent,\n} from './Contents';\nimport { AccountModalContentTypes } from './Types/Types';\nimport { ConnectionDetailsContent } from './Contents/ConnectionDetails';\nimport { PrivyLinkedAccounts } from './Contents/PrivyLinkedAccounts';\nimport { NotificationsContent } from './Contents/Notifications/NotificationContent';\nimport { ExploreEcosystemContent } from './Contents/Ecosystem/ExploreEcosystemContent';\nimport { AppOverviewContent } from './Contents/Ecosystem/AppOverviewContent';\nimport { DisconnectConfirmContent } from './Contents/DisconnectConfirmation';\nimport { CustomizationContent, CustomizationSummaryContent } from './Contents';\nimport { SuccessfulOperationContent } from './Contents/SuccessfulOperation/SuccessfulOperationContent';\nimport { FailedOperationContent } from './Contents/FailedOperation/FailedOperationContent';\nimport { ManageCustomTokenContent } from './Contents/Assets/ManageCustomTokenContent';\nimport { UpgradeSmartAccountContent } from './Contents/UpgradeSmartAccount';\nimport { useModal } from '@/providers/ModalProvider';\nimport { ChangeCurrencyContent } from './Contents/KitSettings';\nimport { useVechainKitThemeConfig } from '@/providers';\nimport { useEffect } from 'react';\n\ntype Props = {\n isOpen: boolean;\n onClose: () => void;\n initialContent?: AccountModalContentTypes;\n};\n\nexport const AccountModal = ({\n isOpen,\n onClose,\n initialContent = 'profile',\n}: Props) => {\n const { account } = useWallet();\n const { themeConfig } = useVechainKitThemeConfig();\n\n const {\n accountModalContent: currentContent,\n setAccountModalContent: setCurrentContent,\n } = useModal();\n\n // Reset refs and set initial content when modal opens\n useEffect(() => {\n if (isOpen) {\n // Modal just opened - reset everything and use initialContent\n setCurrentContent(initialContent);\n }\n }, [isOpen, initialContent, setCurrentContent]);\n\n const renderContent = () => {\n if (typeof currentContent === 'object') {\n switch (currentContent.type) {\n case 'send-token':\n return <SendTokenContent {...currentContent.props} />;\n case 'send-token-summary':\n return (\n <SendTokenSummaryContent {...currentContent.props} />\n );\n case 'swap-token':\n return <SwapTokenContent {...currentContent.props} />;\n case 'choose-name':\n return <ChooseNameContent {...currentContent.props} />;\n case 'choose-name-search':\n return (\n <ChooseNameSearchContent {...currentContent.props} />\n );\n case 'choose-name-summary':\n return (\n <ChooseNameSummaryContent {...currentContent.props} />\n );\n case 'app-overview':\n return (\n <AppOverviewContent\n {...currentContent.props}\n setCurrentContent={setCurrentContent}\n />\n );\n case 'disconnect-confirm':\n return (\n <DisconnectConfirmContent {...currentContent.props} />\n );\n case 'remove-wallet-confirm':\n return (\n <RemoveWalletConfirmContent {...currentContent.props} />\n );\n case 'account-customization':\n return <CustomizationContent {...currentContent.props} />;\n case 'account-customization-summary':\n return (\n <CustomizationSummaryContent\n {...currentContent.props}\n />\n );\n case 'successful-operation':\n return (\n <SuccessfulOperationContent {...currentContent.props} />\n );\n case 'failed-operation':\n return <FailedOperationContent {...currentContent.props} />;\n case 'upgrade-smart-account':\n return (\n <UpgradeSmartAccountContent {...currentContent.props} />\n );\n case 'faq':\n return <FAQContent {...currentContent.props} />;\n case 'terms-and-privacy':\n return <TermsAndPrivacyContent {...currentContent.props} />;\n case 'ecosystem-with-category':\n return (\n <ExploreEcosystemContent\n setCurrentContent={setCurrentContent}\n selectedCategory={\n currentContent.props.selectedCategory\n }\n />\n );\n case 'select-wallet':\n return (\n <SelectWalletContent\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n returnTo={currentContent.props.returnTo}\n onLogoutSuccess={\n currentContent.props.onLogoutSuccess\n }\n />\n );\n case 'main':\n return (\n <AccountMainContent\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n wallet={account}\n switchFeedback={currentContent.props?.switchFeedback}\n />\n );\n case 'profile':\n return (\n <ProfileContent\n setCurrentContent={setCurrentContent}\n onLogoutSuccess={() => {\n onClose();\n }}\n switchFeedback={currentContent.props?.switchFeedback}\n />\n );\n }\n }\n\n switch (currentContent) {\n case 'main':\n return (\n <AccountMainContent\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n wallet={account}\n />\n );\n case 'settings':\n return (\n <SettingsContent\n setCurrentContent={setCurrentContent}\n onLogoutSuccess={() => {\n onClose();\n }}\n />\n );\n case 'profile':\n return (\n <ProfileContent\n setCurrentContent={setCurrentContent}\n onLogoutSuccess={() => {\n onClose();\n }}\n />\n );\n case 'assets':\n return <AssetsContent setCurrentContent={setCurrentContent} />;\n case 'notifications':\n return (\n <NotificationsContent\n setCurrentContent={setCurrentContent}\n />\n );\n case 'receive-token':\n return (\n <ReceiveTokenContent\n setCurrentContent={setCurrentContent}\n />\n );\n case 'swap-token':\n return (\n <SwapTokenContent setCurrentContent={setCurrentContent} />\n );\n case 'connection-details':\n return (\n <ConnectionDetailsContent\n onGoBack={() => setCurrentContent('settings')}\n />\n );\n case 'privy-linked-accounts':\n return (\n <PrivyLinkedAccounts\n onBack={() => setCurrentContent('settings')}\n />\n );\n case 'ecosystem':\n return (\n <ExploreEcosystemContent\n setCurrentContent={setCurrentContent}\n />\n );\n case 'add-custom-token':\n return (\n <ManageCustomTokenContent\n setCurrentContent={setCurrentContent}\n />\n );\n case 'change-currency':\n return (\n <ChangeCurrencyContent\n setCurrentContent={setCurrentContent}\n />\n );\n case 'change-language':\n return (\n <LanguageSettingsContent\n setCurrentContent={setCurrentContent}\n />\n );\n case 'gas-token-settings':\n return (\n <GasTokenSettingsContent\n setCurrentContent={setCurrentContent}\n />\n );\n default:\n return null;\n }\n };\n\n return (\n <BaseModal\n isOpen={isOpen}\n onClose={onClose}\n allowExternalFocus={true}\n blockScrollOnMount={true}\n mobileMinHeight={\n themeConfig?.modal?.useBottomSheetOnMobile ? '520px' : '510px'\n }\n mobileMaxHeight={\n themeConfig?.modal?.useBottomSheetOnMobile ? '520px' : '510px'\n }\n desktopMinHeight={'485px'}\n desktopMaxHeight={'485px'}\n >\n {renderContent()}\n </BaseModal>\n );\n};\n","import {\n ModalBody,\n ModalHeader,\n ModalCloseButton,\n Spinner,\n VStack,\n Text,\n ModalFooter,\n Icon,\n Button,\n} from '@chakra-ui/react';\nimport { StickyHeaderContainer, ModalBackButton } from '@/components/common';\nimport { LuRefreshCw } from 'react-icons/lu';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\n\ntype LoadingContentProps = {\n loadingText?: string;\n title?: string;\n onTryAgain?: () => void;\n onClose: () => void;\n onGoBack: () => void;\n showBackButton?: boolean;\n};\n\nexport const LoadingContent = ({\n loadingText,\n title,\n onTryAgain,\n onClose,\n onGoBack,\n showBackButton = true,\n}: LoadingContentProps) => {\n const { t } = useTranslation();\n const [showTimeout, setShowTimeout] = React.useState(false);\n\n React.useEffect(() => {\n const timer = setTimeout(() => {\n setShowTimeout(true);\n }, 7000);\n\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>\n {showBackButton && <ModalBackButton onClick={onGoBack} />}\n {title ?? t('Connecting...')}\n <ModalCloseButton onClick={onClose} />\n </ModalHeader>\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack\n align={'center'}\n p={6}\n gap={0}\n w={'full'}\n justifyContent={'center'}\n minH={'150px'}\n >\n <Spinner size=\"xl\" />\n </VStack>\n {loadingText && !showTimeout && (\n <Text size=\"sm\" textAlign={'center'}>\n {loadingText}\n </Text>\n )}\n {showTimeout && (\n <VStack mt={4} spacing={2}>\n <Text color=\"orange.300\" size=\"sm\" textAlign={'center'}>\n {t('This is taking longer than expected.')}\n </Text>\n <Text size=\"sm\" textAlign={'center'}>\n {t(\n 'You may want to try establishing the connection again.',\n )}\n </Text>\n </VStack>\n )}\n </ModalBody>\n <ModalFooter justifyContent={'center'}>\n {showTimeout && (\n <Button variant=\"vechainKitPrimary\" onClick={onTryAgain}>\n <Icon mr={2} as={LuRefreshCw} />\n {t('Try again')}\n </Button>\n )}\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalBody,\n ModalHeader,\n VStack,\n ModalCloseButton,\n Text,\n ModalFooter,\n Icon,\n Button,\n} from '@chakra-ui/react';\nimport { StickyHeaderContainer, ModalBackButton } from '@/components/common';\nimport { LuCircleAlert, LuRefreshCw } from 'react-icons/lu';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { useTranslation } from 'react-i18next';\n\ntype ErrorContentProps = {\n error: string;\n onClose: () => void;\n onTryAgain: () => void;\n onGoBack: () => void;\n};\n\nexport const ErrorContent = ({\n error,\n onClose,\n onTryAgain,\n onGoBack,\n}: ErrorContentProps) => {\n const { t } = useTranslation();\n const shouldReduceMotion = useReducedMotion();\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>\n <ModalBackButton onClick={onGoBack} />\n {t('Connection Failed')}\n <ModalCloseButton onClick={onClose} />\n </ModalHeader>\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack\n align={'center'}\n p={6}\n w={'full'}\n justifyContent={'center'}\n minH={'100px'}\n gap={4}\n >\n <motion.div\n transition={{\n duration: 4,\n ease: 'easeInOut',\n repeat: shouldReduceMotion ? 0 : Infinity,\n }}\n animate={{\n scale: shouldReduceMotion ? [1] : [1, 1.1, 1],\n }}\n >\n <Icon\n as={LuCircleAlert}\n color={'#ef4444'}\n fontSize={'60px'}\n opacity={0.5}\n />\n </motion.div>\n <Text w={'full'} size=\"sm\" textAlign={'center'}>\n {error}\n </Text>\n </VStack>\n </ModalBody>\n <ModalFooter justifyContent={'center'}>\n <Button variant=\"vechainKitPrimary\" onClick={onTryAgain}>\n <Icon mr={2} as={LuRefreshCw} />\n {t('Try again')}\n </Button>\n </ModalFooter>\n </>\n );\n};\n","import {\n Box,\n Button,\n Image,\n ModalBody,\n ModalCloseButton,\n ModalFooter,\n ModalHeader,\n Spinner,\n Text,\n VStack,\n useToken,\n} from '@chakra-ui/react';\nimport { ModalBackButton, StickyHeaderContainer } from '@/components/common';\nimport { useCrossAppConnectionCache } from '@/hooks';\nimport { usePrivyCrossAppSdk } from '@/providers/PrivyCrossAppProvider';\nimport { useTranslation } from 'react-i18next';\nimport { PrivyAppInfo } from '@/types';\nimport { isRejectionError } from '@/utils/stringUtils';\nimport { ConnectModalContentsTypes } from '../ConnectModal';\ntype Props = {\n onClose: () => void;\n appsInfo: PrivyAppInfo[];\n isLoading: boolean;\n setCurrentContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n showBackButton?: boolean;\n};\n\nexport const EcosystemContent = ({\n onClose,\n appsInfo,\n isLoading,\n setCurrentContent,\n showBackButton = true,\n}: Props) => {\n const { t } = useTranslation();\n\n // Use semantic token for text color (buttons use variants now)\n const textColor = useToken('colors', 'vechain-kit-text-primary');\n\n const { setConnectionCache } = useCrossAppConnectionCache();\n\n // Login with Vechain - Cross app account login\n const { login: loginWithCrossApp } = usePrivyCrossAppSdk();\n\n const connectWithVebetterDaoApps = async (\n appId: string,\n appName: string,\n ) => {\n setCurrentContent({\n type: 'loading',\n props: {\n title: `${t('Connecting with')} ${appName}`,\n loadingText: t(\n 'Please approve the request in the connection request window...',\n ),\n onTryAgain: () => {\n connectWithVebetterDaoApps(appId, appName);\n },\n },\n });\n try {\n await loginWithCrossApp(appId);\n setConnectionCache({\n name: appName,\n logoUrl: appsInfo.find((app) => app.id === appId)?.logo_url,\n appId: appId,\n website: appsInfo.find((app) => app.id === appId)?.website,\n });\n onClose();\n } catch (error) {\n const errorMsg = (error as { message?: string })?.message;\n\n // Handle user rejection or other errors\n if (errorMsg && isRejectionError(errorMsg)) {\n setCurrentContent({\n type: 'ecosystem',\n props: { appsInfo, isLoading: false },\n });\n return;\n }\n\n // If it's an Error instance, return it, otherwise create new Error\n const errorToShow =\n error instanceof Error\n ? error\n : new Error(\n 'An unexpected issue occurred while logging in with this app. Please try again or contact support.',\n );\n\n setCurrentContent({\n type: 'error',\n props: {\n error: errorToShow.message,\n onTryAgain: () => {\n connectWithVebetterDaoApps(appId, appName);\n },\n },\n });\n }\n };\n\n return (\n <Box>\n <>\n <StickyHeaderContainer>\n <ModalHeader>\n {showBackButton && (\n <ModalBackButton\n onClick={() => setCurrentContent('main')}\n />\n )}\n {t('Already have an x2earn app wallet?')}\n <ModalCloseButton onClick={onClose} />\n </ModalHeader>\n </StickyHeaderContainer>\n\n <ModalBody>\n {isLoading && (\n <VStack\n minH={'200px'}\n w={'full'}\n justifyContent={'center'}\n >\n <Spinner />\n </VStack>\n )}\n\n {!isLoading && appsInfo && (\n <VStack spacing={4} w={'full'} pb={6}>\n {appsInfo.map((appInfo) => (\n <Button\n key={appInfo.id}\n variant=\"loginIn\"\n fontSize={'14px'}\n fontWeight={'400'}\n p={6}\n borderRadius={16}\n w={'full'}\n onClick={() => {\n connectWithVebetterDaoApps(\n appInfo.id,\n appInfo.name,\n );\n }}\n justifyContent={'flex-start'}\n >\n <Image\n src={appInfo.logo_url}\n alt={appInfo.name}\n w={'30px'}\n />\n <Text ml={5}>{appInfo.name}</Text>\n </Button>\n ))}\n </VStack>\n )}\n\n {!isLoading && !appsInfo && (\n <Text textAlign={'center'} color={textColor}>\n {t(\n 'No application from VeChain ecosystem is available to login.',\n )}\n </Text>\n )}\n </ModalBody>\n <ModalFooter pt={0} />\n </>\n </Box>\n );\n};\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport { MainContent } from './Contents/MainContent';\nimport { BaseModal } from '@/components/common';\nimport { FAQContent } from '../AccountModal';\nimport { EcosystemContent, LoadingContent, ErrorContent } from './Contents';\nimport { PrivyAppInfo } from '@/types';\n\ntype Props = {\n isOpen: boolean;\n onClose: () => void;\n initialContent?: ConnectModalContentsTypes;\n preventAutoClose?: boolean;\n};\n\nexport type ConnectModalContentsTypes =\n | 'main'\n | 'faq'\n | {\n type: 'ecosystem';\n props: {\n appsInfo: PrivyAppInfo[];\n isLoading: boolean;\n showBackButton?: boolean;\n };\n }\n | {\n type: 'loading';\n props: {\n title?: string;\n loadingText?: string;\n onTryAgain?: () => void;\n showBackButton?: boolean;\n };\n }\n | {\n type: 'error';\n props: {\n error: string;\n onTryAgain: () => void;\n };\n };\n\nexport const ConnectModal = ({\n isOpen,\n onClose,\n initialContent = 'main',\n preventAutoClose = false,\n}: Props) => {\n const [currentContent, setCurrentContent] =\n useState<ConnectModalContentsTypes>(initialContent);\n\n // Sync currentContent with initialContent when it changes (e.g., when opening from popover)\n useEffect(() => {\n if (isOpen) {\n setCurrentContent(initialContent);\n }\n }, [isOpen, initialContent, setCurrentContent]);\n\n const renderContent = () => {\n // Ensure displayContent is valid\n if (!currentContent) {\n return (\n <MainContent\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n preventAutoClose={preventAutoClose}\n />\n );\n }\n\n switch (currentContent) {\n case 'main':\n return (\n <MainContent\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n preventAutoClose={preventAutoClose}\n />\n );\n case 'faq':\n return (\n <FAQContent onGoBack={() => setCurrentContent('main')} />\n );\n }\n\n if (typeof currentContent === 'object' && 'type' in currentContent) {\n switch (currentContent.type) {\n case 'ecosystem':\n return (\n <EcosystemContent\n onClose={onClose}\n appsInfo={currentContent.props.appsInfo}\n isLoading={currentContent.props.isLoading}\n setCurrentContent={setCurrentContent}\n showBackButton={currentContent.props.showBackButton}\n />\n );\n case 'loading':\n return (\n <LoadingContent\n title={currentContent.props.title}\n loadingText={currentContent.props.loadingText}\n onTryAgain={currentContent.props.onTryAgain}\n onClose={onClose}\n onGoBack={() => setCurrentContent('main')}\n showBackButton={currentContent.props.showBackButton}\n />\n );\n case 'error':\n return (\n <ErrorContent\n error={currentContent.props.error}\n onClose={onClose}\n onTryAgain={currentContent.props.onTryAgain}\n onGoBack={() => setCurrentContent('main')}\n />\n );\n }\n }\n\n return null;\n };\n\n const content = renderContent();\n\n // Ensure we have valid content before rendering\n if (!content) {\n // Fallback to main content if renderContent returns null\n const fallbackContent = (\n <MainContent\n setCurrentContent={setCurrentContent}\n onClose={onClose}\n />\n );\n return (\n <BaseModal\n isOpen={isOpen}\n onClose={onClose}\n allowExternalFocus={true}\n blockScrollOnMount={true}\n mobileMinHeight={'260px'}\n mobileMaxHeight={'400px'}\n desktopMinHeight={'250px'}\n desktopMaxHeight={'400px'}\n >\n {fallbackContent}\n </BaseModal>\n );\n }\n\n return (\n <BaseModal\n isOpen={isOpen}\n onClose={onClose}\n allowExternalFocus={true}\n blockScrollOnMount={true}\n mobileMinHeight={'260px'}\n mobileMaxHeight={'400px'}\n desktopMinHeight={'250px'}\n desktopMaxHeight={'400px'}\n >\n {content}\n </BaseModal>\n );\n};\n","import { Button, ButtonProps, HStack, Icon, Text } from '@chakra-ui/react';\nimport { ReactElement } from 'react';\nimport { IconType } from 'react-icons';\n\ninterface ConnectionButtonProps {\n isDark: boolean;\n onClick: () => void;\n text?: string;\n icon?: IconType;\n customIcon?: ReactElement;\n rightIcon?: ReactElement;\n style?: ButtonProps;\n variant?: string;\n iconWidth?: string;\n}\n\nexport const ConnectionButton = ({\n onClick,\n text,\n icon,\n customIcon,\n rightIcon,\n style,\n variant = 'loginIn',\n iconWidth = '25px',\n}: ConnectionButtonProps) => {\n // If text not provided we just show a button with an icon\n if (!text) {\n return (\n <Button {...style} variant={variant} w={'full'} onClick={onClick}>\n {customIcon ? (\n customIcon\n ) : (\n <Icon as={icon} w={'20px'} h={'20px'} />\n )}\n </Button>\n );\n }\n\n if (text) {\n return (\n <Button {...style} variant={variant} w={'full'} onClick={onClick}>\n <HStack w={'full'} justify={'flex-start'} gap={2}>\n {customIcon ? (\n customIcon\n ) : (\n <Icon as={icon} w={iconWidth} h={iconWidth} />\n )}\n <Text opacity={0.9}>{text}</Text>\n </HStack>\n {rightIcon}\n </Button>\n );\n }\n\n return null;\n};\n","import {\n Button,\n ButtonProps,\n HStack,\n Icon,\n Popover,\n PopoverBody,\n PopoverContent,\n PopoverFooter,\n PopoverTrigger,\n} from '@chakra-ui/react';\nimport { ConnectionOptionsStack } from './Components/ConnectionOptionsStack';\nimport { useTranslation } from 'react-i18next';\nimport { LuChevronDown } from 'react-icons/lu';\nimport { EcosystemButton } from './Components';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useFetchAppInfo, useConnectModal } from '@/hooks';\nimport { ConnectModalContentsTypes } from './ConnectModal';\nimport { useCallback } from 'react';\nimport { SetStateAction } from 'react';\n\ntype ConnectPopoverProps = {\n isLoading: boolean;\n buttonStyle?: ButtonProps;\n};\n\nexport const ConnectPopover = ({\n isLoading,\n buttonStyle,\n}: ConnectPopoverProps) => {\n const { t } = useTranslation();\n const {\n loginMethods,\n darkMode: isDark,\n privyEcosystemAppIDS,\n } = useVeChainKitConfig();\n const showEcosystemButton = loginMethods?.some(\n ({ method }) => method === 'ecosystem',\n );\n const { open: openConnectModal } = useConnectModal();\n\n const { data: appsInfo, isLoading: isEcosystemAppsLoading } =\n useFetchAppInfo(privyEcosystemAppIDS);\n\n // Function to handle content changes from popover - opens ConnectModal\n // When opened from popover, we don't show back button\n const handleSetContent = useCallback(\n (\n content:\n | ConnectModalContentsTypes\n | SetStateAction<ConnectModalContentsTypes>,\n ) => {\n // Handle function form of SetStateAction\n const resolvedContent =\n typeof content === 'function'\n ? content('main') // Use 'main' as previous state (won't be used anyway)\n : content;\n\n // If content is ecosystem or loading, set showBackButton to false\n if (\n typeof resolvedContent === 'object' &&\n 'type' in resolvedContent\n ) {\n if (resolvedContent.type === 'ecosystem') {\n openConnectModal({\n type: 'ecosystem',\n props: {\n ...resolvedContent.props,\n showBackButton: false,\n },\n });\n } else if (resolvedContent.type === 'loading') {\n openConnectModal({\n type: 'loading',\n props: {\n ...resolvedContent.props,\n showBackButton: false,\n },\n });\n } else {\n // Error type or other - don't modify props\n openConnectModal(resolvedContent);\n }\n } else {\n // String type (main, faq, etc.)\n openConnectModal(resolvedContent);\n }\n },\n [openConnectModal],\n );\n\n return (\n <Popover\n placement=\"bottom-start\"\n size={'xl'}\n closeOnBlur={false}\n variant=\"vechainKitBase\"\n >\n {({ isOpen }) => (\n <>\n <PopoverTrigger>\n <Button\n isLoading={isLoading}\n {...buttonStyle}\n isActive={isOpen}\n >\n {t('Login')}\n <Icon\n ml={2}\n as={LuChevronDown}\n transform={\n isOpen ? 'rotate(180deg)' : 'rotate(0deg)'\n }\n transition=\"transform 0.2s\"\n />\n </Button>\n </PopoverTrigger>\n <PopoverContent>\n <PopoverBody>\n <ConnectionOptionsStack\n setCurrentContent={handleSetContent}\n />\n </PopoverBody>\n <PopoverFooter borderTop={'none'} pb={'15px'}>\n {showEcosystemButton && (\n <HStack justify={'center'} w={'full'}>\n <EcosystemButton\n isDark={isDark}\n appsInfo={Object.values(appsInfo || {})}\n isLoading={isEcosystemAppsLoading}\n setCurrentContent={handleSetContent}\n />\n </HStack>\n )}\n </PopoverFooter>\n </PopoverContent>\n </>\n )}\n </Popover>\n );\n};\n","import { useWallet } from '@/hooks';\nimport { humanAddress, humanDomain } from '@/utils';\nimport { HStack, Spinner, Text, VStack } from '@chakra-ui/react';\n\nimport { AssetIcons } from './AssetIcons';\nimport { WalletDisplayVariant } from './types';\n\ntype WalletDisplayProps = {\n variant: WalletDisplayVariant;\n};\n\nexport const WalletDisplay = ({ variant }: WalletDisplayProps) => {\n const { account } = useWallet();\n\n if (!account) return <Spinner />;\n\n if (variant === 'icon') {\n return null;\n }\n\n if (variant === 'iconAndDomain') {\n return account.domain ? (\n <Text fontSize=\"sm\">\n {humanDomain(account?.domain ?? '', 16, 0)}\n </Text>\n ) : (\n <Text fontSize=\"sm\">\n {humanAddress(account.address ?? '', 6, 4)}\n </Text>\n );\n }\n\n if (variant === 'iconDomainAndAssets') {\n return (\n <HStack spacing={4}>\n <VStack spacing={0} alignItems=\"flex-start\">\n {account.domain && (\n <Text fontSize=\"sm\" fontWeight=\"bold\">\n {humanDomain(account?.domain ?? '', 16, 0)}\n </Text>\n )}\n <Text\n fontSize={account.domain ? 'xs' : 'sm'}\n opacity={account.domain ? 0.5 : 1}\n data-testid=\"trimmed-address\"\n >\n {humanAddress(account.address ?? '', 4, 4)}\n </Text>\n </VStack>\n <AssetIcons address={account.address ?? ''} maxIcons={3} />\n </HStack>\n );\n }\n\n return (\n <VStack spacing={0} alignItems=\"flex-start\">\n {account.domain && (\n <Text fontSize=\"sm\" fontWeight=\"bold\">\n {humanDomain(account?.domain ?? '', 16, 0)}\n </Text>\n )}\n <Text\n fontSize={account.domain ? 'xs' : 'sm'}\n opacity={account.domain ? 0.5 : 1}\n >\n {humanAddress(account.address ?? '', 4, 4)}\n </Text>\n </VStack>\n );\n};\n","import { useWallet } from '@/hooks';\nimport { Button, HStack, useMediaQuery } from '@chakra-ui/react';\n\nimport { AccountAvatar } from '../common';\nimport { WalletButtonProps } from './WalletButton';\nimport { WalletDisplay } from './WalletDisplay';\n\ntype ConnectedWalletProps = WalletButtonProps & {\n onOpen: () => void;\n};\n\nexport const ConnectedWallet = ({\n mobileVariant = 'iconAndDomain',\n desktopVariant = 'iconAndDomain',\n onOpen,\n buttonStyle = {},\n}: ConnectedWalletProps) => {\n const { account } = useWallet();\n const [isDesktop] = useMediaQuery('(min-width: 768px)');\n\n return (\n <Button\n {...buttonStyle}\n onClick={onOpen}\n w=\"full\"\n minH={'45px'}\n maxW=\"fit-content\"\n data-testid='wallet-button'\n >\n <HStack w=\"full\" minW=\"fit-content\">\n <AccountAvatar\n wallet={account}\n props={{\n width: 30,\n height: 30,\n minWidth: 30,\n minHeight: 30,\n }}\n />\n\n <WalletDisplay\n variant={isDesktop ? desktopVariant : mobileVariant}\n />\n </HStack>\n </Button>\n );\n};\n","import {\n Button,\n ButtonProps,\n useDisclosure,\n useMediaQuery,\n} from '@chakra-ui/react';\nimport { useWallet, useDAppKitWallet, useDAppKitWalletModal } from '@/hooks';\nimport { ConnectModal, AccountModal } from '@/components';\nimport { ConnectedWallet } from './ConnectedWallet';\nimport { WalletDisplayVariant } from './types';\nimport { useVeChainKitConfig, VechainKitThemeProvider } from '@/providers';\nimport { ConnectPopover } from '../ConnectModal';\n\nexport type WalletButtonProps = {\n mobileVariant?: WalletDisplayVariant;\n desktopVariant?: WalletDisplayVariant;\n buttonStyle?: ButtonProps;\n connectionVariant?: 'modal' | 'popover';\n label?: string;\n};\n\nexport const WalletButton = ({\n mobileVariant = 'iconAndDomain',\n desktopVariant = 'iconDomainAndAddress',\n buttonStyle,\n connectionVariant = 'modal',\n label = 'Login',\n}: WalletButtonProps) => {\n const { darkMode, loginMethods, theme } = useVeChainKitConfig();\n\n const hasOnlyDappKit =\n loginMethods?.length === 1 && loginMethods[0].method === 'dappkit';\n\n const { connection, account } = useWallet();\n const { setSource, connectV2 } = useDAppKitWallet();\n\n const [isMobile] = useMediaQuery('(max-width: 768px)');\n\n const connectModal = useDisclosure();\n const accountModal = useDisclosure();\n const { open: openDappKit } = useDAppKitWalletModal();\n\n const handleConnect = () => {\n if (connection.isInAppBrowser) {\n setSource('veworld');\n connectV2(null);\n } else if (hasOnlyDappKit) {\n openDappKit();\n } else {\n connectModal.onOpen();\n }\n };\n\n return (\n <VechainKitThemeProvider darkMode={darkMode} theme={theme}>\n {connection.isConnected && !!account ? (\n <ConnectedWallet\n mobileVariant={mobileVariant}\n desktopVariant={desktopVariant}\n onOpen={accountModal.onOpen}\n buttonStyle={buttonStyle}\n />\n ) : connectionVariant === 'popover' && !isMobile ? (\n <ConnectPopover\n isLoading={connection.isLoading}\n buttonStyle={buttonStyle}\n />\n ) : (\n <Button\n isLoading={connection.isLoading}\n onClick={handleConnect}\n {...buttonStyle}\n >\n {label}\n </Button>\n )}\n\n <ConnectModal\n isOpen={connectModal.isOpen}\n onClose={connectModal.onClose}\n />\n <AccountModal\n isOpen={accountModal.isOpen}\n onClose={accountModal.onClose}\n />\n </VechainKitThemeProvider>\n );\n};\n","import { HStack, Circle, Icon, useMediaQuery } from '@chakra-ui/react';\nimport { useVeChainKitConfig } from '@/providers';\nimport { FcGoogle } from 'react-icons/fc';\nimport { FaDiscord, FaXTwitter } from 'react-icons/fa6';\nimport { LuPlus } from 'react-icons/lu';\n\nexport const SocialIcons = () => {\n const iconSize = 25;\n const { darkMode } = useVeChainKitConfig();\n const marginLeft = iconSize / 2;\n const [isSmallScreen] = useMediaQuery('(max-width: 280px)');\n const [isMediumScreen] = useMediaQuery('(max-width: 380px)');\n\n return (\n <HStack spacing={0} ml={0}>\n <Circle\n size={`${iconSize}px`}\n borderRadius=\"full\"\n bg={'#F8F8F8'}\n p={2}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={3}\n >\n <Icon as={FcGoogle} fontSize={'20px'} />\n </Circle>\n {!isSmallScreen && (\n <Circle\n ml={`-${marginLeft}px`}\n size={`${iconSize}px`}\n borderRadius=\"full\"\n bg={'black'}\n p={2}\n alignItems=\"center\"\n justifyContent=\"center\"\n zIndex={2}\n >\n <Icon as={FaXTwitter} color={'white'} fontSize={'20px'} />\n </Circle>\n )}\n {!isSmallScreen && !isMediumScreen && (\n <Circle\n ml={`-${marginLeft}px`}\n zIndex={1}\n size={`${iconSize}px`}\n borderRadius=\"full\"\n bg={'#5865F2'}\n p={2}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Icon as={FaDiscord} color={'white'} fontSize={'20px'} />\n </Circle>\n )}\n <Icon\n zIndex={1}\n as={LuPlus}\n color={darkMode ? 'black' : 'white'}\n fontSize={'15px'}\n />\n </HStack>\n );\n};\n","import {\n VStack,\n Text,\n Link,\n Icon,\n HStack,\n Heading,\n Spinner,\n Button,\n IconButton,\n} from '@chakra-ui/react';\nimport React, { useMemo } from 'react';\nimport { TransactionStatus, TransactionStatusErrorType } from '@/types';\nimport {\n LuX,\n LuExternalLink,\n LuCircleAlert,\n LuCircleCheck,\n LuRefreshCw,\n} from 'react-icons/lu';\nimport { useVeChainKitConfig } from '@/providers';\nimport { getConfig } from '@/config';\nimport { useTranslation } from 'react-i18next';\nimport { TransactionReceipt } from '@vechain/sdk-network';\n\ntype TransactionToastContentProps = {\n status: TransactionStatus;\n txReceipt: TransactionReceipt | null;\n onTryAgain: () => void;\n txError?: Error | TransactionStatusErrorType;\n description?: string;\n onClose: () => void;\n};\n\ntype StatusConfig = {\n icon: React.ReactElement | null;\n title: string;\n closeDisabled: boolean;\n description?: string;\n};\n\nexport const TransactionToastContent = ({\n status,\n txReceipt,\n txError,\n onTryAgain,\n description,\n onClose,\n}: TransactionToastContentProps) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const explorerUrl = getConfig(network.type).explorerUrl;\n\n const errorMessage = useMemo(() => {\n if (!txError) return null;\n return (\n (txError as any).reason ||\n t('Something went wrong. Please try again.')\n );\n }, [txError, t]);\n\n const getStatusConfig = (): StatusConfig => {\n // overwrite status to avoid flickering\n const isSendingTransaction = status === 'waitingConfirmation';\n if (isSendingTransaction) {\n status = 'pending';\n }\n\n switch (status) {\n case 'pending':\n return {\n icon: (\n <Spinner\n size=\"md\"\n data-testid=\"pending-spinner-toast\"\n />\n ),\n title: isSendingTransaction\n ? t('Processing transaction...')\n : t('Waiting for confirmation...'),\n closeDisabled: true,\n description: isSendingTransaction\n ? t(\n 'Transaction is being processed, it can take up to 15 seconds.',\n )\n : description ??\n t('Please confirm the transaction in your wallet.'),\n };\n case 'error':\n return {\n icon: (\n <Icon\n as={LuCircleAlert}\n color={'red.500'}\n fontSize={'40px'}\n data-testid=\"error-icon-toast\"\n />\n ),\n title: t('Transaction failed'),\n closeDisabled: false,\n description: errorMessage,\n };\n case 'success':\n return {\n icon: (\n <Icon\n as={LuCircleCheck}\n color={'green.500'}\n fontSize={'40px'}\n data-testid=\"success-icon-toast\"\n />\n ),\n title: t('Transaction successful!'),\n closeDisabled: false,\n description: undefined,\n };\n case 'ready':\n return {\n icon: null,\n title: t('Confirm transaction'),\n closeDisabled: false,\n description:\n description ??\n t(\n 'Confirm the transaction in your wallet to complete it.',\n ),\n };\n default:\n return {\n icon: null,\n title: '',\n closeDisabled: false,\n description: '',\n };\n }\n };\n\n const config = getStatusConfig();\n if (!config) return null;\n\n return (\n <HStack justify=\"space-between\" alignItems={'flex-start'} w=\"full\">\n <VStack spacing={4}>\n <HStack\n spacing={4}\n w={'full'}\n justifyContent={'flex-start'}\n alignItems={'flex-start'}\n >\n {config.icon}\n\n <VStack w={'full'} align={'flex-start'} spacing={2}>\n <VStack spacing={1} w={'full'}>\n <Heading w={'full'} size={'xs'}>\n {config.title}\n </Heading>\n {config.description && (\n <Text fontSize={'xs'}>\n {config.description}\n </Text>\n )}\n </VStack>\n\n {(status === 'error' || status === 'ready') && (\n <Button size=\"xs\" onClick={onTryAgain}>\n {status === 'error' ? (\n <>\n <Icon mr={2} as={LuRefreshCw} />\n {t('Try again')}\n </>\n ) : (\n t('Confirm')\n )}\n </Button>\n )}\n\n {txReceipt && status !== 'pending' && (\n <Link\n fontSize={'xs'}\n isExternal\n href={`${explorerUrl}/${txReceipt.meta.txID}`}\n >\n {t('View on explorer')}{' '}\n <Icon as={LuExternalLink} />\n </Link>\n )}\n </VStack>\n </HStack>\n </VStack>\n\n {!config.closeDisabled && (\n <IconButton\n onClick={onClose}\n size=\"sm\"\n borderRadius={'full'}\n aria-label=\"Close\"\n icon={<Icon as={LuX} boxSize={4} />}\n />\n )}\n </HStack>\n );\n};\n","import { Box } from '@chakra-ui/react';\nimport { TransactionStatus, TransactionStatusErrorType } from '@/types';\nimport { useVeChainKitConfig } from '@/providers';\nimport { TransactionToastContent } from './TransactionToastContent';\nimport { TransactionReceipt } from '@vechain/sdk-network';\n\nexport type TransactionToastProps = {\n isOpen: boolean;\n onClose: () => void;\n status: TransactionStatus;\n txReceipt: TransactionReceipt | null;\n onTryAgain: () => void;\n txError?: Error | TransactionStatusErrorType;\n description?: string;\n};\n\nexport const TransactionToast = ({\n isOpen,\n onClose,\n status,\n txReceipt,\n txError,\n onTryAgain,\n description,\n}: TransactionToastProps) => {\n const { darkMode: isDark } = useVeChainKitConfig();\n\n if (!isOpen) return null;\n\n return (\n <Box\n position=\"fixed\"\n bottom=\"5\"\n left=\"5\"\n zIndex=\"11111\"\n bg={isDark ? '#1f1f1e' : 'white'}\n borderRadius={'md'}\n p={5}\n boxShadow=\"lg\"\n maxW=\"sm\"\n minW=\"300px\"\n >\n <TransactionToastContent\n status={status}\n txReceipt={txReceipt}\n txError={txError}\n onTryAgain={onTryAgain}\n description={description}\n onClose={onClose}\n />\n </Box>\n );\n};\n","import {\n ModalBody,\n ModalCloseButton,\n ModalHeader,\n VStack,\n Text,\n Button,\n ModalFooter,\n Icon,\n Link,\n HStack,\n useToken,\n} from '@chakra-ui/react';\nimport { StickyHeaderContainer } from '@/components/common';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { motion } from 'framer-motion';\nimport { getConfig } from '@/config';\nimport { LuExternalLink, LuCircleCheck } from 'react-icons/lu';\nimport { ShareButtons } from '@/components/TransactionModal';\nimport { UpgradeSmartAccountModalContentsTypes } from '../UpgradeSmartAccountModal';\n\nexport type SuccessfulOperationContentProps = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<UpgradeSmartAccountModalContentsTypes>\n >;\n txId?: string;\n title: string;\n description?: string;\n onDone: () => void;\n showSocialButtons?: boolean;\n};\n\nexport const SuccessfulOperationContent = ({\n txId,\n title,\n description,\n onDone,\n showSocialButtons = false,\n}: SuccessfulOperationContentProps) => {\n const { t } = useTranslation();\n const { network } = useVeChainKitConfig();\n const explorerUrl = getConfig(network.type).explorerUrl;\n const socialDescription = `${explorerUrl}/${txId}`;\n\n const successColor = useToken('colors', 'vechain-kit-success');\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{title}</ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack align={'center'} p={6} spacing={3}>\n <motion.div\n transition={{\n duration: 4,\n ease: 'easeInOut',\n repeat: Infinity,\n }}\n animate={{\n scale: [1, 1.1, 1],\n }}\n >\n <Icon\n as={LuCircleCheck}\n fontSize={'100px'}\n color={successColor}\n />\n </motion.div>\n\n {description && (\n <Text fontSize=\"sm\" textAlign=\"center\">\n {description}\n </Text>\n )}\n\n {showSocialButtons && txId && (\n <VStack mt={2}>\n <Text fontSize=\"xs\">{t('Share on')}</Text>\n <ShareButtons description={socialDescription} />\n </VStack>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter justifyContent={'center'}>\n <VStack width=\"full\" spacing={4}>\n <Button\n onClick={onDone}\n variant=\"vechainKitSecondary\"\n width=\"full\"\n >\n {t('Done')}\n </Button>\n\n {txId && (\n <Link\n href={`${explorerUrl}/${txId}`}\n isExternal\n opacity={0.5}\n fontSize={'14px'}\n textDecoration={'underline'}\n >\n <HStack\n spacing={1}\n alignItems={'center'}\n w={'full'}\n justifyContent={'center'}\n >\n <Text>\n {t('View transaction on the explorer')}\n </Text>\n <Icon size={16} as={LuExternalLink} />\n </HStack>\n </Link>\n )}\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","import {\n ModalHeader,\n ModalBody,\n ModalFooter,\n Text,\n VStack,\n Alert,\n AlertIcon,\n AlertTitle,\n AlertDescription,\n Box,\n ModalCloseButton,\n HStack,\n Circle,\n Image,\n Heading,\n Icon,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport {\n StickyHeaderContainer,\n TransactionButtonAndStatus,\n} from '@/components/common';\nimport { useUpgradeRequired, useUpgradeSmartAccount, useWallet } from '@/hooks';\nimport {\n UpgradeSmartAccountModalContentsTypes,\n UpgradeSmartAccountModalStyle,\n} from '../UpgradeSmartAccountModal';\nimport { LuArrowRight } from 'react-icons/lu';\n\ntype Props = {\n setCurrentContent: React.Dispatch<\n React.SetStateAction<UpgradeSmartAccountModalContentsTypes>\n >;\n handleClose: () => void;\n style?: UpgradeSmartAccountModalStyle;\n};\n\nexport const UpgradeSmartAccountContent = ({\n setCurrentContent,\n handleClose,\n style,\n}: Props) => {\n const { t } = useTranslation();\n const { smartAccount, connectedWallet } = useWallet();\n const { data: upgradeRequired } = useUpgradeRequired(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n 3,\n );\n\n // Set up the upgrade transaction\n const {\n sendTransaction: upgradeSmartAccount,\n isTransactionPending,\n isWaitingForWalletConfirmation,\n error: upgradeError,\n txReceipt,\n } = useUpgradeSmartAccount({\n smartAccountAddress: smartAccount?.address ?? '',\n targetVersion: 3,\n onSuccess: () => {\n setCurrentContent({\n type: 'successful-operation',\n props: {\n setCurrentContent,\n txId: txReceipt?.meta.txID,\n title: t('Upgrade Successful!'),\n description: t(\n 'Your account has been successfully upgraded to the latest version. You can now enjoy a better user experience, lower gas costs, and enhanced security.',\n ),\n onDone: () => {\n handleClose();\n },\n showSocialButtons: false,\n },\n });\n },\n onError: () => {\n console.error('Error upgrading Smart Account');\n },\n });\n\n // Handle the upgrade process\n const handleUpgrade = async () => {\n try {\n await upgradeSmartAccount();\n } catch (err) {\n console.error('Failed to upgrade Smart Account:', err);\n }\n };\n\n return (\n <>\n <StickyHeaderContainer>\n <ModalHeader>{t('Account upgrade required')}</ModalHeader>\n <ModalCloseButton />\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack spacing={10} align=\"stretch\" justifyContent=\"center\">\n <Text fontSize=\"sm\" textAlign=\"center\">\n {t(\n 'To continue interacting with VeChain blockchain and complete your operation, your smart account needs to be upgraded to the latest version (v3).',\n )}\n </Text>\n\n <HStack\n align=\"center\"\n justifyContent=\"space-evenly\"\n rounded=\"md\"\n >\n <Box position=\"relative\" display=\"inline-block\">\n <Circle size=\"60px\" bg=\"gray.200\">\n <Image\n src={smartAccount?.image}\n alt={t('Profile Picture')}\n w=\"100%\"\n h=\"100%\"\n borderRadius=\"full\"\n objectFit=\"cover\"\n />\n </Circle>\n\n <Heading\n position=\"absolute\"\n top=\"-5\"\n right=\"-5\"\n color=\"#D23F63\"\n fontSize=\"28px\"\n >\n {`v1`}\n </Heading>\n </Box>\n\n <Icon as={LuArrowRight} color=\"#3DBA67\" />\n\n <Box position=\"relative\" display=\"inline-block\">\n <Circle size=\"60px\" bg=\"gray.200\">\n <Image\n src={smartAccount?.image}\n alt={t('Profile Picture')}\n w=\"100%\"\n h=\"100%\"\n borderRadius=\"full\"\n objectFit=\"cover\"\n />\n </Circle>\n <Heading\n position=\"absolute\"\n top=\"-5\"\n right=\"-5\"\n color=\"#3DBA67\"\n fontSize=\"28px\"\n >\n {`v3`}\n </Heading>\n </Box>\n </HStack>\n\n <Alert status=\"info\" borderRadius=\"md\">\n <AlertIcon />\n <Box>\n <AlertTitle fontSize=\"sm\">\n {t('Benefits of this upgrade:')}\n </AlertTitle>\n <AlertDescription fontSize=\"xs\">\n <VStack align=\"start\" spacing={0} mt={1}>\n <Text fontSize=\"xs\" lineHeight=\"1.2\">\n • {t('Improved security features')}\n </Text>\n <Text fontSize=\"xs\">\n • {t('Better transaction handling')}\n </Text>\n <Text fontSize=\"xs\">\n •{' '}\n {t('Enhanced compatibility with dApps')}\n </Text>\n <Text fontSize=\"xs\">\n •{' '}\n {t('Reduced gas costs for operations')}\n </Text>\n </VStack>\n </AlertDescription>\n </Box>\n </Alert>\n </VStack>\n </ModalBody>\n\n <ModalFooter justifyContent=\"center\">\n <VStack spacing={3} w=\"full\">\n <TransactionButtonAndStatus\n style={style}\n buttonText={\n upgradeRequired\n ? t('Upgrade account')\n : t('Account already upgraded')\n }\n onConfirm={handleUpgrade}\n isTxWaitingConfirmation={isWaitingForWalletConfirmation}\n isSubmitting={isTransactionPending}\n transactionPendingText={t('Upgrading...')}\n txReceipt={txReceipt}\n transactionError={upgradeError}\n isDisabled={!upgradeRequired}\n />\n </VStack>\n </ModalFooter>\n </>\n );\n};\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport { BaseModal } from '@/components/common';\nimport {\n SuccessfulOperationContent,\n SuccessfulOperationContentProps,\n} from './Contents/SuccessfulOperationContent';\nimport { UpgradeSmartAccountContent } from './Contents/UpgradeSmartAccountContent';\nimport { ThemeTypings } from '@chakra-ui/react';\n\nexport type UpgradeSmartAccountModalStyle = {\n accentColor?: string;\n modalSize?: ThemeTypings['components']['Modal']['sizes'];\n};\n\ntype Props = {\n isOpen: boolean;\n onClose: () => void;\n style?: UpgradeSmartAccountModalStyle;\n};\n\nexport type UpgradeSmartAccountModalContentsTypes =\n | 'upgrade-smart-account'\n | {\n type: 'successful-operation';\n props: SuccessfulOperationContentProps;\n };\n\nexport const UpgradeSmartAccountModal = ({ isOpen, onClose, style }: Props) => {\n const [currentContent, setCurrentContent] =\n useState<UpgradeSmartAccountModalContentsTypes>(\n 'upgrade-smart-account',\n );\n\n useEffect(() => {\n if (isOpen) {\n setCurrentContent('upgrade-smart-account');\n }\n }, [isOpen]);\n\n const renderContent = () => {\n if (typeof currentContent === 'object') {\n switch (currentContent.type) {\n case 'successful-operation':\n return (\n <SuccessfulOperationContent {...currentContent.props} />\n );\n }\n } else if (currentContent === 'upgrade-smart-account') {\n return (\n <UpgradeSmartAccountContent\n setCurrentContent={setCurrentContent}\n handleClose={onClose}\n style={style}\n />\n );\n }\n };\n\n return (\n <BaseModal\n isOpen={isOpen}\n onClose={onClose}\n allowExternalFocus={true}\n blockScrollOnMount={true}\n size={style?.modalSize}\n >\n {renderContent()}\n </BaseModal>\n );\n};\n","import { modalAnatomy as parts } from '@chakra-ui/anatomy';\nimport { createMultiStyleConfigHelpers } from '@chakra-ui/react';\nimport { ThemeTokens } from './tokens';\n\nconst { definePartsStyle, defineMultiStyleConfig } =\n createMultiStyleConfigHelpers(parts.keys);\n\nconst getModalVariants = (tokens: ThemeTokens) => ({\n vechainKitBase: definePartsStyle({\n dialog: {\n scrollbarWidth: 'none',\n overflow: 'scroll',\n overflowX: 'hidden',\n rounded: tokens.modal.rounded ?? tokens.borders.radius.modal,\n backgroundColor: tokens.colors.background.modal,\n backdropFilter: tokens.effects.backdropFilter.modal,\n border: tokens.colors.border.modal,\n },\n overlay: {\n backgroundColor: tokens.colors.background.overlay,\n backdropFilter: tokens.effects.backdropFilter.overlay,\n },\n closeButton: {\n borderRadius: tokens.borders.radius.full,\n color: tokens.colors.text.primary,\n _hover: {\n ...(tokens.buttons.button.hoverBg\n ? { bg: tokens.buttons.button.hoverBg }\n : { opacity: 0.8 }),\n },\n _active: {\n bg: tokens.buttons.button.bg,\n opacity: 0.8,\n },\n },\n header: {\n w: 'full',\n color: tokens.colors.text.primary,\n fontSize: tokens.fonts.sizes.large,\n fontWeight: tokens.fonts.weights.bold,\n textAlign: 'center',\n paddingBottom: 5,\n paddingTop: 5,\n },\n }),\n});\n\nexport const getModalTheme = (tokens: ThemeTokens) =>\n defineMultiStyleConfig({\n variants: getModalVariants(tokens),\n defaultProps: {\n variant: 'vechainKitBase',\n },\n });\n","import { cardAnatomy } from '@chakra-ui/anatomy';\nimport { createMultiStyleConfigHelpers } from '@chakra-ui/react';\nimport { ThemeTokens } from './tokens';\n\nconst { definePartsStyle, defineMultiStyleConfig } =\n createMultiStyleConfigHelpers(cardAnatomy.keys);\n\nconst getCardVariants = (tokens: ThemeTokens) => ({\n vechainKitBase: definePartsStyle({\n container: {\n backgroundColor: tokens.colors.background.card,\n borderRadius: tokens.borders.radius.medium,\n width: 'full',\n border: 'none',\n },\n body: {\n p: 5,\n width: 'full',\n },\n header: {\n p: 5,\n width: 'full',\n borderRadius: `${tokens.borders.radius.medium} ${tokens.borders.radius.medium} 0 0`,\n },\n footer: {\n width: 'full',\n borderRadius: `0 0 ${tokens.borders.radius.medium} ${tokens.borders.radius.medium}`,\n },\n }),\n\n vechainKitWalletCard: definePartsStyle({\n container: {\n backgroundColor: tokens.colors.background.card,\n borderRadius: tokens.borders.radius.medium,\n width: 'full',\n cursor: 'pointer',\n position: 'relative',\n },\n }),\n\n featureAnnouncement: definePartsStyle({\n body: {\n backgroundColor: tokens.buttons.button.bg,\n borderRadius: tokens.borders.radius.medium,\n color: tokens.colors.text.secondary,\n },\n container: {\n borderRadius: tokens.borders.radius.medium,\n backgroundColor: 'transparent',\n },\n }),\n\n vechainKitAppCard: definePartsStyle({\n body: {\n height: 'full',\n borderRadius: tokens.borders.radius.medium,\n backgroundColor: tokens.colors.background.cardElevated,\n border: `1px solid ${tokens.colors.border.default}`,\n },\n container: {\n height: '150px',\n borderRadius: tokens.borders.radius.medium,\n backgroundColor: 'transparent',\n },\n }),\n});\n\nexport const getCardTheme = (tokens: ThemeTokens) =>\n defineMultiStyleConfig({\n variants: getCardVariants(tokens),\n defaultProps: {\n variant: 'vechainKitBase', // default is solid\n },\n });\n","import { defineStyle, defineStyleConfig } from '@chakra-ui/react';\nimport { ThemeTokens } from './tokens';\n\nconst baseStyle = defineStyle({\n borderRadius: '12px',\n});\n\nconst getVariants = (tokens: ThemeTokens) => ({\n // Login variants - maintained for backward compatibility\n // These should eventually be replaced with vechainKitTertiary and vechainKitPrimary\n loginIn: defineStyle(() => ({\n bg: tokens.buttons.loginButton.bg,\n color: tokens.buttons.loginButton.color,\n border: tokens.buttons.loginButton.border,\n fontSize: tokens.fonts.sizes.medium,\n fontWeight: tokens.fonts.weights.normal,\n py: 6,\n px: 3,\n rounded:\n tokens.buttons.loginButton.rounded ?? tokens.borders.radius.large,\n backdropFilter: tokens.buttons.loginButton.backdropFilter,\n _hover: {\n opacity: 0.5,\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: tokens.buttons.loginButton.bg, // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: tokens.buttons.loginButton.bg, // Explicitly set background\n },\n transition: 'all 0.2s',\n })),\n loginWithVechain: defineStyle(() => ({\n color: 'white', // Note: Different from vechainKitPrimary which uses 'white'\n bg: '#1a1a1a',\n fontSize: tokens.fonts.sizes.medium,\n fontWeight: tokens.fonts.weights.normal,\n py: 6,\n px: 3,\n borderRadius: tokens.borders.radius.large,\n border: `1px solid ${tokens.colors.border.button}`,\n _hover: {\n opacity: 0.5,\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: '#1a1a1a', // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: '#1a1a1a', // Explicitly set background\n },\n _dark: {\n color: '#1a1a1a',\n bg: 'white',\n _hover: {\n _disabled: {\n bg: 'white', // Ensure background stays in dark mode\n },\n },\n _disabled: {\n bg: 'white', // Explicitly set background in dark mode\n },\n },\n transition: 'all 0.2s',\n })),\n vechainKitPrimary: defineStyle(() => ({\n fontSize: tokens.fonts.sizes.medium,\n px: 4,\n width: 'full',\n height: '60px',\n rounded:\n tokens.buttons.primaryButton.rounded ?? tokens.borders.radius.large,\n bg: tokens.buttons.primaryButton.bg,\n color: tokens.buttons.primaryButton.color,\n border: tokens.buttons.primaryButton.border,\n backdropFilter: tokens.buttons.primaryButton.backdropFilter,\n _hover: {\n ...(tokens.buttons.primaryButton.hoverBg\n ? { bg: tokens.buttons.primaryButton.hoverBg }\n : { opacity: 0.8 }),\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: tokens.buttons.primaryButton.bg, // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: tokens.buttons.primaryButton.bg, // Explicitly set background\n },\n transition: 'all 0.2s',\n })),\n vechainKitSecondary: defineStyle(() => ({\n fontSize: tokens.fonts.sizes.medium,\n px: 4,\n width: 'full',\n height: '60px',\n rounded: tokens.buttons.button.rounded ?? tokens.borders.radius.large,\n bg: tokens.buttons.button.bg,\n color: tokens.buttons.button.color,\n border:\n tokens.buttons.button.border === 'none'\n ? 'none'\n : tokens.buttons.button.border,\n backdropFilter: tokens.buttons.button.backdropFilter,\n _hover: {\n ...(tokens.buttons.button.hoverBg\n ? { bg: tokens.buttons.button.hoverBg }\n : { opacity: 0.8 }), // Derive hover from bg with opacity if hoverBg not provided\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: tokens.buttons.button.bg, // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: tokens.buttons.button.bg, // Explicitly set background\n },\n transition: 'all 0.2s',\n })),\n vechainKitTertiary: defineStyle(() => ({\n fontSize: tokens.fonts.sizes.medium,\n px: 4,\n width: 'full',\n height: '60px',\n rounded:\n tokens.buttons.tertiaryButton.rounded ??\n tokens.borders.radius.large,\n bg: tokens.buttons.tertiaryButton.bg,\n color: tokens.buttons.tertiaryButton.color,\n border:\n tokens.buttons.tertiaryButton.border === 'none'\n ? 'none'\n : tokens.buttons.tertiaryButton.border,\n backdropFilter: tokens.buttons.tertiaryButton.backdropFilter,\n _hover: {\n opacity: 0.8, // Derive hover from bg with opacity\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: tokens.buttons.tertiaryButton.bg, // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: tokens.buttons.tertiaryButton.bg, // Explicitly set background\n },\n transition: 'all 0.2s',\n })),\n vechainKitLogout: defineStyle(() => ({\n px: 4,\n width: 'full',\n height: '60px',\n rounded: tokens.buttons.button.rounded ?? tokens.borders.radius.large,\n bg: tokens.colors.error + '1f',\n color: tokens.colors.error,\n border:\n tokens.buttons.button.border === 'none'\n ? 'none'\n : tokens.buttons.button.border,\n backdropFilter: tokens.buttons.button.backdropFilter,\n _hover: {\n opacity: 0.8,\n _disabled: {\n opacity: 0.5,\n bg: tokens.colors.error + '1f',\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n },\n transition: 'all 0.2s',\n })),\n vechainKitHeaderIconButtons: defineStyle(() => ({\n bg: tokens.buttons.button.bg,\n color: tokens.buttons.button.color,\n border:\n tokens.buttons.button.border === 'none'\n ? 'none'\n : tokens.buttons.button.border,\n backdropFilter: tokens.buttons.button.backdropFilter,\n _hover: {\n ...(tokens.buttons.button.hoverBg\n ? { bg: tokens.buttons.button.hoverBg }\n : { opacity: 0.8 }), // Derive hover from bg with opacity if hoverBg not provided\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: tokens.buttons.button.bg, // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: tokens.buttons.button.bg, // Explicitly set background\n },\n transition: 'all 0.2s',\n rounded: 'full',\n mt: '8px',\n })),\n actionButton: defineStyle(() => ({\n width: 'full',\n minHeight: '50px',\n height: 'fit-content',\n bg: tokens.buttons.button.bg,\n borderRadius: tokens.borders.radius.xl,\n p: 0,\n color: tokens.buttons.button.color,\n border:\n tokens.buttons.button.border === 'none'\n ? `1px solid ${tokens.colors.border.button}`\n : tokens.buttons.button.border,\n _hover: {\n opacity: 0.8, // Derive hover from bg with opacity\n _disabled: {\n opacity: 0.5, // Override hover opacity when disabled\n bg: tokens.buttons.button.bg, // Ensure background stays\n },\n },\n _disabled: {\n opacity: 0.5,\n cursor: 'not-allowed',\n bg: tokens.buttons.button.bg, // Explicitly set background\n },\n transition: 'all 0.2s',\n })),\n ghost: defineStyle(() => ({\n bg: 'transparent',\n color: tokens.colors.text.primary,\n border: 'none',\n _hover: {\n bg: tokens.buttons.button.bg,\n },\n _active: {\n bg: tokens.buttons.button.bg,\n opacity: 0.8, // Use opacity for active state\n },\n transition: 'all 0.2s',\n })),\n link: defineStyle(() => ({\n color: tokens.colors.text.primary,\n _hover: {\n color: tokens.colors.text.secondary,\n textDecoration: 'underline',\n },\n _active: {\n color: tokens.colors.text.primary,\n },\n transition: 'all 0.2s',\n })),\n});\n\nexport const getButtonTheme = (tokens: ThemeTokens) =>\n defineStyleConfig({\n baseStyle,\n variants: getVariants(tokens),\n });\n\nexport const getIconButtonTheme = (tokens: ThemeTokens) =>\n defineStyleConfig({\n baseStyle,\n variants: getVariants(tokens),\n });\n\nexport const getCloseButtonTheme = (tokens: ThemeTokens) =>\n defineStyleConfig({\n baseStyle,\n variants: getVariants(tokens),\n defaultProps: {\n variant: 'vechainKitHeaderIconButtons',\n },\n });\n","import { popoverAnatomy as parts } from '@chakra-ui/anatomy';\nimport { createMultiStyleConfigHelpers } from '@chakra-ui/react';\nimport { ThemeTokens } from './tokens';\n\nconst { definePartsStyle, defineMultiStyleConfig } =\n createMultiStyleConfigHelpers(parts.keys);\n\nconst getPopoverVariants = (tokens: ThemeTokens) => ({\n vechainKitBase: definePartsStyle({\n popper: {\n zIndex: 1000,\n },\n content: {\n borderRadius: tokens.borders.radius.xl,\n border: tokens.colors.border.modal,\n backgroundColor: tokens.colors.background.modal,\n backdropFilter: tokens.effects.backdropFilter.modal,\n boxShadow: '0px 4px 16px rgba(0, 0, 0, 0.12)',\n minWidth: '380px',\n },\n body: {\n padding: '16px',\n },\n }),\n});\n\nexport const getPopoverTheme = (tokens: ThemeTokens) =>\n defineMultiStyleConfig({\n variants: getPopoverVariants(tokens),\n defaultProps: {\n variant: 'vechainKitBase',\n },\n });\n","import { ThemeConfig, extendTheme, theme as baseTheme } from '@chakra-ui/react';\nimport { getModalTheme } from './modal';\nimport { getCardTheme } from './card';\nimport {\n getButtonTheme,\n getIconButtonTheme,\n getCloseButtonTheme,\n} from './button';\nimport { getPopoverTheme } from './popover';\nimport {\n VechainKitThemeConfig,\n ThemeTokens,\n getDefaultTokens,\n convertThemeConfigToTokens,\n mergeTokens,\n} from './tokens';\n\n// minimal theme that completely disables global styles\nconst getThemeConfig = (\n darkMode: boolean,\n tokens: ThemeTokens,\n): ThemeConfig => ({\n useSystemColorMode: false,\n disableTransitionOnChange: false,\n\n // @ts-ignore\n components: {\n Modal: getModalTheme(tokens),\n Card: getCardTheme(tokens),\n Button: getButtonTheme(tokens),\n IconButton: getIconButtonTheme(tokens),\n CloseButton: getCloseButtonTheme(tokens),\n Popover: getPopoverTheme(tokens),\n },\n // No global styles - fonts will be applied via component-level styles\n // to ensure they only affect VeChain Kit components, not the host app\n styles: {\n global: () => ({}),\n },\n\n // semantic tokens derived from ThemeTokens\n semanticTokens: {\n colors: {\n // Note: chakra-body-text, chakra-body-bg, and chakra-border-color are intentionally omitted\n // to prevent Chakra UI from applying global body/html/border styles that would override host apps\n // Chakra injects: *, *::before, *::after { border-color: var(--chakra-colors-chakra-border-color) }\n // which causes unwanted borders on consumer app elements (e.g., variant=\"link\" buttons)\n // Border colors are applied via scoped CSS in VechainKitThemeProvider LayerSetup instead\n 'chakra-placeholder-color': tokens.colors.text.tertiary,\n // VeChain Kit semantic tokens\n // Main structural background tokens (for component backgrounds)\n 'vechain-kit-modal': tokens.colors.background.modal,\n 'vechain-kit-overlay': tokens.colors.background.overlay,\n 'vechain-kit-card': darkMode\n ? 'rgba(0, 0, 0, 0.3)'\n : 'rgba(0, 0, 0, 0.05)', // Darker card with transparency\n 'vechain-kit-card-elevated': darkMode\n ? 'rgba(0, 0, 0, 0.4)'\n : 'rgba(0, 0, 0, 0.08)', // Darker elevated card with transparency\n 'vechain-kit-sticky-header': tokens.colors.background.stickyHeader,\n 'vechain-kit-text-primary': tokens.colors.text.primary,\n 'vechain-kit-text-secondary': tokens.colors.text.secondary,\n 'vechain-kit-text-tertiary': tokens.colors.text.tertiary,\n 'vechain-kit-border': tokens.colors.border.default,\n 'vechain-kit-border-hover': tokens.colors.border.hover,\n 'vechain-kit-border-focus': tokens.colors.border.focus,\n 'vechain-kit-success': tokens.colors.success,\n 'vechain-kit-error': tokens.colors.error,\n 'vechain-kit-warning': tokens.colors.warning,\n 'vechain-kit-button-primary-bg': tokens.buttons.primaryButton.bg,\n 'vechain-kit-button-primary-color':\n tokens.buttons.primaryButton.color,\n },\n effects: {\n 'vechain-kit-backdrop-filter-modal':\n tokens.effects.backdropFilter.modal,\n 'vechain-kit-backdrop-filter-overlay':\n tokens.effects.backdropFilter.overlay,\n 'vechain-kit-backdrop-filter-sticky-header':\n tokens.effects.backdropFilter.stickyHeader,\n },\n\n config: {\n cssVarPrefix: 'vechain-kit', // consistent naming across all components\n },\n },\n\n // Don't modify fonts in theme - Chakra creates global CSS variables from fonts.body/heading\n // Custom fonts are applied via scoped CSS in VechainKitThemeProvider instead\n fonts: baseTheme.fonts,\n fontSizes: {\n ...baseTheme.fontSizes,\n // Add theme font sizes as standard Chakra font sizes\n sm: tokens.fonts.sizes.small,\n md: tokens.fonts.sizes.medium,\n lg: tokens.fonts.sizes.large,\n },\n fontWeights: {\n ...baseTheme.fontWeights,\n normal: tokens.fonts.weights.normal,\n medium: tokens.fonts.weights.medium,\n bold: tokens.fonts.weights.bold,\n },\n colors: baseTheme.colors,\n space: baseTheme.space,\n});\n\nexport const getVechainKitTheme = (\n darkMode: boolean,\n customThemeConfig?: VechainKitThemeConfig,\n): ReturnType<typeof extendTheme> => {\n // Get default tokens for the mode\n const defaultTokens = getDefaultTokens(darkMode);\n\n // Convert custom config to partial tokens\n const customTokens = convertThemeConfigToTokens(\n customThemeConfig,\n darkMode,\n );\n\n // Merge custom tokens with defaults\n const tokens = mergeTokens(defaultTokens, customTokens);\n\n // Generate theme config with tokens\n const themeConfig = getThemeConfig(darkMode, tokens);\n\n const theme = extendTheme(themeConfig);\n\n // CRITICAL: Completely disable global styles to prevent Chakra from injecting\n // *, *::before, *::after rules that would affect the consumer app\n theme.styles.global = () => ({\n // Return empty object - no global styles should leak to consumer app\n // All VeChain Kit styles are scoped via LayerSetup in VechainKitThemeProvider\n });\n\n // Override CSS variables to prevent them from being set globally\n // They will be set only within VeChain Kit containers via LayerSetup\n if (theme.__cssVars) {\n theme.__cssVars.global = () => {\n // Don't set any CSS variables globally - they're scoped in LayerSetup\n return {};\n };\n }\n\n return theme;\n};\n","import {\n ChakraProvider,\n createStandaloneToast,\n ColorModeScript,\n Box,\n useColorMode,\n} from '@chakra-ui/react';\nimport { CacheProvider, Global, css } from '@emotion/react';\nimport createCache from '@emotion/cache';\nimport {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { getVechainKitTheme } from '@/theme';\nimport { safeQuerySelector } from '@/utils/ssrUtils';\nimport type { VechainKitThemeConfig } from '../theme/tokens';\nimport { VeChainKitContext } from './VeChainKitProvider';\nimport { ThemeTokens } from '@/theme/tokens';\nimport {\n getDefaultTokens,\n convertThemeConfigToTokens,\n mergeTokens,\n} from '@/theme/tokens';\n\ntype Props = {\n children: ReactNode;\n darkMode?: boolean;\n theme?: VechainKitThemeConfig;\n};\n\n// Create a standalone toast system\nconst { ToastContainer } = createStandaloneToast();\n\n// isolated emotion cache for vechain-kit with CSS layer support\nconst createVeChainKitCache = () => {\n return createCache({\n key: 'vechain-kit', // consistent with our layer and class names\n prepend: true,\n // CSS layers will be handled via Global component injection\n });\n};\n\n// CSS Layer setup - simpler approach that doesn't interfere with host app\nconst LayerSetup = ({\n bodyFont,\n headingFont,\n}: {\n bodyFont: string;\n headingFont: string;\n}) => {\n return (\n <Global\n styles={css`\n /* define CSS layers with proper priority order */\n @layer vechain-kit, host-app;\n\n /* All vechain-kit styles go in the vechain-kit layer */\n @layer vechain-kit {\n /* scope all Chakra styles to vechain-kit-root */\n .vechain-kit-root {\n /* vechain-kit styles are contained here */\n }\n\n /* CRITICAL: Remove font CSS variables from :root to prevent leaking to host app */\n /* Chakra UI sets these globally, so we need to explicitly remove them */\n :root {\n --chakra-fonts-body: unset !important;\n --chakra-fonts-heading: unset !important;\n }\n\n /* CRITICAL: Remove Chakra body background and text color CSS variables from :root, html, and body */\n /* These are automatically applied by Chakra UI and would override host app styles */\n :root,\n html,\n body {\n --chakra-body-bg: unset !important;\n --chakra-body-text: unset !important;\n }\n\n /* Apply font family and CSS variables only to VeChain Kit components */\n #vechain-kit-root,\n [data-vechain-kit],\n [id*='headlessui-portal-root'],\n [data-vdk-modal] {\n --chakra-fonts-body: ${bodyFont} !important;\n --chakra-fonts-heading: ${headingFont} !important;\n font-family: ${bodyFont} !important;\n }\n\n /* Apply body font to all text elements */\n #vechain-kit-root *,\n [data-vechain-kit] *,\n [id*='headlessui-portal-root'] *,\n [data-vdk-modal] * {\n font-family: ${bodyFont} !important;\n }\n\n /* Apply heading font to headings */\n #vechain-kit-root h1,\n #vechain-kit-root h2,\n #vechain-kit-root h3,\n #vechain-kit-root h4,\n #vechain-kit-root h5,\n #vechain-kit-root h6,\n [data-vechain-kit] h1,\n [data-vechain-kit] h2,\n [data-vechain-kit] h3,\n [data-vechain-kit] h4,\n [data-vechain-kit] h5,\n [data-vechain-kit] h6,\n [id*='headlessui-portal-root'] h1,\n [id*='headlessui-portal-root'] h2,\n [id*='headlessui-portal-root'] h3,\n [id*='headlessui-portal-root'] h4,\n [id*='headlessui-portal-root'] h5,\n [id*='headlessui-portal-root'] h6,\n [data-vdk-modal] h1,\n [data-vdk-modal] h2,\n [data-vdk-modal] h3,\n [data-vdk-modal] h4,\n [data-vdk-modal] h5,\n [data-vdk-modal] h6 {\n font-family: ${headingFont} !important;\n }\n }\n `}\n />\n );\n};\n\n// Base ChakraProvider conf with style isolation\nconst EnsureChakraProvider = ({\n children,\n theme,\n bodyFont,\n headingFont,\n}: {\n children: ReactNode;\n theme: any;\n bodyFont: string;\n headingFont: string;\n}) => {\n const cache = useMemo(() => createVeChainKitCache(), []);\n\n // Always disable CSS reset to prevent conflicts with host apps\n // vechain-kit components should be self-contained with their own styling\n return (\n <CacheProvider value={cache}>\n <LayerSetup bodyFont={bodyFont} headingFont={headingFont} />\n <ChakraProvider\n theme={theme}\n resetCSS={false}\n // Undefined portal z-index allows host apps to control their own z-index hierarchy\n // instead of Chakra forcing high values (1500+) that might conflict\n portalZIndex={undefined}\n >\n {children}\n </ChakraProvider>\n </CacheProvider>\n );\n};\n\nconst EnsureColorModeScript = ({ darkMode }: { darkMode: boolean }) => {\n try {\n // Check if ColorModeScript already exists by looking for its data attribute\n const existingScript = safeQuerySelector('[data-chakra-color-mode]');\n if (existingScript) {\n return null; // Don't render another one if it exists\n }\n } catch (e) {\n console.error(e);\n }\n\n // If no ColorModeScript exists, provide one\n return <ColorModeScript initialColorMode={darkMode ? 'dark' : 'light'} />;\n};\n\nconst VechainKitThemeContext = createContext<{\n portalRootRef?: React.RefObject<HTMLDivElement | null>;\n tokens?: ThemeTokens;\n themeConfig?: VechainKitThemeConfig;\n}>({\n portalRootRef: undefined,\n tokens: undefined,\n themeConfig: undefined,\n});\n\nexport const useVechainKitThemeConfig = () => {\n const context = useContext(VechainKitThemeContext);\n if (!context) {\n throw new Error(\n 'useVechainKitTheme must be used within a VechainKitThemeProvider',\n );\n }\n return context;\n};\n\nexport const ColorModeSync = ({ darkMode = false }: { darkMode: boolean }) => {\n const { setColorMode, colorMode: currentColorMode } = useColorMode();\n\n useEffect(() => {\n const colorMode = darkMode ? 'dark' : 'light';\n\n if (currentColorMode !== colorMode) setColorMode(colorMode);\n }, [darkMode]);\n\n return <></>;\n};\n\nexport const VechainKitThemeProvider = ({\n children,\n darkMode = false,\n theme: customTheme,\n}: Props) => {\n const portalRootRef = useRef<HTMLDivElement | null>(null);\n\n // Get theme from context if not provided as prop\n const context = useContext(VeChainKitContext);\n const contextTheme = context ? (context as any).theme : undefined;\n const effectiveTheme = customTheme ?? contextTheme;\n\n // Generate tokens for component access\n const tokens = useMemo(() => {\n const defaultTokens = getDefaultTokens(darkMode);\n const customTokens = convertThemeConfigToTokens(\n effectiveTheme,\n darkMode,\n );\n return mergeTokens(defaultTokens, customTokens);\n }, [darkMode, effectiveTheme]);\n\n const theme = useMemo(\n () => ({\n ...getVechainKitTheme(darkMode, effectiveTheme),\n config: {\n ...getVechainKitTheme(darkMode, effectiveTheme).config,\n initialColorMode: darkMode ? 'dark' : 'light',\n },\n }),\n [darkMode, effectiveTheme],\n );\n\n return (\n <VechainKitThemeContext.Provider\n value={{ portalRootRef, tokens, themeConfig: effectiveTheme }}\n >\n <EnsureColorModeScript darkMode={darkMode} />\n <EnsureChakraProvider\n theme={theme}\n bodyFont={tokens.fonts.body}\n headingFont={tokens.fonts.heading}\n >\n <ColorModeSync darkMode={darkMode} />\n <Box\n id=\"vechain-kit-root\"\n ref={portalRootRef}\n bg=\"transparent\"\n borderRadius=\"12px\"\n >\n {children}\n </Box>\n </EnsureChakraProvider>\n <ToastContainer />\n </VechainKitThemeContext.Provider>\n );\n};\n","import {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useState,\n} from 'react';\nimport {\n AccountModal,\n AccountModalContentTypes,\n ConnectModal,\n ConnectModalContentsTypes,\n UpgradeSmartAccountModal,\n UpgradeSmartAccountModalStyle,\n} from '../components';\nimport { useDAppKitWallet } from '@/hooks';\nimport { isBrowser } from '@/utils/ssrUtils';\nimport { VechainKitThemeProvider } from './VechainKitThemeProvider';\nimport { useVeChainKitConfig } from './VeChainKitProvider';\n\nexport type AccountModalOptions = {\n isolatedView?: boolean;\n};\n\ntype ModalContextType = {\n // Connect Modal\n openConnectModal: (\n initialContent?: ConnectModalContentsTypes,\n preventAutoClose?: boolean,\n ) => void;\n closeConnectModal: () => void;\n isConnectModalOpen: boolean;\n connectModalContent: ConnectModalContentsTypes;\n setConnectModalContent: React.Dispatch<\n React.SetStateAction<ConnectModalContentsTypes>\n >;\n connectModalPreventAutoClose: boolean;\n setConnectModalPreventAutoClose: React.Dispatch<\n React.SetStateAction<boolean>\n >;\n // Account Modal\n openAccountModal: (\n content?: AccountModalContentTypes,\n options?: AccountModalOptions,\n ) => void;\n closeAccountModal: () => void;\n isAccountModalOpen: boolean;\n // Account Modal Content State\n accountModalContent: AccountModalContentTypes;\n setAccountModalContent: React.Dispatch<\n React.SetStateAction<AccountModalContentTypes>\n >;\n // Account Modal Options\n isolatedView: boolean;\n // Transaction Modal\n openTransactionModal: () => void;\n closeTransactionModal: () => void;\n isTransactionModalOpen: boolean;\n // Transaction Toast\n openTransactionToast: () => void;\n closeTransactionToast: () => void;\n isTransactionToastOpen: boolean;\n // Upgrade Smart Account Modal\n openUpgradeSmartAccountModal: (\n style?: UpgradeSmartAccountModalStyle,\n ) => void;\n closeUpgradeSmartAccountModal: () => void;\n isUpgradeSmartAccountModalOpen: boolean;\n};\n\nconst ModalContext = createContext<ModalContextType | null>(null);\n\nexport const useModal = () => {\n const context = useContext(ModalContext);\n if (!context) {\n throw new Error('useModal must be used within ModalProvider');\n }\n return context;\n};\n\nexport const ModalProvider = ({ children }: { children: ReactNode }) => {\n const { darkMode, theme } = useVeChainKitConfig();\n const [isConnectModalOpen, setIsConnectModalOpen] = useState(false);\n const [connectModalContent, setConnectModalContent] =\n useState<ConnectModalContentsTypes>('main');\n const [connectModalPreventAutoClose, setConnectModalPreventAutoClose] =\n useState(false);\n const { setSource, connectV2 } = useDAppKitWallet();\n const openConnectModal = useCallback(\n (\n initialContent?: ConnectModalContentsTypes,\n preventAutoClose?: boolean,\n ) => {\n // If the user is in the veworld app, connect to the wallet\n if (\n isBrowser() &&\n window.vechain &&\n window.vechain.isInAppBrowser\n ) {\n setSource('veworld');\n connectV2(null);\n } else {\n // Always set the content - default to 'main' if not provided\n setConnectModalContent(initialContent ?? 'main');\n setConnectModalPreventAutoClose(preventAutoClose ?? false);\n setIsConnectModalOpen(true);\n }\n },\n [],\n );\n const closeConnectModal = useCallback(() => {\n setIsConnectModalOpen(false);\n // Reset content to main when modal closes\n setConnectModalContent('main');\n setConnectModalPreventAutoClose(false);\n }, []);\n\n const [isAccountModalOpen, setIsAccountModalOpen] = useState(false);\n const [isolatedView, setIsolatedView] = useState(false);\n const [accountModalContent, setAccountModalContent] =\n useState<AccountModalContentTypes>('main');\n\n const openAccountModal = useCallback(\n (content?: AccountModalContentTypes, options?: AccountModalOptions) => {\n setAccountModalContent(content ?? 'main');\n setIsolatedView(options?.isolatedView ?? false);\n setIsAccountModalOpen(true);\n },\n [],\n );\n const closeAccountModal = useCallback(() => {\n setIsAccountModalOpen(false);\n // Reset content to main when modal closes\n setAccountModalContent('main');\n // Reset isolatedView after modal close animation completes\n setTimeout(() => {\n setIsolatedView(false);\n }, 300);\n }, []);\n\n const [isTransactionModalOpen, setIsTransactionModalOpen] = useState(false);\n const openTransactionModal = useCallback(\n () => setIsTransactionModalOpen(true),\n [],\n );\n const closeTransactionModal = useCallback(\n () => setIsTransactionModalOpen(false),\n [],\n );\n\n const [isTransactionToastOpen, setIsTransactionToastOpen] = useState(false);\n const openTransactionToast = useCallback(\n () => setIsTransactionToastOpen(true),\n [],\n );\n const closeTransactionToast = useCallback(\n () => setIsTransactionToastOpen(false),\n [],\n );\n\n const [isUpgradeSmartAccountModalOpen, setIsUpgradeSmartAccountModalOpen] =\n useState(false);\n const [upgradeSmartAccountModalStyle, setUpgradeSmartAccountModalStyle] =\n useState<UpgradeSmartAccountModalStyle | undefined>(undefined);\n const openUpgradeSmartAccountModal = useCallback(\n (style?: UpgradeSmartAccountModalStyle) => {\n setUpgradeSmartAccountModalStyle(style);\n setIsUpgradeSmartAccountModalOpen(true);\n },\n [],\n );\n const closeUpgradeSmartAccountModal = useCallback(\n () => setIsUpgradeSmartAccountModalOpen(false),\n [],\n );\n\n return (\n <ModalContext.Provider\n value={{\n openConnectModal,\n closeConnectModal,\n isConnectModalOpen,\n connectModalContent,\n setConnectModalContent,\n connectModalPreventAutoClose,\n setConnectModalPreventAutoClose,\n openAccountModal,\n closeAccountModal,\n isAccountModalOpen,\n setAccountModalContent,\n accountModalContent,\n isolatedView,\n openTransactionModal,\n closeTransactionModal,\n isTransactionModalOpen,\n openTransactionToast,\n closeTransactionToast,\n isTransactionToastOpen,\n openUpgradeSmartAccountModal,\n closeUpgradeSmartAccountModal,\n isUpgradeSmartAccountModalOpen,\n }}\n >\n {children}\n <VechainKitThemeProvider darkMode={darkMode} theme={theme}>\n <ConnectModal\n isOpen={isConnectModalOpen}\n onClose={closeConnectModal}\n initialContent={connectModalContent}\n preventAutoClose={connectModalPreventAutoClose}\n />\n <AccountModal\n isOpen={isAccountModalOpen}\n onClose={closeAccountModal}\n initialContent={accountModalContent}\n />\n <UpgradeSmartAccountModal\n isOpen={isUpgradeSmartAccountModalOpen}\n onClose={closeUpgradeSmartAccountModal}\n style={upgradeSmartAccountModalStyle}\n />\n </VechainKitThemeProvider>\n </ModalContext.Provider>\n );\n};\n","import { useVeChainKitConfig } from '@/providers';\nimport { useModal } from '@/providers/ModalProvider';\nimport { ReactNode } from 'react';\nimport { useDAppKitWalletModal } from '..';\nimport { ConnectModalContentsTypes } from '@/components';\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 const { open: openDappKit, close: closeDappKit } = useDAppKitWalletModal();\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 { useModal } from '@/providers/ModalProvider';\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 { useModal } from '@/providers/ModalProvider';\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 { useModal } from '@/providers/ModalProvider';\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","import { useWallet } from '@/hooks';\nimport { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\nimport type { AccountModalContentTypes } from '@/components/AccountModal/Types';\nimport { ReactNode } from 'react';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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","import { useVeChainKitConfig } from '@/providers';\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 { UpgradeSmartAccountModalStyle } from '@/components';\nimport { useModal } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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 { useModal, AccountModalOptions } from '@/providers/ModalProvider';\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","'use client';\n\nimport { useCallback, useState } from 'react';\nimport { usePrivyWalletProvider } from '@/providers';\nimport { useWallet } from '@/hooks';\nimport { useWallet as useDappKitWallet } from '@vechain/dapp-kit-react';\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 const { requestCertificate } = useDappKitWallet();\n const privyWalletProvider = usePrivyWalletProvider();\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 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 { SignTypedDataParams } from '@privy-io/react-auth';\nimport { usePrivyWalletProvider } from '@/providers';\nimport { useWallet, useDAppKitWallet } from '@/hooks';\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 const { signer } = useDAppKitWallet();\n const { connection } = useWallet();\n const privyWalletProvider = usePrivyWalletProvider();\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 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 { CrossAppConnectionCache } from '@/types';\nimport { useCallback } from 'react';\nimport { getLocalStorageItem, setLocalStorageItem, removeLocalStorageItem } from '@/utils/ssrUtils';\n\nexport const useCrossAppConnectionCache = () => {\n const CACHE_KEY = 'vechain_kit_cross_app_connection';\n\n const setConnectionCache = useCallback(\n (ecosystemApp: {\n name: string;\n logoUrl?: string;\n appId: string;\n website?: string;\n }) => {\n const cacheData: CrossAppConnectionCache = {\n timestamp: Date.now(),\n ecosystemApp,\n };\n setLocalStorageItem(CACHE_KEY, JSON.stringify(cacheData));\n },\n [],\n );\n\n const getConnectionCache =\n useCallback((): CrossAppConnectionCache | null => {\n const cached = getLocalStorageItem(CACHE_KEY);\n if (!cached) return null;\n return JSON.parse(cached) as CrossAppConnectionCache;\n }, []);\n\n const clearConnectionCache = useCallback(() => {\n removeLocalStorageItem(CACHE_KEY);\n }, []);\n\n return {\n setConnectionCache,\n getConnectionCache,\n clearConnectionCache,\n };\n};\n","import { usePrivyCrossAppSdk } from '@/providers/PrivyCrossAppProvider';\nimport { useCrossAppConnectionCache } from '@/hooks/cache/useCrossAppConnectionCache';\nimport { useFetchAppInfo } from '@/hooks';\nimport { VECHAIN_PRIVY_APP_ID } from '@/utils';\nimport { handlePopupError } from '@/utils/handlePopupError';\nimport { VEBETTERDAO_GOVERNANCE_BASE_URL } from '@/constants';\n\nexport const useLoginWithVeChain = () => {\n const { login: loginWithVeChain } = usePrivyCrossAppSdk();\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 { AllowedCategories } from '@/components/AccountModal/Contents/Ecosystem/Components/CategoryLabel';\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","import {\n executeCallClause,\n executeMultipleClausesCall,\n MultipleClausesCallParameters,\n ViewFunctionResult,\n} from '@/utils';\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { useThor } from '@vechain/dapp-kit-react';\nimport { ThorClient } from '@vechain/sdk-network';\nimport {\n ExtractAbiFunctionNames,\n AbiParametersToPrimitiveTypes,\n} from 'abitype';\nimport { Abi, ContractFunctionParameters } from 'viem';\n\nexport * from '@/utils/thorUtils';\n\ntype ExtractViewFunction<\n TAbi extends Abi,\n TMethod extends ExtractAbiFunctionNames<TAbi, 'pure' | 'view'>,\n> = Extract<\n TAbi[number],\n { type: 'function'; stateMutability: 'pure' | 'view'; name: TMethod }\n>;\n\nexport const getCallClauseQueryKey = <\n TAbi extends Abi,\n TMethod extends ExtractAbiFunctionNames<TAbi, 'pure' | 'view'>,\n>({\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n abi,\n address,\n method,\n}: {\n abi: TAbi;\n address: string;\n method: TMethod;\n}) => ['callClause', address, method];\n\n/**\n * Serializes args for query key by converting BigInt values to strings\n * This prevents JSON.stringify errors when React Query serializes the query key\n */\nconst serializeArgsForQueryKey = (args: unknown[]): unknown[] => {\n return args.map((arg) => {\n if (typeof arg === 'bigint') {\n return arg.toString();\n }\n if (Array.isArray(arg)) {\n return serializeArgsForQueryKey(arg);\n }\n if (arg && typeof arg === 'object') {\n return Object.fromEntries(\n Object.entries(arg).map(([key, value]) => [\n key,\n typeof value === 'bigint' ? value.toString() : value,\n ]),\n );\n }\n return arg;\n });\n};\n\nexport const getCallClauseQueryKeyWithArgs = <\n TAbi extends Abi,\n TMethod extends ExtractAbiFunctionNames<TAbi, 'pure' | 'view'>,\n>({\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n abi,\n address,\n method,\n args,\n}: {\n abi: TAbi;\n address: string;\n method: TMethod;\n args?: AbiParametersToPrimitiveTypes<\n ExtractViewFunction<TAbi, TMethod>['inputs'],\n 'inputs'\n >;\n}) => [\n 'callClause',\n address,\n method,\n ...(args?.length ? serializeArgsForQueryKey(args as unknown[]) : []),\n];\n\nexport const useCallClause = <\n TAbi extends Abi,\n TMethod extends ExtractAbiFunctionNames<TAbi, 'pure' | 'view'>,\n TData = ViewFunctionResult<TAbi, TMethod>,\n>({\n address,\n abi,\n method,\n args,\n queryOptions,\n}: {\n address: string;\n abi: TAbi;\n method: TMethod;\n args: AbiParametersToPrimitiveTypes<\n ExtractViewFunction<TAbi, TMethod>['inputs'],\n 'inputs'\n >;\n queryOptions?: Omit<\n UseQueryOptions<\n ViewFunctionResult<TAbi, TMethod>,\n unknown,\n TData,\n ReturnType<typeof getCallClauseQueryKeyWithArgs<TAbi, TMethod>>\n >,\n 'queryKey' | 'queryFn'\n >;\n}) => {\n const thor = useThor();\n\n return useQuery({\n queryKey: getCallClauseQueryKeyWithArgs({\n abi,\n address,\n method,\n args,\n }),\n queryFn: async () =>\n executeCallClause({\n thor,\n contractAddress: address,\n abi,\n method,\n args,\n }),\n ...queryOptions,\n });\n};\n\nexport const useMultipleClausesCall = <\n contracts extends readonly ContractFunctionParameters[],\n allowFailure extends boolean = false,\n>({\n thor,\n calls,\n queryKey,\n enabled = true,\n}: {\n thor: ThorClient;\n calls: MultipleClausesCallParameters<contracts, allowFailure>;\n queryKey: string[];\n enabled?: boolean;\n}) =>\n useQuery({\n queryKey,\n queryFn: () => executeMultipleClausesCall({ thor, calls }),\n enabled,\n });\n","import { useVeChainKitConfig } from '@/providers';\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","import { useVeChainKitConfig } from '@/providers';\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 { getConfig } from '@/config';\nimport { useVeChainKitConfig } from '@/providers';\n\nexport const useGetNodeUrl = () => {\n const { network } = useVeChainKitConfig();\n // If user has set a nodeUrl, use it, otherwise use the default nodeUrl for the network\n return network.nodeUrl ?? getConfig(network.type).nodeUrl;\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 { useQuery } from '@tanstack/react-query';\nimport { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\n return useQuery({\n queryKey: getAccountBalanceQueryKey(address),\n queryFn: () => getAccountBalance(thor, address),\n enabled: !!address && Address.isValid(address),\n refetchInterval: 10000,\n });\n};\n","import { getConfig } from '@/config';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { useVeChainKitConfig } from '@/providers';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useQuery } from '@tanstack/react-query';\nimport { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\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';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useQuery } from '@tanstack/react-query';\nimport { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\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 { useThor } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '@/providers';\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 const thor = useThor();\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 { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useVeChainKitConfig } from '@/providers';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { getConfig } from '@/config';\nimport { getCallClauseQueryKeyWithArgs, useCallClause } from '@/hooks';\n\nconst abi = SocialLoginSmartAccountFactory__factory.abi;\n\nexport const getAccountVersionQueryKey = (\n accountAddress: string,\n ownerAddress: string,\n networkType: NETWORK_TYPE,\n) =>\n getCallClauseQueryKeyWithArgs({\n abi,\n address: getConfig(networkType).accountFactoryAddress,\n method: 'getAccountVersion',\n args: [accountAddress as `0x${string}`, ownerAddress as `0x${string}`],\n });\n\n/**\n * Check if a smart account has a v1 smart account\n * @param accountAddress - The address of the smart account\n * @param ownerAddress - The address of the owner of the smart account\n * @returns The version of the smart account\n */\nexport const useGetAccountVersion = (\n accountAddress: string,\n ownerAddress: string,\n) => {\n const { network } = useVeChainKitConfig();\n\n return useCallClause({\n address: getConfig(network.type).accountFactoryAddress,\n abi,\n method: 'getAccountVersion',\n args: [accountAddress as `0x${string}`, ownerAddress as `0x${string}`],\n queryOptions: {\n select: (data) => {\n return {\n version: parseInt(data[0].toString()),\n isDeployed: data[1],\n };\n },\n },\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useThor } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '@/providers';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { getConfig } from '@/config';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { executeCallClause } from '@/utils/thorUtils';\n\nconst abi = SocialLoginSmartAccountFactory__factory.abi;\nconst method = 'hasLegacyAccount' as const;\n\nexport const getHasV1SmartAccount = async (\n thor: ThorClient,\n ownerAddress?: string,\n networkType?: NETWORK_TYPE,\n): Promise<boolean> => {\n if (!ownerAddress) throw new Error('Owner address is required');\n if (!networkType) throw new Error('Network type is required');\n\n const [hasLegacyAccount] = await executeCallClause({\n thor,\n abi,\n contractAddress: getConfig(networkType).accountFactoryAddress,\n method,\n args: [ownerAddress as `0x${string}`],\n });\n\n return hasLegacyAccount;\n};\n\nexport const getHasV1SmartAccountQueryKey = (\n ownerAddress?: string,\n networkType?: NETWORK_TYPE,\n) => [\n 'VECHAIN_KIT',\n 'SMART_ACCOUNT',\n 'HAS_V1_SMART_ACCOUNT',\n ownerAddress,\n networkType,\n];\n\n/**\n * Check if a smart account has a v1 smart account\n * @param ownerAddress - The address of the owner of the smart account\n * @returns True if the smart account has a v1 smart account, false otherwise\n */\nexport const useHasV1SmartAccount = (ownerAddress?: string) => {\n const thor = useThor();\n const { network } = useVeChainKitConfig();\n\n return useQuery({\n queryKey: getHasV1SmartAccountQueryKey(ownerAddress, network.type),\n queryFn: async () =>\n getHasV1SmartAccount(thor, ownerAddress, network.type),\n enabled: !!thor && !!ownerAddress && !!network,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { useGetNodeUrl } from '@/hooks';\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 { useQueryClient } from '@tanstack/react-query';\nimport { useWallet } from '../../api/wallet/useWallet';\nimport {\n getAccountVersionQueryKey,\n getUpgradeRequiredQueryKey,\n getUpgradeRequiredForAccountQueryKey,\n getCurrentAccountImplementationVersionQueryKey,\n getAccountImplementationAddressQueryKey,\n getHasV1SmartAccountQueryKey,\n getAccountAddressQueryKey,\n} from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\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';\nimport {\n getSmartAccountQueryKey,\n getIsDeployedQueryKey,\n} from '@/hooks';\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","import { useQuery } from '@tanstack/react-query';\nimport { Address } from '@vechain/sdk-core';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { useVeChainKitConfig } from '@/providers';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { getConfig } from '@/config';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useThor } from '@vechain/dapp-kit-react';\n\nexport interface SmartAccountReturnType {\n address: string | undefined;\n isDeployed: boolean;\n}\nexport const getSmartAccount = async (\n thor: ThorClient,\n network: NETWORK_TYPE,\n ownerAddress?: string,\n) => {\n if (!ownerAddress) {\n return { address: undefined };\n }\n\n const res = await thor.contracts\n .load(\n getConfig(network).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\n const accountAddress = Address.of(res[0].toString());\n const accountDetail = await thor.accounts.getAccount(accountAddress);\n\n if (!accountDetail) {\n throw new Error(`Failed to get account detail of ${accountAddress}`);\n }\n\n return {\n address: accountAddress.toString(),\n isDeployed: accountDetail.hasCode,\n };\n};\n\nexport const getSmartAccountQueryKey = (ownerAddress?: string) => {\n return ['VECHAIN_KIT_SMART_ACCOUNT', ownerAddress];\n};\n\nexport const useSmartAccount = (ownerAddress?: string) => {\n const { network } = useVeChainKitConfig();\n const thor = useThor();\n\n return useQuery({\n queryKey: getSmartAccountQueryKey(ownerAddress),\n queryFn: () => getSmartAccount(thor, network.type, ownerAddress),\n enabled: !!ownerAddress && !!network.type && !!thor,\n });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useThor } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '@/providers';\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 const thor = useThor();\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 { useQuery } from '@tanstack/react-query';\nimport { SocialLoginSmartAccountFactory__factory } from '@vechain/vechain-contract-types';\nimport { useThor } from '@vechain/dapp-kit-react';\nimport { useVeChainKitConfig } from '@/providers';\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 const thor = useThor();\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 { useAccountImplementationAddress, useRefreshFactoryQueries, useRefreshSmartAccountQueries, useSendTransaction, UseSendTransactionReturnValue } from '@/hooks';\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 { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\n\n return useQuery({\n queryKey: currentBlockQueryKey(),\n queryFn: async () => {\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 });\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { useThor } from '@vechain/dapp-kit-react';\n\nexport const getChainId = async (thor: ThorClient) => {\n const genesisBlock = await thor.blocks.getGenesisBlock();\n if (!genesisBlock) throw new Error('Genesis block not found');\n const chainId = genesisBlock.id;\n\n return chainId;\n};\nexport const getChainIdQueryKey = () => ['VECHAIN_KIT_CHAIN_ID'];\n\n/**\n * Get the chain id\n * @returns The chain id\n */\nexport const useGetChainId = () => {\n const thor = useThor();\n\n return useQuery({\n queryKey: getChainIdQueryKey(),\n queryFn: () => getChainId(thor),\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","import {\n UseSendTransactionReturnValue,\n useRefreshBalances,\n useSendTransaction,\n} from '@/hooks';\nimport { IERC20__factory } from '@vechain/vechain-contract-types';\nimport { useMemo } from 'react';\nimport { humanAddress, isValidAddress } from '@/utils';\nimport { parseEther } from 'viem';\nimport { 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","import {\n UseSendTransactionReturnValue,\n useRefreshBalances,\n useSendTransaction,\n} from '@/hooks';\nimport { humanAddress, isValidAddress } from '@/utils';\nimport { useMemo } from 'react';\nimport { parseEther } from 'viem';\nimport { 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';\nimport { useWallet } from '@/hooks';\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","'use client';\n\nimport { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\n\n return useQuery({\n queryKey: txReceiptQueryKey(txId),\n queryFn: async () => {\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: !!txId,\n });\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 { useThor } from '@vechain/dapp-kit-react';\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 const thor = useThor();\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 { SignTypedDataParameters } from \"@wagmi/core\";\nimport { encodeFunctionData } from \"viem\";\nimport { ethers } from \"ethers\";\nimport { EnhancedClause, ExecuteWithAuthorizationSignData, ExecuteBatchWithAuthorizationSignData } from \"@/types\";\nimport { Clause, Address, ABIContract, TransactionClause } from '@vechain/sdk-core';\nimport { getConfig } from '@/config';\nimport { usePrivy } from '@privy-io/react-auth';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { usePrivyCrossAppSdk } from '@/providers/PrivyCrossAppProvider';\nimport { useWallet, SmartAccountReturnType, useGetChainId } from \"@/hooks\";\nimport { useVeChainKitConfig } from \"@/providers\";\nimport { SocialLoginSmartAccount__factory, SocialLoginSmartAccountFactory__factory } from \"@vechain/vechain-contract-types\";\n\nexport interface BuildClausesParams {\n clauses: EnhancedClause[];\n smartAccount: SmartAccountReturnType;\n version: number | undefined;\n title?: string;\n description?: string;\n buttonText?: string;\n}\n\n/**\n * Build the typed data structure for executeBatchWithAuthorization\n * @param clauses - The clauses to sign\n * @param chainId - The chain id\n * @param verifyingContract - The address of the smart account\n * @returns The typed data structure for executeBatchWithAuthorization\n */\nexport function buildBatchAuthorizationTypedData({\n clauses,\n chainId,\n verifyingContract,\n}: {\n clauses: TransactionClause[];\n chainId: number;\n verifyingContract: string;\n}): ExecuteBatchWithAuthorizationSignData {\n const toArray: string[] = [];\n const valueArray: string[] = [];\n const dataArray: string[] = [];\n\n clauses.forEach((clause) => {\n toArray.push(clause.to ?? '');\n valueArray.push(String(clause.value));\n if (typeof clause.data === 'object' && 'abi' in clause.data) {\n dataArray.push(encodeFunctionData(clause.data));\n } else {\n dataArray.push(clause.data || '0x');\n }\n });\n\n return {\n domain: {\n name: 'Wallet',\n version: '1',\n chainId,\n verifyingContract: verifyingContract,\n },\n types: {\n ExecuteBatchWithAuthorization: [\n { name: 'to', type: 'address[]' },\n { name: 'value', type: 'uint256[]' },\n { name: 'data', type: 'bytes[]' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n EIP712Domain: [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n ],\n },\n primaryType: 'ExecuteBatchWithAuthorization',\n message: {\n to: toArray,\n value: valueArray,\n data: dataArray,\n validAfter: 0,\n validBefore: Math.floor(Date.now() / 1000) + 300, // e.g. 5 minutes from now\n nonce: ethers.hexlify(ethers.randomBytes(32)),\n },\n };\n};\n\n/**\n * Build the typed data structure for executeWithAuthorization\n * @param clause - The clause to sign\n * @param chainId - The chain id\n * @param smartAccount - The smart account object\n * @returns The typed data structure for executeWithAuthorization\n */\nexport function buildSingleAuthorizationTypedData({\n clause,\n chainId,\n smartAccount,\n}: {\n clause: TransactionClause;\n chainId: number;\n smartAccount: SmartAccountReturnType;\n}): ExecuteWithAuthorizationSignData {\n return {\n domain: {\n name: 'Wallet',\n version: '1',\n chainId: chainId as unknown as number, // convert chainId to a number\n verifyingContract: smartAccount.address ?? '',\n },\n types: {\n ExecuteWithAuthorization: [\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'data', type: 'bytes' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n ],\n EIP712Domain: [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n ],\n },\n primaryType: 'ExecuteWithAuthorization',\n message: {\n validAfter: 0,\n validBefore: Math.floor(Date.now() / 1000) + 60, // 1 minute\n to: clause.to,\n value: String(clause.value),\n data:\n (typeof clause.data === 'object' && 'abi' in clause.data\n ? encodeFunctionData(clause.data)\n : clause.data) || '0x',\n },\n };\n};\n\nfunction setUpBuildClausesParams() {\n const { connection, connectedWallet } = useWallet();\n const { signTypedData: signTypedDataWithCrossApp } = usePrivyCrossAppSdk();\n const { signTypedData: signTypedDataPrivy } = usePrivy();\n const { network } = useVeChainKitConfig();\n const { data: chainId } = useGetChainId();\n\n return {\n connection,\n connectedWallet,\n signTypedDataWithCrossApp,\n signTypedDataPrivy,\n network,\n chainId,\n };\n}\n\n/**\n * Build either executeWithAuthorization or executeBatchWithAuthorization clauses based on smart account version using buildClausesWithAuth\n * @param clauses - Either VET or ERC20 clauses\n * @param smartAccount - The user's smart account object\n * @param version - The smart account version\n * @param title - The title of the transaction\n * @param description - The description of the transaction\n * @param buttonText - The button text of the transaction\n * @returns The clauses for the executeWithAuthorization or executeBatchWithAuthorization function using buildClausesWithAuth\n */\nexport const useBuildClauses = () => {\n const {\n connection,\n connectedWallet,\n signTypedDataWithCrossApp,\n signTypedDataPrivy,\n network,\n chainId,\n } = setUpBuildClausesParams();\n\n const buildClausesWithAuth = async (params: BuildClausesParams) => {\n const { version } = params;\n if (version && version < 3) {\n return await buildSingleExecuteWithAuthorizationClauses(params);\n }\n return await buildBatchExecuteWithAuthorizationClauses(params);\n }\n\n async function buildSingleExecuteWithAuthorizationClauses(params: BuildClausesParams) {\n const {\n clauses: txClauses,\n smartAccount,\n title = 'Sign Transaction',\n description,\n buttonText = 'Sign',\n } = params;\n\n const resultClauses = [];\n\n const dataToSign: ExecuteWithAuthorizationSignData[] =\n txClauses.map((txData: EnhancedClause) =>\n buildSingleAuthorizationTypedData({\n clause: txData,\n chainId: chainId as unknown as number,\n smartAccount: smartAccount,\n }),\n );\n\n // request signatures using privy\n const signatures: string[] = [];\n for (let index = 0; index < dataToSign.length; index++) {\n const data = dataToSign[index];\n const txClause = txClauses[index];\n if (!txClause) {\n throw new Error(\n `Transaction clause at index ${index} is undefined`,\n );\n }\n\n if (connection.isConnectedWithCrossApp) {\n const mutableData = {\n ...data,\n address: connectedWallet?.address as `0x${string}`,\n types: Object.fromEntries(\n Object.entries(data.types).map(([k, v]) => [\n k,\n [...v],\n ]),\n ),\n } as unknown as SignTypedDataParameters;\n const signature = await signTypedDataWithCrossApp(\n mutableData,\n );\n signatures.push(signature);\n continue;\n }\n\n const funcData = txClause.data;\n const signature = (\n await signTypedDataPrivy(data, {\n uiOptions: {\n title,\n description:\n description ??\n ((txClauses[index] as EnhancedClause).comment ||\n (typeof funcData === 'object' &&\n funcData !== null &&\n 'functionName' in funcData\n ? (\n funcData as {\n functionName: string;\n }\n ).functionName\n : ' ')),\n buttonText,\n },\n })\n ).signature;\n signatures.push(signature);\n }\n // if the account smartAccountAddress has no code yet, it's not been deployed/created yet\n if (!smartAccount.isDeployed) {\n resultClauses.push(\n Clause.callFunction(\n Address.of(\n getConfig(network.type as NETWORK_TYPE).accountFactoryAddress,\n ),\n ABIContract.ofAbi(\n SocialLoginSmartAccountFactory__factory.abi,\n ).getFunction('createAccount'),\n [connectedWallet?.address ?? ''], // set the Privy wallet address as the owner of the smart account\n ),\n );\n }\n\n dataToSign.forEach((data, index) => {\n resultClauses.push(\n Clause.callFunction(\n Address.of(smartAccount.address ?? ''),\n ABIContract.ofAbi(\n SocialLoginSmartAccount__factory.abi,\n ).getFunction('executeWithAuthorization'),\n [\n data.message.to as `0x${string}`,\n BigInt(data.message.value),\n data.message.data as `0x${string}`,\n BigInt(data.message.validAfter),\n BigInt(data.message.validBefore),\n signatures[index] as `0x${string}`,\n ],\n ),\n );\n });\n return resultClauses;\n }\n\n async function buildBatchExecuteWithAuthorizationClauses(params: BuildClausesParams) {\n const {\n clauses: txClauses,\n smartAccount,\n title,\n description,\n buttonText = 'Sign',\n } = params;\n\n const resultClauses = [];\n\n const typedData = buildBatchAuthorizationTypedData({\n clauses: txClauses,\n chainId: chainId as unknown as number,\n verifyingContract: smartAccount.address ?? '',\n });\n\n // Sign the typed data (either cross-app or traditional Privy)\n let signature = undefined;\n signature = connection.isConnectedWithCrossApp\n ? await signTypedDataWithCrossApp({\n ...typedData,\n address: connectedWallet?.address as `0x${string}`,\n } as SignTypedDataParameters)\n : (\n await signTypedDataPrivy(typedData, {\n uiOptions: {\n title,\n description,\n buttonText,\n },\n })\n ).signature;\n // If the smart account is not deployed, deploy it first\n if (!smartAccount.isDeployed) {\n resultClauses.push(\n Clause.callFunction(\n Address.of(\n getConfig(network.type as NETWORK_TYPE).accountFactoryAddress,\n ),\n ABIContract.ofAbi(\n SocialLoginSmartAccountFactory__factory.abi,\n ).getFunction('createAccount'),\n [connectedWallet?.address ?? ''],\n ),\n );\n }\n\n // Now the single batch execution call\n resultClauses.push(\n Clause.callFunction(\n Address.of(smartAccount.address ?? ''),\n ABIContract.ofAbi(\n SocialLoginSmartAccount__factory.abi,\n ).getFunction('executeBatchWithAuthorization'),\n [\n typedData.message.to,\n typedData.message.value?.map((val) => BigInt(val)) ?? 0,\n typedData.message.data,\n BigInt(typedData.message.validAfter),\n BigInt(typedData.message.validBefore),\n typedData.message.nonce, // If your contract expects bytes32\n signature as `0x${string}`,\n ],\n ),\n );\n return resultClauses;\n }\n return {\n buildClausesWithAuth,\n };\n};\n","import { useState, useEffect } from 'react';\nimport { getLocalStorageItem, setLocalStorageItem } from '@/utils/ssrUtils';\n\nexport enum LocalStorageKey {\n CUSTOM_TOKENS = 'vechain_kit_custom_tokens',\n ECOSYSTEM_SHORTCUTS = 'vechain-kit-ecosystem-shortcuts',\n CURRENCY = 'vechain_kit_currency',\n NODE_URL = 'vechain_kit_node_url',\n NETWORK = 'vechain_kit_network',\n GAS_TOKEN_PREFERENCES = 'vechain_kit_gas_token_preferences',\n SHOW_ASSETS = 'vechain_kit_show_assets',\n}\n\nexport const useLocalStorage = <T>(key: LocalStorageKey, initialValue: T) => {\n const [storedValue, setStoredValue] = useState<T>(() => {\n try {\n const item = getLocalStorageItem(key);\n return item ? JSON.parse(item) : initialValue;\n } catch (error) {\n console.error(error);\n return initialValue;\n }\n });\n\n useEffect(() => {\n setLocalStorageItem(key, JSON.stringify(storedValue));\n }, [key, storedValue]);\n\n return [storedValue, setStoredValue] as const;\n};\n","import { useCallback, useEffect, useState, useRef } from 'react';\n\nconst STORAGE_CHANGE_EVENT = 'vechain-kit-storage-change';\n\nexport const useSyncableLocalStorage = <T>(key: string, defaultValue: T) => {\n const [value, setValue] = useState<T>(() => {\n if (typeof window === 'undefined') return defaultValue;\n\n try {\n const stored = window.localStorage.getItem(key);\n return stored ? JSON.parse(stored) : defaultValue;\n } catch (err) {\n console.error('Error loading from localStorage:', err);\n return defaultValue;\n }\n });\n\n // Track if we're currently updating to prevent infinite loops\n const isUpdatingRef = useRef(false);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (isUpdatingRef.current) {\n isUpdatingRef.current = false;\n return;\n }\n\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n \n // Dispatch custom event for same-tab sync\n window.dispatchEvent(new CustomEvent(STORAGE_CHANGE_EVENT, {\n detail: { key, value }\n }));\n } catch (err) {\n console.error('Error writing to localStorage:', err);\n }\n }, [key, value]);\n\n // Listen for storage changes from other components\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n const handleStorageChange = (e: StorageEvent) => {\n // Cross-tab changes (standard storage event)\n if (e.key === key && e.newValue) {\n try {\n const newValue = JSON.parse(e.newValue);\n // Only update if value is different\n if (JSON.stringify(newValue) !== JSON.stringify(value)) {\n isUpdatingRef.current = true;\n setValue(newValue);\n }\n } catch (err) {\n console.error('Error parsing storage value:', err);\n }\n }\n };\n\n const handleCustomStorageChange = ((e: CustomEvent) => {\n // Same-tab changes (custom event)\n if (e.detail.key === key) {\n try {\n const stored = window.localStorage.getItem(key);\n if (stored) {\n const newValue = JSON.parse(stored);\n // Only update if value is different\n if (JSON.stringify(newValue) !== JSON.stringify(value)) {\n isUpdatingRef.current = true;\n setValue(newValue);\n }\n }\n } catch (err) {\n console.error('Error parsing storage value:', err);\n }\n }\n }) as EventListener;\n\n window.addEventListener('storage', handleStorageChange);\n window.addEventListener(STORAGE_CHANGE_EVENT, handleCustomStorageChange);\n\n return () => {\n window.removeEventListener('storage', handleStorageChange);\n window.removeEventListener(STORAGE_CHANGE_EVENT, handleCustomStorageChange);\n };\n }, [key, value]);\n\n //Manual sync localStorage and update state\n const sync = useCallback(() => {\n if (typeof window === 'undefined') return;\n try {\n const stored = window.localStorage.getItem(key);\n const newValue = stored ? JSON.parse(stored) : defaultValue;\n if (JSON.stringify(newValue) !== JSON.stringify(value)) {\n setValue(newValue);\n }\n } catch (err) {\n console.error('Error syncing localStorage:', err);\n }\n }, [key, defaultValue, value]);\n\n //Get value directly from localStorage\n const getValue: () => T = useCallback(() => {\n if (typeof window === 'undefined') return defaultValue;\n const stored = window.localStorage.getItem(key);\n return stored ? JSON.parse(stored) : defaultValue;\n }, [key, defaultValue]);\n\n return [value, setValue, sync, getValue] as const;\n};\n","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 {\n Transaction,\n HexUInt,\n TransactionClause\n} from '@vechain/sdk-core';\nimport * as nc_utils from '@noble/curves/abstract/utils';\nimport { GasTokenType, TransactionSpeed, DepositAccount, EstimationResponse, Wallet } from '@/types';\nimport { SmartAccountReturnType, useGasTokenSelection, useWallet, useSmartAccount, useBuildClauses, useGetAccountVersion } from '@/hooks';\nimport { IERC20__factory } from '@vechain/vechain-contract-types';\nimport { parseEther } from 'viem';\nimport { randomTransactionUser, SUPPORTED_GAS_TOKENS } from '@/utils';\nimport { ThorClient } from '@vechain/sdk-network';\nimport { getConfig } from '@/config';\nimport { useVeChainKitConfig } from '@/providers';\nimport { useCallback } from 'react';\n\nexport const estimateGas = async (\n signerAddress: string,\n genericDelegatorUrl: string,\n clauses: any[],\n token: GasTokenType,\n speed: TransactionSpeed,\n) => {\n const estimateUrl = new URL(\n `estimate/clauses/${token.toLowerCase()}`,\n genericDelegatorUrl,\n );\n estimateUrl.searchParams.set('type', 'smartaccount');\n estimateUrl.searchParams.set('speed', speed);\n\n const response = await fetch(estimateUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n clauses: clauses,\n signer: signerAddress,\n }),\n });\n const data = await response.json();\n return data;\n};\n\nexport const getDepositAccount = async (\n genericDelegatorUrl: string,\n): Promise<DepositAccount> => {\n const depositAccountUrl = new URL('deposit/account', genericDelegatorUrl);\n const response = await fetch(depositAccountUrl, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n const data = await response.json();\n return data;\n};\n\nexport const delegateAuthorized = async (encodedSignedTx: string, origin: string, token: GasTokenType, genericDelegatorUrl: string) => {\n const delegateAuthorizedUrl = new URL(\n `sign/transaction/authorized/${token.toLowerCase()}`,\n genericDelegatorUrl,\n );\n const response = await fetch(delegateAuthorizedUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n raw: encodedSignedTx,\n origin: origin,\n token: token.toLowerCase(),\n }),\n });\n const data = await response.json();\n return data;\n}\n\n// Helper to estimate gas and build transaction body\nexport const estimateAndBuildTxBody = async (\n clauses: TransactionClause[],\n thor: ThorClient,\n randomTransactionUser: Wallet,\n isDelegated: boolean\n) => {\n const gasResult = await thor.gas.estimateGas(\n clauses,\n randomTransactionUser?.address ?? '',\n );\n const parsedGasLimit = Math.max(\n gasResult.totalGas,\n 0,\n );\n\n return await thor.transactions.buildTransactionBody(\n clauses,\n parsedGasLimit,\n { isDelegated: isDelegated }\n );\n};\n\n/**\n * Sign the final transaction with the given private key and signature\n * returned by the generic delegator.\n * @param decodedTx The decoded transaction returned by the generic delegator.\n * @param gasPayerSignature The signature returned by the generic delegator.\n * @returns The signed final transaction.\n */\nexport function signVip191Transaction(decodedTx: Transaction, gasPayerSignature: string) {\n return Transaction.of(\n decodedTx.body,\n nc_utils.concatBytes(\n decodedTx.signature ?? new Uint8Array(),\n HexUInt.of(gasPayerSignature.slice(2)).bytes\n )\n )\n}\n\nexport function decodeRawTx(raw: any, isSigned: boolean) {\n return Transaction.decode(\n HexUInt.of(raw.slice(2)).bytes,\n isSigned\n );\n}\n\n/**\n * This function is used to send a transaction using the generic delegator.\n * It will build the necessary clauses, estimate the gas, and send the transaction.\n * @param clauses The clauses to send in the transaction.\n * @param genericDelegatorUrl The URL of the generic delegator.\n * @returns\n */\nexport const useGenericDelegator = () => {\n const { connectedWallet } = useWallet();\n const { data: smartAccount } = useSmartAccount(\n connectedWallet?.address ?? '',\n );\n const { data: smartAccountVersion } = useGetAccountVersion(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n );\n const { preferences } = useGasTokenSelection();\n const ERC20Interface = IERC20__factory.createInterface();\n const { network } = useVeChainKitConfig();\n const { buildClausesWithAuth } = useBuildClauses();\n const thor = ThorClient.at(getConfig(network.type).nodeUrl);\n\n const sendTransactionUsingGenericDelegator = useCallback(async ({\n clauses,\n genericDelegatorUrl\n }: {\n clauses: TransactionClause[];\n genericDelegatorUrl: string;\n }): Promise<string> => {\n try {\n const gasToken = preferences.gasTokenToUse;\n const gasEstimationResponse: EstimationResponse = await estimateGas(smartAccount?.address ?? '', genericDelegatorUrl, clauses as TransactionClause[], gasToken, 'medium');\n\n const depositAccount: DepositAccount = await getDepositAccount(genericDelegatorUrl);\n\n const transferToGenericDelegatorClause = {\n to: gasToken === 'VET' ? depositAccount.depositAccount : SUPPORTED_GAS_TOKENS[gasToken as GasTokenType].address,\n value: gasToken === 'VET' ? parseEther(gasEstimationResponse.transactionCost?.toString() ?? '0').toString() : '0x0',\n data: gasToken === 'VET' ? '0x' : ERC20Interface.encodeFunctionData('transfer', [\n depositAccount.depositAccount,\n parseEther(gasEstimationResponse.transactionCost?.toString() ?? '0'),\n ]),\n comment: `Transfer ${gasEstimationResponse.transactionCost} ${gasToken} to ${depositAccount.depositAccount}`,\n abi: gasToken === 'VET' ? undefined : ERC20Interface.getFunction('transfer'),\n };\n\n const finalExecuteWithAuthorizationClauses = await buildClausesWithAuth({\n clauses: [...clauses, transferToGenericDelegatorClause as TransactionClause],\n smartAccount: smartAccount as SmartAccountReturnType,\n version: smartAccountVersion?.version ?? 0,\n });\n\n const txBody = await estimateAndBuildTxBody(\n finalExecuteWithAuthorizationClauses as TransactionClause[],\n thor,\n randomTransactionUser,\n true\n );\n\n const rawSignedTx = await Transaction.of(txBody).signAsSender(HexUInt.of(randomTransactionUser.privateKey).bytes);\n\n const encodedSignedTx = HexUInt.of(rawSignedTx.encoded).toString()\n\n const gasPayerResponse: {\n signature: string;\n address: string;\n raw: string;\n origin: string;\n } = await delegateAuthorized(encodedSignedTx, randomTransactionUser.address, gasToken, genericDelegatorUrl);\n\n const finalTxSigned = signVip191Transaction(rawSignedTx, gasPayerResponse.signature);\n\n const simulatedTransaction = {\n clauses: finalExecuteWithAuthorizationClauses as TransactionClause[],\n simulateTransactionOptions: {\n caller: randomTransactionUser.address ?? '',\n gasPayer: gasPayerResponse.address,\n }\n };\n\n const simulatedTx1 = await thor.transactions.simulateTransaction(\n simulatedTransaction.clauses,\n {\n ...simulatedTransaction.simulateTransactionOptions\n }\n );\n\n for (let i = 0; i < simulatedTx1.length; i++) {\n if (simulatedTx1[i].reverted) {\n throw new Error(simulatedTx1[i].vmError);\n }\n }\n // Send the transaction\n const sendTransactionResult = await thor.transactions.sendTransaction(finalTxSigned);\n\n return sendTransactionResult.id;\n } catch (error) {\n console.error('Error sending transaction using generic delegator', error);\n }\n throw new Error('Failed to send transaction using generic delegator, no gas tokens have sufficient balance or are enabled in Gas Token Preferences');\n }, [\n preferences,\n smartAccount,\n smartAccountVersion,\n buildClausesWithAuth,\n thor,\n randomTransactionUser,\n ]);\n return {\n sendTransactionUsingGenericDelegator,\n };\n}\n","import { useCallback } from 'react';\nimport { LocalStorageKey, useSyncableLocalStorage } from '../cache';\nimport { GasTokenPreferences, GasTokenType } from '@/types/gasToken';\nimport {\n DEFAULT_GAS_TOKEN_PREFERENCES,\n SUPPORTED_GAS_TOKENS,\n} from '@/utils/constants';\n\nexport const useGasTokenSelection = () => {\n const [preferences, setPreferences] =\n useSyncableLocalStorage<GasTokenPreferences>(\n LocalStorageKey.GAS_TOKEN_PREFERENCES,\n DEFAULT_GAS_TOKEN_PREFERENCES,\n );\n\n const updatePreferences = useCallback(\n (updates: Partial<GasTokenPreferences>) => {\n setPreferences((prev) => ({ ...prev, ...updates }));\n },\n [setPreferences],\n );\n\n // updates the token priority and the available tokens in the order of the token priority but can only order the token that are in the available tokens\n const reorderTokenPriority = useCallback(\n (newOrder: GasTokenType[]) => {\n setPreferences((prev) => {\n const newAvailableGasTokens = newOrder.filter(\n (t) =>\n prev.availableGasTokens.includes(t) &&\n !prev.excludedTokens.includes(t),\n );\n return {\n ...prev,\n tokenPriority: newOrder,\n availableGasTokens: newAvailableGasTokens,\n gasTokenToUse:\n newAvailableGasTokens[0] ?? prev.gasTokenToUse,\n };\n });\n },\n [setPreferences],\n );\n\n const toggleTokenExclusion = useCallback(\n (token: GasTokenType) => {\n setPreferences((prev) => {\n const isExcluded = prev.excludedTokens.includes(token);\n const newExcluded = isExcluded\n ? prev.excludedTokens.filter((t) => t !== token)\n : [...prev.excludedTokens, token];\n // pop the token from the available tokens if it is in excluded tokens, else add the token back to available tokens in the order of the token priority\n const tokenPriorityPosition = prev.tokenPriority.indexOf(token);\n const newAvailableTokens = isExcluded\n ? [\n ...prev.availableGasTokens.slice(\n 0,\n tokenPriorityPosition,\n ),\n token,\n ...prev.availableGasTokens.slice(\n tokenPriorityPosition,\n ),\n ]\n : prev.availableGasTokens.filter((t) => t !== token);\n\n return {\n ...prev,\n excludedTokens: newExcluded,\n availableGasTokens: newAvailableTokens,\n gasTokenToUse: newAvailableTokens[0] ?? prev.gasTokenToUse,\n };\n });\n },\n [setPreferences],\n );\n\n return {\n preferences,\n supportedTokens: SUPPORTED_GAS_TOKENS,\n updatePreferences,\n reorderTokenPriority,\n toggleTokenExclusion,\n };\n};\n","import { useQuery } from '@tanstack/react-query';\nimport { EstimationResponse } from '@/types/gasEstimation';\nimport { EnhancedClause, GasTokenType } from '@/types';\nimport { useSmartAccount, useWallet, estimateGas, useTokenBalances, useGasTokenSelection } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\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 { GasTokenType } from '@/types';\nimport { useSmartAccount, useWallet, estimateGas } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers';\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","import {\n Button,\n HStack,\n Image,\n Text,\n Box,\n VStack,\n ButtonProps,\n useToken,\n} from '@chakra-ui/react';\nimport { TOKEN_LOGOS, TOKEN_LOGO_COMPONENTS } from '@/utils/constants';\nimport React from 'react';\nimport { CURRENCY } from '@/types';\nimport { LocalStorageKey, useLocalStorage } from '@/hooks';\nimport {\n formatCompactCurrency,\n SupportedCurrency,\n} from '@/utils/currencyUtils';\n\ntype AssetButtonProps = ButtonProps & {\n symbol: string;\n amount: number;\n currencyValue: number;\n currentCurrency: CURRENCY;\n isDisabled?: boolean;\n onClick?: () => void;\n};\n\nexport const AssetButton = ({\n symbol,\n amount,\n currencyValue,\n currentCurrency,\n isDisabled,\n onClick,\n ...buttonProps\n}: AssetButtonProps) => {\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const [showAssets] = useLocalStorage(LocalStorageKey.SHOW_ASSETS, true);\n\n return (\n <Button\n height=\"72px\"\n variant=\"ghost\"\n justifyContent=\"space-between\"\n isDisabled={isDisabled}\n p={4}\n w=\"100%\"\n _disabled={{\n cursor: 'not-allowed',\n opacity: 0.5,\n }}\n onClick={onClick}\n data-testid={`asset-${symbol}`}\n {...buttonProps}\n >\n <HStack>\n {TOKEN_LOGO_COMPONENTS[symbol] ? (\n React.cloneElement(TOKEN_LOGO_COMPONENTS[symbol], {\n boxSize: '24px',\n borderRadius: 'full',\n })\n ) : (\n <Image\n src={TOKEN_LOGOS[symbol]}\n alt={`${symbol} logo`}\n boxSize=\"24px\"\n borderRadius=\"full\"\n fallback={\n <Box\n boxSize=\"24px\"\n borderRadius=\"full\"\n bg=\"whiteAlpha.200\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Text\n fontSize=\"10px\"\n fontWeight=\"bold\"\n color={textPrimary}\n >\n {symbol.slice(0, 3)}\n </Text>\n </Box>\n }\n />\n )}\n <Text color={textPrimary}>{symbol}</Text>\n </HStack>\n <VStack align=\"flex-end\" spacing={0}>\n <Text color={textPrimary}>\n {showAssets ? amount.toLocaleString(undefined, {\n maximumFractionDigits: 2,\n }) : '*'.repeat(4)}{' '}\n </Text>\n <Text\n fontSize=\"sm\"\n color={textSecondary}\n data-testid={`${symbol}-balance`}\n >\n {showAssets ? formatCompactCurrency(currencyValue, {\n currency: currentCurrency as SupportedCurrency,\n }) : '*'.repeat(4)}\n </Text>\n </VStack>\n </Button>\n );\n};\n","import {\n Text,\n HStack,\n VStack,\n Image,\n Skeleton,\n useToken,\n} from '@chakra-ui/react';\nimport { humanAddress } from '@/utils';\nimport { useTotalBalance, useTokensWithValues } from '@/hooks';\nimport { useTranslation } from 'react-i18next';\nimport { useMemo } from 'react';\n\ntype AddressDisplayCardProps = {\n address: string;\n domain?: string;\n imageSrc: string;\n imageAlt?: string;\n hideAddress?: boolean;\n balance?: number;\n tokenAddress?: string;\n};\n\nexport const AddressDisplayCard = ({\n address,\n domain,\n imageSrc,\n imageAlt = 'Account',\n hideAddress = false,\n balance,\n tokenAddress,\n}: AddressDisplayCardProps) => {\n const { t } = useTranslation();\n\n const textColor = useToken('colors', 'vechain-kit-text-primary');\n const secondaryTextColor = useToken('colors', 'vechain-kit-text-secondary');\n const cardBg = useToken('colors', 'vechain-kit-card');\n\n const { isLoading: totalBalanceLoading } = useTotalBalance({ address });\n const { tokens, isLoading: tokensLoading } = useTokensWithValues({\n address,\n });\n\n // Find token by address if specified\n const tokenData = useMemo(() => {\n if (!tokenAddress) return null;\n return tokens.find((token) => token.address === tokenAddress);\n }, [tokens, tokenAddress]);\n\n // Determine what balance to display\n const displayBalance = useMemo(() => {\n // If balance is explicitly provided, always use that\n if (balance !== undefined) return balance;\n\n // Otherwise, find the actual token balance, not its currency value\n if (tokenData) {\n return Number(tokenData.balance);\n }\n return 0;\n }, [balance, tokenData]);\n\n const displaySymbol = tokenData?.symbol || '';\n const isLoading = totalBalanceLoading || tokensLoading;\n\n if (isLoading) {\n return (\n <HStack\n minH={'50px'}\n justify=\"space-between\"\n p={4}\n borderRadius=\"2xl\"\n bg={cardBg}\n >\n <HStack>\n <Skeleton boxSize=\"40px\" borderRadius=\"full\" />\n <VStack align=\"start\" spacing={0}>\n <Skeleton\n height=\"16px\"\n width=\"120px\"\n borderRadius=\"md\"\n />\n {!hideAddress && (\n <Skeleton\n mt={2}\n height=\"12px\"\n width=\"100px\"\n borderRadius=\"md\"\n />\n )}\n </VStack>\n </HStack>\n\n <VStack\n justify=\"flex-start\"\n align=\"flex-end\"\n spacing={0}\n mr={2}\n >\n <Text fontSize=\"sm\" fontWeight=\"medium\" color={textColor}>\n {t('Balance')}\n </Text>\n <Skeleton height=\"12px\" width=\"80px\" borderRadius=\"md\" />\n </VStack>\n </HStack>\n );\n }\n\n return (\n <HStack\n minH={'50px'}\n justify=\"space-between\"\n p={4}\n borderRadius=\"2xl\"\n bg={cardBg}\n >\n <HStack>\n <Image\n src={imageSrc}\n alt={imageAlt}\n boxSize=\"40px\"\n borderRadius=\"full\"\n objectFit=\"cover\"\n />\n <VStack align=\"start\" spacing={0}>\n {domain ? (\n <>\n <Text\n fontWeight=\"medium\"\n fontSize=\"sm\"\n color={textColor}\n >\n {domain}\n </Text>\n {!hideAddress && (\n <Text fontSize=\"xs\" color={secondaryTextColor}>\n {humanAddress(address, 6, 4)}\n </Text>\n )}\n </>\n ) : (\n <Text\n fontWeight=\"medium\"\n fontSize=\"sm\"\n color={textColor}\n >\n {humanAddress(address, 6, 4)}\n </Text>\n )}\n </VStack>\n </HStack>\n\n <VStack justify=\"flex-start\" align=\"flex-end\" spacing={0} mr={2}>\n <Text fontSize=\"sm\" fontWeight=\"medium\" color={textColor}>\n {t('Balance')}\n </Text>\n <Text fontSize=\"xs\" color={secondaryTextColor}>\n {displayBalance.toLocaleString(undefined, {\n maximumFractionDigits: 2,\n })}\n {displaySymbol && ` ${displaySymbol}`}\n </Text>\n </VStack>\n </HStack>\n );\n};\n","import { IconButton, IconButtonProps, Icon } from '@chakra-ui/react';\nimport { LuCircleHelp } from 'react-icons/lu';\n\ntype FAQButtonProps = {\n onClick: () => void;\n} & Partial<IconButtonProps>;\n\nexport const ModalFAQButton = ({ onClick, ...props }: FAQButtonProps) => {\n return (\n <IconButton\n aria-label=\"FAQ\"\n icon={<Icon as={LuCircleHelp} fontSize={'17px'} />}\n size=\"sm\"\n variant=\"vechainKitHeaderIconButtons\"\n position=\"absolute\"\n lineHeight={'normal'}\n left=\"10px\"\n top=\"8px\"\n onClick={onClick}\n {...props}\n />\n );\n};\n","import { VStack, StackProps } from '@chakra-ui/react';\nimport { useScrollToTop } from '@/hooks/utils/useScrollToTop';\n\nexport const ScrollToTopWrapper = ({ children, ...props }: StackProps) => {\n useScrollToTop();\n\n return <VStack {...props}>{children}</VStack>;\n};\n","import { Wallet } from '@/types';\nimport { Image, ImageProps, Skeleton } from '@chakra-ui/react';\nimport { useRef, useEffect } from 'react';\n\ntype AccountAvatarProps = {\n wallet?: Wallet;\n props?: ImageProps;\n};\n\nexport const AccountAvatar = ({ wallet, props }: AccountAvatarProps) => {\n // Store the previous image URL to maintain during loading\n // Use wallet address as key to ensure ref is reset when wallet changes\n const previousImageRef = useRef<string | undefined>(wallet?.image);\n const walletAddressRef = useRef<string | undefined>(wallet?.address);\n\n // Reset ref when wallet address changes\n useEffect(() => {\n if (walletAddressRef.current !== wallet?.address) {\n previousImageRef.current = wallet?.image;\n walletAddressRef.current = wallet?.address;\n }\n }, [wallet?.address]);\n\n // Update the ref when we have a valid image and it's not loading\n useEffect(() => {\n if (wallet?.image && !wallet.isLoadingMetadata) {\n previousImageRef.current = wallet.image;\n }\n }, [wallet?.image, wallet?.isLoadingMetadata]);\n\n if (\n (!props?.src && !wallet?.image && !previousImageRef.current) ||\n wallet?.isLoadingMetadata\n ) {\n return (\n <Skeleton\n rounded=\"full\"\n width={props?.width}\n height={props?.height}\n />\n );\n }\n return (\n <Image\n src={props?.src || wallet?.image || previousImageRef.current}\n alt={props?.alt || wallet?.domain}\n objectFit=\"cover\"\n rounded=\"full\"\n // fallbackSrc={getPicassoImage(wallet?.address ?? '')}\n {...props}\n />\n );\n};\n","import { useVeChainKitConfig } from '@/providers';\nimport { Button, Link, Text, VStack, Box } from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { useEffect, useMemo } from 'react';\nimport { TransactionStatusErrorType } from '@/types';\nimport { getConfig } from '@/config';\nimport { TransactionReceipt } from '@vechain/sdk-network';\n\nexport type TransactionButtonAndStatusProps = {\n isSubmitting: boolean;\n isTxWaitingConfirmation: boolean;\n onConfirm: () => void;\n onRetry?: () => void;\n transactionPendingText: string;\n txReceipt: TransactionReceipt | null;\n transactionError?: Error | TransactionStatusErrorType | null;\n isSubmitForm?: boolean;\n buttonText: string;\n isDisabled?: boolean;\n style?: {\n accentColor?: string;\n };\n onError?: (error: string) => void;\n // Gas estimation error props\n gasEstimationError?: Error | null;\n hasEnoughGasBalance?: boolean;\n isLoadingGasEstimation?: boolean;\n showGasEstimationError?: boolean;\n context?: 'send' | 'customization' | 'domain' | 'transaction';\n};\n\nexport const TransactionButtonAndStatus = ({\n transactionError,\n isSubmitting,\n isTxWaitingConfirmation,\n onConfirm,\n onRetry,\n transactionPendingText,\n txReceipt,\n isSubmitForm = false,\n buttonText,\n isDisabled = false,\n style,\n onError,\n gasEstimationError,\n hasEnoughGasBalance = true,\n isLoadingGasEstimation = false,\n showGasEstimationError = false,\n context = 'transaction',\n}: TransactionButtonAndStatusProps) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { network } = useVeChainKitConfig();\n\n const errorMessage = useMemo(() => {\n if (!transactionError) return null;\n return (\n (transactionError as any).reason ||\n t('Something went wrong. Please try again.')\n );\n }, [transactionError, t]);\n\n useEffect(() => {\n if (errorMessage) {\n onError?.(errorMessage);\n }\n }, [errorMessage, onError]);\n\n const buttonBg = useMemo(() => {\n if (style?.accentColor) return `${style.accentColor} !important`;\n return undefined;\n }, [style?.accentColor]);\n\n // Gas estimation error details - simplified\n const gasEstimationErrorDetails = useMemo(() => {\n // Don't show errors while loading or if we shouldn't show them\n if (!showGasEstimationError || isLoadingGasEstimation) {\n return null;\n }\n\n // Only show errors if we have an actual error OR if we've completed estimation\n // This prevents showing errors on initial render before estimation starts\n const hasAttemptedEstimation =\n gasEstimationError || hasEnoughGasBalance;\n if (!hasAttemptedEstimation) {\n return null;\n }\n\n // No gas tokens enabled (only if we have an error but no specific balance issue)\n if (!hasEnoughGasBalance && !gasEstimationError) {\n return {\n message: t(\n \"You don't have any gas tokens enabled. Please enable at least one gas token in Gas Token Preferences.\",\n ),\n };\n }\n\n // Has estimation error - show simple contextual message\n if (gasEstimationError) {\n let message = '';\n switch (context) {\n case 'send':\n message = t(\n 'Insufficient balance to complete this transfer and cover gas fees.' as any,\n );\n break;\n case 'customization':\n message = t(\n 'Insufficient balance to update your profile and cover gas fees.' as any,\n );\n break;\n case 'domain':\n message = t(\n 'Insufficient balance to claim this domain and cover gas fees.' as any,\n );\n break;\n default:\n message = t(\n 'Insufficient balance to complete this transaction and cover gas fees.' as any,\n );\n }\n\n return { message };\n }\n\n return null;\n }, [\n gasEstimationError,\n hasEnoughGasBalance,\n isLoadingGasEstimation,\n showGasEstimationError,\n context,\n t,\n ]);\n\n return (\n <VStack width=\"full\" spacing={4}>\n {errorMessage && (\n <Box\n p={3}\n borderRadius=\"md\"\n bg={\n isDark\n ? 'rgba(218, 90, 90, 0.1)'\n : 'rgba(218, 90, 90, 0.05)'\n }\n borderWidth=\"1px\"\n borderColor={\n isDark\n ? 'rgba(218, 90, 90, 0.3)'\n : 'rgba(218, 90, 90, 0.2)'\n }\n w=\"full\"\n >\n <Text\n color=\"#da5a5a\"\n fontSize=\"sm\"\n fontWeight=\"medium\"\n data-testid=\"tx-send-error-msg\"\n >\n {errorMessage}\n </Text>\n </Box>\n )}\n\n {gasEstimationErrorDetails && !errorMessage && (\n <Box\n p={3}\n borderRadius=\"md\"\n bg={\n isDark\n ? 'rgba(218, 90, 90, 0.1)'\n : 'rgba(218, 90, 90, 0.05)'\n }\n borderWidth=\"1px\"\n borderColor={\n isDark\n ? 'rgba(218, 90, 90, 0.3)'\n : 'rgba(218, 90, 90, 0.2)'\n }\n w=\"full\"\n >\n <Text\n color=\"#da5a5a\"\n fontSize=\"sm\"\n fontWeight=\"medium\"\n data-testid=\"gas-estimation-error\"\n >\n {gasEstimationErrorDetails.message}\n </Text>\n </Box>\n )}\n\n <Button\n px={4}\n variant={\n errorMessage ? 'vechainKitSecondary' : 'vechainKitPrimary'\n }\n bg={buttonBg}\n onClick={() =>\n errorMessage && onRetry ? onRetry() : onConfirm()\n }\n type={isSubmitForm ? 'submit' : 'button'}\n isLoading={isSubmitting}\n isDisabled={isDisabled}\n loadingText={\n isTxWaitingConfirmation\n ? t('Waiting wallet confirmation...')\n : transactionPendingText\n }\n data-testid=\"confirm-button\"\n >\n {errorMessage\n ? t('Retry')\n : buttonText\n ? buttonText\n : t('Confirm')}\n </Button>\n {errorMessage && txReceipt?.meta.txID && (\n <Link\n isExternal\n fontSize=\"sm\"\n color={isDark ? 'whiteAlpha.600' : 'blackAlpha.600'}\n textAlign=\"center\"\n width=\"full\"\n href={`${getConfig(network.type).explorerUrl}/${\n txReceipt?.meta.txID\n }`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {t('View transaction on the explorer')}\n </Link>\n )}\n </VStack>\n );\n};\n","import { IconButton, IconButtonProps, Box } from '@chakra-ui/react';\nimport { LuBell } from 'react-icons/lu';\n\ntype NotificationButtonProps = {\n onClick: () => void;\n hasUnreadNotifications?: boolean;\n} & Partial<IconButtonProps>;\n\nexport const ModalNotificationButton = ({\n onClick,\n hasUnreadNotifications,\n ...props\n}: NotificationButtonProps) => {\n return (\n <IconButton\n aria-label=\"Notifications\"\n size=\"sm\"\n variant=\"ghost\"\n position=\"absolute\"\n borderRadius={'50%'}\n left=\"10px\"\n top=\"10px\"\n onClick={onClick}\n icon={\n <Box position=\"relative\">\n <LuBell fontSize={'20px'} />\n {hasUnreadNotifications && (\n <Box\n position=\"absolute\"\n top=\"-1px\"\n right=\"-1px\"\n minWidth=\"8px\"\n height=\"8px\"\n bg=\"red.500\"\n borderRadius=\"full\"\n />\n )}\n </Box>\n }\n {...props}\n />\n );\n};\n","import React from 'react';\nimport {\n ModalHeader,\n ModalBody,\n ModalFooter,\n Button,\n VStack,\n HStack,\n Text,\n Box,\n Skeleton,\n Switch,\n FormControl,\n FormLabel,\n useToken,\n} from '@chakra-ui/react';\nimport { useTranslation } from 'react-i18next';\nimport { GasTokenType } from '@/types/gasToken';\nimport { SUPPORTED_GAS_TOKENS, TOKEN_LOGO_COMPONENTS } from '@/utils/constants';\nimport { formatGasCost } from '@/types/gasEstimation';\nimport { useTokenBalances } from '@/hooks';\nimport { BaseModal } from './BaseModal';\n\ninterface GasFeeTokenSelectorProps {\n isOpen: boolean;\n onClose: () => void;\n selectedToken: GasTokenType;\n onTokenSelect: (token: GasTokenType, rememberChoice: boolean) => void;\n availableTokens: GasTokenType[];\n tokenEstimations: Record<GasTokenType, { cost: number; loading: boolean }>;\n walletAddress: string;\n}\n\nexport const GasFeeTokenSelector = ({\n isOpen,\n onClose,\n selectedToken,\n onTokenSelect,\n availableTokens,\n tokenEstimations,\n walletAddress,\n}: GasFeeTokenSelectorProps) => {\n const { t } = useTranslation();\n const { balances } = useTokenBalances(walletAddress);\n const [tempSelectedToken, setTempSelectedToken] =\n React.useState(selectedToken);\n const [rememberChoice, setRememberChoice] = React.useState(false);\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n const textTertiary = useToken('colors', 'vechain-kit-text-tertiary');\n const errorColor = useToken('colors', 'vechain-kit-error');\n\n const itemBg = (selected: boolean) =>\n selected ? textTertiary : 'transparent';\n const itemBorderColor = (selected: boolean) =>\n selected ? textPrimary : 'transparent';\n\n React.useEffect(() => {\n if (isOpen) {\n setTempSelectedToken(selectedToken);\n setRememberChoice(false);\n }\n }, [isOpen, selectedToken]);\n\n const handleApply = () => {\n onTokenSelect(tempSelectedToken, rememberChoice);\n onClose();\n };\n\n const getTokenBalance = (tokenSymbol: string) => {\n const balance = balances.find((b) => b.symbol === tokenSymbol);\n return balance\n ? Number(balance.balance).toLocaleString(undefined, {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n : '0.00';\n };\n\n const hasInsufficientBalance = (tokenSymbol: GasTokenType) => {\n const balance = balances.find((b) => b.symbol === tokenSymbol);\n const estimation = tokenEstimations[tokenSymbol];\n if (!balance || !estimation) return false;\n return Number(balance.balance) < estimation.cost;\n };\n\n return (\n <BaseModal isOpen={isOpen} onClose={onClose} size=\"sm\">\n <ModalHeader>\n <Text fontSize=\"lg\" fontWeight=\"semibold\" color={textPrimary}>\n {t('Fee token')}\n </Text>\n <Text\n fontSize=\"sm\"\n fontWeight=\"normal\"\n color={textSecondary}\n mt={1}\n >\n {t('Select the token to pay the fee with')}\n </Text>\n </ModalHeader>\n\n <ModalBody>\n <VStack spacing={2} align=\"stretch\">\n {availableTokens.map((token) => {\n const tokenInfo = SUPPORTED_GAS_TOKENS[token];\n const isSelected = tempSelectedToken === token;\n const estimation = tokenEstimations[token] || {\n cost: 0,\n loading: true,\n };\n const insufficient = hasInsufficientBalance(token);\n\n return (\n <Box\n key={token}\n cursor={\n insufficient ? 'not-allowed' : 'pointer'\n }\n bg={itemBg(isSelected)}\n border=\"1px\"\n borderColor={itemBorderColor(isSelected)}\n borderRadius=\"md\"\n p={3}\n transition=\"all 0.2s ease\"\n _hover={{\n backgroundColor: insufficient\n ? itemBg(isSelected)\n : textSecondary\n ? '#ffffff12'\n : textSecondary,\n borderColor: insufficient\n ? itemBorderColor(isSelected)\n : textSecondary,\n }}\n opacity={insufficient ? 0.5 : 1}\n onClick={() =>\n !insufficient && setTempSelectedToken(token)\n }\n >\n <HStack spacing={3} justify=\"space-between\">\n <HStack spacing={3} flex={1}>\n {React.cloneElement(\n TOKEN_LOGO_COMPONENTS[token],\n {\n boxSize: '36px',\n borderRadius: 'full',\n },\n )}\n <VStack align=\"start\" spacing={0}>\n <Text\n fontWeight=\"medium\"\n color={textPrimary}\n >\n {tokenInfo.symbol}\n </Text>\n <Text\n fontSize=\"xs\"\n color={textSecondary}\n >\n {t('Balance')}:{' '}\n {getTokenBalance(token)}\n </Text>\n {insufficient && (\n <Text\n fontSize=\"xs\"\n color={errorColor}\n >\n {t('Insufficient balance')}\n </Text>\n )}\n </VStack>\n </HStack>\n <VStack align=\"end\" spacing={0}>\n {estimation.loading ? (\n <Skeleton\n height=\"16px\"\n width=\"60px\"\n />\n ) : (\n <>\n <Text\n fontSize=\"sm\"\n fontWeight=\"semibold\"\n color={textPrimary}\n >\n {formatGasCost(\n estimation.cost,\n 2,\n )}\n </Text>\n <Text\n fontSize=\"xs\"\n color={textSecondary}\n >\n {tokenInfo.symbol}\n </Text>\n </>\n )}\n </VStack>\n </HStack>\n </Box>\n );\n })}\n\n {tempSelectedToken !== selectedToken && (\n <FormControl\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"space-between\"\n >\n <FormLabel\n htmlFor=\"remember-choice\"\n mb=\"0\"\n fontSize=\"sm\"\n color={textPrimary}\n >\n {t('Use this token for future transactions')}\n </FormLabel>\n <Switch\n id=\"remember-choice\"\n isChecked={rememberChoice}\n onChange={(e) =>\n setRememberChoice(e.target.checked)\n }\n color={textPrimary}\n />\n </FormControl>\n )}\n </VStack>\n </ModalBody>\n\n <ModalFooter>\n <VStack spacing={3} w=\"full\">\n <Button\n variant=\"vechainKitPrimary\"\n onClick={handleApply}\n isDisabled={hasInsufficientBalance(tempSelectedToken)}\n >\n {t('Apply')}\n </Button>\n <Button variant=\"ghost\" width=\"full\" onClick={onClose}>\n {t('Cancel')}\n </Button>\n </VStack>\n </ModalFooter>\n </BaseModal>\n );\n};\n","import React, { useState, useCallback, useEffect } from 'react';\nimport {\n HStack,\n Text,\n Skeleton,\n Icon,\n useDisclosure,\n VStack,\n Button,\n Divider,\n useToken,\n} from '@chakra-ui/react';\nimport { LuChevronDown } from 'react-icons/lu';\nimport { useTranslation } from 'react-i18next';\nimport { useVeChainKitConfig } from '@/providers';\nimport { GasTokenType } from '@/types/gasToken';\nimport { SUPPORTED_GAS_TOKENS, TOKEN_LOGO_COMPONENTS } from '@/utils/constants';\nimport { formatGasCost } from '@/types/gasEstimation';\nimport {\n useWallet,\n useGasTokenSelection,\n useEstimateAllTokens,\n useTokenBalances,\n} from '@/hooks';\nimport { EstimationResponse } from '@/types/gasEstimation';\nimport { GasFeeTokenSelector } from './GasFeeTokenSelector';\nimport { TransactionClause } from '@vechain/sdk-core';\n\ninterface GasFeeSummaryProps {\n estimation: (EstimationResponse & { usedToken: string }) | undefined;\n isLoading: boolean | undefined;\n isLoadingTransaction?: boolean;\n onTokenChange?: (token: GasTokenType) => void;\n clauses?: TransactionClause[];\n userSelectedToken?: GasTokenType | null; // Track user's manual selection\n}\n\nexport const GasFeeSummary: React.FC<GasFeeSummaryProps> = ({\n estimation,\n isLoading,\n isLoadingTransaction,\n onTokenChange,\n clauses = [],\n userSelectedToken,\n}: GasFeeSummaryProps) => {\n const { t } = useTranslation();\n const { feeDelegation } = useVeChainKitConfig();\n const { connection, account } = useWallet();\n const { preferences, reorderTokenPriority } = useGasTokenSelection();\n const { isOpen, onOpen, onClose } = useDisclosure();\n\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const textSecondary = useToken('colors', 'vechain-kit-text-secondary');\n\n const [tokenEstimations, setTokenEstimations] = useState<\n Record<GasTokenType, { cost: number; loading: boolean }>\n >(() => {\n // Initialize with loading states for all available tokens\n const initialStates: Record<\n string,\n { cost: number; loading: boolean }\n > = {};\n preferences.availableGasTokens.forEach((token) => {\n initialStates[token] = { cost: 0, loading: true };\n });\n return initialStates as Record<\n GasTokenType,\n { cost: number; loading: boolean }\n >;\n });\n\n // Fetch estimates for all available tokens when modal opens\n const { data: allTokenEstimates, isLoading: isLoadingAllEstimates } =\n useEstimateAllTokens({\n clauses: clauses,\n tokens: preferences.availableGasTokens,\n enabled: clauses.length > 0,\n });\n // Preload all token estimates to avoid re-fetching per token switch and to enable\n // fallback display when single-token estimation is undefined.\n // Initialize token estimations from prefetch results as soon as they are ready\n useEffect(() => {\n if (!isLoadingAllEstimates && allTokenEstimates) {\n setTokenEstimations(allTokenEstimates);\n }\n }, [allTokenEstimates, isLoadingAllEstimates]);\n\n // Update current token estimation\n useEffect(() => {\n if (estimation) {\n setTokenEstimations((prev) => ({\n ...prev,\n [estimation.usedToken as GasTokenType]: {\n cost: estimation.transactionCost || 0,\n loading: false,\n },\n }));\n }\n }, [estimation]);\n\n // Initialize loading states while prefetch is loading\n useEffect(() => {\n if (isLoadingAllEstimates) {\n const loadingStates = preferences.availableGasTokens.reduce(\n (acc, token) => {\n acc[token] = { cost: 0, loading: true };\n return acc;\n },\n {} as Record<GasTokenType, { cost: number; loading: boolean }>,\n );\n setTokenEstimations(loadingStates);\n }\n }, [isLoadingAllEstimates, preferences.availableGasTokens]);\n\n const handleTokenSelect = useCallback(\n (token: GasTokenType, rememberChoice: boolean) => {\n if (rememberChoice) {\n // Move selected token to the top of priority order\n // This has the same effect as dragging it to the top in settings\n const newTokenPriority = [\n token,\n ...preferences.tokenPriority.filter((t) => t !== token),\n ];\n reorderTokenPriority(newTokenPriority);\n }\n\n // Trigger re-estimation\n if (onTokenChange && token !== estimation?.usedToken) {\n onTokenChange(token);\n }\n },\n [\n estimation,\n onTokenChange,\n reorderTokenPriority,\n preferences.tokenPriority,\n ],\n );\n\n if (feeDelegation?.delegatorUrl) {\n return null;\n }\n\n if (connection.isConnectedWithDappKit) {\n return null;\n }\n\n // If no tokens are available, don't render anything\n if (preferences.availableGasTokens.length === 0) {\n return null;\n }\n\n const { balances } = useTokenBalances(account?.address ?? '');\n\n const hasInsufficientBalanceForToken = (token: GasTokenType) => {\n const balance = balances.find((b) => b.symbol === token);\n const est = tokenEstimations[token];\n if (!balance || !est || est.loading) return true;\n return Number(balance.balance) < est.cost;\n };\n\n // Determine display token and cost:\n // Priority order:\n // 1. Successfully used token from estimation (shows what will actually be used)\n // 2. User's manual selection while loading (shows what they picked during estimation)\n // 3. First available token with sufficient balance\n // 4. First available token with loaded estimate\n // 5. First available token\n const preferredToken = estimation?.usedToken as GasTokenType | undefined;\n const availableTokens = preferences.availableGasTokens as GasTokenType[];\n\n let displayToken: GasTokenType | undefined;\n\n // Priority 1: Successfully used token from estimation (always show what will actually be used)\n if (preferredToken) {\n displayToken = preferredToken;\n }\n // Priority 2: User's manual selection while loading (keeps UI stable during estimation)\n else if (userSelectedToken && availableTokens.includes(userSelectedToken)) {\n displayToken = userSelectedToken;\n }\n // Priority 3 & 4: Auto-select based on availability\n else {\n displayToken = availableTokens.find(\n (t) =>\n tokenEstimations[t] &&\n !tokenEstimations[t].loading &&\n !hasInsufficientBalanceForToken(t),\n );\n if (!displayToken) {\n displayToken = availableTokens.find(\n (t) => tokenEstimations[t] && !tokenEstimations[t].loading,\n );\n }\n if (!displayToken) {\n displayToken = availableTokens[0];\n }\n }\n\n const displayEstimation = displayToken\n ? tokenEstimations[displayToken]\n : undefined;\n\n // Show cost for the displayed token\n // If we have a successful estimation, use its cost; otherwise use the display token's estimation\n const totalCost =\n preferredToken && estimation?.transactionCost\n ? estimation.transactionCost\n : displayEstimation?.cost || 0;\n\n const tokenInfo = displayToken\n ? SUPPORTED_GAS_TOKENS[displayToken]\n : undefined;\n\n return (\n <>\n <Divider mt={3} />\n\n <HStack mt={3} w=\"full\" justifyContent=\"start\" alignItems=\"center\">\n <VStack align=\"start\" spacing={0} w=\"full\">\n <Text\n fontSize=\"sm\"\n fontWeight=\"light\"\n textAlign=\"left\"\n w=\"full\"\n color={textSecondary}\n >\n {t('Fee')}\n </Text>\n\n <HStack\n align=\"start\"\n justifyContent=\"space-between\"\n spacing={0}\n w=\"full\"\n >\n <HStack justifyContent=\"flex-start\" w=\"full\">\n {isLoading ||\n (!preferredToken &&\n (!displayEstimation ||\n displayEstimation.loading)) ||\n !tokenInfo ? (\n <>\n <Skeleton\n height=\"16px\"\n width=\"120px\"\n borderRadius=\"md\"\n />\n <Skeleton\n height=\"16px\"\n width=\"60px\"\n borderRadius=\"md\"\n />\n </>\n ) : (\n <>\n <Text\n color={textPrimary}\n fontSize=\"sm\"\n fontWeight=\"semibold\"\n >\n {formatGasCost(totalCost, 2)}{' '}\n {tokenInfo.symbol}\n </Text>\n <Text color={textSecondary} fontSize=\"xs\">\n {'≈'} ${(totalCost * 0.01).toFixed(2)}\n </Text>\n </>\n )}\n </HStack>\n </HStack>\n </VStack>\n\n <Button\n onClick={onOpen}\n variant=\"outline\"\n size=\"sm\"\n borderRadius=\"full\"\n px={6}\n disabled={isLoadingTransaction}\n color={textSecondary}\n borderColor={textSecondary}\n _hover={{\n bg: textSecondary,\n }}\n leftIcon={React.cloneElement(\n TOKEN_LOGO_COMPONENTS[\n (displayToken as GasTokenType) ||\n preferences.availableGasTokens[0]\n ],\n {\n boxSize: '20px',\n borderRadius: 'full',\n },\n )}\n >\n <Text fontSize=\"sm\" fontWeight=\"semibold\">\n {displayToken || preferences.availableGasTokens[0]}\n </Text>\n <Icon\n as={LuChevronDown}\n boxSize={5}\n color={textSecondary}\n />\n </Button>\n </HStack>\n\n <GasFeeTokenSelector\n isOpen={isOpen}\n onClose={onClose}\n selectedToken={\n (displayToken as GasTokenType) ||\n preferences.availableGasTokens[0]\n }\n onTokenSelect={handleTokenSelect}\n availableTokens={preferences.availableGasTokens}\n tokenEstimations={tokenEstimations}\n walletAddress={account?.address ?? ''}\n />\n </>\n );\n};\n","import {\n Box,\n HStack,\n Icon,\n Text,\n useToken,\n useColorModeValue,\n} from '@chakra-ui/react';\nimport { keyframes } from '@emotion/react';\nimport { LuCheck } from 'react-icons/lu';\nimport { useEffect, useState } from 'react';\n\ntype Props = {\n message: string;\n duration?: number;\n onClose?: () => void;\n};\n\nconst slideIn = keyframes`\n from {\n transform: translateY(-100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n`;\n\nconst slideOut = keyframes`\n from {\n transform: translateY(0);\n opacity: 1;\n }\n to {\n transform: translateY(-100%);\n opacity: 0;\n }\n`;\n\nexport const InlineFeedback = ({\n message,\n duration = 2000,\n onClose,\n}: Props) => {\n const [isVisible, setIsVisible] = useState(true);\n const textPrimary = useToken('colors', 'vechain-kit-text-primary');\n const bgColor = useColorModeValue('#f0f9ff', '#0000009e');\n const borderColor = useColorModeValue('#bfdbfe', '#3b3b3b');\n const iconColor = useToken('colors', 'vechain-kit-primary');\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setIsVisible(false);\n setTimeout(() => {\n onClose?.();\n }, 300); // Wait for animation to complete\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, onClose]);\n\n return (\n <Box\n position=\"absolute\"\n w=\"fit-content\"\n margin=\"auto\"\n animation={`${isVisible ? slideIn : slideOut} 0.3s ease-in-out`}\n zIndex={10}\n >\n <Box\n bg={bgColor}\n borderWidth={1}\n borderColor={borderColor}\n borderRadius=\"md\"\n px={4}\n py={3}\n mx={4}\n mt={2}\n >\n <HStack spacing={3} align=\"center\">\n <Icon\n as={LuCheck}\n boxSize={5}\n color={iconColor}\n flexShrink={0}\n />\n <Text\n fontSize=\"sm\"\n fontWeight=\"500\"\n color={textPrimary}\n flex={1}\n >\n {message}\n </Text>\n </HStack>\n </Box>\n </Box>\n );\n};\n","import { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { InlineFeedback } from './InlineFeedback';\n\ntype Props = {\n /**\n * Show feedback flag passed via content props (desktop)\n * If true, shows the feedback message\n */\n showFeedback?: boolean;\n};\n\n/**\n * Component that displays inline feedback when a wallet switch occurs.\n * Handles both desktop (via props) and VeWorld in-app browser (via address change detection).\n * Simply add this component where you want the feedback to appear.\n */\nexport const WalletSwitchFeedback = ({ showFeedback = false }: Props) => {\n const { t } = useTranslation();\n const [showSwitchFeedback, setShowSwitchFeedback] = useState(false);\n\n // Handle prop-based feedback (desktop)\n useEffect(() => {\n if (showFeedback) {\n setShowSwitchFeedback(true);\n } else {\n // Reset feedback when prop becomes false/undefined (e.g., modal closed and reopened)\n setShowSwitchFeedback(false);\n }\n }, [showFeedback]);\n\n if (!showSwitchFeedback) {\n return null;\n }\n\n return (\n <InlineFeedback\n message={t('Account Changed')}\n duration={2000}\n onClose={() => {\n setShowSwitchFeedback(false);\n }}\n />\n );\n};\n","import { motion } from 'framer-motion';\nimport { ReactNode } from 'react';\nimport {\n Card,\n CardBody,\n Text,\n useMediaQuery,\n ModalCloseButton,\n ModalHeader,\n} from '@chakra-ui/react';\nimport { BaseModal, StickyHeaderContainer, ModalBackButton } from '../common';\n\nexport type Step<T extends string> = {\n key: T;\n content: ReactNode;\n title?: string;\n description?: string;\n};\n\nexport type StepModalProps<T extends string> = {\n isOpen: boolean;\n onClose: () => void;\n steps: Step<T>[];\n goToPrevious: () => void;\n goToNext?: () => void;\n setActiveStep: (step: number) => void;\n activeStep: number;\n disableBackButton?: boolean;\n disableCloseButton?: boolean;\n closeOnOverlayClick?: boolean;\n isCloseable?: boolean;\n};\n\nexport const StepModal = <T extends string>({\n isOpen,\n onClose,\n steps,\n activeStep,\n goToPrevious,\n setActiveStep,\n disableBackButton,\n disableCloseButton,\n closeOnOverlayClick = true,\n isCloseable = true,\n}: StepModalProps<T>) => {\n const handleClose = () => {\n // reset the active step to 0\n setActiveStep(0);\n // close the modal\n onClose();\n };\n const [isDesktop] = useMediaQuery('(min-width: 1060px)');\n\n const currentStepContent = steps[activeStep];\n\n const isFirstStep = activeStep === 0;\n\n const showHeader =\n (!isFirstStep && !disableBackButton) ||\n currentStepContent?.title ||\n (isDesktop && !disableCloseButton);\n\n if (!currentStepContent) {\n return null;\n }\n\n return (\n <BaseModal\n closeOnOverlayClick={closeOnOverlayClick}\n isOpen={isOpen}\n onClose={handleClose}\n isCloseable={isCloseable}\n blockScrollOnMount={true}\n >\n <Card p={0} bg=\"none\">\n <CardBody p={0}>\n {showHeader ? (\n <StickyHeaderContainer>\n {currentStepContent?.title ? (\n <ModalHeader>\n {currentStepContent.title}\n </ModalHeader>\n ) : null}\n\n {!isFirstStep && !disableBackButton ? (\n <ModalBackButton onClick={goToPrevious} />\n ) : null}\n\n {isDesktop && !disableCloseButton ? (\n <ModalCloseButton onClick={onClose} />\n ) : null}\n </StickyHeaderContainer>\n ) : null}\n {currentStepContent?.description ? (\n <Text\n fontSize={{ base: 14, md: 16 }}\n fontWeight={400}\n px={4}\n >\n {currentStepContent?.description}\n </Text>\n ) : null}\n\n <motion.div\n initial=\"hidden\"\n animate=\"visible\"\n key={currentStepContent.key}\n style={{ width: '100%' }}\n >\n {currentStepContent.content}\n </motion.div>\n </CardBody>\n </Card>\n </BaseModal>\n );\n};\n","import { useVeChainKitConfig } from '@/providers';\nimport { EnrichedLegalDocument } from '@/types';\nimport { Checkbox, HStack, Icon, Input, Link, Text } from '@chakra-ui/react';\nimport { UseFormRegister } from 'react-hook-form';\nimport { useTranslation } from 'react-i18next';\nimport { LuExternalLink } from 'react-icons/lu';\n\ntype Props = {\n document: EnrichedLegalDocument;\n register: UseFormRegister<any>;\n isText?: boolean;\n};\n\nexport const LegalDocumentItem = ({\n document,\n register,\n isText = false,\n}: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const documentName = document.displayName ?? t('Policy');\n\n const borderColor = isDark ? 'whiteAlpha.400' : 'blackAlpha.400';\n\n const linkColor = isDark ? 'blue.300' : 'blue.500';\n const linkHoverColor = isDark ? 'blue.200' : 'blue.700';\n\n // Get document type display text\n const getDocumentTypeDisplay = (): string => {\n if (!document.documentType) return documentName;\n\n switch (document.documentType) {\n case 'terms':\n return document.displayName || 'Terms of Service';\n case 'privacy':\n return document.displayName || 'Privacy Policy';\n case 'cookies':\n return document.displayName || 'Cookie Policy';\n default:\n return document.displayName || 'Legal Document';\n }\n };\n\n const displayName = getDocumentTypeDisplay();\n\n if (isText) {\n return (\n <Link\n key={document.id}\n href={document.url}\n isExternal\n color={'blue.500'}\n textDecoration=\"underline\"\n _hover={{\n color: 'blue.300',\n textDecoration: 'underline',\n }}\n fontWeight=\"medium\"\n display=\"contents\"\n alignItems=\"center\"\n >\n <Input\n {...register(document.id, {\n required: document.required,\n })}\n type=\"checkbox\"\n hidden\n />\n {displayName}\n <Icon as={LuExternalLink} ml={1} boxSize={3} />\n </Link>\n );\n }\n\n return (\n <HStack\n width=\"full\"\n borderRadius=\"md\"\n transition=\"all 0.2s\"\n key={document.id}\n >\n <HStack align=\"flex-start\" spacing={3} width=\"full\">\n <Checkbox\n mt=\"2px\"\n size=\"md\"\n colorScheme=\"blue\"\n borderColor={borderColor}\n {...register(document.id, {\n required: document.required,\n })}\n data-testid=\"tnc-checkbox\"\n />\n\n <Text fontSize=\"xs\">\n {t('I have read and agree to ')}\n <Link\n href={document.url}\n isExternal\n color={linkColor}\n textDecoration=\"underline\"\n _hover={{\n color: linkHoverColor,\n textDecoration: 'underline',\n }}\n fontWeight=\"medium\"\n display=\"contents\"\n alignItems=\"center\"\n >\n {displayName}\n <Icon as={LuExternalLink} ml={1} />\n </Link>\n {document.required && (\n <Text as=\"span\" color=\"red.500\" fontWeight=\"bold\">\n *\n </Text>\n )}\n </Text>\n </HStack>\n </HStack>\n );\n};\n","import { StickyHeaderContainer } from '@/components/common';\nimport { useLegalDocuments, useVeChainKitConfig } from '@/providers';\nimport { EnrichedLegalDocument } from '@/types';\nimport {\n Button,\n ModalBody,\n ModalFooter,\n ModalHeader,\n Stack,\n Text,\n VStack,\n} from '@chakra-ui/react';\nimport { Fragment, useCallback, useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport { LegalDocumentItem } from './Components';\n\ntype Props = {\n onAgree: (\n documents: EnrichedLegalDocument | EnrichedLegalDocument[],\n ) => void;\n onReject: () => void;\n onlyOptionalDocuments?: boolean;\n};\n\nexport const LegalDocumentsContent = ({\n onAgree,\n onReject,\n onlyOptionalDocuments = false,\n}: Props) => {\n const { t } = useTranslation();\n const { darkMode: isDark } = useVeChainKitConfig();\n const { documentsNotAgreed } = useLegalDocuments();\n\n const { requiredDocuments, optionalDocuments } = useMemo(() => {\n return documentsNotAgreed.reduce<{\n requiredDocuments: EnrichedLegalDocument[];\n optionalDocuments: EnrichedLegalDocument[];\n }>(\n (acc, document) => {\n if (document.required) {\n acc.requiredDocuments.push(document);\n } else {\n acc.optionalDocuments.push(document);\n }\n return acc;\n },\n { requiredDocuments: [], optionalDocuments: [] },\n );\n }, [documentsNotAgreed]);\n\n const defaultFormValues = useMemo(() => {\n return documentsNotAgreed.reduce<Record<string, boolean>>(\n (acc, document) => {\n acc[document.id] = document.required;\n return acc;\n },\n {},\n );\n }, [documentsNotAgreed]);\n\n const {\n handleSubmit,\n register,\n formState: { isValid },\n watch,\n } = useForm<Record<string, boolean>>({\n defaultValues: defaultFormValues,\n });\n\n const formValues = watch();\n\n // Calculate if any optional documents are selected\n const selectedDocuments = useMemo(() => {\n return documentsNotAgreed.filter((document) => formValues[document.id]);\n }, [documentsNotAgreed, formValues]);\n\n // Calculate if all optional documents are selected\n const allSelected = documentsNotAgreed?.length === selectedDocuments.length;\n\n const onSubmit = useCallback(\n (data: Record<string, boolean>) => {\n const agreedDocumentIds = new Set(\n Object.entries(data)\n .filter(([_, checked]) => checked)\n .map(([docId]) => docId),\n );\n\n const agreedDocuments = documentsNotAgreed.filter((document) =>\n agreedDocumentIds.has(document.id),\n );\n return onAgree(agreedDocuments);\n },\n [documentsNotAgreed, onAgree],\n );\n\n const borderColor = isDark ? '#3a3a3a' : '#eaeaea';\n const sectionBgColor = isDark ? '#2a2a2a' : '#f5f5f5';\n const headingColor = isDark ? 'gray.300' : 'gray.600';\n const sectionBoxShadow = isDark\n ? '0 2px 8px rgba(0, 0, 0, 0.2)'\n : '0 2px 8px rgba(0, 0, 0, 0.05)';\n\n const hasRequiredDocuments = requiredDocuments.length > 0;\n const hasOptionalDocuments = optionalDocuments.length > 0;\n\n // Determine the text for the accept button based on selection state\n const acceptButtonText = useMemo(() => {\n const selectedOptionalCount = optionalDocuments.filter(\n (doc) => formValues[doc.id],\n ).length;\n\n if (allSelected) {\n return t('Accept all');\n }\n if (onlyOptionalDocuments && selectedOptionalCount === 0) {\n return t('Ignore and continue');\n }\n if (\n (hasRequiredDocuments && !hasOptionalDocuments) ||\n (hasRequiredDocuments && selectedOptionalCount === 0)\n ) {\n return t('Accept');\n }\n return t('Accept selected');\n }, [onlyOptionalDocuments, allSelected, optionalDocuments, formValues]);\n\n const requiredTextDivider = (index: number) => {\n //If the last two documents, and there are more than 1 document, return ' and '\n if (\n index === requiredDocuments.length - 2 &&\n requiredDocuments.length > 1\n ) {\n return t(' and ');\n }\n return ', ';\n };\n\n return (\n <Stack width=\"full\">\n <form onSubmit={handleSubmit(onSubmit)}>\n <StickyHeaderContainer>\n <ModalHeader>{t('Terms and Policies')}</ModalHeader>\n </StickyHeaderContainer>\n\n <ModalBody>\n <VStack align=\"stretch\" spacing={5} width=\"full\">\n {hasRequiredDocuments && (\n <Text as=\"span\" fontSize=\"sm\">\n {t('By continuing, you agree to')}{' '}\n {requiredDocuments.map((document, index) => (\n <Fragment key={document.id}>\n <LegalDocumentItem\n key={document.id}\n document={document}\n register={register}\n isText={true}\n />\n {index < requiredDocuments.length - 1\n ? requiredTextDivider(index)\n : null}\n </Fragment>\n ))}\n .{' '}\n {t(\n 'Please take a moment to review all the policies, with acceptance being mandatory to continue.',\n )}\n </Text>\n )}\n {onlyOptionalDocuments && (\n <Text fontSize=\"sm\" color={headingColor} mb={3}>\n <Trans\n i18nKey=\"<bold>Your privacy matters.</bold> You’re in control, accept to enable optional features like cookies that help us enhance your experience.\"\n components={{\n bold: (\n <Text\n as=\"span\"\n fontWeight=\"semibold\"\n color={headingColor}\n />\n ),\n }}\n />\n </Text>\n )}\n\n {hasOptionalDocuments && (\n <Stack\n p={4}\n borderRadius=\"xl\"\n bg={sectionBgColor}\n borderWidth=\"1px\"\n borderColor={borderColor}\n boxShadow={sectionBoxShadow}\n spacing={5}\n >\n <Text\n fontSize=\"md\"\n fontWeight=\"bold\"\n color={headingColor}\n >\n {t('Optional')}\n </Text>\n <VStack align=\"stretch\" spacing={4}>\n {optionalDocuments.map((document) => (\n <LegalDocumentItem\n key={document.id}\n document={document}\n register={register}\n />\n ))}\n </VStack>\n </Stack>\n )}\n </VStack>\n </ModalBody>\n <ModalFooter>\n <VStack width=\"full\" spacing={3}>\n <Button\n variant=\"vechainKitPrimary\"\n width=\"full\"\n type=\"submit\"\n isDisabled={!isValid}\n data-testid={'accept-tnc-button'}\n >\n {acceptButtonText}\n </Button>\n {!onlyOptionalDocuments && (\n <Button\n variant=\"ghost\"\n width=\"full\"\n onClick={onReject}\n data-testid={'reject-tnc-button'}\n colorScheme=\"red\"\n >\n {t('Reject and logout')}\n </Button>\n )}\n </VStack>\n </ModalFooter>\n </form>\n </Stack>\n );\n};\n","'use client';\n\nimport { EnrichedLegalDocument } from '@/types';\nimport { Step, StepModal } from '../StepModal/StepModal';\nimport { useSteps } from '@chakra-ui/react';\nimport { DisconnectConfirmContent } from '../AccountModal/Contents/DisconnectConfirmation/DisconnectConfirmContent';\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { LegalDocumentsContent } from './LegalDocumentsContent';\n\ntype Props = {\n isOpen: boolean;\n onAgree: (\n documents: EnrichedLegalDocument | EnrichedLegalDocument[],\n ) => void;\n handleLogout: () => void;\n onlyOptionalDocuments?: boolean;\n};\n\nexport type LegalDocumentsModalContentsTypes = 'legal-documents';\n\nenum LegalDocumentsSteps {\n REVIEW_DOCUMENTS = 'REVIEW_DOCUMENTS',\n REJECT_DOCUMENTS = 'REJECT_DOCUMENTS',\n}\nexport const LegalDocumentsModal = ({\n isOpen,\n onAgree,\n handleLogout,\n onlyOptionalDocuments,\n}: Props) => {\n const { t } = useTranslation();\n const { activeStep, goToPrevious, setActiveStep, goToNext } = useSteps({\n index: 0,\n count: Object.keys(LegalDocumentsSteps).length,\n });\n\n const goToFirstStep = () => {\n setActiveStep(0);\n };\n\n const goToLogoutScreen = () => {\n goToNext();\n };\n\n const logout = () => {\n handleLogout();\n goToFirstStep();\n };\n\n const steps = useMemo<Step<LegalDocumentsSteps>[]>(\n () => [\n {\n key: LegalDocumentsSteps.REVIEW_DOCUMENTS,\n content: (\n <LegalDocumentsContent\n onAgree={onAgree}\n onReject={goToLogoutScreen}\n onlyOptionalDocuments={onlyOptionalDocuments}\n />\n ),\n },\n {\n key: LegalDocumentsSteps.REJECT_DOCUMENTS,\n content: (\n <DisconnectConfirmContent\n onDisconnect={logout}\n onBack={goToPrevious}\n onClose={goToPrevious}\n text={t(\n 'Are you sure you want to reject the policies and disconnect?',\n )}\n showCloseButton={false}\n />\n ),\n },\n ],\n [LegalDocumentsContent, DisconnectConfirmContent, onAgree, logout],\n );\n\n return (\n <StepModal\n isOpen={isOpen}\n onClose={() => {}}\n goToPrevious={goToPrevious}\n goToNext={goToNext}\n setActiveStep={setActiveStep}\n steps={steps}\n disableCloseButton={true}\n disableBackButton={true}\n isCloseable={false}\n closeOnOverlayClick={false}\n activeStep={activeStep}\n />\n );\n};\n","import { EnrichedLegalDocument, LegalDocumentAgreement } from '@/types';\nimport { getLocalStorageItem } from './ssrUtils';\n\nexport const LEGAL_DOCS_LOCAL_STORAGE_KEY = 'vechain-kit-legal-documents';\nexport const LEGAL_DOCS_OPTIONAL_REJECT_LOCAL_STORAGE_KEY =\n 'vechain-kit-legal-documents-optional-reject';\n/**\n * Generate a unique ID for a document based on its type, URL and version\n */\nconst getDocumentId = (document: Omit<EnrichedLegalDocument, 'id'>): string => {\n return `${document.documentType}-${document.url.replace(\n /[^\\w-]+/g,\n '-',\n )}-v${document.version}`;\n};\n\n/**\n * Format documents by adding IDs\n */\nexport const formatDocuments = (\n documents: Omit<EnrichedLegalDocument, 'id'>[],\n): EnrichedLegalDocument[] => {\n return documents.map((document) => ({\n ...document,\n id: getDocumentId(document),\n }));\n};\n\n/**\n * Get only optional documents\n */\nexport const getOptionalDocuments = (\n documents: EnrichedLegalDocument[],\n): EnrichedLegalDocument[] => {\n return documents.filter((document) => !document.required);\n};\n\n/**\n * Get agreements from localStorage\n */\nexport const getStoredAgreements = (): LegalDocumentAgreement[] => {\n try {\n // Try new storage format first\n const storedData = getLocalStorageItem(LEGAL_DOCS_LOCAL_STORAGE_KEY);\n if (storedData) {\n return JSON.parse(storedData);\n }\n\n return [];\n } catch (e) {\n console.warn(\n 'Error reading legal document agreements from localStorage',\n e,\n );\n return [];\n }\n};\n\n/**\n * Get rejected optional documents from localStorage\n */\nexport const getStoredRejectedDocuments = (): LegalDocumentAgreement[] => {\n try {\n const storedData = getLocalStorageItem(\n LEGAL_DOCS_OPTIONAL_REJECT_LOCAL_STORAGE_KEY,\n );\n if (storedData) {\n return JSON.parse(storedData);\n }\n\n return [];\n } catch (e) {\n console.warn(\n 'Error reading rejected legal document agreements from localStorage',\n e,\n );\n return [];\n }\n};\n\n/**\n * Create document records for a user\n */\nexport const createDocumentRecords = (\n docs: EnrichedLegalDocument[],\n walletAddress: string,\n) => {\n const timestamp = Date.now();\n return docs.map((doc) => ({\n ...doc,\n walletAddress,\n timestamp,\n }));\n};\n","import { LegalDocumentsModal } from '@/components/LegalDocumentsModal';\nimport { useWallet, useSyncableLocalStorage } from '@/hooks';\nimport { useVeChainKitConfig } from '@/providers/VeChainKitProvider';\nimport {\n EnrichedLegalDocument,\n LegalDocumentAgreement,\n LegalDocumentSource,\n LegalDocumentType,\n} from '@/types';\nimport { compareAddresses } from '@/utils';\nimport {\n createDocumentRecords,\n formatDocuments,\n getOptionalDocuments,\n LEGAL_DOCS_LOCAL_STORAGE_KEY,\n LEGAL_DOCS_OPTIONAL_REJECT_LOCAL_STORAGE_KEY,\n} from '@/utils/legalDocumentsUtils';\nimport {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { VechainKitThemeProvider } from './VechainKitThemeProvider';\n\ntype Props = {\n children: Readonly<ReactNode>;\n};\n\ntype LegalDocumentsContextType = {\n hasAgreedToRequiredDocuments: boolean;\n agreements: LegalDocumentAgreement[];\n walletAddress?: string;\n documents: EnrichedLegalDocument[];\n documentsNotAgreed: EnrichedLegalDocument[];\n};\n\nconst LegalDocumentsContext = createContext<\n LegalDocumentsContextType | undefined\n>(undefined);\n\nexport const useLegalDocuments = () => {\n const context = useContext(LegalDocumentsContext);\n if (!context) {\n // This fallback is used to avoid errors when the context is not available\n return {\n hasAgreedToRequiredDocuments: true,\n agreements: [],\n walletAddress: undefined,\n documents: [],\n documentsNotAgreed: [],\n };\n }\n return context;\n};\n\nexport const LegalDocumentsProvider = ({ children }: Props) => {\n const { connection, account, disconnect } = useWallet();\n const { darkMode, legalDocuments, theme } = useVeChainKitConfig();\n\n const [storedAgreements, setStoredAgreements] = useSyncableLocalStorage<\n LegalDocumentAgreement[]\n >(LEGAL_DOCS_LOCAL_STORAGE_KEY, []);\n\n const [optionalRejected, setOptionalRejected] = useSyncableLocalStorage<\n LegalDocumentAgreement[]\n >(LEGAL_DOCS_OPTIONAL_REJECT_LOCAL_STORAGE_KEY, []);\n\n const [showTermsModal, setShowTermsModal] = useState(false);\n\n const isDocumentRejectedByUser = useCallback(\n (doc: EnrichedLegalDocument, walletAddress: string) => {\n return optionalRejected.some(\n (rejected) =>\n compareAddresses(rejected.walletAddress, walletAddress) &&\n rejected.id === doc.id,\n );\n },\n [optionalRejected],\n );\n\n const [documents, requiredDocuments] = useMemo(() => {\n // Create document mappings once with consistent naming\n const documentConfigs = [\n {\n items: legalDocuments?.cookiePolicy || [],\n type: LegalDocumentType.COOKIES,\n source: LegalDocumentSource.APPLICATION,\n },\n {\n items: legalDocuments?.privacyPolicy || [],\n type: LegalDocumentType.PRIVACY,\n source: LegalDocumentSource.APPLICATION,\n },\n {\n items: legalDocuments?.termsAndConditions || [],\n type: LegalDocumentType.TERMS,\n source: LegalDocumentSource.APPLICATION,\n },\n ];\n\n // Flatten all documents with their types and sources\n const allDocs = documentConfigs.flatMap((config) =>\n config.items.map((item) => ({\n ...item,\n documentType: config.type,\n documentSource: config.source,\n })),\n );\n\n // Format documents with IDs and filter required ones in one pass\n const formattedDocs = formatDocuments(allDocs);\n const required = formattedDocs.filter((doc) => doc.required);\n\n return [formattedDocs, required];\n }, [legalDocuments]);\n\n const documentsNotAgreed = useMemo(() => {\n if (!account?.address) return [];\n\n return documents.filter((document) => {\n // Use in-memory storedAgreements instead of reading from localStorage\n const isAgreed = storedAgreements.some(\n (agreement) =>\n compareAddresses(\n agreement.walletAddress,\n account.address,\n ) && agreement.id === document.id,\n );\n\n if (isAgreed) return false;\n\n const isRejected = optionalRejected.some(\n (rejection) =>\n compareAddresses(\n rejection.walletAddress,\n account.address,\n ) && rejection.id === document.id,\n );\n\n return !isRejected;\n });\n }, [documents, account?.address, storedAgreements, optionalRejected]);\n\n const hasAgreedToRequiredDocuments = useMemo(() => {\n //This is using the local storage hook instead of utils , since it needs a dependency hook\n //Otherwise it will not re-render when the user disconnects and connects again\n //Which will not notify external usages of this hook\n if (!requiredDocuments.length || !account?.address) return true;\n\n return requiredDocuments.every((document) =>\n storedAgreements.some(\n (saved) =>\n compareAddresses(saved.walletAddress, account.address) &&\n saved.id === document.id,\n ),\n );\n }, [requiredDocuments, storedAgreements, account?.address]);\n\n const hasOptionalDocumentsToShow = useMemo(() => {\n if (!account?.address || !documentsNotAgreed?.length) return false;\n\n // Get optional documents that haven't been agreed to\n const optionalDocsNotAgreed = getOptionalDocuments(documentsNotAgreed);\n\n if (optionalDocsNotAgreed.length === 0) return false;\n\n // Check if any of these haven't been rejected yet\n return optionalDocsNotAgreed.some(\n (doc) => !isDocumentRejectedByUser(doc, account.address),\n );\n }, [\n documentsNotAgreed,\n account?.address,\n getOptionalDocuments,\n isDocumentRejectedByUser,\n ]);\n\n const onlyOptionalDocuments = useMemo(() => {\n return hasAgreedToRequiredDocuments && hasOptionalDocumentsToShow;\n }, [hasAgreedToRequiredDocuments, hasOptionalDocumentsToShow]);\n\n useMemo(() => {\n const storedAgreementIds = new Set(\n storedAgreements.map((agreement) => agreement.id),\n );\n\n return documents.some((doc) => storedAgreementIds.has(doc.id));\n }, [documents, storedAgreements]);\n\n useEffect(() => {\n if (connection.isConnected && account?.address) {\n setShowTermsModal(\n !hasAgreedToRequiredDocuments || hasOptionalDocumentsToShow,\n );\n } else {\n setShowTermsModal(false);\n }\n }, [\n connection.isConnected,\n account?.address,\n hasAgreedToRequiredDocuments,\n hasOptionalDocumentsToShow,\n ]);\n\n const agreeToDocs = useCallback(\n (\n documents: EnrichedLegalDocument | EnrichedLegalDocument[],\n walletAddress: string,\n ) => {\n const documentsArray = Array.isArray(documents)\n ? documents\n : [documents];\n if (!documentsArray.length) return;\n\n const newAgreements = createDocumentRecords(\n documentsArray,\n walletAddress,\n );\n\n const filteredAgreements = storedAgreements.filter(\n (saved) =>\n !compareAddresses(saved.walletAddress, walletAddress) ||\n !documentsArray.some((term) => term.id === saved.id),\n );\n\n const updated = [...filteredAgreements, ...newAgreements];\n setStoredAgreements(updated);\n },\n [storedAgreements, createDocumentRecords],\n );\n\n const handleOptionalRejection = useCallback(\n (acceptedDocs: EnrichedLegalDocument[]) => {\n if (!account?.address) return;\n\n // Find optional documents that were not accepted\n const optionalDocuments = getOptionalDocuments(documentsNotAgreed);\n if (optionalDocuments.length === 0) return;\n\n const acceptedDocIds = acceptedDocs.map((doc) => doc.id);\n const rejectedOptionals = optionalDocuments.filter(\n (doc) => !acceptedDocIds.includes(doc.id),\n );\n\n // If no optional documents were rejected, return\n if (!rejectedOptionals?.length) {\n return;\n }\n\n const newRejections = createDocumentRecords(\n rejectedOptionals,\n account.address,\n );\n setOptionalRejected((prev) => [...prev, ...newRejections]);\n },\n [\n account?.address,\n documentsNotAgreed,\n getOptionalDocuments,\n createDocumentRecords,\n ],\n );\n\n const handleAgree = useCallback(\n (documents: EnrichedLegalDocument | EnrichedLegalDocument[]) => {\n if (!account?.address) return;\n\n const docsArray = Array.isArray(documents)\n ? documents\n : [documents];\n\n // Store accepted documents\n if (docsArray.length > 0) {\n agreeToDocs(docsArray, account.address);\n }\n\n // Handle optional rejection\n handleOptionalRejection(docsArray);\n\n // Close the modal\n setShowTermsModal(false);\n },\n [account?.address, agreeToDocs, handleOptionalRejection],\n );\n\n const handleLogout = () => {\n disconnect();\n setShowTermsModal(false);\n };\n\n return (\n <LegalDocumentsContext.Provider\n value={{\n hasAgreedToRequiredDocuments,\n agreements: storedAgreements,\n walletAddress: account?.address,\n documents,\n documentsNotAgreed,\n }}\n >\n {children}\n <VechainKitThemeProvider darkMode={darkMode} theme={theme}>\n <LegalDocumentsModal\n isOpen={showTermsModal}\n onAgree={handleAgree}\n handleLogout={\n onlyOptionalDocuments ? () => {} : handleLogout\n }\n onlyOptionalDocuments={onlyOptionalDocuments}\n />\n </VechainKitThemeProvider>\n </LegalDocumentsContext.Provider>\n );\n};\n","'use client';\n\nimport React, { createContext, useContext, useCallback } from 'react';\nimport { SignTypedDataParams, usePrivy } from '@privy-io/react-auth';\nimport { TransactionBody, TransactionClause } from '@vechain/sdk-core';\nimport {\n ThorClient,\n VeChainProvider,\n ProviderInternalBaseWallet,\n signerUtils,\n} from '@vechain/sdk-network';\nimport { getGenericDelegatorUrl, randomTransactionUser } from '../utils';\nimport {\n GasTokenType,\n TransactionSpeed,\n} from '@/types';\nimport {\n useSmartAccount,\n useWallet,\n useGenericDelegator,\n useHasV1SmartAccount,\n SmartAccountReturnType,\n estimateAndBuildTxBody,\n useBuildClauses,\n useGetAccountVersion,\n} from '@/hooks';\nimport { getConfig } from '@/config';\nimport { useVeChainKitConfig } from './VeChainKitProvider';\nimport { usePrivyCrossAppSdk } from './PrivyCrossAppProvider';\nimport { SignTypedDataParameters } from '@wagmi/core';\n\nexport interface PrivyWalletProviderContextType {\n accountFactory: string;\n delegateAllTransactions: boolean;\n sendTransaction: (tx: {\n txClauses: TransactionClause[];\n title?: string;\n description?: string;\n buttonText?: string;\n currentGasToken?: GasTokenType;\n delegationUrl?: string;\n }) => Promise<string>;\n signTypedData: (data: SignTypedDataParams) => Promise<string>;\n signMessage: (message: string) => Promise<string>;\n exportWallet: () => Promise<void>;\n}\n\nconst PrivyWalletProviderContext =\n createContext<PrivyWalletProviderContextType | null>(null);\n\n/**\n * This provider is responsible for retrieving the smart account address\n * of a Privy wallet and providing the necessary context for the smart account.\n * Upon initialization this provider will execute a few useEffect hooks to:\n * - retrieve the smart account address of the embedded wallet\n * - retrieve the chain id\n * - check if the smart account is deployed\n *\n * It also provides a function to send transactions on vechain by asking the privy wallet\n * to sign the transaction and then forwarding the transaction to the node api.\n * When sending a transaction this provider will check if the smart account is deployed and if not,\n * it will deploy it.\n */\nexport const PrivyWalletProvider = ({\n children,\n nodeUrl,\n delegatorUrl = getGenericDelegatorUrl(),\n delegateAllTransactions,\n genericDelegator,\n}: {\n children: React.ReactNode;\n nodeUrl: string;\n delegatorUrl?: string;\n delegateAllTransactions: boolean;\n genericDelegator?: boolean;\n}) => {\n const {\n signTypedData: signTypedDataPrivy,\n exportWallet,\n signMessage: signMessagePrivy,\n } = usePrivy();\n const {\n signTypedData: signTypedDataWithCrossApp,\n signMessage: signMessageWithCrossApp,\n } = usePrivyCrossAppSdk();\n const { connection, connectedWallet } = useWallet();\n const { network } = useVeChainKitConfig();\n const { data: smartAccount } = useSmartAccount(\n connectedWallet?.address ?? '',\n );\n const { data: smartAccountVersion } = useGetAccountVersion(\n smartAccount?.address ?? '',\n connectedWallet?.address ?? '',\n );\n const { data: hasV1SmartAccount } = useHasV1SmartAccount(\n connectedWallet?.address ?? '',\n );\n const { buildClausesWithAuth } = useBuildClauses();\n const { sendTransactionUsingGenericDelegator } = useGenericDelegator();\n\n const thor = ThorClient.at(nodeUrl);\n\n // Helper to sign and send transaction for regular fee delegation transactions\n const signAndSend = async (\n txBody: TransactionBody,\n delegationUrl?: string,\n walletOverride?: any,\n signerOverride?: any\n ) => {\n if (!smartAccount?.address) {\n throw new Error('Smart account address is not set');\n }\n\n const walletToUse = walletOverride ?? new ProviderInternalBaseWallet(\n [\n {\n privateKey: Buffer.from(\n randomTransactionUser.privateKey.slice(2),\n 'hex',\n ),\n address: randomTransactionUser.address,\n },\n ],\n { gasPayer: { gasPayerServiceUrl: delegationUrl ?? delegatorUrl } },\n );\n const provider = new VeChainProvider(\n thor,\n walletToUse,\n true\n );\n const signer = signerOverride ?? await provider.getSigner(\n randomTransactionUser.address,\n );\n const txInput = signerUtils.transactionBodyToTransactionRequestInput(\n txBody,\n randomTransactionUser.address,\n );\n const rawDelegateSigned = await signer.signTransaction(txInput);\n\n // publish the hexlified signed transaction directly on the node api\n const transactionsUrl = new URL('transactions', nodeUrl);\n const { id } = (await fetch(transactionsUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n },\n body: JSON.stringify({\n raw: rawDelegateSigned,\n }),\n }).then((res) => res.json())) as { id: string };\n\n return id;\n };\n\n /**\n * Sends a transaction on behalf of a smart account using either feeDelegation or genericDelegator\n * @param txClauses - The clauses to send in the transaction\n * @param title - The title of the transaction (used for the UI)\n * @param description - The description of the transaction\n * @param buttonText - The button text of the transaction (used for the UI)\n * @param currentGasToken - The current gas token for the transaction\n * @param speed - The speed of the transaction\n * @returns The id of the transaction\n **/\n\n const sendTransaction = useCallback(async ({\n txClauses = [],\n title = 'Sign Transaction',\n description,\n buttonText = 'Sign',\n delegationUrl,\n }: {\n txClauses: TransactionClause[];\n title?: string;\n description?: string;\n buttonText?: string;\n delegationUrl?: string;\n currentGasToken?: GasTokenType;\n speed?: TransactionSpeed;\n }): Promise<string> => {\n if (\n !smartAccount ||\n (smartAccount && !smartAccount.address) ||\n !connectedWallet ||\n (connectedWallet && !connectedWallet.address)\n ) {\n throw new Error('Address or embedded wallet is missing');\n }\n\n // if using generic delegator, use the useGenericDelegator hook, build the clauses, estimate the gas, build the tx body, sign and send, if dAppSponsored is undefined use the generic delegator\n if (genericDelegator && !delegationUrl) {\n return await sendTransactionUsingGenericDelegator({\n clauses: txClauses,\n genericDelegatorUrl: delegatorUrl ?? '',\n });\n }\n\n // else send a regular delegated transaction using the feeDelegationUrl, default to v3 if no version is found so we build the executeBatchWithAuthorization clauses, else we build the executeWithAuthorization clauses for v1 smart accounts\n const clauses = await buildClausesWithAuth({\n clauses: txClauses,\n smartAccount: smartAccount as SmartAccountReturnType,\n version: !hasV1SmartAccount ? (smartAccountVersion?.version ?? 3) : 1,\n title,\n description,\n buttonText,\n });\n\n // set the simulated transaction options\n const simulatedTransaction = {\n clauses: clauses,\n simulateTransactionOptions: {\n caller: randomTransactionUser.address\n }\n };\n\n const simulatedTx1 = await thor.transactions.simulateTransaction(\n simulatedTransaction.clauses,\n {\n ...simulatedTransaction.simulateTransactionOptions\n }\n );\n\n // check if the simulated transaction reverted\n for (let i = 0; i < simulatedTx1.length; i++) {\n if (simulatedTx1[i].reverted) {\n console.error(`simulatedTx1[i].vmError: ${simulatedTx1[i].vmError}`);\n return simulatedTx1[i].vmError;\n }\n }\n\n const txBody = await estimateAndBuildTxBody(\n clauses,\n thor,\n randomTransactionUser,\n true\n );\n\n return await signAndSend(\n txBody,\n delegationUrl,\n );\n }, [\n sendTransactionUsingGenericDelegator,\n genericDelegator,\n smartAccount,\n connectedWallet,\n delegatorUrl,\n buildClausesWithAuth,\n hasV1SmartAccount,\n smartAccountVersion,\n thor,\n ]);\n\n /**\n * Sign a message using the VechainKit wallet\n * @param message - The message to sign\n * @returns The signature of the message\n */\n const signMessage = async (message: string): Promise<string> => {\n if (connection.isConnectedWithCrossApp) {\n return await signMessageWithCrossApp(message);\n }\n\n return (\n await signMessagePrivy({\n message,\n })\n ).signature;\n };\n\n /**\n * Sign a typed data using the VechainKit wallet\n * @param data - The typed data to sign\n * @returns The signature of the typed data\n */\n const signTypedData = async (\n data: SignTypedDataParams,\n ): Promise<string> => {\n if (connection.isConnectedWithCrossApp) {\n const mutableData = {\n ...data,\n address: connectedWallet?.address as `0x${string}`,\n types: Object.fromEntries(\n Object.entries(data.types).map(([k, v]) => [k, [...v]]),\n ),\n } as unknown as SignTypedDataParameters & {\n address: `0x${string}`;\n };\n return await signTypedDataWithCrossApp(mutableData);\n }\n\n return (await signTypedDataPrivy(data)).signature;\n };\n\n return (\n <PrivyWalletProviderContext.Provider\n value={{\n accountFactory: getConfig(network.type).accountFactoryAddress,\n sendTransaction,\n signMessage,\n signTypedData,\n exportWallet,\n delegateAllTransactions,\n }}\n >\n {children}\n </PrivyWalletProviderContext.Provider>\n );\n};\n\nexport const usePrivyWalletProvider = () => {\n const context = useContext(PrivyWalletProviderContext);\n if (!context) {\n throw new Error(\n 'usePrivyWalletProvider must be used within a PrivyWalletProvider',\n );\n }\n return context;\n};\n","import { getConfig } from '@/config';\nimport { NETWORK_TYPE } from '@/config/network';\nimport { CURRENCY, PrivyLoginMethod } from '@/types';\nimport { isValidUrl } from '@/utils';\nimport { getLocalStorageItem, setLocalStorageItem } from '@/utils/ssrUtils';\nimport { initializeI18n } from '@/utils/i18n';\nimport {\n LoginMethodOrderOption,\n NonEmptyArray,\n PrivyProvider,\n WalletListEntry,\n} from '@privy-io/react-auth';\nimport { ReactQueryDevtools } from '@tanstack/react-query-devtools';\nimport {\n WalletSource as DAppKitWalletSource,\n LogLevel,\n} from '@vechain/dapp-kit';\nimport { DAppKitProvider } from '@vechain/dapp-kit-react';\nimport { WalletConnectOptions } from '@vechain/dapp-kit-react';\nimport { CustomizedStyle, I18n, SourceInfo } from '@vechain/dapp-kit-ui';\nimport {\n createContext,\n ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n useRef,\n} from 'react';\nimport { VechainKitThemeConfig } from '@/theme/tokens';\nimport {\n getDefaultTokens,\n convertThemeConfigToTokens,\n mergeTokens,\n} from '@/theme/tokens';\nimport {\n generateDAppKitCSSVariables,\n generatePrivyCSSVariables,\n applyPrivyCSSVariables,\n applyDAppKitButtonStyles,\n improvePrivyReadability,\n} from '@/utils/cssVariables';\n\nimport i18n from '../../i18n';\nimport { EnsureQueryClient } from './EnsureQueryClient';\nimport { LegalDocumentsProvider } from './LegalDocumentsProvider';\nimport { ModalProvider } from './ModalProvider';\nimport {\n VECHAIN_KIT_STORAGE_KEYS,\n DEFAULT_PRIVY_ECOSYSTEM_APPS,\n getGenericDelegatorUrl,\n} from '@/utils/constants';\nimport { Certificate, CertificateData } from '@vechain/sdk-core';\nimport { PrivyCrossAppProvider } from './PrivyCrossAppProvider';\nimport { PrivyWalletProvider } from './PrivyWalletProvider';\n\ntype AlwaysAvailableMethods = 'vechain' | 'dappkit' | 'ecosystem';\ntype PrivyDependentMethods = 'email' | 'google' | 'github' | 'passkey' | 'more';\n\ntype LoginMethodOrder = {\n method:\n | AlwaysAvailableMethods\n | (VechainKitProviderProps['privy'] extends undefined\n ? never\n : PrivyDependentMethods);\n gridColumn?: number;\n allowedApps?: string[]; // Only used by ecosystem method, if it's not provided, it will use default apps\n};\n\nexport type LegalDocumentOptions = {\n privacyPolicy?: LegalDocument[];\n termsAndConditions?: LegalDocument[];\n cookiePolicy?: LegalDocument[];\n};\n\nexport type LegalDocument = {\n url: string;\n version: number;\n required: boolean;\n displayName?: string;\n};\n\nexport type VechainKitProviderProps = {\n children: ReactNode;\n privy?: {\n appId: string;\n clientId: string;\n appearance: {\n walletList?: WalletListEntry[];\n accentColor?: `#${string}`;\n loginMessage: string;\n logo: string;\n };\n embeddedWallets?: {\n createOnLogin: 'users-without-wallets' | 'all-users' | 'off';\n };\n loginMethods: PrivyLoginMethod[];\n };\n feeDelegation?: {\n delegatorUrl?: string;\n delegateAllTransactions?: boolean;\n genericDelegatorUrl?: string;\n b3trTransfers?: {\n minAmountInEther: number;\n };\n };\n dappKit?: {\n allowedWallets?: DAppKitWalletSource[];\n walletConnectOptions?: WalletConnectOptions;\n usePersistence?: boolean;\n useFirstDetectedSource?: boolean;\n logLevel?: LogLevel;\n themeVariables?: CustomizedStyle;\n modalParent?: HTMLElement;\n onSourceClick?: (source?: SourceInfo) => void;\n v2Api?: {\n enabled?: boolean;\n external?: boolean; // whether to disconnect the user on every visit\n };\n };\n loginModalUI?: {\n logo?: string;\n description?: string;\n };\n loginMethods?: LoginMethodOrder[];\n darkMode?: boolean;\n i18n?: I18n;\n language?: string;\n network?: {\n type?: string; // Accepts any string, validated internally to 'main' | 'test' | 'solo'\n nodeUrl?: string;\n requireCertificate?: boolean;\n // TODO: migration check these types\n connectionCertificate?: {\n message?: Certificate;\n options?: CertificateData;\n };\n };\n allowCustomTokens?: boolean;\n legalDocuments?: LegalDocumentOptions;\n defaultCurrency?: CURRENCY;\n theme?: VechainKitThemeConfig;\n onLanguageChange?: (language: string) => void;\n onCurrencyChange?: (currency: CURRENCY) => void;\n};\n\n/**\n * Configuration object returned by useVeChainKitConfig hook\n */\nexport type VeChainKitConfig = {\n privy?: VechainKitProviderProps['privy'];\n privyEcosystemAppIDS: string[];\n feeDelegation?: VechainKitProviderProps['feeDelegation'];\n dappKit: VechainKitProviderProps['dappKit'];\n loginModalUI?: VechainKitProviderProps['loginModalUI'];\n loginMethods?: VechainKitProviderProps['loginMethods'];\n darkMode: boolean;\n i18n?: VechainKitProviderProps['i18n'];\n network: {\n type: NETWORK_TYPE;\n nodeUrl: string;\n requireCertificate?: boolean;\n connectionCertificate?: {\n message?: Certificate;\n options?: CertificateData;\n };\n };\n /** Current runtime language value. Reflects the active language in VeChainKit. */\n currentLanguage: string;\n allowCustomTokens?: boolean;\n legalDocuments?: VechainKitProviderProps['legalDocuments'];\n /** Current runtime currency value. Reflects the active currency in VeChainKit. */\n currentCurrency: CURRENCY;\n theme?: VechainKitThemeConfig;\n /** Function to change the language from the host app. Changes will sync to VeChainKit. */\n setLanguage: (language: string) => void;\n /** Function to change the currency from the host app. Changes will sync to VeChainKit. */\n setCurrency: (currency: CURRENCY) => void;\n};\n\n/**\n * Context to store the Privy and DAppKit configs so that they can be used by the hooks/components\n */\nexport const VeChainKitContext = createContext<VeChainKitConfig | null>(null);\n\n/**\n * Hook to get the VeChainKit configuration\n *\n * @returns VeChainKitConfig object containing:\n * - `currentLanguage`: Current runtime language value\n * - `currentCurrency`: Current runtime currency value\n * - `setLanguage`: Function to change language from host app\n * - `setCurrency`: Function to change currency from host app\n * - Other configuration values (network, darkMode, etc.)\n *\n * @example\n * ```tsx\n * const config = useVeChainKitConfig();\n * console.log(config.currentLanguage); // 'fr' (current value)\n * console.log(config.currentCurrency); // 'eur' (current value)\n * config.setLanguage('de'); // Change language\n * ```\n */\nexport const useVeChainKitConfig = () => {\n const context = useContext(VeChainKitContext);\n if (!context) {\n throw new Error('useVeChainKitConfig must be used within VeChainKit');\n }\n return context;\n};\n\nconst validateConfig = (\n props: Omit<VechainKitProviderProps, 'queryClient'>,\n) => {\n const errors: string[] = [];\n\n const validatedProps = { ...props };\n\n // Set default dappKit if not provided\n if (!validatedProps.dappKit) {\n validatedProps.dappKit = {\n allowedWallets: ['veworld'],\n };\n }\n\n // Check if fee delegation is required based on conditions\n const requiresFeeDelegation =\n validatedProps.privy !== undefined ||\n validatedProps.loginMethods?.some(\n (method) =>\n method.method === 'vechain' || method.method === 'ecosystem',\n );\n\n // Validate fee delegation\n if (requiresFeeDelegation) {\n if (!validatedProps.feeDelegation) {\n validatedProps.feeDelegation = {\n genericDelegatorUrl: getGenericDelegatorUrl(),\n };\n } else {\n if (\n !validatedProps.feeDelegation.delegatorUrl &&\n !validatedProps.feeDelegation.genericDelegatorUrl\n ) {\n validatedProps.feeDelegation.genericDelegatorUrl =\n getGenericDelegatorUrl();\n }\n }\n }\n\n // Validate network - always ensure we have a valid network configuration\n if (!validatedProps.network || !validatedProps.network.type) {\n validatedProps.network = {\n type: 'main',\n };\n } else {\n const networkType = validatedProps.network.type;\n // Validate and narrow the network type\n if (!['main', 'test', 'solo'].includes(networkType)) {\n // Provide helpful error with the invalid value\n errors.push('network.type must be either \"main\", \"test\" or \"solo\"');\n }\n }\n\n // Set default login methods if not provided\n if (!validatedProps.loginMethods) {\n validatedProps.loginMethods = [\n { method: 'vechain', gridColumn: 4 },\n { method: 'ecosystem', gridColumn: 4 },\n { method: 'dappkit', gridColumn: 4 },\n ];\n }\n\n // Validate login methods if Privy is not configured\n if (validatedProps.loginMethods) {\n if (!validatedProps.privy) {\n const invalidMethods = validatedProps.loginMethods.filter(\n (method) =>\n ['email', 'google', 'passkey', 'more'].includes(\n method.method,\n ),\n );\n\n if (invalidMethods.length > 0) {\n errors.push(\n `Login methods ${invalidMethods\n .map((m) => `\"${m.method}\"`)\n .join(', ')} require Privy configuration. ` +\n `Please either remove these methods or configure the privy prop.`,\n );\n }\n }\n }\n\n if (validatedProps?.legalDocuments) {\n if (validatedProps.legalDocuments.termsAndConditions) {\n validatedProps.legalDocuments.termsAndConditions.forEach((term) => {\n if (!isValidUrl(term.url)) {\n errors.push(\n `legalDocuments.termsAndConditions.url is invalid: ${term.url}`,\n );\n }\n });\n }\n if (validatedProps.legalDocuments.privacyPolicy) {\n validatedProps.legalDocuments.privacyPolicy.forEach((term) => {\n if (!isValidUrl(term.url)) {\n errors.push(\n `legalDocuments.privacyPolicy.url is invalid: ${term.url}`,\n );\n }\n });\n }\n if (validatedProps.legalDocuments.cookiePolicy) {\n validatedProps.legalDocuments.cookiePolicy.forEach((term) => {\n if (!isValidUrl(term.url)) {\n errors.push(\n `legalDocuments.cookiePolicy.url is invalid: ${term.url}`,\n );\n }\n });\n }\n }\n\n if (errors.length > 0) {\n throw new Error(\n 'VeChainKit Configuration Error:\\n' + errors.join('\\n'),\n );\n }\n\n return validatedProps;\n};\n\n/**\n * Provider to wrap the application with Privy and DAppKit\n */\nconst CURRENCY_STORAGE_KEY = 'vechain_kit_currency';\n\nexport const VeChainKitProvider = (\n props: Omit<VechainKitProviderProps, 'queryClient'>,\n) => {\n // Validate all configurations at the start\n const validatedProps = validateConfig(props);\n const {\n children,\n privy,\n feeDelegation,\n dappKit: _dappKit,\n loginModalUI,\n loginMethods,\n darkMode = false,\n i18n: i18nConfig,\n language = 'en',\n network: _network,\n allowCustomTokens,\n legalDocuments,\n defaultCurrency = 'usd',\n theme: customTheme,\n onLanguageChange,\n onCurrencyChange,\n } = validatedProps;\n\n // After validation, network and dappKit are guaranteed to be defined\n // Cast the network type to NETWORK_TYPE since validation ensures it's valid\n const networkType = (_network?.type ?? 'main') as NETWORK_TYPE;\n\n //To avoid this fallback across the codebase, do it globally in the provider\n const nodeUrl = _network?.nodeUrl ?? getConfig(networkType).nodeUrl;\n\n const network = {\n ..._network,\n type: networkType,\n nodeUrl,\n };\n\n const dappKit = _dappKit ?? {\n allowedWallets: ['veworld'] as DAppKitWalletSource[],\n };\n\n // Initialize current language from i18n or prop\n const [currentLanguage, setCurrentLanguageState] = useState<string>(() => {\n if (typeof window !== 'undefined') {\n const stored = getLocalStorageItem('i18nextLng');\n return stored || language;\n }\n return language;\n });\n\n // Initialize current currency from localStorage or prop\n const [currentCurrency, setCurrentCurrencyState] = useState<CURRENCY>(\n () => {\n try {\n const stored = getLocalStorageItem(CURRENCY_STORAGE_KEY);\n return (stored as CURRENCY) || defaultCurrency;\n } catch {\n return defaultCurrency;\n }\n },\n );\n\n // Track if we're updating from prop to avoid loops\n const isUpdatingFromPropRef = useRef(false);\n const isUpdatingCurrencyFromPropRef = useRef(false);\n\n // Remove the validateLoginMethods call since it's now handled in validateConfig\n const validatedLoginMethods = loginMethods;\n\n const allowedEcosystemApps = useMemo(() => {\n const userEcosystemMethods = validatedLoginMethods?.find(\n (method) => method.method === 'ecosystem',\n );\n return (\n userEcosystemMethods?.allowedApps ??\n DEFAULT_PRIVY_ECOSYSTEM_APPS.map((app) => app.id)\n );\n }, [validatedLoginMethods]);\n\n let privyAppId: string, privyClientId: string;\n if (!privy) {\n // We set dummy values for the appId and clientId so that the PrivyProvider doesn't throw an error\n privyAppId = 'clzdb5k0b02b9qvzjm6jpknsc';\n privyClientId = 'client-WY2oy87y6KNrHFnpXuwVsiFMkwPZKTYpExtjvUQuMbCMF';\n } else {\n privyAppId = privy.appId;\n privyClientId = privy.clientId;\n }\n\n // Initialize i18n with stored language or prop, and merge translations\n useEffect(() => {\n // Initialize translations from VeChainKit\n initializeI18n(i18n);\n\n if (i18nConfig) {\n // Add custom translations from the app if provided\n Object.keys(i18nConfig).forEach((lang) => {\n i18n.addResourceBundle(\n lang,\n 'translation',\n i18nConfig[lang],\n true,\n true,\n );\n });\n }\n\n // Initialize i18n with stored language or currentLanguage state\n // This ensures stored preferences are respected on page refresh\n const storedLanguage =\n typeof window !== 'undefined'\n ? getLocalStorageItem('i18nextLng')\n : null;\n const initialLanguage = storedLanguage || currentLanguage;\n\n if (initialLanguage && i18n.language !== initialLanguage) {\n isUpdatingFromPropRef.current = true;\n i18n.changeLanguage(initialLanguage);\n if (initialLanguage !== currentLanguage) {\n setCurrentLanguageState(initialLanguage);\n }\n isUpdatingFromPropRef.current = false;\n }\n }, []); // Only run once on mount\n\n // Sync language prop changes to i18n and state (but only if no stored value exists)\n useEffect(() => {\n // Skip on initial mount - let the initialization effect handle it\n const storedLanguage =\n typeof window !== 'undefined'\n ? getLocalStorageItem('i18nextLng')\n : null;\n\n // Only sync prop if there's no stored preference and prop differs from current\n if (language && !storedLanguage && language !== currentLanguage) {\n isUpdatingFromPropRef.current = true;\n i18n.changeLanguage(language);\n setCurrentLanguageState(language);\n isUpdatingFromPropRef.current = false;\n }\n }, [language, currentLanguage]);\n\n // Listen to i18n language changes (from kit settings)\n useEffect(() => {\n const handleLanguageChanged = (lng: string) => {\n if (!isUpdatingFromPropRef.current && lng !== currentLanguage) {\n setCurrentLanguageState(lng);\n onLanguageChange?.(lng);\n }\n };\n\n i18n.on('languageChanged', handleLanguageChanged);\n\n return () => {\n i18n.off('languageChanged', handleLanguageChanged);\n };\n }, [currentLanguage, onLanguageChange]);\n\n // Sync currency prop changes to state (but only if no stored value exists)\n useEffect(() => {\n const stored = getLocalStorageItem(CURRENCY_STORAGE_KEY);\n\n // Only sync prop if there's no stored preference and prop differs from current\n if (defaultCurrency && !stored && defaultCurrency !== currentCurrency) {\n isUpdatingCurrencyFromPropRef.current = true;\n setCurrentCurrencyState(defaultCurrency);\n setLocalStorageItem(CURRENCY_STORAGE_KEY, defaultCurrency);\n isUpdatingCurrencyFromPropRef.current = false;\n }\n }, [defaultCurrency, currentCurrency]);\n\n // Listen to currency localStorage changes (from kit settings)\n useEffect(() => {\n const checkCurrencyChange = () => {\n try {\n const stored = getLocalStorageItem(CURRENCY_STORAGE_KEY);\n if (\n stored &&\n stored !== currentCurrency &&\n !isUpdatingCurrencyFromPropRef.current\n ) {\n const newCurrency = stored as CURRENCY;\n setCurrentCurrencyState(newCurrency);\n onCurrencyChange?.(newCurrency);\n }\n } catch {\n // Ignore errors\n }\n };\n\n // Check on mount\n checkCurrencyChange();\n\n // Listen to storage events (for cross-tab sync)\n const handleStorageChange = (e: StorageEvent) => {\n if (e.key === CURRENCY_STORAGE_KEY && e.newValue) {\n checkCurrencyChange();\n }\n };\n\n window.addEventListener('storage', handleStorageChange);\n\n // Poll for changes (in case storage event doesn't fire)\n const interval = setInterval(checkCurrencyChange, 500);\n\n return () => {\n window.removeEventListener('storage', handleStorageChange);\n clearInterval(interval);\n };\n }, [currentCurrency, onCurrencyChange]);\n\n // Functions to set language/currency from host app\n const setLanguage = (lang: string) => {\n isUpdatingFromPropRef.current = true;\n i18n.changeLanguage(lang);\n setCurrentLanguageState(lang);\n isUpdatingFromPropRef.current = false;\n };\n\n const setCurrency = (currency: CURRENCY) => {\n isUpdatingCurrencyFromPropRef.current = true;\n setCurrentCurrencyState(currency);\n setLocalStorageItem(CURRENCY_STORAGE_KEY, currency);\n isUpdatingCurrencyFromPropRef.current = false;\n };\n\n useEffect(() => {\n setLocalStorageItem(VECHAIN_KIT_STORAGE_KEYS.NETWORK, networkType);\n }, [networkType]);\n\n // Generate tokens from custom theme config\n const tokens = useMemo(() => {\n const defaultTokens = getDefaultTokens(darkMode);\n const customTokens = convertThemeConfigToTokens(customTheme, darkMode);\n return mergeTokens(defaultTokens, customTokens);\n }, [customTheme, darkMode]);\n\n // Generate CSS variables for DAppKit and Privy\n const dappKitThemeVariables = useMemo(\n () => generateDAppKitCSSVariables(tokens, darkMode),\n [tokens, darkMode],\n );\n\n const privyCSSVariables = useMemo(\n () => generatePrivyCSSVariables(tokens, darkMode),\n [tokens, darkMode],\n );\n\n // Apply Privy CSS variables to document and inject backdrop filter + card styles\n useEffect(() => {\n // Prepare card backgrounds with readability improvements\n const privyCardBg = improvePrivyReadability(\n tokens.colors.background.card,\n darkMode,\n );\n const privyCardElevatedBg = improvePrivyReadability(\n tokens.colors.background.cardElevated,\n darkMode,\n );\n // Use loginIn variant style: white (light) / transparent (dark) background\n const privyButtonBaseBg = darkMode ? 'transparent' : '#ffffff';\n const privyButtonHoverBg = darkMode ? 'transparent' : '#ffffff';\n const privyButtonActiveBg = darkMode ? 'transparent' : '#ffffff';\n\n applyPrivyCSSVariables(\n privyCSSVariables,\n tokens.effects.backdropFilter.modal,\n privyCardBg,\n privyCardElevatedBg,\n privyButtonBaseBg,\n privyButtonHoverBg,\n privyButtonActiveBg,\n tokens.colors.border.default,\n );\n }, [\n privyCSSVariables,\n tokens.effects.backdropFilter.modal,\n tokens.colors.background.card,\n tokens.colors.background.cardElevated,\n tokens.colors.border.default,\n darkMode,\n ]);\n\n // Apply DAppKit button styles (hover opacity matching loginIn variant)\n useEffect(() => {\n applyDAppKitButtonStyles();\n }, []);\n\n return (\n <EnsureQueryClient>\n <ReactQueryDevtools initialIsOpen={false} />\n <PrivyCrossAppProvider privyEcosystemAppIDS={allowedEcosystemApps}>\n <VeChainKitContext.Provider\n value={{\n privy,\n privyEcosystemAppIDS: allowedEcosystemApps,\n feeDelegation,\n dappKit,\n loginModalUI,\n loginMethods: validatedLoginMethods,\n darkMode,\n i18n: i18nConfig,\n currentLanguage,\n network,\n allowCustomTokens,\n legalDocuments,\n currentCurrency,\n theme: customTheme,\n setLanguage,\n setCurrency,\n }}\n >\n <PrivyProvider\n appId={privyAppId}\n clientId={privyClientId}\n config={{\n // loginMethods: privy?.loginMethods,\n loginMethodsAndOrder: {\n primary: (privy?.loginMethods.slice(0, 4) ??\n []) as NonEmptyArray<LoginMethodOrderOption>,\n overflow: (privy?.loginMethods.slice(4) ??\n []) as Array<LoginMethodOrderOption>,\n },\n externalWallets: {\n walletConnect: {\n enabled: false,\n },\n },\n appearance: {\n theme: darkMode ? 'dark' : 'light',\n accentColor:\n privy?.appearance.accentColor ??\n (tokens.buttons.primaryButton.bg?.startsWith(\n '#',\n )\n ? (tokens.buttons.primaryButton\n .bg as `#${string}`)\n : darkMode\n ? '#3182CE'\n : '#2B6CB0'),\n loginMessage: privy?.appearance.loginMessage,\n logo: privy?.appearance.logo,\n },\n embeddedWallets: {\n createOnLogin:\n privy?.embeddedWallets?.createOnLogin ??\n 'all-users',\n },\n passkeys: {\n shouldUnlinkOnUnenrollMfa: false,\n },\n }}\n >\n <DAppKitProvider\n node={network.nodeUrl}\n alwaysShowConnect={true}\n v2Api={{\n enabled: dappKit.v2Api?.enabled ?? true, //defaults to true\n external: dappKit.v2Api?.external ?? false, //defaults to false\n }}\n language={currentLanguage}\n logLevel={dappKit.logLevel}\n modalParent={dappKit.modalParent}\n onSourceClick={dappKit.onSourceClick}\n usePersistence={dappKit.usePersistence ?? true}\n allowedWallets={dappKit.allowedWallets}\n walletConnectOptions={dappKit.walletConnectOptions}\n themeMode={darkMode ? 'DARK' : 'LIGHT'}\n themeVariables={\n dappKit.themeVariables\n ? {\n ...dappKitThemeVariables,\n ...dappKit.themeVariables,\n }\n : dappKitThemeVariables\n }\n >\n <PrivyWalletProvider\n nodeUrl={network.nodeUrl}\n delegatorUrl={\n feeDelegation?.delegatorUrl ??\n feeDelegation?.genericDelegatorUrl\n }\n delegateAllTransactions={\n feeDelegation?.delegateAllTransactions ??\n false\n }\n genericDelegator={\n !feeDelegation?.delegatorUrl &&\n feeDelegation?.genericDelegatorUrl\n ? true\n : false\n }\n >\n <ModalProvider>\n <LegalDocumentsProvider>\n {children}\n </LegalDocumentsProvider>\n </ModalProvider>\n </PrivyWalletProvider>\n </DAppKitProvider>\n </PrivyProvider>\n </VeChainKitContext.Provider>\n </PrivyCrossAppProvider>\n </EnsureQueryClient>\n );\n};\n"],"mappings":"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"}
|