@vechain/vechain-kit 1.5.13 → 1.6.0

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { IVechainEnergyOracleV1__factory, IB3TR__factory, IVOT3__factory, GalaxyMember__factory, NodeManagement__factory, X2EarnApps__factory, XAllocationVoting__factory, XAllocationVotingGovernor__factory, XAllocationPool__factory, VoterRewards__factory, VeBetterPassport__factory, IERC20__factory, MockENS__factory, SubdomainClaimer__factory, IReverseRegistrar__factory, ERC20__factory, SimpleAccountFactory__factory, SimpleAccount__factory, Emissions__factory, X2EarnRewardsPool__factory } from './chunk-FOSPSOWT.js';
2
- import { getConfig, humanNumber, NodeStrengthLevelToImage, allNodeStrengthLevelToName, notFoundImage, convertUriToUrl, resolveMediaTypeFromMimeType, gmNfts, DEFAULT_PRIVY_ECOSYSTEM_APPS, humanAddress, getPicassoImage, VECHAIN_PRIVY_APP_ID, compareAddresses, isValidAddress, TOKEN_LOGO_COMPONENTS, TOKEN_LOGOS, humanDomain, uploadBlobToIPFS, randomTransactionUser } from './chunk-YPHGCDGO.js';
3
- export { getConfig } from './chunk-YPHGCDGO.js';
4
- import { SimpleAccountFactoryABI, VechainLogo, VechainLogoLight, VechainLogoDark, VechainEnergy, PrivyLogo, SimpleAccountABI } from './chunk-G7I2W6XJ.js';
2
+ import { VECHAIN_KIT_MIXPANEL_PROJECT_TOKEN, ENV, getConfig, humanNumber, NodeStrengthLevelToImage, allNodeStrengthLevelToName, notFoundImage, convertUriToUrl, resolveMediaTypeFromMimeType, gmNfts, DEFAULT_PRIVY_ECOSYSTEM_APPS, humanAddress, getPicassoImage, VECHAIN_PRIVY_APP_ID, compareAddresses, isValidAddress, TOKEN_LOGO_COMPONENTS, TOKEN_LOGOS, humanDomain, VECHAIN_KIT_STORAGE_KEYS, uploadBlobToIPFS, randomTransactionUser } from './chunk-WJ5LYJZQ.js';
3
+ export { getConfig } from './chunk-WJ5LYJZQ.js';
4
+ import { SimpleAccountFactoryABI, VechainLogo, VechainLogoLight, VechainLogoDark, VeWorldLogoLight, VeWorldLogoDark, VechainEnergy, PrivyLogo, SimpleAccountABI } from './chunk-Z4FE6MMP.js';
5
5
  import './chunk-PZ5AY32C.js';
6
6
  import React10, { createContext, useState, useEffect, useMemo, useCallback, useRef, useContext } from 'react';
7
7
  import { useLoginWithOAuth, usePrivy, useLoginWithEmail, useMfaEnrollment, useSetWalletRecovery, useLoginWithPasskey as useLoginWithPasskey$1, PrivyProvider } from '@privy-io/react-auth';
@@ -18,11 +18,12 @@ import { abi, Transaction } from 'thor-devkit';
18
18
  import imageCompression from 'browser-image-compression';
19
19
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
20
20
  import { Interface, formatEther as formatEther$1, isAddress, ethers, namehash, toUtf8String, zeroPadValue, toBeHex, parseEther as parseEther$1 } from 'ethers';
21
+ import VeChainKitMixpanel from 'mixpanel-browser';
21
22
  import { z } from 'zod';
22
23
  import { useAccount, createConfig, http, WagmiProvider, useConnect, useSignTypedData, useSignMessage, useDisconnect } from 'wagmi';
23
24
  import { toPrivyWalletConnector } from '@privy-io/cross-app-connect/rainbow-kit';
24
25
  import { isMobile } from 'react-device-detect';
25
- import { createMultiStyleConfigHelpers, defineStyle, defineStyleConfig, extendTheme, createStandaloneToast, IconButton, VStack, Text, InputGroup, InputLeftElement, Icon, Input, InputRightElement, HStack, Link, Box, useMediaQuery, Modal, ModalOverlay, ModalContent, Button, Image, Skeleton, Spinner, useDisclosure, GridItem, ModalHeader, ModalCloseButton, ModalBody, ModalFooter, Tag, Heading, useColorModeValue, Tabs, TabList, Tab, TabPanels, TabPanel, Grid, Card, CardBody, Alert, AlertIcon, CardHeader, Center, CardFooter, Divider, Container, FormControl, Select, FormLabel, Textarea, Circle, AlertTitle, AlertDescription, Popover, PopoverTrigger, PopoverContent, PopoverBody, PinInput, PinInputField, Stack, Accordion, AccordionItem, AccordionButton, AccordionPanel, List, ChakraProvider, ColorModeScript, ListItem, Flex } from '@chakra-ui/react';
26
+ import { createMultiStyleConfigHelpers, defineStyle, defineStyleConfig, extendTheme, createStandaloneToast, IconButton, VStack, Text, InputGroup, InputLeftElement, Icon, Input, InputRightElement, HStack, Link, Box, useMediaQuery, Modal, ModalOverlay, ModalContent, Button, Image, Skeleton, useDisclosure, GridItem, ModalHeader, ModalCloseButton, ModalBody, ModalFooter, Tag, Heading, useColorModeValue, Tabs, TabList, Tab, TabPanels, TabPanel, Grid, Card, CardBody, Alert, AlertIcon, CardHeader, Center, CardFooter, Divider, Container, FormControl, Select, FormLabel, Textarea, Circle, AlertTitle, AlertDescription, Popover, PopoverTrigger, PopoverContent, PopoverBody, PopoverFooter, Spinner, PinInput, PinInputField, Stack, Accordion, AccordionItem, AccordionButton, AccordionPanel, List, ChakraProvider, ColorModeScript, ListItem, Flex } from '@chakra-ui/react';
26
27
  import { motion } from 'framer-motion';
27
28
  import { IoChevronBack, IoCheckmarkOutline, IoCopyOutline, IoWalletOutline, IoCloseCircle, IoCogSharp, IoShieldOutline, IoOpenOutline, IoTrashBin, IoChevronUp, IoChevronDown, IoCloseOutline, IoTrashOutline } from 'react-icons/io5';
28
29
  import { FaRegAddressCard, FaExternalLinkAlt, FaGlobe, FaEnvelope, FaArrowRight, FaTelegramPlane, FaChevronDown, FaEdit, FaGoogle, FaTwitter, FaPhone, FaSpotify, FaApple, FaInstagram, FaTiktok, FaGithub, FaLinkedin, FaTelegram, FaDiscord as FaDiscord$1, FaWallet, FaPlus } from 'react-icons/fa';
@@ -32,7 +33,6 @@ import { LuMail, LuArrowDownToLine } from 'react-icons/lu';
32
33
  import { MdOutlineNavigateNext, MdOutlineSettingsBackupRestore, MdPhotoCamera, MdOutlineRefresh, MdOutlineErrorOutline, MdEmail, MdSwapHoriz } from 'react-icons/md';
33
34
  import { FcGoogle, FcCheckmark } from 'react-icons/fc';
34
35
  import { IoIosFingerPrint, IoIosArrowForward, IoMdApps, IoMdSettings, IoIosCheckmarkCircleOutline } from 'react-icons/io';
35
- import { AiOutlineUser } from 'react-icons/ai';
36
36
  import { CiCircleMore, CiSearch } from 'react-icons/ci';
37
37
  import { VscRefresh, VscDebugDisconnect } from 'react-icons/vsc';
38
38
  import { RiLogoutBoxLine, RiEdit2Line, RiTwitterXFill, RiSwap3Line } from 'react-icons/ri';
@@ -40,6 +40,7 @@ import { FiSlash, FiArrowDown, FiSend } from 'react-icons/fi';
40
40
  import { GrUserAdmin } from 'react-icons/gr';
41
41
  import { GiHouseKeys } from 'react-icons/gi';
42
42
  import { BiBell, BiArchive } from 'react-icons/bi';
43
+ import { CgProfile } from 'react-icons/cg';
43
44
  import { PiLineVertical } from 'react-icons/pi';
44
45
  import { useForm } from 'react-hook-form';
45
46
  import { QRCode } from 'react-qrcode-logo';
@@ -2897,6 +2898,445 @@ var useEnsRecordExists = (name) => {
2897
2898
  enabled: !!name
2898
2899
  });
2899
2900
  };
2901
+ var APP_SOURCE = document.title || "";
2902
+ var PAGE_SOURCE = window?.location?.origin || "";
2903
+ if (typeof window !== "undefined" && VECHAIN_KIT_MIXPANEL_PROJECT_TOKEN) {
2904
+ VeChainKitMixpanel.init(VECHAIN_KIT_MIXPANEL_PROJECT_TOKEN, {
2905
+ debug: !ENV.isProduction
2906
+ });
2907
+ if (ENV.isDevelopment) {
2908
+ console.info("Analytics initialized in DEVELOPMENT mode");
2909
+ }
2910
+ }
2911
+ var isFirstLogin = (userId) => {
2912
+ try {
2913
+ const userDataKey = `user_data_${userId}`;
2914
+ const userData = localStorage.getItem(userDataKey);
2915
+ if (userData) {
2916
+ const parsedData = JSON.parse(userData);
2917
+ return !parsedData.first_login_date;
2918
+ }
2919
+ return true;
2920
+ } catch (e) {
2921
+ console.warn("Error checking first login status", e);
2922
+ return true;
2923
+ }
2924
+ };
2925
+ var storeUserData = (userId, properties) => {
2926
+ try {
2927
+ const userDataKey = `user_data_${userId}`;
2928
+ const existingData = localStorage.getItem(userDataKey);
2929
+ let userData = properties;
2930
+ if (existingData) {
2931
+ userData = { ...JSON.parse(existingData), ...properties };
2932
+ }
2933
+ localStorage.setItem(userDataKey, JSON.stringify(userData));
2934
+ } catch (e) {
2935
+ console.warn("Error storing user data", e);
2936
+ }
2937
+ };
2938
+ var trackEvent = (event, properties = {}) => {
2939
+ try {
2940
+ if (!VECHAIN_KIT_MIXPANEL_PROJECT_TOKEN) {
2941
+ console.warn("No project token found");
2942
+ return;
2943
+ }
2944
+ if (typeof navigator !== "undefined" && !navigator.onLine) {
2945
+ return;
2946
+ }
2947
+ VeChainKitMixpanel.track(event, {
2948
+ ...properties,
2949
+ source: APP_SOURCE,
2950
+ page: PAGE_SOURCE
2951
+ });
2952
+ } catch (error) {
2953
+ console.error(`Analytics error when tracking "${event}":`, error);
2954
+ }
2955
+ };
2956
+ var setUserProperties = (properties, userId) => {
2957
+ try {
2958
+ VeChainKitMixpanel.people.set({
2959
+ ...properties,
2960
+ source: APP_SOURCE,
2961
+ page: PAGE_SOURCE
2962
+ });
2963
+ if (userId) {
2964
+ storeUserData(userId, properties);
2965
+ }
2966
+ } catch (error) {
2967
+ console.error("Error setting user properties:", error);
2968
+ }
2969
+ };
2970
+ var identifyUser = (userId) => {
2971
+ try {
2972
+ if (!userId) {
2973
+ return;
2974
+ }
2975
+ VeChainKitMixpanel.identify(userId);
2976
+ } catch (error) {
2977
+ console.error("Error identifying user:", error);
2978
+ }
2979
+ };
2980
+ var incrementUserProperty = (property, value = 1) => {
2981
+ try {
2982
+ VeChainKitMixpanel.people.increment(property, value);
2983
+ } catch (error) {
2984
+ console.error(`Error incrementing property ${property}:`, error);
2985
+ }
2986
+ };
2987
+ var Analytics = {
2988
+ auth: {
2989
+ trackAuth: (action, properties) => {
2990
+ trackEvent("Auth Flow", {
2991
+ action,
2992
+ ...properties,
2993
+ isError: !!properties?.error
2994
+ });
2995
+ },
2996
+ flowStarted: (loginMethod) => {
2997
+ Analytics.auth.trackAuth("start", {
2998
+ loginMethod
2999
+ });
3000
+ },
3001
+ tryAgain: (method35, platform) => {
3002
+ Analytics.auth.trackAuth("try_again", {
3003
+ loginMethod: method35,
3004
+ platform
3005
+ });
3006
+ },
3007
+ methodSelected: (method35) => {
3008
+ Analytics.auth.trackAuth("method_selected", {
3009
+ loginMethod: method35
3010
+ });
3011
+ },
3012
+ completed: ({
3013
+ userId,
3014
+ loginMethod,
3015
+ platform
3016
+ }) => {
3017
+ if (userId) {
3018
+ identifyUser(userId);
3019
+ setUserProperties(
3020
+ {
3021
+ last_login_date: (/* @__PURE__ */ new Date()).toISOString(),
3022
+ preferred_login_method: loginMethod
3023
+ },
3024
+ userId
3025
+ );
3026
+ if (isFirstLogin(userId)) {
3027
+ Analytics.user.profile.markFirstLogin(userId);
3028
+ }
3029
+ }
3030
+ incrementUserProperty("total_logins");
3031
+ Analytics.auth.trackAuth("connect_success", {
3032
+ loginMethod,
3033
+ platform
3034
+ });
3035
+ },
3036
+ failed: (loginMethod, reason) => {
3037
+ Analytics.auth.trackAuth("connect_failed", {
3038
+ loginMethod,
3039
+ error: reason
3040
+ });
3041
+ },
3042
+ dropOff: (stage, properties) => {
3043
+ Analytics.auth.trackAuth("drop_off", {
3044
+ dropOffStage: stage,
3045
+ ...properties
3046
+ });
3047
+ },
3048
+ connectionListViewed: (totalConnections) => {
3049
+ Analytics.auth.trackAuth("start", { totalConnections });
3050
+ },
3051
+ walletConnectInitiated: (walletType) => {
3052
+ Analytics.auth.trackAuth("connect_initiated", {
3053
+ loginMethod: walletType
3054
+ });
3055
+ },
3056
+ walletDisconnectInitiated: () => {
3057
+ Analytics.auth.trackAuth("disconnect_initiated");
3058
+ },
3059
+ logoutCompleted: () => {
3060
+ Analytics.auth.trackAuth("logout");
3061
+ }
3062
+ },
3063
+ user: {
3064
+ profile: {
3065
+ trackAccount: (action, properties) => {
3066
+ trackEvent("Account Flow", {
3067
+ action,
3068
+ ...properties,
3069
+ isError: !!properties?.error
3070
+ });
3071
+ },
3072
+ markFirstLogin: (userId) => {
3073
+ const firstLoginDate = (/* @__PURE__ */ new Date()).toISOString();
3074
+ setUserProperties({ first_login_date: firstLoginDate }, userId);
3075
+ trackEvent("First Login", { date: firstLoginDate });
3076
+ },
3077
+ markActive: (userId) => {
3078
+ const activeDate = (/* @__PURE__ */ new Date()).toISOString();
3079
+ setUserProperties({ last_active: activeDate }, userId);
3080
+ },
3081
+ viewed: () => Analytics.user.profile.trackAccount("view"),
3082
+ addressCopied: (fromScreen) => Analytics.user.profile.trackAccount("address_copied", {
3083
+ fromScreen
3084
+ }),
3085
+ customiseOpened: () => Analytics.user.profile.trackAccount("customise_opened")
3086
+ }
3087
+ },
3088
+ customization: {
3089
+ trackCustomization: (action, properties) => {
3090
+ trackEvent("Customization Flow", {
3091
+ action,
3092
+ ...properties,
3093
+ isError: !!properties?.error
3094
+ });
3095
+ },
3096
+ started: () => {
3097
+ Analytics.customization.trackCustomization("started");
3098
+ },
3099
+ completed: (changes) => {
3100
+ Analytics.customization.trackCustomization("completed", changes);
3101
+ },
3102
+ dropOff: ({
3103
+ stage,
3104
+ reason,
3105
+ error
3106
+ }) => {
3107
+ Analytics.customization.trackCustomization("drop_off", {
3108
+ stage,
3109
+ reason,
3110
+ error
3111
+ });
3112
+ },
3113
+ imageUploaded: (success, error) => {
3114
+ Analytics.customization.trackCustomization("image_upload", {
3115
+ success,
3116
+ error
3117
+ });
3118
+ },
3119
+ failed: (stage, error) => {
3120
+ Analytics.customization.trackCustomization("customization_failed", {
3121
+ stage,
3122
+ error
3123
+ });
3124
+ }
3125
+ },
3126
+ swap: {
3127
+ trackSwap: (action, properties) => {
3128
+ trackEvent("Swap Flow", {
3129
+ action,
3130
+ ...properties,
3131
+ isError: !!properties?.error
3132
+ });
3133
+ },
3134
+ opened: () => Analytics.swap.trackSwap("view"),
3135
+ buttonClicked: () => Analytics.swap.trackSwap("button_click"),
3136
+ launchBetterSwap: () => Analytics.swap.trackSwap("launch_better_swap")
3137
+ },
3138
+ wallet: {
3139
+ trackWallet: (action, properties) => {
3140
+ trackEvent("Wallet Flow", {
3141
+ action,
3142
+ ...properties,
3143
+ isError: !!properties?.error
3144
+ });
3145
+ },
3146
+ opened: (connected) => Analytics.wallet.trackWallet("view", { connected }),
3147
+ closed: (connected) => Analytics.wallet.trackWallet("close", { connected }),
3148
+ balanceRefreshed: () => Analytics.wallet.trackWallet("balance_refresh"),
3149
+ assetsViewed: () => Analytics.wallet.trackWallet("assets_view"),
3150
+ maxTokenSelected: (tokenSymbol) => Analytics.wallet.trackWallet("max_token_selected", { tokenSymbol }),
3151
+ receiveQRGenerated: () => Analytics.wallet.trackWallet("receive_qr_generated"),
3152
+ addressCopied: (context) => Analytics.wallet.trackWallet("address_copied", { context })
3153
+ },
3154
+ send: {
3155
+ trackSend: (action, properties) => {
3156
+ trackEvent("Send Flow", {
3157
+ action,
3158
+ ...properties,
3159
+ isError: !!properties?.error
3160
+ });
3161
+ },
3162
+ initiated: (tokenSymbol, recipientType) => Analytics.send.trackSend("initiated", {
3163
+ tokenSymbol,
3164
+ recipientType
3165
+ }),
3166
+ completed: (tokenSymbol, amount, txHash, transactionType) => Analytics.send.trackSend("completed", {
3167
+ tokenSymbol,
3168
+ amount,
3169
+ txHash,
3170
+ transactionType
3171
+ }),
3172
+ flow: (action, properties) => {
3173
+ Analytics.send.trackSend(action, properties);
3174
+ },
3175
+ tokenSearchPerformed: (query) => Analytics.send.trackSend("token_search", {
3176
+ query
3177
+ }),
3178
+ tokenPageViewed: (tokenSymbol) => Analytics.send.trackSend("token_page_view", {
3179
+ tokenSymbol
3180
+ }),
3181
+ tokenSelected: (tokenSymbol) => Analytics.send.trackSend("token_selected", {
3182
+ tokenSymbol
3183
+ })
3184
+ },
3185
+ bridge: {
3186
+ trackBridge: (action, properties) => {
3187
+ trackEvent("Bridge Flow", {
3188
+ action,
3189
+ ...properties,
3190
+ isError: !!properties?.error
3191
+ });
3192
+ },
3193
+ opened: () => Analytics.bridge.trackBridge("view"),
3194
+ buttonClicked: () => Analytics.bridge.trackBridge("button_click"),
3195
+ launchVeChainEnergy: () => Analytics.bridge.trackBridge("launch_vechain_energy")
3196
+ },
3197
+ ecosystem: {
3198
+ trackEcosystem: (action, properties) => {
3199
+ trackEvent("Ecosystem Flow", {
3200
+ action,
3201
+ ...properties,
3202
+ isError: !!properties?.error
3203
+ });
3204
+ },
3205
+ opened: () => Analytics.ecosystem.trackEcosystem("view"),
3206
+ buttonClicked: () => Analytics.ecosystem.trackEcosystem("button_click"),
3207
+ searchPerformed: (query, resultsCount) => Analytics.ecosystem.trackEcosystem("search", {
3208
+ query,
3209
+ resultsCount
3210
+ }),
3211
+ appSelected: (appName) => Analytics.ecosystem.trackEcosystem("app_select", { appName }),
3212
+ launchApp: (appName) => Analytics.ecosystem.trackEcosystem("app_launch", { appName }),
3213
+ addAppToShortcuts: (appName) => Analytics.ecosystem.trackEcosystem("add_shortcut", { appName })
3214
+ },
3215
+ settings: {
3216
+ trackSettings: (action, properties) => {
3217
+ trackEvent("Settings Flow", {
3218
+ action,
3219
+ ...properties,
3220
+ isError: !!properties?.error
3221
+ });
3222
+ },
3223
+ opened: (section) => Analytics.settings.trackSettings("view", { section }),
3224
+ accessAndSecurityViewed: () => Analytics.settings.trackSettings("security_view"),
3225
+ embeddedWalletViewed: () => Analytics.settings.trackSettings("embedded_wallet_view"),
3226
+ connectionDetailsViewed: () => Analytics.settings.trackSettings("connection_view"),
3227
+ manageSecuritySettings: () => Analytics.settings.trackSettings("manage_security_settings"),
3228
+ language: {
3229
+ changed: (language, previousLanguage) => Analytics.settings.trackSettings("language_changed", {
3230
+ language,
3231
+ previousLanguage
3232
+ })
3233
+ }
3234
+ },
3235
+ nameSelection: {
3236
+ trackNameSelection: (action, properties) => {
3237
+ trackEvent("Name Selection Flow", {
3238
+ action,
3239
+ ...properties,
3240
+ isError: !!properties?.error
3241
+ });
3242
+ },
3243
+ started: (source) => {
3244
+ Analytics.nameSelection.trackNameSelection(
3245
+ "name_selection_started",
3246
+ {
3247
+ source
3248
+ }
3249
+ );
3250
+ },
3251
+ completed: (name, isOwnDomain) => {
3252
+ Analytics.nameSelection.trackNameSelection(
3253
+ "name_selection_completed",
3254
+ {
3255
+ newName: name,
3256
+ isOwnDomain
3257
+ }
3258
+ );
3259
+ },
3260
+ dropOff: (stage, properties) => {
3261
+ Analytics.nameSelection.trackNameSelection(
3262
+ "name_selection_drop_off",
3263
+ {
3264
+ stage,
3265
+ ...properties
3266
+ }
3267
+ );
3268
+ },
3269
+ failed: (stage, properties) => {
3270
+ Analytics.nameSelection.trackNameSelection(
3271
+ "name_selection_failed",
3272
+ {
3273
+ stage,
3274
+ ...properties
3275
+ }
3276
+ );
3277
+ },
3278
+ retry: (stage) => {
3279
+ Analytics.nameSelection.trackNameSelection("name_selection_retry", {
3280
+ stage
3281
+ });
3282
+ },
3283
+ searched: (name, isAvailable) => {
3284
+ Analytics.nameSelection.trackNameSelection(
3285
+ "name_selection_searched",
3286
+ {
3287
+ newName: name,
3288
+ isAvailable
3289
+ }
3290
+ );
3291
+ }
3292
+ },
3293
+ notifications: {
3294
+ trackNotification: (action, properties) => {
3295
+ trackEvent("Notification Flow", {
3296
+ action,
3297
+ ...properties
3298
+ });
3299
+ },
3300
+ viewed: () => {
3301
+ Analytics.notifications.trackNotification("view");
3302
+ },
3303
+ cleared: (notificationType, count) => {
3304
+ Analytics.notifications.trackNotification("clear", {
3305
+ notificationType,
3306
+ totalCount: count
3307
+ });
3308
+ },
3309
+ archived: (notificationType) => {
3310
+ Analytics.notifications.trackNotification("archive", {
3311
+ notificationType
3312
+ });
3313
+ },
3314
+ toggleView: (viewType) => {
3315
+ Analytics.notifications.trackNotification("toggle_view", {
3316
+ viewType
3317
+ });
3318
+ },
3319
+ dismissed: (notificationType) => {
3320
+ Analytics.notifications.trackNotification("dismiss", {
3321
+ notificationType
3322
+ });
3323
+ }
3324
+ },
3325
+ help: {
3326
+ trackFAQ: (action, properties) => {
3327
+ trackEvent("FAQ Flow", {
3328
+ action,
3329
+ ...properties,
3330
+ isError: !!properties?.error
3331
+ });
3332
+ },
3333
+ pageViewed: () => Analytics.help.trackFAQ("view"),
3334
+ faqViewed: (faqId, faqTitle) => Analytics.help.trackFAQ("faq_opened", { faqId, faqTitle }),
3335
+ categorySelected: (category) => Analytics.help.trackFAQ("category_selected", { category }),
3336
+ questionExpanded: (faqId, faqTitle) => Analytics.help.trackFAQ("question_expanded", { faqId, faqTitle }),
3337
+ searchPerformed: (searchQuery, resultsCount) => Analytics.help.trackFAQ("search", { searchQuery, resultsCount })
3338
+ }
3339
+ };
2900
3340
  var useRefreshMetadata = (domain, address) => {
2901
3341
  const queryClient = useQueryClient();
2902
3342
  const { network } = useVeChainKitConfig();
@@ -3082,6 +3522,7 @@ var useClaimVeWorldSubdomain = ({
3082
3522
  network.type
3083
3523
  );
3084
3524
  refreshMetadata();
3525
+ Analytics.nameSelection.completed(subdomain, alreadyOwned);
3085
3526
  onSuccess?.();
3086
3527
  }, [
3087
3528
  onSuccess,
@@ -3100,7 +3541,9 @@ var useClaimVeWorldSubdomain = ({
3100
3541
  buttonText: "Sign to continue"
3101
3542
  },
3102
3543
  onTxConfirmed: handleOnSuccess,
3103
- onTxFailedOrCancelled: onError
3544
+ onTxFailedOrCancelled: () => {
3545
+ onError?.();
3546
+ }
3104
3547
  });
3105
3548
  return {
3106
3549
  ...result,
@@ -3263,27 +3706,200 @@ var useGetDomainsOfAddress = (address, parentDomain) => {
3263
3706
  enabled: !!address && !!network.type
3264
3707
  });
3265
3708
  };
3266
- var getAvatar = async (name, networkType) => {
3709
+ var nameInterface = new Interface([
3710
+ "function resolver(bytes32 node) returns (address resolverAddress)",
3711
+ "function text(bytes32 node, string key) returns (string avatar)"
3712
+ ]);
3713
+ var erc721Interface = new Interface([
3714
+ "function tokenURI(uint256 tokenId) view returns (string)",
3715
+ "function uri(uint256 id) view returns (string)"
3716
+ ]);
3717
+ var getAvatarLegacy = async (networkType, nodeUrl, name) => {
3267
3718
  if (!name) throw new Error("Name is required");
3719
+ const node = namehash(name);
3268
3720
  try {
3269
- const response = await fetch(
3270
- `${getConfig(networkType).vetDomainAvatarUrl}/${name}`
3721
+ const resolverResponse = await fetch(`${nodeUrl}/accounts/*`, {
3722
+ method: "POST",
3723
+ headers: {
3724
+ "content-type": "application/json"
3725
+ },
3726
+ body: JSON.stringify({
3727
+ clauses: [
3728
+ {
3729
+ to: getConfig(networkType).vetDomainsContractAddress,
3730
+ data: nameInterface.encodeFunctionData("resolver", [
3731
+ node
3732
+ ])
3733
+ }
3734
+ ]
3735
+ })
3736
+ });
3737
+ const [{ data: resolverData, reverted: noResolver }] = await resolverResponse.json();
3738
+ if (noResolver) {
3739
+ return null;
3740
+ }
3741
+ const { resolverAddress } = nameInterface.decodeFunctionResult(
3742
+ "resolver",
3743
+ resolverData
3271
3744
  );
3272
- if (!response.ok) {
3745
+ const avatarResponse = await fetch(`${nodeUrl}/accounts/*`, {
3746
+ method: "POST",
3747
+ headers: {
3748
+ "content-type": "application/json"
3749
+ },
3750
+ body: JSON.stringify({
3751
+ clauses: [
3752
+ {
3753
+ to: resolverAddress,
3754
+ data: nameInterface.encodeFunctionData("text", [
3755
+ node,
3756
+ "avatar"
3757
+ ])
3758
+ }
3759
+ ]
3760
+ })
3761
+ });
3762
+ const [{ data: lookupData, reverted: noLookup }] = await avatarResponse.json();
3763
+ if (noLookup || lookupData === "0x") {
3764
+ return null;
3765
+ }
3766
+ try {
3767
+ const { avatar } = nameInterface.decodeFunctionResult(
3768
+ "text",
3769
+ lookupData
3770
+ );
3771
+ const avatarRecord = avatar === "" ? null : avatar;
3772
+ if (!avatarRecord) return null;
3773
+ return parseAvatarRecord(avatarRecord, networkType, nodeUrl);
3774
+ } catch (decodeError) {
3775
+ console.error("Failed to decode avatar data:", decodeError);
3273
3776
  return null;
3274
3777
  }
3275
- const blob = await response.blob();
3778
+ } catch (error) {
3779
+ console.error("Error fetching avatar using legacy API:", error);
3780
+ throw error;
3781
+ }
3782
+ };
3783
+ var getAvatarLegacyQueryKey = (name, networkType) => ["VECHAIN_KIT", "VET_DOMAINS", "AVATAR", "LEGACY", name, networkType];
3784
+ async function parseAvatarRecord(record, networkType, nodeUrl) {
3785
+ try {
3786
+ if (record.startsWith("http") || record.startsWith("ipfs://") || record.startsWith("ar://")) {
3787
+ return convertUriToUrl(record, networkType) || null;
3788
+ }
3789
+ const match = record.match(
3790
+ /eip155:(\d+)\/(?:erc721|erc1155):([^/]+)\/(\d+)/
3791
+ );
3792
+ if (match) {
3793
+ const [, chainId, contractAddress, tokenId] = match;
3794
+ const isErc1155 = record.includes("erc1155");
3795
+ if (!chainId || !contractAddress || tokenId === void 0) {
3796
+ return null;
3797
+ }
3798
+ const clauses = [
3799
+ {
3800
+ to: contractAddress,
3801
+ data: erc721Interface.encodeFunctionData(
3802
+ isErc1155 ? "uri" : "tokenURI",
3803
+ [BigInt(tokenId)]
3804
+ )
3805
+ }
3806
+ ];
3807
+ const [{ data, reverted }] = await fetch(`${nodeUrl}/accounts/*`, {
3808
+ method: "POST",
3809
+ headers: {
3810
+ "content-type": "application/json"
3811
+ },
3812
+ body: JSON.stringify({ clauses })
3813
+ }).then((res) => res.json());
3814
+ if (reverted) {
3815
+ console.error("Failed to fetch tokenURI");
3816
+ return null;
3817
+ }
3818
+ let tokenUri = "";
3819
+ try {
3820
+ tokenUri = erc721Interface.decodeFunctionResult(
3821
+ isErc1155 ? "uri" : "tokenURI",
3822
+ data
3823
+ )[0];
3824
+ } catch (e) {
3825
+ console.error("Failed to decode avatar data:", e);
3826
+ tokenUri = toUtf8String(data);
3827
+ }
3828
+ tokenUri = convertUriToUrl(tokenUri, networkType) || tokenUri;
3829
+ if (isErc1155) {
3830
+ tokenUri = tokenUri.replace(
3831
+ "{id}",
3832
+ zeroPadValue(toBeHex(BigInt(tokenId)), 32).slice(2)
3833
+ );
3834
+ }
3835
+ const metadataResponse = await fetch(tokenUri);
3836
+ if (!metadataResponse.ok) {
3837
+ console.error("Failed to fetch metadata");
3838
+ return null;
3839
+ }
3840
+ const metadata = await metadataResponse.json();
3841
+ const imageUrl = metadata.image || metadata.image_url || metadata.image_data;
3842
+ if (!imageUrl) {
3843
+ console.error("No image URL in metadata");
3844
+ return null;
3845
+ }
3846
+ return convertUriToUrl(imageUrl, networkType) || imageUrl;
3847
+ }
3848
+ return null;
3849
+ } catch (error) {
3850
+ console.error("Error parsing avatar record:", error);
3851
+ return null;
3852
+ }
3853
+ }
3854
+ var useGetAvatarLegacy = (name) => {
3855
+ const { network } = useVeChainKitConfig();
3856
+ const nodeUrl = network.nodeUrl ?? getConfig(network.type).nodeUrl;
3857
+ const avatarQuery = useQuery({
3858
+ queryKey: getAvatarLegacyQueryKey(name ?? "", network.type),
3859
+ queryFn: async () => {
3860
+ if (!name) return null;
3861
+ return getAvatarLegacy(network.type, nodeUrl, name);
3862
+ },
3863
+ enabled: !!name && !!nodeUrl && !!network.type
3864
+ });
3865
+ return avatarQuery;
3866
+ };
3867
+
3868
+ // src/hooks/api/vetDomains/useGetAvatar.ts
3869
+ var getAvatar = async (name, network) => {
3870
+ if (!name) throw new Error("Name is required");
3871
+ const result = await fetchAvatar(name, network) || await fetchAvatarDirectly(name, network);
3872
+ if (!result) return null;
3873
+ if (result instanceof Blob) {
3276
3874
  return new Promise((resolve) => {
3277
3875
  const reader = new FileReader();
3278
- reader.readAsDataURL(blob);
3876
+ reader.readAsDataURL(result);
3279
3877
  reader.onloadend = () => {
3280
3878
  resolve(reader.result);
3281
3879
  };
3282
3880
  });
3881
+ }
3882
+ return result;
3883
+ };
3884
+ var fetchAvatar = async (name, network) => {
3885
+ try {
3886
+ const response = await fetch(
3887
+ `${getConfig(network.type).vetDomainAvatarUrl}/${name}`
3888
+ );
3889
+ if (response.ok) {
3890
+ return response.blob();
3891
+ }
3283
3892
  } catch (error) {
3284
3893
  console.error("Error fetching avatar:", error);
3285
- return null;
3286
3894
  }
3895
+ return null;
3896
+ };
3897
+ var fetchAvatarDirectly = async (name, network) => {
3898
+ const nodeUrl = network.nodeUrl ?? getConfig(network.type).nodeUrl;
3899
+ if (!nodeUrl) return null;
3900
+ const avatar = await getAvatarLegacy(network.type, nodeUrl, name);
3901
+ if (!avatar) return null;
3902
+ return avatar;
3287
3903
  };
3288
3904
  var getAvatarQueryKey = (name, networkType) => [
3289
3905
  "VECHAIN_KIT",
@@ -3298,13 +3914,13 @@ var useGetAvatar = (name) => {
3298
3914
  queryKey: getAvatarQueryKey(name ?? "", network.type),
3299
3915
  queryFn: async () => {
3300
3916
  if (!name) return null;
3301
- return getAvatar(name, network.type);
3917
+ return getAvatar(name, network);
3302
3918
  },
3303
3919
  enabled: !!name && !!network.type
3304
3920
  });
3305
3921
  return avatarQuery;
3306
3922
  };
3307
- var nameInterface = new Interface([
3923
+ var nameInterface2 = new Interface([
3308
3924
  "function resolver(bytes32 node) returns (address resolverAddress)",
3309
3925
  "function text(bytes32 node, string key) view returns (string)"
3310
3926
  ]);
@@ -3321,7 +3937,7 @@ var getTextRecords = async (nodeUrl, network, domain) => {
3321
3937
  clauses: [
3322
3938
  {
3323
3939
  to: getConfig(network).vetDomainsContractAddress,
3324
- data: nameInterface.encodeFunctionData("resolver", [
3940
+ data: nameInterface2.encodeFunctionData("resolver", [
3325
3941
  node
3326
3942
  ])
3327
3943
  }
@@ -3332,7 +3948,7 @@ var getTextRecords = async (nodeUrl, network, domain) => {
3332
3948
  if (noResolver) {
3333
3949
  return {};
3334
3950
  }
3335
- const { resolverAddress } = nameInterface.decodeFunctionResult(
3951
+ const { resolverAddress } = nameInterface2.decodeFunctionResult(
3336
3952
  "resolver",
3337
3953
  resolverData
3338
3954
  );
@@ -3344,7 +3960,7 @@ var getTextRecords = async (nodeUrl, network, domain) => {
3344
3960
  body: JSON.stringify({
3345
3961
  clauses: ENS_TEXT_RECORDS.map((key) => ({
3346
3962
  to: resolverAddress,
3347
- data: nameInterface.encodeFunctionData("text", [node, key])
3963
+ data: nameInterface2.encodeFunctionData("text", [node, key])
3348
3964
  }))
3349
3965
  })
3350
3966
  });
@@ -3353,7 +3969,7 @@ var getTextRecords = async (nodeUrl, network, domain) => {
3353
3969
  (acc, { data, reverted }, index) => {
3354
3970
  if (!reverted && data && data !== "0x") {
3355
3971
  try {
3356
- const value = nameInterface.decodeFunctionResult(
3972
+ const value = nameInterface2.decodeFunctionResult(
3357
3973
  "text",
3358
3974
  data
3359
3975
  )[0];
@@ -3503,7 +4119,9 @@ var useSendTransaction = ({
3503
4119
  setSendTransactionError(
3504
4120
  error2 instanceof Error ? error2.message : String(error2)
3505
4121
  );
3506
- onTxFailedOrCancelled?.();
4122
+ onTxFailedOrCancelled?.(
4123
+ error2 instanceof Error ? error2 : new Error(String(error2))
4124
+ );
3507
4125
  } finally {
3508
4126
  setSendTransactionPending(false);
3509
4127
  }
@@ -3610,7 +4228,7 @@ var useSendTransaction = ({
3610
4228
  };
3611
4229
 
3612
4230
  // src/hooks/api/vetDomains/useUpdateTextRecord.ts
3613
- var nameInterface2 = new Interface([
4231
+ var nameInterface3 = new Interface([
3614
4232
  "function resolver(bytes32 node) returns (address resolverAddress)",
3615
4233
  "function setText(bytes32 node, string key, string value) external"
3616
4234
  ]);
@@ -3630,7 +4248,7 @@ var useUpdateTextRecord = ({
3630
4248
  const node = namehash(domain);
3631
4249
  clauses.push({
3632
4250
  to: resolverAddress,
3633
- data: nameInterface2.encodeFunctionData("setText", [
4251
+ data: nameInterface3.encodeFunctionData("setText", [
3634
4252
  node,
3635
4253
  key,
3636
4254
  value
@@ -3645,9 +4263,11 @@ var useUpdateTextRecord = ({
3645
4263
  );
3646
4264
  const result = useSendTransaction({
3647
4265
  signerAccountAddress,
3648
- onTxConfirmed: onSuccess,
4266
+ onTxConfirmed: async () => {
4267
+ await onSuccess?.();
4268
+ },
3649
4269
  onTxFailedOrCancelled: async () => {
3650
- onError?.();
4270
+ await onError?.();
3651
4271
  },
3652
4272
  privyUIOptions: {
3653
4273
  title: "Update Profile Information",
@@ -3662,7 +4282,7 @@ var useUpdateTextRecord = ({
3662
4282
  }
3663
4283
  };
3664
4284
  };
3665
- var nameInterface3 = new Interface([
4285
+ var nameInterface4 = new Interface([
3666
4286
  "function resolver(bytes32 node) returns (address resolverAddress)"
3667
4287
  ]);
3668
4288
  var getResolverAddress = async (nodeUrl, network, domain) => {
@@ -3675,14 +4295,14 @@ var getResolverAddress = async (nodeUrl, network, domain) => {
3675
4295
  clauses: [
3676
4296
  {
3677
4297
  to: getConfig(network).vetDomainsContractAddress,
3678
- data: nameInterface3.encodeFunctionData("resolver", [node])
4298
+ data: nameInterface4.encodeFunctionData("resolver", [node])
3679
4299
  }
3680
4300
  ]
3681
4301
  })
3682
4302
  });
3683
4303
  const [{ data: resolverData, reverted: noResolver }] = await resolverResponse.json();
3684
4304
  if (noResolver) throw new Error("Failed to get resolver address");
3685
- const { resolverAddress } = nameInterface3.decodeFunctionResult(
4305
+ const { resolverAddress } = nameInterface4.decodeFunctionResult(
3686
4306
  "resolver",
3687
4307
  resolverData
3688
4308
  );
@@ -3725,164 +4345,6 @@ var useGetAvatarOfAddress = (address) => {
3725
4345
  enabled: !!address && domainsQuery.isSuccess && (primaryDomain ? avatarQuery.isSuccess : true)
3726
4346
  });
3727
4347
  };
3728
- var nameInterface4 = new Interface([
3729
- "function resolver(bytes32 node) returns (address resolverAddress)",
3730
- "function text(bytes32 node, string key) returns (string avatar)"
3731
- ]);
3732
- var erc721Interface = new Interface([
3733
- "function tokenURI(uint256 tokenId) view returns (string)",
3734
- "function uri(uint256 id) view returns (string)"
3735
- ]);
3736
- var getAvatarLegacy = async (networkType, nodeUrl, name) => {
3737
- if (!name) throw new Error("Name is required");
3738
- const node = namehash(name);
3739
- try {
3740
- const resolverResponse = await fetch(`${nodeUrl}/accounts/*`, {
3741
- method: "POST",
3742
- headers: {
3743
- "content-type": "application/json"
3744
- },
3745
- body: JSON.stringify({
3746
- clauses: [
3747
- {
3748
- to: getConfig(networkType).vetDomainsContractAddress,
3749
- data: nameInterface4.encodeFunctionData("resolver", [
3750
- node
3751
- ])
3752
- }
3753
- ]
3754
- })
3755
- });
3756
- const [{ data: resolverData, reverted: noResolver }] = await resolverResponse.json();
3757
- if (noResolver) {
3758
- return null;
3759
- }
3760
- const { resolverAddress } = nameInterface4.decodeFunctionResult(
3761
- "resolver",
3762
- resolverData
3763
- );
3764
- const avatarResponse = await fetch(`${nodeUrl}/accounts/*`, {
3765
- method: "POST",
3766
- headers: {
3767
- "content-type": "application/json"
3768
- },
3769
- body: JSON.stringify({
3770
- clauses: [
3771
- {
3772
- to: resolverAddress,
3773
- data: nameInterface4.encodeFunctionData("text", [
3774
- node,
3775
- "avatar"
3776
- ])
3777
- }
3778
- ]
3779
- })
3780
- });
3781
- const [{ data: lookupData, reverted: noLookup }] = await avatarResponse.json();
3782
- if (noLookup || lookupData === "0x") {
3783
- return null;
3784
- }
3785
- try {
3786
- const { avatar } = nameInterface4.decodeFunctionResult(
3787
- "text",
3788
- lookupData
3789
- );
3790
- const avatarRecord = avatar === "" ? null : avatar;
3791
- if (!avatarRecord) return null;
3792
- return parseAvatarRecord(avatarRecord, networkType, nodeUrl);
3793
- } catch (decodeError) {
3794
- console.error("Failed to decode avatar data:", decodeError);
3795
- return null;
3796
- }
3797
- } catch (error) {
3798
- console.error("Error fetching avatar:", error);
3799
- throw error;
3800
- }
3801
- };
3802
- var getAvatarLegacyQueryKey = (name, networkType) => ["VECHAIN_KIT", "VET_DOMAINS", "AVATAR", "LEGACY", name, networkType];
3803
- async function parseAvatarRecord(record, networkType, nodeUrl) {
3804
- try {
3805
- if (record.startsWith("http") || record.startsWith("ipfs://") || record.startsWith("ar://")) {
3806
- return convertUriToUrl(record, networkType) || null;
3807
- }
3808
- const match = record.match(
3809
- /eip155:(\d+)\/(?:erc721|erc1155):([^/]+)\/(\d+)/
3810
- );
3811
- if (match) {
3812
- const [, chainId, contractAddress, tokenId] = match;
3813
- const isErc1155 = record.includes("erc1155");
3814
- if (!chainId || !contractAddress || tokenId === void 0) {
3815
- return null;
3816
- }
3817
- const clauses = [
3818
- {
3819
- to: contractAddress,
3820
- data: erc721Interface.encodeFunctionData(
3821
- isErc1155 ? "uri" : "tokenURI",
3822
- [BigInt(tokenId)]
3823
- )
3824
- }
3825
- ];
3826
- const [{ data, reverted }] = await fetch(`${nodeUrl}/accounts/*`, {
3827
- method: "POST",
3828
- headers: {
3829
- "content-type": "application/json"
3830
- },
3831
- body: JSON.stringify({ clauses })
3832
- }).then((res) => res.json());
3833
- if (reverted) {
3834
- console.error("Failed to fetch tokenURI");
3835
- return null;
3836
- }
3837
- let tokenUri = "";
3838
- try {
3839
- tokenUri = erc721Interface.decodeFunctionResult(
3840
- isErc1155 ? "uri" : "tokenURI",
3841
- data
3842
- )[0];
3843
- } catch (e) {
3844
- console.error("Failed to decode avatar data:", e);
3845
- tokenUri = toUtf8String(data);
3846
- }
3847
- tokenUri = convertUriToUrl(tokenUri, networkType) || tokenUri;
3848
- if (isErc1155) {
3849
- tokenUri = tokenUri.replace(
3850
- "{id}",
3851
- zeroPadValue(toBeHex(BigInt(tokenId)), 32).slice(2)
3852
- );
3853
- }
3854
- const metadataResponse = await fetch(tokenUri);
3855
- if (!metadataResponse.ok) {
3856
- console.error("Failed to fetch metadata");
3857
- return null;
3858
- }
3859
- const metadata = await metadataResponse.json();
3860
- const imageUrl = metadata.image || metadata.image_url || metadata.image_data;
3861
- if (!imageUrl) {
3862
- console.error("No image URL in metadata");
3863
- return null;
3864
- }
3865
- return convertUriToUrl(imageUrl, networkType) || imageUrl;
3866
- }
3867
- return null;
3868
- } catch (error) {
3869
- console.error("Error parsing avatar record:", error);
3870
- return null;
3871
- }
3872
- }
3873
- var useGetAvatarLegacy = (name) => {
3874
- const { network } = useVeChainKitConfig();
3875
- const nodeUrl = network.nodeUrl ?? getConfig(network.type).nodeUrl;
3876
- const avatarQuery = useQuery({
3877
- queryKey: getAvatarLegacyQueryKey(name ?? "", network.type),
3878
- queryFn: async () => {
3879
- if (!name) return null;
3880
- return getAvatarLegacy(network.type, nodeUrl, name);
3881
- },
3882
- enabled: !!name && !!nodeUrl && !!network.type
3883
- });
3884
- return avatarQuery;
3885
- };
3886
4348
  var ReverseRegistrarInterface3 = IReverseRegistrar__factory.createInterface();
3887
4349
  var useUnsetDomain = ({
3888
4350
  onSuccess,
@@ -4064,6 +4526,17 @@ var useBalances = ({ address = "" }) => {
4064
4526
  customTokensLoading
4065
4527
  ]);
4066
4528
  };
4529
+
4530
+ // src/utils/StringUtils.ts
4531
+ var isRejectionError = (errorMessage) => {
4532
+ if (!errorMessage) return false;
4533
+ const rejectionTerms = ["rejected", "cancelled", "user denied", "closed"];
4534
+ return rejectionTerms.some(
4535
+ (term) => errorMessage.toLowerCase().includes(term.toLowerCase())
4536
+ );
4537
+ };
4538
+
4539
+ // src/utils/handlePopupError.ts
4067
4540
  var handlePopupError = ({
4068
4541
  error,
4069
4542
  mobileBrowserPopupMessage = "Mobile browser blocked the window. Please try again.",
@@ -4071,10 +4544,10 @@ var handlePopupError = ({
4071
4544
  defaultMessage = "Operation failed"
4072
4545
  }) => {
4073
4546
  const errorMsg = error?.message;
4074
- if (isMobile && !errorMsg?.includes("rejected")) {
4547
+ if (isMobile && errorMsg && !isRejectionError(errorMsg)) {
4075
4548
  return new Error(mobileBrowserPopupMessage);
4076
4549
  }
4077
- if (errorMsg?.includes("rejected") || errorMsg?.includes("closed")) {
4550
+ if (errorMsg && isRejectionError(errorMsg)) {
4078
4551
  return new Error(rejectedMessage);
4079
4552
  }
4080
4553
  return error instanceof Error ? error : new Error(defaultMessage);
@@ -4216,14 +4689,12 @@ var usePrivyCrossAppSdk = () => {
4216
4689
  // src/hooks/api/wallet/useWalletMetadata.ts
4217
4690
  var useWalletMetadata = (address, networkType) => {
4218
4691
  const { data: domain, isLoading: isLoadingVechainDomain } = useVechainDomain(address ?? "");
4219
- const { data: avatar, isLoading: isLoadingMetadata } = useGetAvatar(
4220
- domain?.domain ?? ""
4221
- );
4692
+ const { data: avatar, isLoading: isLoadingMetadata } = useGetAvatarOfAddress(address ?? "");
4222
4693
  const { data: textRecords, isLoading: isLoadingRecords } = useGetTextRecords(domain?.domain ?? "");
4223
4694
  const headerUrl = textRecords?.header ? convertUriToUrl(textRecords.header, networkType) : null;
4224
4695
  return {
4225
4696
  domain: domain?.domain,
4226
- image: avatar ?? getPicassoImage(address ?? ""),
4697
+ image: avatar,
4227
4698
  records: {
4228
4699
  ...textRecords,
4229
4700
  header: headerUrl
@@ -5399,7 +5870,8 @@ var AddressDisplay = ({
5399
5870
  wallet,
5400
5871
  label,
5401
5872
  style,
5402
- showHumanAddress = true
5873
+ showHumanAddress = true,
5874
+ fromScreen
5403
5875
  }) => {
5404
5876
  const [copied, setCopied] = useState(false);
5405
5877
  const [copiedDomain, setCopiedDomain] = useState(false);
@@ -5409,6 +5881,7 @@ var AddressDisplay = ({
5409
5881
  setTimeout(() => {
5410
5882
  setCopied2(false);
5411
5883
  }, 2e3);
5884
+ Analytics.user.profile.addressCopied(fromScreen);
5412
5885
  };
5413
5886
  return /* @__PURE__ */ jsx(VStack, { w: "full", justifyContent: "center", ...style, children: /* @__PURE__ */ jsxs(VStack, { w: "full", spacing: 4, children: [
5414
5887
  label && /* @__PURE__ */ jsx(Text, { fontSize: "sm", opacity: 0.7, children: label }),
@@ -5510,7 +5983,7 @@ var AddressDisplay = ({
5510
5983
  // package.json
5511
5984
  var package_default = {
5512
5985
  name: "@vechain/vechain-kit",
5513
- version: "1.5.13",
5986
+ version: "1.6.0",
5514
5987
  private: false,
5515
5988
  homepage: "https://github.com/vechain/vechain-kit",
5516
5989
  repository: "github:vechain/vechain-kit",
@@ -5536,9 +6009,10 @@ var package_default = {
5536
6009
  dependencies: {
5537
6010
  "@chakra-ui/react": "^2.8.2",
5538
6011
  "@choc-ui/chakra-autocomplete": "^5.3.0",
5539
- "@privy-io/cross-app-connect": "0.1.8-beta-20250228192559",
5540
- "@privy-io/react-auth": "2.4.5",
6012
+ "@privy-io/cross-app-connect": "0.1.8",
6013
+ "@privy-io/react-auth": "2.8.0",
5541
6014
  "@rainbow-me/rainbowkit": "^2.1.5",
6015
+ "@solana/web3.js": "^1.98.0",
5542
6016
  "@tanstack/react-query": "^5.64.2",
5543
6017
  "@tanstack/react-query-devtools": "^5.64.1",
5544
6018
  "@vechain/dapp-kit-react": "1.5.0",
@@ -5557,6 +6031,7 @@ var package_default = {
5557
6031
  "https-browserify": "^1.0.0",
5558
6032
  i18next: "^24.2.1",
5559
6033
  "i18next-browser-languagedetector": "^8.0.2",
6034
+ "mixpanel-browser": "^2.61.1",
5560
6035
  net: "^1.0.2",
5561
6036
  process: "^0.11.10",
5562
6037
  react: "^18.2.0",
@@ -5572,6 +6047,7 @@ var package_default = {
5572
6047
  wagmi: "^2.13.4"
5573
6048
  },
5574
6049
  devDependencies: {
6050
+ "@types/mixpanel-browser": "^2.51.0",
5575
6051
  "@types/react": "^18.2.28",
5576
6052
  "@types/react-dom": "^18.2.13",
5577
6053
  "cross-env": "^7.0.3",
@@ -5970,8 +6446,15 @@ var AccountAvatar = ({ wallet, props }) => {
5970
6446
  previousImageRef.current = wallet.image;
5971
6447
  }
5972
6448
  }, [wallet?.image, wallet?.isLoadingMetadata]);
5973
- if (wallet?.isLoadingMetadata && !previousImageRef.current) {
5974
- return /* @__PURE__ */ jsx(Spinner, { size: "sm" });
6449
+ if (!props?.src && !wallet?.image && !previousImageRef.current || wallet?.isLoadingMetadata) {
6450
+ return /* @__PURE__ */ jsx(
6451
+ Skeleton,
6452
+ {
6453
+ rounded: "full",
6454
+ width: props?.width,
6455
+ height: props?.height
6456
+ }
6457
+ );
5975
6458
  }
5976
6459
  return /* @__PURE__ */ jsx(
5977
6460
  Image,
@@ -5980,7 +6463,6 @@ var AccountAvatar = ({ wallet, props }) => {
5980
6463
  alt: props?.alt || wallet?.domain,
5981
6464
  objectFit: "cover",
5982
6465
  rounded: "full",
5983
- fallbackSrc: getPicassoImage(wallet?.address ?? ""),
5984
6466
  ...props
5985
6467
  }
5986
6468
  );
@@ -5990,12 +6472,14 @@ var TransactionButtonAndStatus = ({
5990
6472
  isSubmitting,
5991
6473
  isTxWaitingConfirmation,
5992
6474
  onConfirm,
6475
+ onRetry,
5993
6476
  transactionPendingText,
5994
6477
  txReceipt,
5995
6478
  isSubmitForm = false,
5996
6479
  buttonText,
5997
6480
  isDisabled = false,
5998
- style
6481
+ style,
6482
+ onError
5999
6483
  }) => {
6000
6484
  const { t } = useTranslation();
6001
6485
  const { darkMode: isDark } = useVeChainKitConfig();
@@ -6004,6 +6488,11 @@ var TransactionButtonAndStatus = ({
6004
6488
  if (!transactionError) return null;
6005
6489
  return transactionError.reason || t("Something went wrong. Please try again.");
6006
6490
  }, [transactionError, t]);
6491
+ useEffect(() => {
6492
+ if (errorMessage) {
6493
+ onError?.(errorMessage);
6494
+ }
6495
+ }, [errorMessage, onError]);
6007
6496
  const buttonBg = useMemo(() => {
6008
6497
  if (style?.accentColor) return `${style.accentColor} !important`;
6009
6498
  return void 0;
@@ -6016,7 +6505,7 @@ var TransactionButtonAndStatus = ({
6016
6505
  px: 4,
6017
6506
  variant: "vechainKitPrimary",
6018
6507
  bg: buttonBg,
6019
- onClick: onConfirm,
6508
+ onClick: () => errorMessage && onRetry ? onRetry() : onConfirm(),
6020
6509
  type: isSubmitForm ? "submit" : "button",
6021
6510
  isLoading: isSubmitting,
6022
6511
  isDisabled,
@@ -6230,6 +6719,8 @@ var EmailLoginButton = () => {
6230
6719
  const { sendCode, state: emailState } = useLoginWithEmail({});
6231
6720
  const emailCodeVerificationModal = useDisclosure();
6232
6721
  const handleSendCode = async () => {
6722
+ Analytics.auth.flowStarted("email" /* EMAIL */);
6723
+ Analytics.auth.methodSelected("email" /* EMAIL */);
6233
6724
  await sendCode({ email });
6234
6725
  emailCodeVerificationModal.onOpen();
6235
6726
  };
@@ -6307,9 +6798,13 @@ var LoginWithGoogleButton = ({ isDark, gridColumn }) => {
6307
6798
  ConnectionButton,
6308
6799
  {
6309
6800
  isDark,
6310
- onClick: () => initOAuth({
6311
- provider: "google"
6312
- }),
6801
+ onClick: () => {
6802
+ Analytics.auth.flowStarted("google" /* GOOGLE */);
6803
+ Analytics.auth.methodSelected("google" /* GOOGLE */);
6804
+ initOAuth({
6805
+ provider: "google"
6806
+ });
6807
+ },
6313
6808
  icon: FcGoogle,
6314
6809
  text: t("Continue with Google")
6315
6810
  }
@@ -6336,6 +6831,7 @@ var VeChainLoginButton = ({ isDark, gridColumn }) => {
6336
6831
  const [loginError, setLoginError] = useState();
6337
6832
  const loginLoadingModal = useDisclosure();
6338
6833
  const handleLoginWithVeChain = async () => {
6834
+ Analytics.auth.flowStarted("vechain" /* VECHAIN */);
6339
6835
  loginLoadingModal.onOpen();
6340
6836
  try {
6341
6837
  setLoginError(void 0);
@@ -6348,6 +6844,10 @@ var VeChainLoginButton = ({ isDark, gridColumn }) => {
6348
6844
  );
6349
6845
  }
6350
6846
  };
6847
+ const tryAgain = () => {
6848
+ Analytics.auth.tryAgain("vechain" /* VECHAIN */);
6849
+ handleLoginWithVeChain();
6850
+ };
6351
6851
  return /* @__PURE__ */ jsxs(Fragment, { children: [
6352
6852
  /* @__PURE__ */ jsx(GridItem, { colSpan: gridColumn ? gridColumn : 4, w: "full", children: /* @__PURE__ */ jsx(
6353
6853
  ConnectionButton,
@@ -6367,7 +6867,7 @@ var VeChainLoginButton = ({ isDark, gridColumn }) => {
6367
6867
  onClose: () => {
6368
6868
  loginLoadingModal.onClose();
6369
6869
  },
6370
- onTryAgain: handleLoginWithVeChain,
6870
+ onTryAgain: tryAgain,
6371
6871
  error: loginError,
6372
6872
  title: t("Connecting to VeChain"),
6373
6873
  loadingText: t(
@@ -6383,18 +6883,32 @@ var PasskeyLoginButton = ({ isDark, gridColumn }) => {
6383
6883
  const [loginError, setLoginError] = useState();
6384
6884
  const loginLoadingModal = useDisclosure();
6385
6885
  const handleLoginWithPasskey = async () => {
6886
+ Analytics.auth.flowStarted("passkey" /* PASSKEY */);
6887
+ Analytics.auth.methodSelected("passkey" /* PASSKEY */);
6386
6888
  loginLoadingModal.onOpen();
6387
6889
  try {
6388
6890
  setLoginError(void 0);
6389
6891
  await loginWithPasskey();
6390
6892
  loginLoadingModal.onClose();
6391
6893
  } catch (error) {
6894
+ const errorMsg = error instanceof Error ? error.message.toLowerCase() : "";
6895
+ if (errorMsg.includes("not found")) {
6896
+ Analytics.auth.dropOff("passkey-prompt");
6897
+ } else if (errorMsg.includes("abort")) {
6898
+ Analytics.auth.dropOff("passkey-authentication");
6899
+ } else {
6900
+ Analytics.auth.failed("passkey" /* PASSKEY */, errorMsg);
6901
+ }
6392
6902
  console.error(error);
6393
6903
  setLoginError(
6394
6904
  error instanceof Error ? error.message : t("Failed to connect with Passkey")
6395
6905
  );
6396
6906
  }
6397
6907
  };
6908
+ const handleTryAgain = () => {
6909
+ Analytics.auth.tryAgain("passkey" /* PASSKEY */);
6910
+ handleLoginWithPasskey();
6911
+ };
6398
6912
  return /* @__PURE__ */ jsxs(Fragment, { children: [
6399
6913
  /* @__PURE__ */ jsx(GridItem, { colSpan: gridColumn, w: "full", children: /* @__PURE__ */ jsx(
6400
6914
  ConnectionButton,
@@ -6415,55 +6929,82 @@ var PasskeyLoginButton = ({ isDark, gridColumn }) => {
6415
6929
  error: loginError,
6416
6930
  title: t("Connecting with Passkey"),
6417
6931
  loadingText: t("Please complete the passkey authentication..."),
6418
- onTryAgain: handleLoginWithPasskey
6932
+ onTryAgain: handleTryAgain
6419
6933
  }
6420
6934
  )
6421
6935
  ] });
6422
6936
  };
6423
6937
  var DappKitButton = ({ isDark, gridColumn = 2 }) => {
6424
6938
  const { t } = useTranslation();
6425
- const { open: openDappKitModal } = useWalletModal();
6939
+ const { open: openDappKitModal, onConnectionStatusChange } = useWalletModal();
6940
+ const { dappKit } = useVeChainKitConfig();
6941
+ const { user } = usePrivy();
6942
+ const { source } = useWallet$1();
6943
+ const buttonText = !dappKit?.allowedWallets?.includes("sync2") ? "Connect with VeWorld wallet" : t("Connect wallet");
6944
+ useEffect(() => {
6945
+ const handleConnectionChange = (address, error) => {
6946
+ if (!address) {
6947
+ if (error?.message) {
6948
+ const errorMsg = error.message.toLowerCase();
6949
+ if (errorMsg.includes("veworld")) {
6950
+ return Analytics.auth.dropOff("dappkit-veworld", {
6951
+ ...source && { source }
6952
+ });
6953
+ }
6954
+ if (errorMsg.includes("sync2")) {
6955
+ return Analytics.auth.dropOff("dappkit-sync2", {
6956
+ ...source && { source }
6957
+ });
6958
+ }
6959
+ if (errorMsg.includes("wallet-connect")) {
6960
+ return Analytics.auth.dropOff(
6961
+ "dappkit-wallet-connect",
6962
+ {
6963
+ ...source && { source }
6964
+ }
6965
+ );
6966
+ }
6967
+ if (errorMsg && isRejectionError(errorMsg)) {
6968
+ return Analytics.auth.dropOff("dappkit-view", {
6969
+ ...source && { source }
6970
+ });
6971
+ }
6972
+ }
6973
+ return Analytics.auth.dropOff("dappkit-view", {
6974
+ ...source && { source }
6975
+ });
6976
+ } else {
6977
+ Analytics.auth.completed({
6978
+ loginMethod: "dappkit" /* DAPPKIT */
6979
+ });
6980
+ }
6981
+ };
6982
+ onConnectionStatusChange(handleConnectionChange);
6983
+ }, [onConnectionStatusChange]);
6984
+ const handleDappKitClick = () => {
6985
+ Analytics.auth.flowStarted("dappkit" /* DAPPKIT */);
6986
+ Analytics.auth.methodSelected("dappkit" /* DAPPKIT */);
6987
+ openDappKitModal();
6988
+ if (source) {
6989
+ Analytics.auth.completed({
6990
+ userId: user?.id,
6991
+ loginMethod: "dappkit" /* DAPPKIT */,
6992
+ platform: source
6993
+ });
6994
+ }
6995
+ };
6426
6996
  return /* @__PURE__ */ jsx(GridItem, { colSpan: gridColumn ? gridColumn : 2, w: "full", children: /* @__PURE__ */ jsx(
6427
6997
  ConnectionButton,
6428
6998
  {
6429
6999
  isDark,
6430
- onClick: openDappKitModal,
6431
- icon: IoWalletOutline,
6432
- text: gridColumn >= 2 ? t("Connect wallet") : void 0,
6433
- rightIcon: /* @__PURE__ */ jsx(Icon, { as: IoIosArrowForward })
7000
+ onClick: handleDappKitClick,
7001
+ icon: !dappKit?.allowedWallets?.includes("sync2") ? isDark ? VeWorldLogoLight : VeWorldLogoDark : IoWalletOutline,
7002
+ iconWidth: "27px",
7003
+ text: gridColumn >= 2 ? buttonText : void 0,
7004
+ rightIcon: dappKit?.allowedWallets?.includes("sync2") && /* @__PURE__ */ jsx(Icon, { as: IoIosArrowForward }) || void 0
6434
7005
  }
6435
7006
  ) });
6436
7007
  };
6437
- var EcosystemButton = ({
6438
- isDark,
6439
- appsInfo,
6440
- isLoading,
6441
- gridColumn
6442
- }) => {
6443
- const { t } = useTranslation();
6444
- const ecosystemModal = useDisclosure();
6445
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6446
- /* @__PURE__ */ jsx(GridItem, { colSpan: gridColumn, w: "full", children: /* @__PURE__ */ jsx(
6447
- ConnectionButton,
6448
- {
6449
- isDark,
6450
- onClick: ecosystemModal.onOpen,
6451
- icon: AiOutlineUser,
6452
- text: gridColumn && gridColumn >= 2 ? t("Other options") : void 0,
6453
- rightIcon: /* @__PURE__ */ jsx(Icon, { as: IoIosArrowForward })
6454
- }
6455
- ) }),
6456
- /* @__PURE__ */ jsx(
6457
- EcosystemModal,
6458
- {
6459
- isOpen: ecosystemModal.isOpen,
6460
- onClose: ecosystemModal.onClose,
6461
- appsInfo,
6462
- isLoading
6463
- }
6464
- )
6465
- ] });
6466
- };
6467
7008
  var PrivyButton = ({ isDark, onViewMoreLogin, gridColumn }) => {
6468
7009
  const { t } = useTranslation();
6469
7010
  return /* @__PURE__ */ jsx(GridItem, { colSpan: gridColumn, w: "full", children: /* @__PURE__ */ jsx(
@@ -6478,11 +7019,7 @@ var PrivyButton = ({ isDark, onViewMoreLogin, gridColumn }) => {
6478
7019
  ) });
6479
7020
  };
6480
7021
  var ConnectionOptionsStack = () => {
6481
- const {
6482
- privyEcosystemAppIDS,
6483
- loginMethods,
6484
- darkMode: isDark
6485
- } = useVeChainKitConfig();
7022
+ const { loginMethods, darkMode: isDark } = useVeChainKitConfig();
6486
7023
  const { login: viewMoreLogin } = usePrivy();
6487
7024
  const {
6488
7025
  showGoogleLogin,
@@ -6490,11 +7027,9 @@ var ConnectionOptionsStack = () => {
6490
7027
  showPasskey,
6491
7028
  showVeChainLogin,
6492
7029
  showDappKit,
6493
- showEcosystem,
6494
7030
  showMoreLogin,
6495
7031
  isOfficialVeChainApp
6496
7032
  } = useLoginModalContent();
6497
- const { data: appsInfo, isLoading: isEcosystemAppsLoading } = useFetchAppInfo(privyEcosystemAppIDS);
6498
7033
  return /* @__PURE__ */ jsx(Stack, { spacing: 4, w: "full", align: "center", children: /* @__PURE__ */ jsx(Grid, { templateColumns: "repeat(4, 1fr)", gap: 2, w: "full", children: loginMethods?.map(({ method: method35, gridColumn }) => {
6499
7034
  switch (method35) {
6500
7035
  case "email":
@@ -6542,17 +7077,6 @@ var ConnectionOptionsStack = () => {
6542
7077
  },
6543
7078
  "dappkit"
6544
7079
  );
6545
- case "ecosystem":
6546
- return showEcosystem && /* @__PURE__ */ jsx(
6547
- EcosystemButton,
6548
- {
6549
- isDark,
6550
- appsInfo: Object.values(appsInfo || {}),
6551
- isLoading: isEcosystemAppsLoading,
6552
- gridColumn
6553
- },
6554
- "ecosystem"
6555
- );
6556
7080
  case "more":
6557
7081
  return showMoreLogin && /* @__PURE__ */ jsx(
6558
7082
  PrivyButton,
@@ -6568,19 +7092,57 @@ var ConnectionOptionsStack = () => {
6568
7092
  }
6569
7093
  }) }) });
6570
7094
  };
7095
+ var EcosystemButton = ({ appsInfo, isLoading }) => {
7096
+ const { t } = useTranslation();
7097
+ const ecosystemModal = useDisclosure();
7098
+ const handleEcosystemClick = () => {
7099
+ Analytics.auth.flowStarted("ecosystem" /* ECOSYSTEM */);
7100
+ Analytics.auth.methodSelected("ecosystem" /* ECOSYSTEM */);
7101
+ ecosystemModal.onOpen();
7102
+ };
7103
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
7104
+ /* @__PURE__ */ jsx(
7105
+ Button,
7106
+ {
7107
+ fontSize: "sm",
7108
+ variant: "link",
7109
+ onClick: handleEcosystemClick,
7110
+ children: t("Already have an x2earn app wallet?")
7111
+ }
7112
+ ),
7113
+ /* @__PURE__ */ jsx(
7114
+ EcosystemModal,
7115
+ {
7116
+ isOpen: ecosystemModal.isOpen,
7117
+ onClose: ecosystemModal.onClose,
7118
+ appsInfo,
7119
+ isLoading
7120
+ }
7121
+ )
7122
+ ] });
7123
+ };
6571
7124
  var MainContent = ({ setCurrentContent, onClose }) => {
6572
7125
  const { t } = useTranslation();
6573
7126
  const { darkMode: isDark } = useVeChainKitConfig();
6574
7127
  const { connection } = useWallet();
6575
7128
  const { loginModalUI } = useVeChainKitConfig();
7129
+ const { loginMethods, privyEcosystemAppIDS } = useVeChainKitConfig();
7130
+ const { data: appsInfo, isLoading: isEcosystemAppsLoading } = useFetchAppInfo(privyEcosystemAppIDS);
7131
+ const handleFAQClick = () => {
7132
+ Analytics.help.faqViewed();
7133
+ setCurrentContent("faq");
7134
+ };
6576
7135
  useEffect(() => {
6577
7136
  if (connection.isConnected) {
6578
7137
  onClose();
6579
7138
  }
6580
7139
  }, [connection.isConnected, onClose]);
7140
+ const showEcosystemButton = loginMethods?.some(
7141
+ ({ method: method35 }) => method35 === "ecosystem"
7142
+ );
6581
7143
  return /* @__PURE__ */ jsxs(Fragment, { children: [
6582
7144
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
6583
- /* @__PURE__ */ jsx(ModalFAQButton, { onClick: () => setCurrentContent("faq") }),
7145
+ /* @__PURE__ */ jsx(ModalFAQButton, { onClick: handleFAQClick }),
6584
7146
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Log in or sign up") }),
6585
7147
  /* @__PURE__ */ jsx(ModalCloseButton, {})
6586
7148
  ] }),
@@ -6616,7 +7178,14 @@ var MainContent = ({ setCurrentContent, onClose }) => {
6616
7178
  ),
6617
7179
  /* @__PURE__ */ jsx(ConnectionOptionsStack, {})
6618
7180
  ] }),
6619
- /* @__PURE__ */ jsx(ModalFooter, { pt: 0, pb: "5px", children: /* @__PURE__ */ jsx(VersionFooter, {}) })
7181
+ showEcosystemButton ? /* @__PURE__ */ jsx(ModalFooter, { children: /* @__PURE__ */ jsx(HStack, { justify: "center", w: "full", children: /* @__PURE__ */ jsx(
7182
+ EcosystemButton,
7183
+ {
7184
+ isDark,
7185
+ appsInfo: Object.values(appsInfo || {}),
7186
+ isLoading: isEcosystemAppsLoading
7187
+ }
7188
+ ) }) }) : /* @__PURE__ */ jsx(ModalFooter, { pt: 0, pb: "5px" })
6620
7189
  ] });
6621
7190
  };
6622
7191
  var AccountMainContent = ({ setCurrentContent, wallet }) => {
@@ -7028,6 +7597,7 @@ var BalanceSection = ({
7028
7597
  const { refresh } = useRefreshBalances();
7029
7598
  const [isRefreshing, setIsRefreshing] = useState(false);
7030
7599
  const handleRefresh = async () => {
7600
+ Analytics.wallet.balanceRefreshed();
7031
7601
  setIsRefreshing(true);
7032
7602
  await refresh();
7033
7603
  setTimeout(() => {
@@ -7221,12 +7791,18 @@ var QUICK_ACTIONS = [
7221
7791
  {
7222
7792
  icon: MdSwapHoriz,
7223
7793
  label: "Swap",
7224
- onClick: (setCurrentContent) => setCurrentContent("swap-token")
7794
+ onClick: (setCurrentContent) => {
7795
+ Analytics.swap.opened();
7796
+ setCurrentContent("swap-token");
7797
+ }
7225
7798
  },
7226
7799
  {
7227
7800
  icon: LuArrowDownToLine,
7228
7801
  label: "Receive",
7229
- onClick: (setCurrentContent) => setCurrentContent("receive-token")
7802
+ onClick: (setCurrentContent) => {
7803
+ Analytics.wallet.trackWallet("receive_qr_generated");
7804
+ setCurrentContent("receive-token");
7805
+ }
7230
7806
  },
7231
7807
  {
7232
7808
  icon: FiSend,
@@ -7243,17 +7819,26 @@ var QUICK_ACTIONS = [
7243
7819
  {
7244
7820
  icon: RiSwap3Line,
7245
7821
  label: "Bridge",
7246
- onClick: (setCurrentContent) => setCurrentContent("bridge")
7822
+ onClick: (setCurrentContent) => {
7823
+ Analytics.bridge.opened();
7824
+ setCurrentContent("bridge");
7825
+ }
7247
7826
  },
7248
7827
  {
7249
7828
  icon: IoMdApps,
7250
7829
  label: "Ecosystem",
7251
- onClick: (setCurrentContent) => setCurrentContent("ecosystem")
7830
+ onClick: (setCurrentContent) => {
7831
+ Analytics.ecosystem.opened();
7832
+ setCurrentContent("ecosystem");
7833
+ }
7252
7834
  },
7253
7835
  {
7254
7836
  icon: IoMdSettings,
7255
7837
  label: "Settings",
7256
- onClick: (setCurrentContent) => setCurrentContent("settings")
7838
+ onClick: (setCurrentContent) => {
7839
+ Analytics.settings.opened("general");
7840
+ setCurrentContent("settings");
7841
+ }
7257
7842
  }
7258
7843
  ];
7259
7844
  var QuickActionButton = ({
@@ -7521,6 +8106,7 @@ var CrossAppConnectionSecurityCard = () => {
7521
8106
  variant: "vechainKitSecondary",
7522
8107
  w: "full",
7523
8108
  onClick: () => {
8109
+ Analytics.settings.manageSecuritySettings();
7524
8110
  window.open(
7525
8111
  connectionCache?.ecosystemApp.website ?? "https://governance.vebetterdao.org/",
7526
8112
  "_blank"
@@ -7547,6 +8133,15 @@ var AccessAndSecurityContent = ({ setCurrentContent }) => {
7547
8133
  connectedWallet?.address ?? "",
7548
8134
  3
7549
8135
  );
8136
+ const handleUpgradeSmartAccountClick = () => {
8137
+ setCurrentContent({
8138
+ type: "upgrade-smart-account",
8139
+ props: {
8140
+ setCurrentContent,
8141
+ initialContent: "access-and-security"
8142
+ }
8143
+ });
8144
+ };
7550
8145
  return /* @__PURE__ */ jsxs(ScrollToTopWrapper, { children: [
7551
8146
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
7552
8147
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Access and security") }),
@@ -7584,15 +8179,7 @@ var AccessAndSecurityContent = ({ setCurrentContent }) => {
7584
8179
  description: t(
7585
8180
  "A new version is available for your account"
7586
8181
  ),
7587
- onClick: () => {
7588
- setCurrentContent({
7589
- type: "upgrade-smart-account",
7590
- props: {
7591
- setCurrentContent,
7592
- initialContent: "access-and-security"
7593
- }
7594
- });
7595
- },
8182
+ onClick: handleUpgradeSmartAccountClick,
7596
8183
  leftIcon: IoCogSharp,
7597
8184
  extraContent: /* @__PURE__ */ jsx(
7598
8185
  Box,
@@ -7614,6 +8201,7 @@ var AccessAndSecurityContent = ({ setCurrentContent }) => {
7614
8201
  {
7615
8202
  title: t("Your embedded wallet"),
7616
8203
  onClick: () => {
8204
+ Analytics.settings.embeddedWalletViewed();
7617
8205
  setCurrentContent("embedded-wallet");
7618
8206
  },
7619
8207
  leftIcon: HiOutlineWallet,
@@ -7891,7 +8479,7 @@ var SettingsContent = ({
7891
8479
  const contentRef = useRef(null);
7892
8480
  const { t } = useTranslation();
7893
8481
  const { privy } = useVeChainKitConfig();
7894
- const { connection, disconnect, account, smartAccount, connectedWallet } = useWallet();
8482
+ const { connection, disconnect, smartAccount, connectedWallet, account } = useWallet();
7895
8483
  const { getConnectionCache } = useCrossAppConnectionCache();
7896
8484
  const connectionCache = getConnectionCache();
7897
8485
  const { data: appInfo } = useFetchAppInfo(privy?.appId ?? "");
@@ -7908,6 +8496,51 @@ var SettingsContent = ({
7908
8496
  contentRef.current.scrollTop = 0;
7909
8497
  }
7910
8498
  }, []);
8499
+ const handleCustomizeProfile = () => {
8500
+ Analytics.customization.started();
8501
+ setCurrentContent({
8502
+ type: "account-customization",
8503
+ props: {
8504
+ setCurrentContent,
8505
+ initialContentSource: "settings"
8506
+ }
8507
+ });
8508
+ };
8509
+ const handleNameChange = () => {
8510
+ Analytics.nameSelection.started("settings");
8511
+ if (account?.domain) {
8512
+ setCurrentContent({
8513
+ type: "choose-name-search",
8514
+ props: {
8515
+ name: "",
8516
+ setCurrentContent,
8517
+ initialContentSource: "settings"
8518
+ }
8519
+ });
8520
+ } else {
8521
+ setCurrentContent({
8522
+ type: "choose-name",
8523
+ props: {
8524
+ setCurrentContent,
8525
+ initialContentSource: "settings",
8526
+ onBack: () => setCurrentContent("settings")
8527
+ }
8528
+ });
8529
+ }
8530
+ };
8531
+ const handleAccessAndSecurity = () => {
8532
+ setCurrentContent("access-and-security");
8533
+ Analytics.settings.accessAndSecurityViewed();
8534
+ };
8535
+ const handleConnectionDetails = () => {
8536
+ setCurrentContent("connection-details");
8537
+ Analytics.settings.connectionDetailsViewed();
8538
+ };
8539
+ const handleLogout = () => {
8540
+ Analytics.auth.trackAuth("disconnect_initiated");
8541
+ disconnect();
8542
+ onLogoutSuccess();
8543
+ };
7911
8544
  return /* @__PURE__ */ jsxs(Box, { children: [
7912
8545
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
7913
8546
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Settings") }),
@@ -7915,36 +8548,39 @@ var SettingsContent = ({
7915
8548
  /* @__PURE__ */ jsx(ModalCloseButton, {})
7916
8549
  ] }),
7917
8550
  /* @__PURE__ */ jsx(ModalBody, { w: "full", children: /* @__PURE__ */ jsxs(VStack, { w: "full", spacing: 0, children: [
8551
+ /* @__PURE__ */ jsx(
8552
+ Heading,
8553
+ {
8554
+ size: "xs",
8555
+ fontWeight: "500",
8556
+ w: "full",
8557
+ opacity: 0.5,
8558
+ children: t("Wallet")
8559
+ }
8560
+ ),
7918
8561
  /* @__PURE__ */ jsx(
7919
8562
  ActionButton,
7920
8563
  {
7921
8564
  style: {
7922
8565
  marginTop: "10px",
8566
+ borderBottomRadius: "0px"
8567
+ },
8568
+ title: t("Customize profile"),
8569
+ onClick: handleCustomizeProfile,
8570
+ leftIcon: CgProfile,
8571
+ rightIcon: MdOutlineNavigateNext
8572
+ }
8573
+ ),
8574
+ /* @__PURE__ */ jsx(
8575
+ ActionButton,
8576
+ {
8577
+ style: {
8578
+ borderTopRadius: "0px",
7923
8579
  borderBottomRadius: connection.isConnectedWithPrivy ? "0px" : "12px"
7924
8580
  },
7925
8581
  title: t("Choose account name"),
7926
8582
  description: t("Choose a name for your account."),
7927
- onClick: () => {
7928
- if (account?.domain) {
7929
- setCurrentContent({
7930
- type: "choose-name-search",
7931
- props: {
7932
- name: "",
7933
- setCurrentContent,
7934
- initialContentSource: "settings"
7935
- }
7936
- });
7937
- } else {
7938
- setCurrentContent({
7939
- type: "choose-name",
7940
- props: {
7941
- setCurrentContent,
7942
- initialContentSource: "settings",
7943
- onBack: () => setCurrentContent("settings")
7944
- }
7945
- });
7946
- }
7947
- },
8583
+ onClick: handleNameChange,
7948
8584
  leftIcon: FaRegAddressCard,
7949
8585
  rightIcon: MdOutlineNavigateNext
7950
8586
  }
@@ -7959,9 +8595,7 @@ var SettingsContent = ({
7959
8595
  description: t(
7960
8596
  "Manage your embedded wallet security settings or back it up to a new device."
7961
8597
  ),
7962
- onClick: () => {
7963
- setCurrentContent("access-and-security");
7964
- },
8598
+ onClick: handleAccessAndSecurity,
7965
8599
  leftIcon: IoShieldOutline,
7966
8600
  rightIcon: MdOutlineNavigateNext,
7967
8601
  extraContent: upgradeRequired && /* @__PURE__ */ jsx(
@@ -7978,6 +8612,17 @@ var SettingsContent = ({
7978
8612
  )
7979
8613
  }
7980
8614
  ),
8615
+ /* @__PURE__ */ jsx(
8616
+ Heading,
8617
+ {
8618
+ size: "xs",
8619
+ fontWeight: "500",
8620
+ w: "full",
8621
+ opacity: 0.5,
8622
+ mt: 10,
8623
+ children: t("General")
8624
+ }
8625
+ ),
7981
8626
  /* @__PURE__ */ jsx(
7982
8627
  ActionButton,
7983
8628
  {
@@ -7989,9 +8634,7 @@ var SettingsContent = ({
7989
8634
  description: t(
7990
8635
  "View the details of your connection to this app."
7991
8636
  ),
7992
- onClick: () => {
7993
- setCurrentContent("connection-details");
7994
- },
8637
+ onClick: handleConnectionDetails,
7995
8638
  leftIcon: VscDebugDisconnect,
7996
8639
  rightIcon: MdOutlineNavigateNext
7997
8640
  }
@@ -8006,6 +8649,7 @@ var SettingsContent = ({
8006
8649
  title: t("Notifications"),
8007
8650
  description: t("View your notifications and updates."),
8008
8651
  onClick: () => {
8652
+ Analytics.notifications.viewed();
8009
8653
  setCurrentContent("notifications");
8010
8654
  },
8011
8655
  leftIcon: BiBell,
@@ -8054,10 +8698,7 @@ var SettingsContent = ({
8054
8698
  onClick: () => setCurrentContent({
8055
8699
  type: "disconnect-confirm",
8056
8700
  props: {
8057
- onDisconnect: () => {
8058
- disconnect();
8059
- onLogoutSuccess();
8060
- },
8701
+ onDisconnect: handleLogout,
8061
8702
  onBack: () => setCurrentContent("settings")
8062
8703
  }
8063
8704
  }),
@@ -8396,7 +9037,8 @@ var EmbeddedWalletContent = ({ setCurrentContent }) => {
8396
9037
  {
8397
9038
  wallet: connectedWallet,
8398
9039
  style: { mt: 2 },
8399
- showHumanAddress: false
9040
+ showHumanAddress: false,
9041
+ fromScreen: "account"
8400
9042
  }
8401
9043
  )
8402
9044
  ] }),
@@ -8492,6 +9134,11 @@ var SelectTokenContent = ({ onSelectToken, onBack }) => {
8492
9134
  }
8493
9135
  return Number(b.numericBalance) * b.price - Number(a.numericBalance) * a.price;
8494
9136
  });
9137
+ useEffect(() => {
9138
+ if (searchQuery) {
9139
+ Analytics.send.tokenSearchPerformed(searchQuery);
9140
+ }
9141
+ }, [searchQuery, filteredTokens.length]);
8495
9142
  return /* @__PURE__ */ jsxs(Fragment, { children: [
8496
9143
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
8497
9144
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Select Token") }),
@@ -8571,7 +9218,7 @@ var SendTokenContent = ({
8571
9218
  setCurrentContent,
8572
9219
  isNavigatingFromMain = false,
8573
9220
  preselectedToken,
8574
- onBack = () => setCurrentContent("main")
9221
+ onBack: parentOnBack = () => setCurrentContent("main")
8575
9222
  }) => {
8576
9223
  const { t } = useTranslation();
8577
9224
  const { darkMode: isDark } = useVeChainKitConfig();
@@ -8596,11 +9243,55 @@ var SendTokenContent = ({
8596
9243
  },
8597
9244
  mode: "onChange"
8598
9245
  });
8599
- const { toAddressOrDomain } = watch();
9246
+ const { toAddressOrDomain, amount } = watch();
9247
+ useEffect(() => {
9248
+ if (selectedToken && amount) {
9249
+ Analytics.send.flow("amount", {
9250
+ tokenSymbol: selectedToken.symbol,
9251
+ amount
9252
+ });
9253
+ }
9254
+ }, [amount, selectedToken]);
9255
+ useEffect(() => {
9256
+ if (selectedToken && toAddressOrDomain) {
9257
+ Analytics.send.flow("recipient", {
9258
+ tokenSymbol: selectedToken.symbol,
9259
+ recipientAddress: toAddressOrDomain,
9260
+ recipientType: toAddressOrDomain.includes(".") ? "domain" : "address"
9261
+ });
9262
+ }
9263
+ }, [toAddressOrDomain, selectedToken]);
8600
9264
  const { data: resolvedDomainData } = useVechainDomain(toAddressOrDomain);
8601
9265
  const handleSetMaxAmount = () => {
8602
9266
  if (selectedToken) {
8603
9267
  setValue("amount", selectedToken.numericBalance);
9268
+ Analytics.send.flow("amount", {
9269
+ tokenSymbol: selectedToken.symbol,
9270
+ amount: selectedToken.numericBalance
9271
+ });
9272
+ }
9273
+ };
9274
+ const handleBack = () => {
9275
+ if (selectedToken) {
9276
+ Analytics.send.flow("review", {
9277
+ tokenSymbol: selectedToken.symbol,
9278
+ amount: amount || void 0,
9279
+ recipientAddress: toAddressOrDomain || void 0,
9280
+ error: "back_button",
9281
+ isError: false
9282
+ });
9283
+ }
9284
+ parentOnBack();
9285
+ };
9286
+ const handleClose = () => {
9287
+ if (selectedToken) {
9288
+ Analytics.send.flow("review", {
9289
+ tokenSymbol: selectedToken.symbol,
9290
+ amount: amount || void 0,
9291
+ recipientAddress: toAddressOrDomain || void 0,
9292
+ error: "modal_closed",
9293
+ isError: false
9294
+ });
8604
9295
  }
8605
9296
  };
8606
9297
  const onSubmit = async (data) => {
@@ -8611,6 +9302,10 @@ var SendTokenContent = ({
8611
9302
  type: "manual",
8612
9303
  message: t("Invalid address or domain")
8613
9304
  });
9305
+ Analytics.send.flow("review", {
9306
+ tokenSymbol: selectedToken.symbol,
9307
+ error: "Invalid address or domain"
9308
+ });
8614
9309
  return;
8615
9310
  }
8616
9311
  if (selectedToken) {
@@ -8622,9 +9317,19 @@ var SendTokenContent = ({
8622
9317
  symbol: selectedToken.symbol
8623
9318
  })
8624
9319
  });
9320
+ Analytics.send.flow("review", {
9321
+ tokenSymbol: selectedToken.symbol,
9322
+ error: "Insufficient balance"
9323
+ });
8625
9324
  return;
8626
9325
  }
8627
9326
  }
9327
+ Analytics.send.flow("review", {
9328
+ tokenSymbol: selectedToken.symbol,
9329
+ amount: data.amount,
9330
+ recipientAddress: resolvedDomainData?.address || data.toAddressOrDomain,
9331
+ recipientType: resolvedDomainData?.domain ? "domain" : "address"
9332
+ });
8628
9333
  setCurrentContent({
8629
9334
  type: "send-token-summary",
8630
9335
  props: {
@@ -8643,14 +9348,27 @@ var SendTokenContent = ({
8643
9348
  {
8644
9349
  setCurrentContent,
8645
9350
  onSelectToken: (token) => {
9351
+ Analytics.send.tokenPageViewed(token.symbol);
8646
9352
  setSelectedToken(token);
8647
9353
  setIsSelectingToken(false);
8648
9354
  setIsInitialTokenSelection(false);
8649
9355
  },
8650
9356
  onBack: () => {
8651
9357
  if (isInitialTokenSelection) {
9358
+ if (selectedToken) {
9359
+ Analytics.send.flow("token_select", {
9360
+ tokenSymbol: selectedToken.symbol,
9361
+ error: "User cancelled - back to main"
9362
+ });
9363
+ }
8652
9364
  setCurrentContent("main");
8653
9365
  } else {
9366
+ if (selectedToken) {
9367
+ Analytics.send.flow("token_select", {
9368
+ tokenSymbol: selectedToken.symbol,
9369
+ error: "User cancelled - back to form"
9370
+ });
9371
+ }
8654
9372
  setIsSelectingToken(false);
8655
9373
  }
8656
9374
  }
@@ -8660,8 +9378,8 @@ var SendTokenContent = ({
8660
9378
  return /* @__PURE__ */ jsxs(Fragment, { children: [
8661
9379
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
8662
9380
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Send") }),
8663
- /* @__PURE__ */ jsx(ModalBackButton, { onClick: onBack }),
8664
- /* @__PURE__ */ jsx(ModalCloseButton, {})
9381
+ /* @__PURE__ */ jsx(ModalBackButton, { onClick: handleBack }),
9382
+ /* @__PURE__ */ jsx(ModalCloseButton, { onClick: handleClose })
8665
9383
  ] }),
8666
9384
  /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { spacing: 1, align: "stretch", position: "relative", children: [
8667
9385
  /* @__PURE__ */ jsx(
@@ -8917,6 +9635,57 @@ var SendTokenSummaryContent = ({
8917
9635
  }
8918
9636
  return getPicassoImage(resolvedAddress || toAddressOrDomain);
8919
9637
  }, [avatar, network.type, resolvedAddress, toAddressOrDomain]);
9638
+ const handleSend = async () => {
9639
+ if (upgradeRequired) {
9640
+ openUpgradeSmartAccountModal();
9641
+ return;
9642
+ }
9643
+ try {
9644
+ Analytics.send.flow("review", {
9645
+ tokenSymbol: selectedToken.symbol,
9646
+ amount,
9647
+ recipientAddress: resolvedAddress || toAddressOrDomain,
9648
+ recipientType: resolvedDomain ? "domain" : "address"
9649
+ });
9650
+ if (selectedToken.symbol === "VET") {
9651
+ await transferVET();
9652
+ } else {
9653
+ await transferERC20();
9654
+ }
9655
+ } catch (error) {
9656
+ Analytics.send.flow("review", {
9657
+ tokenSymbol: selectedToken.symbol,
9658
+ error: error instanceof Error ? error.message : "Unknown error"
9659
+ });
9660
+ console.error(t("Transaction failed:"), error);
9661
+ }
9662
+ };
9663
+ const handleSuccess = (txId) => {
9664
+ Analytics.send.flow("confirmation", {
9665
+ tokenSymbol: selectedToken.symbol,
9666
+ amount,
9667
+ recipientAddress: resolvedAddress || toAddressOrDomain,
9668
+ recipientType: resolvedDomain ? "domain" : "address"
9669
+ });
9670
+ Analytics.send.completed(
9671
+ selectedToken.symbol,
9672
+ amount,
9673
+ txId,
9674
+ selectedToken.symbol === "VET" ? "vet" : "erc20"
9675
+ );
9676
+ setCurrentContent({
9677
+ type: "successful-operation",
9678
+ props: {
9679
+ setCurrentContent,
9680
+ txId,
9681
+ title: t("Transaction successful"),
9682
+ onDone: () => {
9683
+ setCurrentContent("main");
9684
+ },
9685
+ showSocialButtons: true
9686
+ }
9687
+ });
9688
+ };
8920
9689
  const {
8921
9690
  sendTransaction: transferERC20,
8922
9691
  txReceipt: transferERC20Receipt,
@@ -8930,18 +9699,10 @@ var SendTokenSummaryContent = ({
8930
9699
  tokenAddress: selectedToken.address,
8931
9700
  tokenName: selectedToken.symbol,
8932
9701
  onSuccess: () => {
8933
- setCurrentContent({
8934
- type: "successful-operation",
8935
- props: {
8936
- setCurrentContent,
8937
- txId: transferERC20Receipt?.meta.txID,
8938
- title: t("Transaction successful"),
8939
- onDone: () => {
8940
- setCurrentContent("main");
8941
- },
8942
- showSocialButtons: true
8943
- }
8944
- });
9702
+ handleSuccess(transferERC20Receipt?.meta.txID ?? "");
9703
+ },
9704
+ onError: (error) => {
9705
+ handleError(error ?? "");
8945
9706
  }
8946
9707
  });
8947
9708
  const {
@@ -8955,42 +9716,65 @@ var SendTokenSummaryContent = ({
8955
9716
  receiverAddress: resolvedAddress || toAddressOrDomain,
8956
9717
  amount,
8957
9718
  onSuccess: () => {
8958
- setCurrentContent({
8959
- type: "successful-operation",
8960
- props: {
8961
- setCurrentContent,
8962
- txId: transferVETReceipt?.meta.txID,
8963
- title: t("Transaction successful"),
8964
- onDone: () => {
8965
- setCurrentContent("main");
8966
- },
8967
- showSocialButtons: true
8968
- }
8969
- });
9719
+ handleSuccess(transferVETReceipt?.meta.txID ?? "");
8970
9720
  },
8971
- onError: () => {
9721
+ onError: (error) => {
9722
+ handleError(error ?? "");
8972
9723
  }
8973
9724
  });
8974
9725
  const getTxReceipt = () => {
8975
9726
  return selectedToken.symbol === "VET" ? transferVETReceipt : transferERC20Receipt;
8976
9727
  };
8977
- const handleSend = async () => {
8978
- if (upgradeRequired) {
8979
- openUpgradeSmartAccountModal();
8980
- return;
8981
- }
8982
- try {
8983
- if (selectedToken.symbol === "VET") {
8984
- await transferVET();
8985
- } else {
8986
- await transferERC20();
9728
+ const isTxWaitingConfirmation = transferERC20WaitingForWalletConfirmation || transferVETWaitingForWalletConfirmation;
9729
+ const isSubmitting = isTxWaitingConfirmation || transferERC20Pending || transferVETPending;
9730
+ const handleBack = () => {
9731
+ Analytics.send.flow("review", {
9732
+ tokenSymbol: selectedToken.symbol,
9733
+ amount,
9734
+ recipientAddress: resolvedAddress || toAddressOrDomain,
9735
+ recipientType: resolvedDomain ? "domain" : "address",
9736
+ error: "back_button",
9737
+ isError: false
9738
+ });
9739
+ setCurrentContent({
9740
+ type: "send-token",
9741
+ props: {
9742
+ setCurrentContent,
9743
+ preselectedToken: selectedToken
8987
9744
  }
8988
- } catch (error) {
8989
- console.error(t("Transaction failed:"), error);
9745
+ });
9746
+ };
9747
+ const handleClose = () => {
9748
+ Analytics.send.flow("review", {
9749
+ tokenSymbol: selectedToken.symbol,
9750
+ amount,
9751
+ recipientAddress: resolvedAddress || toAddressOrDomain,
9752
+ recipientType: resolvedDomain ? "domain" : "address",
9753
+ error: "modal_closed",
9754
+ isError: false
9755
+ });
9756
+ };
9757
+ const handleError = (error) => {
9758
+ if (error && isRejectionError(error)) {
9759
+ Analytics.send.flow("review", {
9760
+ tokenSymbol: selectedToken.symbol,
9761
+ amount,
9762
+ recipientAddress: resolvedAddress || toAddressOrDomain,
9763
+ recipientType: resolvedDomain ? "domain" : "address",
9764
+ error: "wallet_rejected",
9765
+ isError: true
9766
+ });
9767
+ } else {
9768
+ Analytics.send.flow("review", {
9769
+ tokenSymbol: selectedToken.symbol,
9770
+ amount,
9771
+ recipientAddress: resolvedAddress || toAddressOrDomain,
9772
+ recipientType: resolvedDomain ? "domain" : "address",
9773
+ error,
9774
+ isError: true
9775
+ });
8990
9776
  }
8991
9777
  };
8992
- const isTxWaitingConfirmation = transferERC20WaitingForWalletConfirmation || transferVETWaitingForWalletConfirmation;
8993
- const isSubmitting = isTxWaitingConfirmation || transferERC20Pending || transferVETPending;
8994
9778
  return /* @__PURE__ */ jsxs(Fragment, { children: [
8995
9779
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
8996
9780
  /* @__PURE__ */ jsx(ModalHeader, { children: "Send" }),
@@ -8998,15 +9782,16 @@ var SendTokenSummaryContent = ({
8998
9782
  ModalBackButton,
8999
9783
  {
9000
9784
  isDisabled: isSubmitting,
9001
- onClick: () => setCurrentContent({
9002
- type: "send-token",
9003
- props: {
9004
- setCurrentContent
9005
- }
9006
- })
9785
+ onClick: handleBack
9007
9786
  }
9008
9787
  ),
9009
- /* @__PURE__ */ jsx(ModalCloseButton, { isDisabled: isSubmitting })
9788
+ /* @__PURE__ */ jsx(
9789
+ ModalCloseButton,
9790
+ {
9791
+ isDisabled: isSubmitting,
9792
+ onClick: handleClose
9793
+ }
9794
+ )
9010
9795
  ] }),
9011
9796
  /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { spacing: 6, align: "stretch", w: "full", children: [
9012
9797
  connection.isConnectedWithPrivy && /* @__PURE__ */ jsx(ExchangeWarningAlert, {}),
@@ -9118,7 +9903,14 @@ var ReceiveTokenContent = ({ setCurrentContent }) => {
9118
9903
  }
9119
9904
  }
9120
9905
  ),
9121
- /* @__PURE__ */ jsx(AddressDisplay, { wallet: account, style: { w: "85%" } }),
9906
+ /* @__PURE__ */ jsx(
9907
+ AddressDisplay,
9908
+ {
9909
+ wallet: account,
9910
+ style: { w: "85%" },
9911
+ fromScreen: "receive"
9912
+ }
9913
+ ),
9122
9914
  /* @__PURE__ */ jsx(Text, { fontSize: "sm", textAlign: "center", children: t("Copy your address or scan this QR code") }),
9123
9915
  /* @__PURE__ */ jsx(Text, { fontSize: "xs", textAlign: "center", opacity: 0.5, children: t("This address only supports VeChain assets.") })
9124
9916
  ] }) }),
@@ -9128,6 +9920,10 @@ var ReceiveTokenContent = ({ setCurrentContent }) => {
9128
9920
  };
9129
9921
  var SwapTokenContent = ({ setCurrentContent }) => {
9130
9922
  const { t } = useTranslation();
9923
+ const handleLaunchBetterSwap = () => {
9924
+ Analytics.swap.launchBetterSwap();
9925
+ window.open("https://swap.tbc.vet/", "_blank");
9926
+ };
9131
9927
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9132
9928
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
9133
9929
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Swap") }),
@@ -9153,9 +9949,7 @@ var SwapTokenContent = ({ setCurrentContent }) => {
9153
9949
  Button,
9154
9950
  {
9155
9951
  variant: "vechainKitSecondary",
9156
- onClick: () => {
9157
- window.open("https://swap.tbc.vet/", "_blank");
9158
- },
9952
+ onClick: handleLaunchBetterSwap,
9159
9953
  children: [
9160
9954
  t("Launch BetterSwap"),
9161
9955
  /* @__PURE__ */ jsx(Icon, { as: FaExternalLinkAlt, ml: 2 })
@@ -9171,11 +9965,26 @@ var ChooseNameContent = ({
9171
9965
  }) => {
9172
9966
  const { t } = useTranslation();
9173
9967
  const { darkMode: isDark } = useVeChainKitConfig();
9968
+ const handleClose = () => {
9969
+ Analytics.nameSelection.dropOff("search", {
9970
+ isError: false,
9971
+ name: "",
9972
+ reason: "modal_closed"
9973
+ });
9974
+ };
9975
+ const handleBack = () => {
9976
+ Analytics.nameSelection.dropOff("search", {
9977
+ isError: false,
9978
+ name: "",
9979
+ reason: "back_button"
9980
+ });
9981
+ onBack();
9982
+ };
9174
9983
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9175
9984
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
9176
9985
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Choose your account name") }),
9177
- /* @__PURE__ */ jsx(ModalBackButton, { onClick: onBack }),
9178
- /* @__PURE__ */ jsx(ModalCloseButton, {})
9986
+ /* @__PURE__ */ jsx(ModalBackButton, { onClick: handleBack }),
9987
+ /* @__PURE__ */ jsx(ModalCloseButton, { onClick: handleClose })
9179
9988
  ] }),
9180
9989
  /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { spacing: 6, align: "center", py: 8, children: [
9181
9990
  /* @__PURE__ */ jsx(
@@ -9446,10 +10255,15 @@ var ChooseNameSearchContent = ({
9446
10255
  ];
9447
10256
  useEffect(() => {
9448
10257
  if (!hasInteracted) return;
10258
+ const hasSpecialChars = /[^a-zA-Z0-9-]|\s/.test(name);
9449
10259
  if (name.length < 3) {
9450
10260
  setError(t("Name must be at least 3 characters long"));
9451
10261
  setIsAvailable(false);
9452
10262
  setIsOwnDomain(false);
10263
+ } else if (hasSpecialChars) {
10264
+ setError(t("Only letters, numbers, and hyphens are allowed"));
10265
+ setIsAvailable(false);
10266
+ setIsOwnDomain(false);
9453
10267
  } else if (isProtected) {
9454
10268
  setError(t("This domain is protected"));
9455
10269
  setIsAvailable(false);
@@ -9470,6 +10284,9 @@ var ChooseNameSearchContent = ({
9470
10284
  setIsAvailable(true);
9471
10285
  setIsOwnDomain(false);
9472
10286
  }
10287
+ if (name.length >= 3 && !isFetchingDomainInfo) {
10288
+ Analytics.nameSelection.searched(name, isAvailable);
10289
+ }
9473
10290
  }, [
9474
10291
  name,
9475
10292
  hasInteracted,
@@ -9477,7 +10294,9 @@ var ChooseNameSearchContent = ({
9477
10294
  isEnsCheckLoading,
9478
10295
  domainInfo,
9479
10296
  account?.address,
9480
- isProtected
10297
+ isProtected,
10298
+ isAvailable,
10299
+ isFetchingDomainInfo
9481
10300
  ]);
9482
10301
  const handleContinue = () => {
9483
10302
  if (isAvailable && !error) {
@@ -9520,16 +10339,26 @@ var ChooseNameSearchContent = ({
9520
10339
  }
9521
10340
  });
9522
10341
  };
10342
+ const handleClose = () => {
10343
+ Analytics.nameSelection.dropOff("search", {
10344
+ isError: false,
10345
+ name,
10346
+ error: "modal_closed"
10347
+ });
10348
+ };
10349
+ const handleBack = () => {
10350
+ Analytics.nameSelection.dropOff("search", {
10351
+ isError: false,
10352
+ name,
10353
+ reason: "back_button"
10354
+ });
10355
+ setCurrentContent(initialContentSource);
10356
+ };
9523
10357
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9524
10358
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
9525
10359
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Choose Name") }),
9526
- /* @__PURE__ */ jsx(
9527
- ModalBackButton,
9528
- {
9529
- onClick: () => setCurrentContent(initialContentSource)
9530
- }
9531
- ),
9532
- /* @__PURE__ */ jsx(ModalCloseButton, {})
10360
+ /* @__PURE__ */ jsx(ModalBackButton, { onClick: handleBack }),
10361
+ /* @__PURE__ */ jsx(ModalCloseButton, { onClick: handleClose })
9533
10362
  ] }),
9534
10363
  /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { spacing: 4, align: "stretch", children: [
9535
10364
  /* @__PURE__ */ jsx(
@@ -9622,6 +10451,21 @@ var ChooseNameSummaryContent = ({
9622
10451
  3
9623
10452
  );
9624
10453
  const { open: openUpgradeSmartAccountModal } = useUpgradeSmartAccountModal();
10454
+ const handleError = (error) => {
10455
+ if (isRejectionError(error)) {
10456
+ Analytics.nameSelection.dropOff("confirmation", {
10457
+ isError: true,
10458
+ name,
10459
+ error,
10460
+ reason: "wallet_rejected"
10461
+ });
10462
+ } else {
10463
+ Analytics.nameSelection.failed("confirmation", {
10464
+ error,
10465
+ name
10466
+ });
10467
+ }
10468
+ };
9625
10469
  const unsetDomainHook = useUnsetDomain({
9626
10470
  onSuccess: () => handleSuccess()
9627
10471
  });
@@ -9672,24 +10516,49 @@ var ChooseNameSummaryContent = ({
9672
10516
  console.error("Transaction failed:", error);
9673
10517
  }
9674
10518
  };
10519
+ const handleRetry = () => {
10520
+ Analytics.nameSelection.retry("confirmation");
10521
+ handleConfirm();
10522
+ };
10523
+ const handleClose = () => {
10524
+ Analytics.nameSelection.dropOff("confirmation", {
10525
+ isError: false,
10526
+ name: isUnsetting ? "" : name,
10527
+ error: "modal_closed"
10528
+ });
10529
+ };
10530
+ const handleBack = () => {
10531
+ Analytics.nameSelection.dropOff("confirmation", {
10532
+ isError: false,
10533
+ name: isUnsetting ? "" : name,
10534
+ error: "back_button"
10535
+ });
10536
+ setCurrentContent({
10537
+ type: "choose-name-search",
10538
+ props: {
10539
+ setCurrentContent,
10540
+ name,
10541
+ initialContentSource
10542
+ }
10543
+ });
10544
+ };
9675
10545
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9676
10546
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
9677
10547
  /* @__PURE__ */ jsx(ModalHeader, { children: isUnsetting ? t("Confirm Unset Domain") : t("Confirm Name") }),
9678
10548
  /* @__PURE__ */ jsx(
9679
10549
  ModalBackButton,
9680
10550
  {
9681
- onClick: () => setCurrentContent({
9682
- type: "choose-name-search",
9683
- props: {
9684
- setCurrentContent,
9685
- name,
9686
- initialContentSource
9687
- }
9688
- }),
10551
+ onClick: handleBack,
9689
10552
  isDisabled: isTransactionPending
9690
10553
  }
9691
10554
  ),
9692
- /* @__PURE__ */ jsx(ModalCloseButton, { isDisabled: isTransactionPending })
10555
+ /* @__PURE__ */ jsx(
10556
+ ModalCloseButton,
10557
+ {
10558
+ isDisabled: isTransactionPending,
10559
+ onClick: handleClose
10560
+ }
10561
+ )
9693
10562
  ] }),
9694
10563
  /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { spacing: 4, w: "full", textAlign: "center", children: [
9695
10564
  /* @__PURE__ */ jsx(Text, { fontSize: "lg", children: isUnsetting ? t(
@@ -9706,10 +10575,12 @@ var ChooseNameSummaryContent = ({
9706
10575
  isSubmitting: isTransactionPending,
9707
10576
  isTxWaitingConfirmation: isWaitingForWalletConfirmation,
9708
10577
  onConfirm: handleConfirm,
10578
+ onRetry: handleRetry,
9709
10579
  transactionPendingText: isUnsetting ? t("Unsetting current domain...") : t("Claiming name..."),
9710
10580
  txReceipt,
9711
10581
  buttonText: t("Confirm"),
9712
- isDisabled: isTransactionPending
10582
+ isDisabled: isTransactionPending,
10583
+ onError: handleError
9713
10584
  }
9714
10585
  ) })
9715
10586
  ] });
@@ -9906,6 +10777,7 @@ var en_default = {
9906
10777
  "Address is required": "Address is required",
9907
10778
  "All apps": "All apps",
9908
10779
  "Already have an app account?": "Already have an app account?",
10780
+ "Already have an x2earn app wallet?": "Already have an x2earn app wallet?",
9909
10781
  Amount: "Amount",
9910
10782
  "Amount is required": "Amount is required",
9911
10783
  "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.",
@@ -10047,6 +10919,7 @@ var en_default = {
10047
10919
  "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.",
10048
10920
  "Frequently asked questions": "Frequently asked questions",
10049
10921
  From: "From",
10922
+ General: "General",
10050
10923
  Github: "Github",
10051
10924
  "Give a nickname to your wallet to easily identify it.": "Give a nickname to your wallet to easily identify it.",
10052
10925
  "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.",
@@ -10132,6 +11005,7 @@ var en_default = {
10132
11005
  "Node URL": "Node URL",
10133
11006
  "Not available": "Not available",
10134
11007
  Notifications: "Notifications",
11008
+ "Only letters, numbers, and hyphens are allowed": "Only letters, numbers, and hyphens are allowed",
10135
11009
  Other: "Other",
10136
11010
  "Other options": "Other options",
10137
11011
  Passkey: "Passkey",
@@ -10408,6 +11282,7 @@ var de_default = {
10408
11282
  "Address is required": "Adresse ist erforderlich",
10409
11283
  "All apps": "Alle Apps",
10410
11284
  "Already have an app account?": "Haben Sie bereits ein App-Konto?",
11285
+ "Already have an x2earn app wallet?": "Haben Sie bereits eine x2earn-App-Wallet?",
10411
11286
  Amount: "Betrag",
10412
11287
  "Amount is required": "Betrag ist erforderlich",
10413
11288
  "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\xFCr umweltfreundliche Aktionen mit B3TR-Token belohnt. Diese Apps m\xFCssen B3TR verteilen, Benutzer-Wallets verkn\xFCpfen und den Nachweis nachhaltiger Aktionen erbringen. Sie treten VeBetterDAO durch Unterst\xFCtzung bei und nehmen an w\xF6chentlichen Token-Zuweisungsrunden teil.",
@@ -10549,6 +11424,7 @@ var de_default = {
10549
11424
  "For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.": "Aus Sicherheitsgr\xFCnden k\xF6nnen Sie die Einstellungen Ihrer eingebetteten Wallet nur auf der {{appName}} Plattform verwalten.",
10550
11425
  "Frequently asked questions": "H\xE4ufig gestellte Fragen",
10551
11426
  From: "Von",
11427
+ General: "Allgemein",
10552
11428
  Github: "Github",
10553
11429
  "Give a nickname to your wallet to easily identify it.": "Geben Sie Ihrer Brieftasche einen Spitznamen, um sie leicht identifizieren zu k\xF6nnen.",
10554
11430
  "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\xE4ndig f\xFCr Smart-Accounts unterst\xFCtzt. Sie k\xF6nnen jetzt von einer besseren Benutzererfahrung, niedrigeren Gaskosten und erh\xF6hter Sicherheit profitieren.",
@@ -10634,6 +11510,7 @@ var de_default = {
10634
11510
  "Node URL": "Knoten-URL",
10635
11511
  "Not available": "Nicht verf\xFCgbar",
10636
11512
  Notifications: "Benachrichtigungen",
11513
+ "Only letters, numbers, and hyphens are allowed": "Es sind nur Buchstaben, Zahlen und Bindestriche erlaubt",
10637
11514
  Other: "Andere",
10638
11515
  "Other options": "Weitere Optionen",
10639
11516
  Passkey: "Passwort",
@@ -10910,6 +11787,7 @@ var it_default = {
10910
11787
  "Address is required": "L'indirizzo \xE8 richiesto",
10911
11788
  "All apps": "Tutte le app",
10912
11789
  "Already have an app account?": "Hai gi\xE0 un account nell'app?",
11790
+ "Already have an x2earn app wallet?": "Hai gi\xE0 un portafoglio x2earn app?",
10913
11791
  Amount: "Importo",
10914
11792
  "Amount is required": "\xC8 richiesto l'importo",
10915
11793
  "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 \xE8 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.",
@@ -11051,6 +11929,7 @@ var it_default = {
11051
11929
  "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}}.",
11052
11930
  "Frequently asked questions": "Domande frequenti",
11053
11931
  From: "Da",
11932
+ General: "Generale",
11054
11933
  Github: "Github",
11055
11934
  "Give a nickname to your wallet to easily identify it.": "Dai un soprannome al tuo portafoglio per identificarlo facilmente.",
11056
11935
  "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.",
@@ -11136,6 +12015,7 @@ var it_default = {
11136
12015
  "Node URL": "URL del nodo",
11137
12016
  "Not available": "Non disponibile",
11138
12017
  Notifications: "Notifiche",
12018
+ "Only letters, numbers, and hyphens are allowed": "Sono ammessi solo lettere, numeri e trattini",
11139
12019
  Other: "Altro",
11140
12020
  "Other options": "Altre opzioni",
11141
12021
  Passkey: "Chiave di accesso",
@@ -11412,6 +12292,7 @@ var fr_default = {
11412
12292
  "Address is required": "L'adresse est requise",
11413
12293
  "All apps": "Toutes les applications",
11414
12294
  "Already have an app account?": "Vous avez d\xE9j\xE0 un compte sur l'application\xA0?",
12295
+ "Already have an x2earn app wallet?": "Vous avez d\xE9j\xE0 un portefeuille d'application x2earn ?",
11415
12296
  Amount: "Montant",
11416
12297
  "Amount is required": "Le montant est requis",
11417
12298
  "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\xE9compense les utilisateurs avec des tokens B3TR pour des actions \xE9cologiques. Ces applications doivent distribuer B3TR, lier les portefeuilles utilisateurs et fournir une preuve des actions durables. Elles rejoignent VeBetterDAO par recommandation et participent \xE0 des rondes d\u2019allocation de tokens hebdomadaires.",
@@ -11553,6 +12434,7 @@ var fr_default = {
11553
12434
  "For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.": "Pour des raisons de s\xE9curit\xE9, vous pouvez g\xE9rer les param\xE8tres de votre portefeuille int\xE9gr\xE9 uniquement sur la plateforme {{appName}}.",
11554
12435
  "Frequently asked questions": "Questions fr\xE9quemment pos\xE9es",
11555
12436
  From: "De",
12437
+ General: "G\xE9n\xE9ral",
11556
12438
  Github: "Github",
11557
12439
  "Give a nickname to your wallet to easily identify it.": "Donnez un surnom \xE0 votre portefeuille pour l'identifier facilement.",
11558
12440
  "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\xE9sormais enti\xE8rement prises en charge pour les comptes intelligents. Vous pouvez d\xE9sormais profiter d'une meilleure exp\xE9rience utilisateur, de frais de gaz r\xE9duits et d'une s\xE9curit\xE9 renforc\xE9e.",
@@ -11638,6 +12520,7 @@ var fr_default = {
11638
12520
  "Node URL": "URL du n\u0153ud",
11639
12521
  "Not available": "Non disponible",
11640
12522
  Notifications: "Notifications",
12523
+ "Only letters, numbers, and hyphens are allowed": "Seules les lettres, les chiffres et les tirets sont autoris\xE9s",
11641
12524
  Other: "Autre",
11642
12525
  "Other options": "Autres options",
11643
12526
  Passkey: "Cl\xE9 de passe",
@@ -11914,6 +12797,7 @@ var es_default = {
11914
12797
  "Address is required": "Se requiere direcci\xF3n",
11915
12798
  "All apps": "Todas las aplicaciones",
11916
12799
  "Already have an app account?": "\xBFYa tienes una cuenta de la aplicaci\xF3n?",
12800
+ "Already have an x2earn app wallet?": "\xBFYa tienes una billetera de aplicaci\xF3n x2earn?",
11917
12801
  Amount: "Cantidad",
11918
12802
  "Amount is required": "Se requiere un monto",
11919
12803
  "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\xF3n X2Earn en VeBetterDAO es una app sostenible que recompensa a los usuarios con tokens B3TR por acciones ecol\xF3gicas. Estas aplicaciones deben distribuir B3TR, vincular las billeteras de los usuarios y proporcionar pruebas de acciones sostenibles. Se unen a VeBetterDAO a trav\xE9s de la recomendaci\xF3n y participan en rondas semanales de asignaci\xF3n de tokens.",
@@ -12055,6 +12939,7 @@ var es_default = {
12055
12939
  "For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.": "Por razones de seguridad, puedes gestionar la configuraci\xF3n de tu billetera integrada solo en la plataforma {{appName}}.",
12056
12940
  "Frequently asked questions": "Preguntas frecuentes",
12057
12941
  From: "De",
12942
+ General: "General",
12058
12943
  Github: "Github",
12059
12944
  "Give a nickname to your wallet to easily identify it.": "Dale un apodo a tu billetera para identificarla f\xE1cilmente.",
12060
12945
  "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.": "\xA1Buenas noticias! Las transacciones multicl\xE1usula ahora son totalmente compatibles con las cuentas inteligentes. Ahora puedes disfrutar de una mejor experiencia de usuario, menores costos de gas y mayor seguridad.",
@@ -12140,6 +13025,7 @@ var es_default = {
12140
13025
  "Node URL": "URL del nodo",
12141
13026
  "Not available": "No disponible",
12142
13027
  Notifications: "Notificaciones",
13028
+ "Only letters, numbers, and hyphens are allowed": "Solo se permiten letras, n\xFAmeros y guiones",
12143
13029
  Other: "Otro",
12144
13030
  "Other options": "Otras opciones",
12145
13031
  Passkey: "Clave de acceso",
@@ -12416,6 +13302,7 @@ var zh_default = {
12416
13302
  "Address is required": "\u5730\u5740\u662F\u5FC5\u9700\u7684",
12417
13303
  "All apps": "\u6240\u6709\u5E94\u7528",
12418
13304
  "Already have an app account?": "\u5DF2\u7ECF\u6709\u4E00\u4E2A\u5E94\u7528\u8D26\u6237\uFF1F",
13305
+ "Already have an x2earn app wallet?": "\u5DF2\u7ECF\u6709\u4E00\u4E2Ax2earn\u5E94\u7528\u94B1\u5305\u4E86\u5417\uFF1F",
12419
13306
  Amount: "\u91D1\u989D",
12420
13307
  "Amount is required": "\u91D1\u989D\u662F\u5FC5\u9700\u7684",
12421
13308
  "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 \u7684 X2Earn \u5E94\u7528\u7A0B\u5E8F\u662F\u4E00\u6B3E\u53EF\u6301\u7EED\u53D1\u5C55\u7684\u5E94\u7528\u7A0B\u5E8F\uFF0C\u7528\u6237\u56E0\u751F\u6001\u53CB\u597D\u884C\u4E3A\u800C\u83B7\u5F97 B3TR \u4EE3\u5E01\u5956\u52B1\u3002\u8FD9\u4E9B\u5E94\u7528\u7A0B\u5E8F\u5FC5\u987B\u5206\u53D1 B3TR\uFF0C\u94FE\u63A5\u7528\u6237\u94B1\u5305\u5E76\u63D0\u4F9B\u53EF\u6301\u7EED\u884C\u52A8\u7684\u8BC1\u660E\u3002\u5B83\u4EEC\u901A\u8FC7\u80CC\u4E66\u52A0\u5165 VeBetterDAO\uFF0C\u5E76\u53C2\u4E0E\u6BCF\u5468\u7684\u4EE3\u5E01\u5206\u914D\u8F6E\u6B21\u3002",
@@ -12557,6 +13444,7 @@ var zh_default = {
12557
13444
  "For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.": "\u51FA\u4E8E\u5B89\u5168\u539F\u56E0\uFF0C\u60A8\u53EA\u80FD\u5728 {{appName}} \u5E73\u53F0\u4E0A\u7BA1\u7406\u5D4C\u5165\u5F0F\u94B1\u5305\u8BBE\u7F6E\u3002",
12558
13445
  "Frequently asked questions": "\u5E38\u89C1\u95EE\u9898\u89E3\u7B54",
12559
13446
  From: "\u81EA",
13447
+ General: "\u5E38\u89C4",
12560
13448
  Github: "Github",
12561
13449
  "Give a nickname to your wallet to easily identify it.": "\u7ED9\u60A8\u7684\u94B1\u5305\u8D77\u4E00\u4E2A\u6635\u79F0\uFF0C\u4EE5\u4FBF\u4E8E\u8BC6\u522B\u3002",
12562
13450
  "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.": "\u597D\u6D88\u606F\uFF01\u591A\u6761\u6B3E\u4EA4\u6613\u73B0\u5728\u5DF2\u5B8C\u5168\u652F\u6301\u667A\u80FD\u8D26\u6237\u3002\u60A8\u73B0\u5728\u53EF\u4EE5\u4EAB\u53D7\u66F4\u597D\u7684\u7528\u6237\u4F53\u9A8C\u3001\u66F4\u4F4E\u7684\u71C3\u6C14\u6210\u672C\u548C\u66F4\u9AD8\u7684\u5B89\u5168\u6027\u3002",
@@ -12642,6 +13530,7 @@ var zh_default = {
12642
13530
  "Node URL": "\u8282\u70B9 URL",
12643
13531
  "Not available": "\u4E0D\u53EF\u7528",
12644
13532
  Notifications: "\u901A\u77E5",
13533
+ "Only letters, numbers, and hyphens are allowed": "\u53EA\u5141\u8BB8\u4F7F\u7528\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26",
12645
13534
  Other: "\u5176\u4ED6",
12646
13535
  "Other options": "\u5176\u4ED6\u9009\u9879",
12647
13536
  Passkey: "\u901A\u884C\u5BC6\u94A5",
@@ -12918,6 +13807,7 @@ var ja_default = {
12918
13807
  "Address is required": "\u30A2\u30C9\u30EC\u30B9\u304C\u5FC5\u8981\u3067\u3059",
12919
13808
  "All apps": "\u3059\u3079\u3066\u306E\u30A2\u30D7\u30EA",
12920
13809
  "Already have an app account?": "\u65E2\u306B\u30A2\u30D7\u30EA\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u304A\u6301\u3061\u3067\u3059\u304B\uFF1F",
13810
+ "Already have an x2earn app wallet?": "\u65E2\u306Bx2earn\u30A2\u30D7\u30EA\u306E\u30A6\u30A9\u30EC\u30C3\u30C8\u3092\u304A\u6301\u3061\u3067\u3059\u304B\uFF1F",
12921
13811
  Amount: "\u91D1\u984D",
12922
13812
  "Amount is required": "\u91D1\u984D\u304C\u5FC5\u8981\u3067\u3059",
12923
13813
  "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\u306EX2Earn\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306F\u3001\u74B0\u5883\u306B\u512A\u3057\u3044\u884C\u52D5\u3092\u3068\u308B\u30E6\u30FC\u30B6\u30FC\u306BB3TR\u30C8\u30FC\u30AF\u30F3\u3092\u5831\u916C\u3068\u3057\u3066\u63D0\u4F9B\u3059\u308B\u6301\u7D9A\u53EF\u80FD\u306A\u30A2\u30D7\u30EA\u3067\u3059\u3002\u3053\u308C\u3089\u306E\u30A2\u30D7\u30EA\u306FB3TR\u3092\u914D\u5E03\u3057\u3001\u30E6\u30FC\u30B6\u306E\u30A6\u30A9\u30EC\u30C3\u30C8\u3092\u30EA\u30F3\u30AF\u3057\u3001\u6301\u7D9A\u53EF\u80FD\u306A\u884C\u52D5\u306E\u8A3C\u660E\u3092\u63D0\u4F9B\u3057\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093\u3002\u3053\u308C\u3089\u306F\u63A8\u85A6\u3092\u901A\u3058\u3066VeBetterDAO\u306B\u53C2\u52A0\u3057\u3001\u9031\u3054\u3068\u306E\u30C8\u30FC\u30AF\u30F3\u5272\u308A\u5F53\u3066\u30E9\u30A6\u30F3\u30C9\u306B\u53C2\u52A0\u3057\u307E\u3059\u3002",
@@ -13059,6 +13949,7 @@ var ja_default = {
13059
13949
  "For security reasons, you can manage your embedded wallet settings only on the {{appName}} platform.": "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u4E0A\u306E\u7406\u7531\u304B\u3089\u3001\u57CB\u3081\u8FBC\u307F\u30A6\u30A9\u30EC\u30C3\u30C8\u306E\u8A2D\u5B9A\u306F{{appName}}\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3067\u306E\u307F\u7BA1\u7406\u3067\u304D\u307E\u3059\u3002",
13060
13950
  "Frequently asked questions": "\u3088\u304F\u3042\u308B\u8CEA\u554F",
13061
13951
  From: "\u9001\u4FE1\u5143",
13952
+ General: "\u4E00\u822C",
13062
13953
  Github: "\u30AE\u30C3\u30C8\u30CF\u30D6",
13063
13954
  "Give a nickname to your wallet to easily identify it.": "\u30A6\u30A9\u30EC\u30C3\u30C8\u306B\u30CB\u30C3\u30AF\u30CD\u30FC\u30E0\u3092\u4ED8\u3051\u3066\u7C21\u5358\u306B\u8B58\u5225\u3057\u307E\u3057\u3087\u3046\u3002",
13064
13955
  "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.": "\u6717\u5831\u3067\u3059\uFF01\u30B9\u30DE\u30FC\u30C8\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u305F\u3081\u306B\u3001\u30DE\u30EB\u30C1\u30AF\u30ED\u30FC\u30BA\u53D6\u5F15\u304C\u5B8C\u5168\u306B\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u308B\u3088\u3046\u306B\u306A\u308A\u307E\u3057\u305F\u3002\u3053\u308C\u3067\u3001\u3088\u308A\u826F\u3044\u30E6\u30FC\u30B6\u30FC\u4F53\u9A13\u3001\u4F4E\u30B3\u30B9\u30C8\u306E\u30AC\u30B9\u3001\u305D\u3057\u3066\u5F37\u5316\u3055\u308C\u305F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u3092\u697D\u3057\u3080\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002",
@@ -13144,6 +14035,7 @@ var ja_default = {
13144
14035
  "Node URL": "\u30CE\u30FC\u30C9URL",
13145
14036
  "Not available": "\u5229\u7528\u4E0D\u53EF",
13146
14037
  Notifications: "\u901A\u77E5",
14038
+ "Only letters, numbers, and hyphens are allowed": "\u4F7F\u7528\u3067\u304D\u308B\u306E\u306F\u6587\u5B57\u3001\u6570\u5B57\u3001\u30CF\u30A4\u30D5\u30F3\u306E\u307F\u3067\u3059",
13147
14039
  Other: "\u305D\u306E\u4ED6",
13148
14040
  "Other options": "\u305D\u306E\u4ED6\u306E\u30AA\u30D7\u30B7\u30E7\u30F3",
13149
14041
  Passkey: "\u30D1\u30B9\u30AD\u30FC",
@@ -13446,6 +14338,10 @@ var i18n_default = i18n;
13446
14338
  var FAQContent = ({ onGoBack }) => {
13447
14339
  const { network, darkMode: isDark } = useVeChainKitConfig();
13448
14340
  const { i18n: i18n2, t } = useTranslation();
14341
+ const handleLanguageChange = (e) => {
14342
+ Analytics.settings.language.changed(e.target.value, i18n2.language);
14343
+ i18n2.changeLanguage(e.target.value);
14344
+ };
13449
14345
  return /* @__PURE__ */ jsxs(ScrollToTopWrapper, { children: [
13450
14346
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
13451
14347
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Help") }),
@@ -13490,7 +14386,7 @@ var FAQContent = ({ onGoBack }) => {
13490
14386
  size: "sm",
13491
14387
  width: "auto",
13492
14388
  value: i18n2.language,
13493
- onChange: (e) => i18n2.changeLanguage(e.target.value),
14389
+ onChange: handleLanguageChange,
13494
14390
  bg: isDark ? "whiteAlpha.200" : "gray.100",
13495
14391
  borderColor: isDark ? "whiteAlpha.300" : "gray.200",
13496
14392
  _hover: {
@@ -13528,7 +14424,8 @@ var FAQContent = ({ onGoBack }) => {
13528
14424
  ] });
13529
14425
  };
13530
14426
  var CustomizationContent = ({
13531
- setCurrentContent
14427
+ setCurrentContent,
14428
+ initialContentSource = "profile"
13532
14429
  }) => {
13533
14430
  const { t } = useTranslation();
13534
14431
  const { network } = useVeChainKitConfig();
@@ -13597,9 +14494,14 @@ var CustomizationContent = ({
13597
14494
  network.type
13598
14495
  );
13599
14496
  setAvatarIpfsHash(ipfsHash);
14497
+ Analytics.customization.imageUploaded(true);
13600
14498
  } catch (error) {
13601
14499
  console.error("Error uploading image:", error);
13602
14500
  setPreviewImageUrl(null);
14501
+ Analytics.customization.imageUploaded(
14502
+ false,
14503
+ error instanceof Error ? error.message : "Unknown error"
14504
+ );
13603
14505
  } finally {
13604
14506
  setIsUploading(false);
13605
14507
  }
@@ -13635,15 +14537,43 @@ var CustomizationContent = ({
13635
14537
  type: "account-customization-summary",
13636
14538
  props: {
13637
14539
  setCurrentContent,
13638
- changes: getChangedValues()
14540
+ changes: getChangedValues(),
14541
+ onDoneRedirectContent: initialContentSource
13639
14542
  }
13640
14543
  });
13641
14544
  };
14545
+ const handleClose = () => {
14546
+ if (isUploading) {
14547
+ Analytics.customization.dropOff({
14548
+ stage: "avatar",
14549
+ reason: "modal_closed_during_upload"
14550
+ });
14551
+ } else {
14552
+ Analytics.customization.dropOff({
14553
+ stage: "form",
14554
+ reason: "modal_closed"
14555
+ });
14556
+ }
14557
+ };
14558
+ const handleBack = () => {
14559
+ if (isUploading) {
14560
+ Analytics.customization.dropOff({
14561
+ stage: "avatar",
14562
+ reason: "back_button_during_upload"
14563
+ });
14564
+ } else {
14565
+ Analytics.customization.dropOff({
14566
+ stage: "form",
14567
+ reason: "back_button"
14568
+ });
14569
+ }
14570
+ setCurrentContent("profile");
14571
+ };
13642
14572
  return /* @__PURE__ */ jsxs(Box, { children: [
13643
14573
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
13644
14574
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Customization") }),
13645
- /* @__PURE__ */ jsx(ModalBackButton, { onClick: () => setCurrentContent("profile") }),
13646
- /* @__PURE__ */ jsx(ModalCloseButton, {})
14575
+ /* @__PURE__ */ jsx(ModalBackButton, { onClick: handleBack }),
14576
+ /* @__PURE__ */ jsx(ModalCloseButton, { onClick: handleClose })
13647
14577
  ] }),
13648
14578
  /* @__PURE__ */ jsxs(ModalBody, { children: [
13649
14579
  /* @__PURE__ */ jsxs(
@@ -13741,13 +14671,21 @@ var CustomizationContent = ({
13741
14671
  "Choose a unique .vet domain name for your account."
13742
14672
  ),
13743
14673
  onClick: () => {
14674
+ Analytics.nameSelection.started(
14675
+ "account-customization"
14676
+ );
13744
14677
  if (account?.domain) {
13745
14678
  setCurrentContent({
13746
14679
  type: "choose-name-search",
13747
14680
  props: {
13748
14681
  name: "",
13749
14682
  setCurrentContent,
13750
- initialContentSource: "account-customization"
14683
+ initialContentSource: {
14684
+ type: "account-customization",
14685
+ props: {
14686
+ setCurrentContent
14687
+ }
14688
+ }
13751
14689
  }
13752
14690
  });
13753
14691
  } else {
@@ -13755,10 +14693,18 @@ var CustomizationContent = ({
13755
14693
  type: "choose-name",
13756
14694
  props: {
13757
14695
  setCurrentContent,
13758
- initialContentSource: "account-customization",
13759
- onBack: () => setCurrentContent(
13760
- "account-customization"
13761
- )
14696
+ initialContentSource: {
14697
+ type: "account-customization",
14698
+ props: {
14699
+ setCurrentContent
14700
+ }
14701
+ },
14702
+ onBack: () => setCurrentContent({
14703
+ type: "account-customization",
14704
+ props: {
14705
+ setCurrentContent
14706
+ }
14707
+ })
13762
14708
  }
13763
14709
  });
13764
14710
  }
@@ -13975,7 +14921,8 @@ var CustomizationContent = ({
13975
14921
  };
13976
14922
  var CustomizationSummaryContent = ({
13977
14923
  setCurrentContent,
13978
- changes
14924
+ changes,
14925
+ onDoneRedirectContent
13979
14926
  }) => {
13980
14927
  const { t } = useTranslation();
13981
14928
  const { darkMode: isDark } = useVeChainKitConfig();
@@ -14009,7 +14956,12 @@ var CustomizationSummaryContent = ({
14009
14956
  // Pass the pre-fetched resolver address
14010
14957
  signerAccountAddress: account?.address ?? "",
14011
14958
  onSuccess: async () => {
14012
- refreshMetadata();
14959
+ Analytics.customization.completed({
14960
+ hasAvatar: !!changes.avatarIpfsHash,
14961
+ hasDisplayName: !!changes.displayName,
14962
+ hasDescription: !!changes.description,
14963
+ hasSocials: !!(changes.twitter || changes.website || changes.email)
14964
+ });
14013
14965
  setCurrentContent({
14014
14966
  type: "successful-operation",
14015
14967
  props: {
@@ -14020,10 +14972,29 @@ var CustomizationSummaryContent = ({
14020
14972
  "Your changes have been saved successfully."
14021
14973
  ),
14022
14974
  onDone: () => {
14023
- setCurrentContent("profile");
14975
+ setCurrentContent(onDoneRedirectContent);
14024
14976
  }
14025
14977
  }
14026
14978
  });
14979
+ try {
14980
+ await refreshMetadata();
14981
+ } catch (error) {
14982
+ console.error("Error refreshing data:", error);
14983
+ }
14984
+ },
14985
+ onError: (error) => {
14986
+ if (error && isRejectionError(error?.message ?? "")) {
14987
+ Analytics.customization.dropOff({
14988
+ stage: "confirmation",
14989
+ reason: "wallet_rejected",
14990
+ error: error?.message
14991
+ });
14992
+ } else {
14993
+ Analytics.customization.failed(
14994
+ "confirmation",
14995
+ error instanceof Error ? error.message : "Unknown error"
14996
+ );
14997
+ }
14027
14998
  }
14028
14999
  });
14029
15000
  const onSubmit = async (data) => {
@@ -14053,6 +15024,11 @@ var CustomizationSummaryContent = ({
14053
15024
  }
14054
15025
  } catch (error) {
14055
15026
  console.error("Error saving changes:", error);
15027
+ Analytics.customization.dropOff({
15028
+ stage: "confirmation",
15029
+ reason: "transaction_error",
15030
+ error: error instanceof Error ? error.message : "Unknown error"
15031
+ });
14056
15032
  }
14057
15033
  };
14058
15034
  const renderField = (label, value) => {
@@ -14069,6 +15045,31 @@ var CustomizationSummaryContent = ({
14069
15045
  /* @__PURE__ */ jsx(Text, { fontSize: "md", children: value })
14070
15046
  ] });
14071
15047
  };
15048
+ const handleRetry = () => {
15049
+ Analytics.customization.failed(
15050
+ "confirmation",
15051
+ txError instanceof Error ? txError.message : "Unknown error"
15052
+ );
15053
+ handleSubmit(onSubmit)();
15054
+ };
15055
+ const handleClose = () => {
15056
+ Analytics.customization.dropOff({
15057
+ stage: "confirmation",
15058
+ reason: "modal_closed"
15059
+ });
15060
+ };
15061
+ const handleBack = () => {
15062
+ Analytics.customization.dropOff({
15063
+ stage: "confirmation",
15064
+ reason: "back_button"
15065
+ });
15066
+ setCurrentContent({
15067
+ type: "account-customization",
15068
+ props: {
15069
+ setCurrentContent
15070
+ }
15071
+ });
15072
+ };
14072
15073
  return /* @__PURE__ */ jsxs(Box, { as: "form", onSubmit: handleSubmit(onSubmit), children: [
14073
15074
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
14074
15075
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Confirm Changes") }),
@@ -14076,10 +15077,16 @@ var CustomizationSummaryContent = ({
14076
15077
  ModalBackButton,
14077
15078
  {
14078
15079
  isDisabled: isTransactionPending,
14079
- onClick: () => setCurrentContent("account-customization")
15080
+ onClick: handleBack
14080
15081
  }
14081
15082
  ),
14082
- /* @__PURE__ */ jsx(ModalCloseButton, { isDisabled: isTransactionPending })
15083
+ /* @__PURE__ */ jsx(
15084
+ ModalCloseButton,
15085
+ {
15086
+ isDisabled: isTransactionPending,
15087
+ onClick: handleClose
15088
+ }
15089
+ )
14083
15090
  ] }),
14084
15091
  /* @__PURE__ */ jsx(ModalBody, { children: /* @__PURE__ */ jsxs(VStack, { spacing: 4, align: "stretch", children: [
14085
15092
  changes.avatarIpfsHash && /* @__PURE__ */ jsxs(VStack, { align: "flex-start", w: "full", spacing: 1, children: [
@@ -14106,6 +15113,7 @@ var CustomizationSummaryContent = ({
14106
15113
  isSubmitting: isTransactionPending,
14107
15114
  isTxWaitingConfirmation: isWaitingForWalletConfirmation,
14108
15115
  onConfirm: handleSubmit(onSubmit),
15116
+ onRetry: handleRetry,
14109
15117
  transactionPendingText: t("Saving changes..."),
14110
15118
  txReceipt,
14111
15119
  buttonText: t("Confirm"),
@@ -14136,7 +15144,15 @@ var ProfileContent = ({
14136
15144
  /* @__PURE__ */ jsx(
14137
15145
  ProfileCard,
14138
15146
  {
14139
- onEditClick: () => setCurrentContent("account-customization"),
15147
+ onEditClick: () => {
15148
+ Analytics.customization.started();
15149
+ setCurrentContent({
15150
+ type: "account-customization",
15151
+ props: {
15152
+ setCurrentContent
15153
+ }
15154
+ });
15155
+ },
14140
15156
  address: account?.address ?? "",
14141
15157
  showHeader: false,
14142
15158
  style: {
@@ -14618,6 +15634,10 @@ var ManageCustomTokenContent = ({
14618
15634
  var BridgeContent = ({ setCurrentContent }) => {
14619
15635
  const { t } = useTranslation();
14620
15636
  const { darkMode: isDark } = useVeChainKitConfig();
15637
+ const handleLaunchVeChainEnergy = () => {
15638
+ Analytics.bridge.launchVeChainEnergy();
15639
+ window.open("https://swap.vechain.energy/", "_blank");
15640
+ };
14621
15641
  return /* @__PURE__ */ jsxs(Fragment, { children: [
14622
15642
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
14623
15643
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Bridge") }),
@@ -14634,9 +15654,7 @@ var BridgeContent = ({ setCurrentContent }) => {
14634
15654
  Button,
14635
15655
  {
14636
15656
  variant: "vechainKitSecondary",
14637
- onClick: () => {
14638
- window.open("https://swap.vechain.energy/", "_blank");
14639
- },
15657
+ onClick: handleLaunchVeChainEnergy,
14640
15658
  children: [
14641
15659
  t("Launch vechain.energy"),
14642
15660
  /* @__PURE__ */ jsx(Icon, { as: FaExternalLinkAlt, ml: 2 })
@@ -15238,6 +16256,10 @@ var NotificationItem = ({
15238
16256
  onMarkAsRead
15239
16257
  }) => {
15240
16258
  const { t } = useTranslation();
16259
+ const handleDismiss = () => {
16260
+ Analytics.notifications.dismissed(notification.status);
16261
+ onMarkAsRead(notification.id);
16262
+ };
15241
16263
  if (notification.isRead && !isArchiveView) {
15242
16264
  return null;
15243
16265
  }
@@ -15250,6 +16272,8 @@ var NotificationItem = ({
15250
16272
  pr: 8,
15251
16273
  position: "relative",
15252
16274
  opacity: notification.isRead ? 0.7 : 1,
16275
+ cursor: "pointer",
16276
+ _hover: { opacity: 0.8 },
15253
16277
  children: [
15254
16278
  /* @__PURE__ */ jsx(AlertIcon, { boxSize: "16px" }),
15255
16279
  /* @__PURE__ */ jsxs(Box, { children: [
@@ -15265,7 +16289,10 @@ var NotificationItem = ({
15265
16289
  size: "sm",
15266
16290
  variant: "ghost",
15267
16291
  icon: /* @__PURE__ */ jsx(IoCloseCircle, {}),
15268
- onClick: () => onMarkAsRead(notification.id),
16292
+ onClick: (e) => {
16293
+ e.stopPropagation();
16294
+ handleDismiss();
16295
+ },
15269
16296
  "aria-label": "Mark as read and archive"
15270
16297
  }
15271
16298
  )
@@ -15288,11 +16315,16 @@ var NotificationsContent = ({ setCurrentContent }) => {
15288
16315
  getArchivedNotifications()
15289
16316
  );
15290
16317
  const handleClearAll = () => {
16318
+ Analytics.notifications.cleared(void 0, notifications.length);
15291
16319
  clearAllNotifications();
15292
16320
  setArchivedNotifications([...archivedNotifications, ...notifications]);
15293
16321
  setNotifications([]);
15294
16322
  };
15295
16323
  const handleMarkAsRead = (id) => {
16324
+ const notification = notifications.find((n) => n.id === id);
16325
+ if (notification) {
16326
+ Analytics.notifications.archived(notification.status);
16327
+ }
15296
16328
  markAsRead(id);
15297
16329
  const notificationToArchive = notifications.find((n) => n.id === id);
15298
16330
  setNotifications(notifications.filter((n) => n.id !== id));
@@ -15303,6 +16335,12 @@ var NotificationsContent = ({ setCurrentContent }) => {
15303
16335
  ]);
15304
16336
  }
15305
16337
  };
16338
+ const handleToggleView = () => {
16339
+ Analytics.notifications.toggleView(
16340
+ isArchiveView ? "current" : "archived"
16341
+ );
16342
+ setIsArchiveView(!isArchiveView);
16343
+ };
15306
16344
  const currentNotifications = isArchiveView ? archivedNotifications : notifications;
15307
16345
  const sortedNotifications = [...currentNotifications].sort((a, b) => {
15308
16346
  if (a.id === "welcome") return -1;
@@ -15338,7 +16376,7 @@ var NotificationsContent = ({ setCurrentContent }) => {
15338
16376
  }
15339
16377
  ),
15340
16378
  size: "sm",
15341
- onClick: () => setIsArchiveView(!isArchiveView),
16379
+ onClick: handleToggleView,
15342
16380
  children: isArchiveView ? t("Current") : t("Archived")
15343
16381
  }
15344
16382
  ),
@@ -15412,6 +16450,21 @@ var AppComponent = ({ xApp, setCurrentContent }) => {
15412
16450
  const { data: logo, isLoading: isLogoLoading } = useIpfsImage(
15413
16451
  appMetadata?.logo
15414
16452
  );
16453
+ const handleAppClick = () => {
16454
+ if (appMetadata?.name) {
16455
+ Analytics.ecosystem.appSelected(appMetadata.name);
16456
+ setCurrentContent({
16457
+ type: "app-overview",
16458
+ props: {
16459
+ name: appMetadata.name,
16460
+ image: logo?.image ?? "",
16461
+ url: appMetadata?.external_url ?? "",
16462
+ description: appMetadata?.description ?? "",
16463
+ setCurrentContent
16464
+ }
16465
+ });
16466
+ }
16467
+ };
15415
16468
  return /* @__PURE__ */ jsx(
15416
16469
  Skeleton,
15417
16470
  {
@@ -15424,18 +16477,7 @@ var AppComponent = ({ xApp, setCurrentContent }) => {
15424
16477
  name: appMetadata?.name ?? "",
15425
16478
  imageUrl: logo?.image ?? "",
15426
16479
  linkUrl: appMetadata?.external_url ?? "",
15427
- onClick: () => {
15428
- setCurrentContent({
15429
- type: "app-overview",
15430
- props: {
15431
- name: appMetadata?.name ?? "",
15432
- image: logo?.image ?? "",
15433
- url: appMetadata?.external_url ?? "",
15434
- description: appMetadata?.description ?? "",
15435
- setCurrentContent
15436
- }
15437
- });
15438
- }
16480
+ onClick: handleAppClick
15439
16481
  }
15440
16482
  )
15441
16483
  }
@@ -15449,22 +16491,27 @@ var CustomAppComponent = ({
15449
16491
  logoComponent,
15450
16492
  setCurrentContent
15451
16493
  }) => {
16494
+ const handleAppClick = () => {
16495
+ Analytics.ecosystem.appSelected(name);
16496
+ setCurrentContent({
16497
+ type: "app-overview",
16498
+ props: {
16499
+ name,
16500
+ image,
16501
+ url,
16502
+ description,
16503
+ logoComponent,
16504
+ setCurrentContent
16505
+ }
16506
+ });
16507
+ };
15452
16508
  return /* @__PURE__ */ jsx(
15453
16509
  SharedAppCard,
15454
16510
  {
15455
16511
  name,
15456
16512
  imageUrl: image,
15457
16513
  linkUrl: url,
15458
- onClick: () => setCurrentContent({
15459
- type: "app-overview",
15460
- props: {
15461
- name,
15462
- image,
15463
- url,
15464
- description,
15465
- logoComponent
15466
- }
15467
- }),
16514
+ onClick: handleAppClick,
15468
16515
  ...logoComponent && { logoComponent }
15469
16516
  }
15470
16517
  );
@@ -15565,6 +16612,16 @@ var ExploreEcosystemContent = ({ setCurrentContent }) => {
15565
16612
  return dapp;
15566
16613
  });
15567
16614
  const { shortcuts } = useEcosystemShortcuts();
16615
+ const handleSearchChange = (e) => {
16616
+ const query = e.target.value;
16617
+ setSearchQuery(query);
16618
+ if (query) {
16619
+ Analytics.ecosystem.searchPerformed(
16620
+ query,
16621
+ filteredDefaultApps.length + filteredDapps.length
16622
+ );
16623
+ }
16624
+ };
15568
16625
  return /* @__PURE__ */ jsxs(Box, { children: [
15569
16626
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
15570
16627
  /* @__PURE__ */ jsx(ModalHeader, { children: t("Ecosystem") }),
@@ -15589,7 +16646,7 @@ var ExploreEcosystemContent = ({ setCurrentContent }) => {
15589
16646
  {
15590
16647
  placeholder: t("Search Apps"),
15591
16648
  value: searchQuery,
15592
- onChange: (e) => setSearchQuery(e.target.value),
16649
+ onChange: handleSearchChange,
15593
16650
  bg: isDark ? "#00000038" : "gray.50",
15594
16651
  borderRadius: "xl",
15595
16652
  height: "56px",
@@ -15633,6 +16690,14 @@ var ShortcutButton = ({ name, image, url, description }) => {
15633
16690
  const { t } = useTranslation();
15634
16691
  const { isShortcut, addShortcut, removeShortcut } = useEcosystemShortcuts();
15635
16692
  const hasShortcut = isShortcut(url);
16693
+ const handleShortcutClick = () => {
16694
+ if (hasShortcut) {
16695
+ removeShortcut(url);
16696
+ } else {
16697
+ Analytics.ecosystem.addAppToShortcuts(name);
16698
+ addShortcut({ name, image, url, description });
16699
+ }
16700
+ };
15636
16701
  return /* @__PURE__ */ jsx(
15637
16702
  Button,
15638
16703
  {
@@ -15641,13 +16706,7 @@ var ShortcutButton = ({ name, image, url, description }) => {
15641
16706
  height: "45px",
15642
16707
  variant: "vechainKitSecondary",
15643
16708
  borderRadius: "xl",
15644
- onClick: () => {
15645
- if (hasShortcut) {
15646
- removeShortcut(url);
15647
- } else {
15648
- addShortcut({ name, image, url, description });
15649
- }
15650
- },
16709
+ onClick: handleShortcutClick,
15651
16710
  leftIcon: /* @__PURE__ */ jsx(Icon, { as: hasShortcut ? BsBookmarkFill : BsBookmark }),
15652
16711
  children: hasShortcut ? t("Remove from shortcuts") : t("Add to shortcuts")
15653
16712
  }
@@ -15662,6 +16721,10 @@ var AppOverviewContent = ({
15662
16721
  logoComponent
15663
16722
  }) => {
15664
16723
  const { t } = useTranslation();
16724
+ const handleLaunchApp = () => {
16725
+ Analytics.ecosystem.launchApp(name);
16726
+ window.open(url, "_blank");
16727
+ };
15665
16728
  return /* @__PURE__ */ jsxs(Box, { children: [
15666
16729
  /* @__PURE__ */ jsxs(StickyHeaderContainer, { children: [
15667
16730
  /* @__PURE__ */ jsx(ModalHeader, { children: name }),
@@ -15696,9 +16759,7 @@ var AppOverviewContent = ({
15696
16759
  Button,
15697
16760
  {
15698
16761
  variant: "vechainKitSecondary",
15699
- onClick: () => {
15700
- window.open(url, "_blank");
15701
- },
16762
+ onClick: handleLaunchApp,
15702
16763
  children: [
15703
16764
  t("Launch {{name}}", { name }),
15704
16765
  /* @__PURE__ */ jsx(Icon, { as: FaExternalLinkAlt, ml: 2 })
@@ -16075,7 +17136,7 @@ var SuccessfulOperationContent = ({
16075
17136
  justifyContent: "center",
16076
17137
  children: [
16077
17138
  /* @__PURE__ */ jsx(Text, { children: t("View transaction on the explorer") }),
16078
- /* @__PURE__ */ jsx(Icon, { size: "sm", as: GoLinkExternal })
17139
+ /* @__PURE__ */ jsx(Icon, { size: 16, as: GoLinkExternal })
16079
17140
  ]
16080
17141
  }
16081
17142
  )
@@ -16098,6 +17159,7 @@ var AccountModal = ({
16098
17159
  useEffect(() => {
16099
17160
  if (isOpen && initialContent) {
16100
17161
  setCurrentContent(initialContent);
17162
+ Analytics.wallet.opened(!!account);
16101
17163
  }
16102
17164
  }, [isOpen, initialContent, setCurrentContent]);
16103
17165
  const renderContent = () => {
@@ -16143,6 +17205,14 @@ var AccountModal = ({
16143
17205
  return /* @__PURE__ */ jsx(UpgradeSmartAccountContent, { ...currentContent.props });
16144
17206
  case "faq":
16145
17207
  return /* @__PURE__ */ jsx(FAQContent, { ...currentContent.props });
17208
+ case "account-customization":
17209
+ return /* @__PURE__ */ jsx(
17210
+ CustomizationContent,
17211
+ {
17212
+ ...currentContent.props,
17213
+ setCurrentContent
17214
+ }
17215
+ );
16146
17216
  }
16147
17217
  }
16148
17218
  switch (currentContent) {
@@ -16160,7 +17230,10 @@ var AccountModal = ({
16160
17230
  SettingsContent,
16161
17231
  {
16162
17232
  setCurrentContent,
16163
- onLogoutSuccess: onClose
17233
+ onLogoutSuccess: () => {
17234
+ Analytics.auth.logoutCompleted();
17235
+ onClose();
17236
+ }
16164
17237
  }
16165
17238
  );
16166
17239
  case "profile":
@@ -16168,7 +17241,10 @@ var AccountModal = ({
16168
17241
  ProfileContent,
16169
17242
  {
16170
17243
  setCurrentContent,
16171
- onLogoutSuccess: onClose
17244
+ onLogoutSuccess: () => {
17245
+ Analytics.auth.logoutCompleted();
17246
+ onClose();
17247
+ }
16172
17248
  }
16173
17249
  );
16174
17250
  case "assets":
@@ -16219,13 +17295,6 @@ var AccountModal = ({
16219
17295
  setCurrentContent
16220
17296
  }
16221
17297
  );
16222
- case "account-customization":
16223
- return /* @__PURE__ */ jsx(
16224
- CustomizationContent,
16225
- {
16226
- setCurrentContent
16227
- }
16228
- );
16229
17298
  case "embedded-wallet":
16230
17299
  return /* @__PURE__ */ jsx(
16231
17300
  EmbeddedWalletContent,
@@ -16292,7 +17361,8 @@ var ConnectionButton = ({
16292
17361
  customIcon,
16293
17362
  rightIcon,
16294
17363
  style,
16295
- variant = "loginIn"
17364
+ variant = "loginIn",
17365
+ iconWidth = "25px"
16296
17366
  }) => {
16297
17367
  if (!text) {
16298
17368
  return /* @__PURE__ */ jsx(Button, { ...style, variant, w: "full", onClick, children: customIcon ? customIcon : /* @__PURE__ */ jsx(Icon, { as: icon, w: "20px", h: "20px" }) });
@@ -16300,7 +17370,7 @@ var ConnectionButton = ({
16300
17370
  if (text) {
16301
17371
  return /* @__PURE__ */ jsxs(Button, { ...style, variant, w: "full", onClick, children: [
16302
17372
  /* @__PURE__ */ jsxs(HStack, { w: "full", justify: "flex-start", gap: 2, children: [
16303
- customIcon ? customIcon : /* @__PURE__ */ jsx(Icon, { as: icon, w: "25px", h: "25px" }),
17373
+ customIcon ? customIcon : /* @__PURE__ */ jsx(Icon, { as: icon, w: iconWidth, h: iconWidth }),
16304
17374
  /* @__PURE__ */ jsx(Text, { opacity: 0.9, children: text })
16305
17375
  ] }),
16306
17376
  rightIcon
@@ -16313,6 +17383,15 @@ var ConnectPopover = ({
16313
17383
  buttonStyle
16314
17384
  }) => {
16315
17385
  const { t } = useTranslation();
17386
+ const {
17387
+ loginMethods,
17388
+ darkMode: isDark,
17389
+ privyEcosystemAppIDS
17390
+ } = useVeChainKitConfig();
17391
+ const showEcosystemButton = loginMethods?.some(
17392
+ ({ method: method35 }) => method35 === "ecosystem"
17393
+ );
17394
+ const { data: appsInfo, isLoading: isEcosystemAppsLoading } = useFetchAppInfo(privyEcosystemAppIDS);
16316
17395
  return /* @__PURE__ */ jsx(
16317
17396
  Popover,
16318
17397
  {
@@ -16341,7 +17420,17 @@ var ConnectPopover = ({
16341
17420
  ]
16342
17421
  }
16343
17422
  ) }),
16344
- /* @__PURE__ */ jsx(PopoverContent, { children: /* @__PURE__ */ jsx(PopoverBody, { children: /* @__PURE__ */ jsx(ConnectionOptionsStack, {}) }) })
17423
+ /* @__PURE__ */ jsxs(PopoverContent, { children: [
17424
+ /* @__PURE__ */ jsx(PopoverBody, { children: /* @__PURE__ */ jsx(ConnectionOptionsStack, {}) }),
17425
+ /* @__PURE__ */ jsx(PopoverFooter, { borderTop: "none", pb: "15px", children: showEcosystemButton && /* @__PURE__ */ jsx(HStack, { justify: "center", w: "full", children: /* @__PURE__ */ jsx(
17426
+ EcosystemButton,
17427
+ {
17428
+ isDark,
17429
+ appsInfo: Object.values(appsInfo || {}),
17430
+ isLoading: isEcosystemAppsLoading
17431
+ }
17432
+ ) }) })
17433
+ ] })
16345
17434
  ] })
16346
17435
  }
16347
17436
  );
@@ -16429,16 +17518,20 @@ var WalletButton = ({
16429
17518
  connectionVariant = "modal"
16430
17519
  }) => {
16431
17520
  const { t } = useTranslation();
16432
- const { darkMode } = useVeChainKitConfig();
17521
+ const { darkMode, loginMethods } = useVeChainKitConfig();
17522
+ const hasOnlyDappKit = loginMethods?.length === 1 && loginMethods[0].method === "dappkit";
16433
17523
  const { connection, account } = useWallet();
16434
17524
  const { setSource, connect } = useWallet$1();
16435
17525
  const [isMobile3] = useMediaQuery("(max-width: 768px)");
16436
17526
  const connectModal = useDisclosure();
16437
17527
  const accountModal = useDisclosure();
17528
+ const { open: openDappKit } = useWalletModal();
16438
17529
  const handleConnect = () => {
16439
17530
  if (connection.isInAppBrowser) {
16440
17531
  setSource("veworld");
16441
17532
  connect();
17533
+ } else if (hasOnlyDappKit) {
17534
+ openDappKit();
16442
17535
  } else {
16443
17536
  connectModal.onOpen();
16444
17537
  }
@@ -16840,6 +17933,7 @@ var EcosystemContent = ({ onClose, appsInfo, isLoading }) => {
16840
17933
  const [loginError, setLoginError] = useState();
16841
17934
  const [selectedApp, setSelectedApp] = useState();
16842
17935
  const loginLoadingModal = useDisclosure();
17936
+ const { user } = usePrivy();
16843
17937
  const { setConnectionCache } = useCrossAppConnectionCache();
16844
17938
  const { login: loginWithCrossApp } = usePrivyCrossAppSdk();
16845
17939
  const connectWithVebetterDaoApps = async (appId, appName) => {
@@ -16849,6 +17943,9 @@ var EcosystemContent = ({ onClose, appsInfo, isLoading }) => {
16849
17943
  setSelectedApp(appName);
16850
17944
  try {
16851
17945
  await loginWithCrossApp(appId);
17946
+ Analytics.auth.trackAuth("connect_initiated", {
17947
+ totalConnections: appsInfo.length
17948
+ });
16852
17949
  loginLoadingModal.onClose();
16853
17950
  setConnectionCache({
16854
17951
  name: appName,
@@ -16856,10 +17953,17 @@ var EcosystemContent = ({ onClose, appsInfo, isLoading }) => {
16856
17953
  appId,
16857
17954
  website: appsInfo.find((app) => app.id === appId)?.website
16858
17955
  });
17956
+ Analytics.auth.completed({
17957
+ userId: user?.id,
17958
+ loginMethod: "ecosystem" /* ECOSYSTEM */
17959
+ });
16859
17960
  onClose();
16860
17961
  } catch (error) {
16861
17962
  const errorMsg = error?.message;
16862
- if (errorMsg?.includes("rejected") || errorMsg?.includes("closed")) {
17963
+ if (errorMsg && isRejectionError(errorMsg)) {
17964
+ Analytics.auth.dropOff("ecosystem-app-connect", {
17965
+ ...appName && { appName }
17966
+ });
16863
17967
  return new Error("Login request was cancelled.");
16864
17968
  }
16865
17969
  const errorToShow = error instanceof Error ? error : new Error(
@@ -16876,30 +17980,26 @@ var EcosystemContent = ({ onClose, appsInfo, isLoading }) => {
16876
17980
  };
16877
17981
  const handleTryAgain = () => {
16878
17982
  if (selectedApp) {
17983
+ Analytics.auth.tryAgain("ecosystem" /* ECOSYSTEM */, selectedApp);
16879
17984
  const app = appsInfo.find((app2) => app2.name === selectedApp);
16880
17985
  if (app) {
16881
17986
  connectWithVebetterDaoApps(app.id, app.name);
16882
17987
  }
16883
17988
  }
16884
17989
  };
17990
+ const handleClose = () => {
17991
+ Analytics.auth.dropOff("ecosystem-view", {
17992
+ ...selectedApp && { appName: selectedApp }
17993
+ });
17994
+ onClose();
17995
+ };
16885
17996
  return /* @__PURE__ */ jsxs(Box, { children: [
16886
17997
  /* @__PURE__ */ jsxs(Fragment, { children: [
16887
17998
  /* @__PURE__ */ jsx(StickyHeaderContainer, { children: /* @__PURE__ */ jsxs(ModalHeader, { children: [
16888
- t("Already have an app account?"),
16889
- /* @__PURE__ */ jsx(ModalCloseButton, {})
17999
+ t("Already have an x2earn app wallet?"),
18000
+ /* @__PURE__ */ jsx(ModalCloseButton, { onClick: handleClose })
16890
18001
  ] }) }),
16891
18002
  /* @__PURE__ */ jsxs(ModalBody, { children: [
16892
- /* @__PURE__ */ jsx(
16893
- Text,
16894
- {
16895
- fontSize: "12px",
16896
- fontWeight: "400",
16897
- opacity: 0.5,
16898
- mb: 4,
16899
- textAlign: "center",
16900
- children: t("Sign in with a wallet from other x2earn apps.")
16901
- }
16902
- ),
16903
18003
  isLoading && /* @__PURE__ */ jsx(
16904
18004
  VStack,
16905
18005
  {
@@ -17118,7 +18218,8 @@ var ProfileCard = ({
17118
18218
  isLoadingMetadata: metadata?.isLoading,
17119
18219
  metadata: metadata?.records
17120
18220
  },
17121
- style: { mt: 4 }
18221
+ style: { mt: 4 },
18222
+ fromScreen: "profile"
17122
18223
  }
17123
18224
  )
17124
18225
  ] })
@@ -17233,7 +18334,7 @@ var SuccessfulOperationContent2 = ({
17233
18334
  justifyContent: "center",
17234
18335
  children: [
17235
18336
  /* @__PURE__ */ jsx(Text, { children: t("View transaction on the explorer") }),
17236
- /* @__PURE__ */ jsx(Icon, { size: "sm", as: GoLinkExternal })
18337
+ /* @__PURE__ */ jsx(Icon, { size: 16, as: GoLinkExternal })
17237
18338
  ]
17238
18339
  }
17239
18340
  )
@@ -17559,12 +18660,15 @@ var ModalProvider = ({ children }) => {
17559
18660
  );
17560
18661
  };
17561
18662
  var useConnectModal = () => {
17562
- const {
17563
- openConnectModal: open,
17564
- closeConnectModal: close,
17565
- isConnectModalOpen: isOpen
17566
- } = useModal();
17567
- return { open, close, isOpen };
18663
+ const { loginMethods } = useVeChainKitConfig();
18664
+ const hasOnlyDappKit = loginMethods?.length === 1 && loginMethods[0].method === "dappkit";
18665
+ const { openConnectModal, closeConnectModal, isConnectModalOpen } = useModal();
18666
+ const { open: openDappKit, close: closeDappKit } = useWalletModal();
18667
+ return {
18668
+ open: hasOnlyDappKit ? openDappKit : openConnectModal,
18669
+ close: hasOnlyDappKit ? closeDappKit : closeConnectModal,
18670
+ isOpen: hasOnlyDappKit ? false : isConnectModalOpen
18671
+ };
17568
18672
  };
17569
18673
  var ConnectModalProvider = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
17570
18674
  var useAccountModal = () => {
@@ -17758,9 +18862,19 @@ var useFAQModal = () => {
17758
18862
  };
17759
18863
  var FAQModalProvider = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
17760
18864
  var useAccountCustomizationModal = () => {
17761
- const { openAccountModal, closeAccountModal, isAccountModalOpen } = useModal();
18865
+ const {
18866
+ openAccountModal,
18867
+ closeAccountModal,
18868
+ isAccountModalOpen,
18869
+ setAccountModalContent
18870
+ } = useModal();
17762
18871
  const open = () => {
17763
- openAccountModal("account-customization");
18872
+ openAccountModal({
18873
+ type: "account-customization",
18874
+ props: {
18875
+ setCurrentContent: setAccountModalContent
18876
+ }
18877
+ });
17764
18878
  };
17765
18879
  const close = () => {
17766
18880
  closeAccountModal();
@@ -17926,8 +19040,8 @@ var useTransferERC20 = ({
17926
19040
  buttonText: "Sign to continue"
17927
19041
  },
17928
19042
  onTxConfirmed: handleOnSuccess,
17929
- onTxFailedOrCancelled: async () => {
17930
- onError?.();
19043
+ onTxFailedOrCancelled: async (error) => {
19044
+ onError?.(error instanceof Error ? error.message : String(error));
17931
19045
  }
17932
19046
  });
17933
19047
  return {
@@ -17979,8 +19093,8 @@ var useTransferVET = ({
17979
19093
  refresh();
17980
19094
  onSuccess?.();
17981
19095
  },
17982
- onTxFailedOrCancelled: async () => {
17983
- onError?.();
19096
+ onTxFailedOrCancelled: async (error) => {
19097
+ onError?.(error instanceof Error ? error.message : String(error));
17984
19098
  }
17985
19099
  });
17986
19100
  return {
@@ -18104,23 +19218,62 @@ var useSignTypedData2 = () => {
18104
19218
  };
18105
19219
  var useLoginWithPasskey = () => {
18106
19220
  const { loginWithPasskey: privyLoginWithPasskey } = useLoginWithPasskey$1();
19221
+ const { user } = usePrivy();
18107
19222
  const loginWithPasskey = async () => {
18108
19223
  try {
19224
+ Analytics.auth.flowStarted("passkey" /* PASSKEY */);
19225
+ Analytics.auth.methodSelected("passkey" /* PASSKEY */);
18109
19226
  await privyLoginWithPasskey();
19227
+ Analytics.auth.completed({
19228
+ userId: user?.id,
19229
+ loginMethod: "passkey" /* PASSKEY */
19230
+ });
18110
19231
  } catch (error) {
18111
- console.error("Passkey login failed:", error);
19232
+ Analytics.auth.failed(
19233
+ "passkey" /* PASSKEY */,
19234
+ error instanceof Error ? error.message : "Unknown error"
19235
+ );
18112
19236
  throw error;
18113
19237
  }
18114
19238
  };
18115
19239
  return { loginWithPasskey };
18116
19240
  };
19241
+ var providerToLoginMethod = {
19242
+ google: "google" /* GOOGLE */,
19243
+ twitter: "email" /* EMAIL */,
19244
+ apple: "email" /* EMAIL */,
19245
+ discord: "email" /* EMAIL */
19246
+ };
19247
+ var providerToSocialMethod = {
19248
+ google: "email" /* EMAIL */,
19249
+ twitter: "X" /* X */,
19250
+ apple: "email" /* EMAIL */,
19251
+ discord: "Discord" /* DISCORD */
19252
+ };
18117
19253
  var useLoginWithOAuth2 = () => {
18118
19254
  const { initOAuth: privyInitOAuth } = useLoginWithOAuth();
19255
+ const { user } = usePrivy();
18119
19256
  const initOAuth = async ({ provider }) => {
19257
+ const loginMethod = providerToLoginMethod[provider];
19258
+ const socialMethod = providerToSocialMethod[provider];
18120
19259
  try {
19260
+ Analytics.auth.flowStarted(loginMethod);
19261
+ Analytics.auth.methodSelected(loginMethod);
18121
19262
  await privyInitOAuth({ provider });
19263
+ Analytics.auth.completed({
19264
+ userId: user?.id,
19265
+ loginMethod,
19266
+ platform: socialMethod
19267
+ });
18122
19268
  } catch (error) {
18123
- console.error("OAuth login failed:", error);
19269
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
19270
+ if (isRejectionError(errorMsg)) {
19271
+ Analytics.auth.dropOff("oauth", {
19272
+ ...provider && { provider }
19273
+ });
19274
+ } else {
19275
+ Analytics.auth.failed(loginMethod, errorMsg);
19276
+ }
18124
19277
  throw error;
18125
19278
  }
18126
19279
  };
@@ -18158,8 +19311,10 @@ var useLoginWithVeChain = () => {
18158
19311
  const { login: loginWithVeChain } = usePrivyCrossAppSdk();
18159
19312
  const { setConnectionCache } = useCrossAppConnectionCache();
18160
19313
  const { data: appsInfo } = useFetchAppInfo([VECHAIN_PRIVY_APP_ID]);
19314
+ const { user } = usePrivy();
18161
19315
  const login = async () => {
18162
19316
  try {
19317
+ Analytics.auth.methodSelected("vechain" /* VECHAIN */);
18163
19318
  await loginWithVeChain(VECHAIN_PRIVY_APP_ID);
18164
19319
  setConnectionCache({
18165
19320
  name: "VeChain",
@@ -18167,7 +19322,17 @@ var useLoginWithVeChain = () => {
18167
19322
  appId: VECHAIN_PRIVY_APP_ID,
18168
19323
  website: "https://governance.vebetterdao.org"
18169
19324
  });
19325
+ Analytics.auth.completed({
19326
+ userId: user?.id,
19327
+ loginMethod: "vechain" /* VECHAIN */
19328
+ });
18170
19329
  } catch (error) {
19330
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
19331
+ if (isRejectionError(errorMsg)) {
19332
+ Analytics.auth.dropOff("vechain-approval");
19333
+ } else {
19334
+ Analytics.auth.failed("vechain" /* VECHAIN */, errorMsg);
19335
+ }
18171
19336
  throw handlePopupError({
18172
19337
  error,
18173
19338
  mobileBrowserPopupMessage: "Your mobile browser blocked the login window. Please click 'Try again' to open the login window or change your browser settings.",
@@ -18759,6 +19924,9 @@ var VeChainKitProvider = (props) => {
18759
19924
  });
18760
19925
  }
18761
19926
  }, [language, i18nConfig]);
19927
+ useEffect(() => {
19928
+ localStorage.setItem(VECHAIN_KIT_STORAGE_KEYS.NETWORK, network.type);
19929
+ }, [network]);
18762
19930
  return /* @__PURE__ */ jsxs(EnsureQueryClient, { children: [
18763
19931
  /* @__PURE__ */ jsx(ReactQueryDevtools, { initialIsOpen: false }),
18764
19932
  /* @__PURE__ */ jsx(PrivyCrossAppProvider, { privyEcosystemAppIDS: allowedEcosystemApps, children: /* @__PURE__ */ jsx(