From a162642097ba4cdc85d2ecc5c65ba0e04afe61d9 Mon Sep 17 00:00:00 2001 From: Minimoi Date: Wed, 21 Jan 2026 17:05:48 +0100 Subject: [PATCH 1/7] auto-claude: subtask-1-1 - Add useRef to track if save has already been attempted Add saveAttemptedRef to prevent duplicate wallet saves when both handleViewWallet and handleClose could trigger saveAndSelectWallet. The ref is checked at the start of saveAndSelectWallet and set to true before proceeding with the save. Co-Authored-By: Claude Opus 4.5 --- .../routes/CreateWallet/CreateSuccess.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx index c7110c3db06..6632703401f 100644 --- a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx @@ -1,6 +1,6 @@ import { Button, Icon, Text, VStack } from '@chakra-ui/react' import { useQueryClient } from '@tanstack/react-query' -import { useCallback } from 'react' +import { useCallback, useRef } from 'react' import { IoIosCheckmarkCircle } from 'react-icons/io' import { useTranslate } from 'react-polyglot' import type { Location } from 'react-router-dom' @@ -33,8 +33,12 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { const queryClient = useQueryClient() const { dispatch, getAdapter } = useWallet() const localWallet = useLocalWallet() + const saveAttemptedRef = useRef(false) const saveAndSelectWallet = useCallback(async () => { + if (saveAttemptedRef.current) return + saveAttemptedRef.current = true + if (location.state?.vault?.label && location.state?.vault?.mnemonic) { const wallet = await addWallet({ label: location.state.vault.label, From e8f198ce475a425d5ea404cd19087353ccdf38ab Mon Sep 17 00:00:00 2001 From: Minimoi Date: Wed, 21 Jan 2026 17:08:15 +0100 Subject: [PATCH 2/7] auto-claude: subtask-1-2 - Add useEffect to call saveAndSelectWallet() on mount This ensures the wallet is saved immediately when the CreateSuccess screen renders, rather than only when the user clicks the "View wallet" button. The existing saveAttemptedRef prevents duplicate save attempts. Co-Authored-By: Claude Opus 4.5 --- .../routes/CreateWallet/CreateSuccess.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx index 6632703401f..b4e5a3f13e9 100644 --- a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx @@ -1,6 +1,6 @@ import { Button, Icon, Text, VStack } from '@chakra-ui/react' import { useQueryClient } from '@tanstack/react-query' -import { useCallback, useRef } from 'react' +import { useCallback, useEffect, useRef } from 'react' import { IoIosCheckmarkCircle } from 'react-icons/io' import { useTranslate } from 'react-polyglot' import type { Location } from 'react-router-dom' @@ -97,6 +97,10 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { setWelcomeModal, ]) + useEffect(() => { + saveAndSelectWallet() + }, [saveAndSelectWallet]) + const handleViewWallet = useCallback(() => { saveAndSelectWallet() onClose() From dc84f31cd4b67cd671e2c5b856fa9d240e7750d2 Mon Sep 17 00:00:00 2001 From: Minimoi Date: Wed, 21 Jan 2026 17:10:21 +0100 Subject: [PATCH 3/7] auto-claude: subtask-2-1 - Add useRef to track if connection has already been Add hasConnectedRef to prevent duplicate wallet connection attempts in ImportSuccess component. This follows the same pattern used in ManualBackup.tsx. Co-Authored-By: Claude Opus 4.5 --- .../MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx index c822e7dfd1a..6b1d2c323d4 100644 --- a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx @@ -1,6 +1,6 @@ import { Button, Icon, VStack } from '@chakra-ui/react' import type { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' -import { useCallback } from 'react' +import { useCallback, useRef } from 'react' import { IoIosCheckmarkCircle } from 'react-icons/io' import { useTranslate } from 'react-polyglot' import type { Location } from 'react-router-dom' @@ -32,9 +32,12 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { const { getAdapter, dispatch } = useWallet() const localWallet = useLocalWallet() const translate = useTranslate() + const hasConnectedRef = useRef(false) const handleWalletConnection = useCallback(async () => { + if (hasConnectedRef.current) return if (!location.state?.vault) return + hasConnectedRef.current = true const adapter = await getAdapter(KeyManager.Mobile) if (!adapter) throw new Error('Native adapter not found') try { From f55ce41915e5bbf6efbdeba57dae2d22a8a97f9f Mon Sep 17 00:00:00 2001 From: Minimoi Date: Wed, 21 Jan 2026 17:12:32 +0100 Subject: [PATCH 4/7] auto-claude: subtask-2-2 - Add useEffect that calls handleWalletConnection() Adds a useEffect hook that calls handleWalletConnection() on component mount. This ensures the wallet is connected immediately when ImportSuccess mounts, rather than only when the user clicks the close/view wallet button. Duplicate calls are prevented by the existing hasConnectedRef guard in handleWalletConnection(). Co-Authored-By: Claude Opus 4.5 --- .auto-claude-security.json | 307 ++++++++++++++++++ .auto-claude-status | 25 ++ .claude_settings.json | 39 +++ .gitignore | 3 + .../routes/ImportWallet/ImportSuccess.tsx | 6 +- 5 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 .auto-claude-security.json create mode 100644 .auto-claude-status create mode 100644 .claude_settings.json diff --git a/.auto-claude-security.json b/.auto-claude-security.json new file mode 100644 index 00000000000..49d630db104 --- /dev/null +++ b/.auto-claude-security.json @@ -0,0 +1,307 @@ +{ + "base_commands": [ + ".", + "[", + "[[", + "ag", + "awk", + "basename", + "bash", + "bc", + "break", + "cat", + "cd", + "chmod", + "clear", + "cmp", + "column", + "comm", + "command", + "continue", + "cp", + "curl", + "cut", + "date", + "df", + "diff", + "dig", + "dirname", + "du", + "echo", + "egrep", + "env", + "eval", + "exec", + "exit", + "expand", + "export", + "expr", + "false", + "fd", + "fgrep", + "file", + "find", + "fmt", + "fold", + "gawk", + "gh", + "git", + "grep", + "gunzip", + "gzip", + "head", + "help", + "host", + "iconv", + "id", + "jobs", + "join", + "jq", + "kill", + "killall", + "less", + "let", + "ln", + "ls", + "lsof", + "man", + "mkdir", + "mktemp", + "more", + "mv", + "nl", + "paste", + "pgrep", + "ping", + "pkill", + "popd", + "printenv", + "printf", + "ps", + "pushd", + "pwd", + "read", + "readlink", + "realpath", + "reset", + "return", + "rev", + "rg", + "rm", + "rmdir", + "sed", + "seq", + "set", + "sh", + "shuf", + "sleep", + "sort", + "source", + "split", + "stat", + "tail", + "tar", + "tee", + "test", + "time", + "timeout", + "touch", + "tr", + "tree", + "true", + "type", + "uname", + "unexpand", + "uniq", + "unset", + "unzip", + "watch", + "wc", + "wget", + "whereis", + "which", + "whoami", + "xargs", + "yes", + "yq", + "zip", + "zsh" + ], + "stack_commands": [ + "ant", + "ar", + "cargo", + "cargo-audit", + "cargo-clippy", + "cargo-deny", + "cargo-dist", + "cargo-doc", + "cargo-edit", + "cargo-fmt", + "cargo-llvm-cov", + "cargo-make", + "cargo-miri", + "cargo-nextest", + "cargo-outdated", + "cargo-release", + "cargo-tarpaulin", + "cargo-update", + "cargo-watch", + "cargo-xtask", + "clang", + "clang++", + "cmake", + "composer", + "cross", + "dotnet", + "eslint", + "g++", + "gcc", + "gradle", + "gradlew", + "ipython", + "jar", + "java", + "javac", + "jupyter", + "kotlin", + "kotlinc", + "ld", + "make", + "maven", + "mdbook", + "meson", + "msbuild", + "mvn", + "ninja", + "nm", + "node", + "notebook", + "npm", + "npx", + "nuget", + "nvm", + "objdump", + "pdb", + "php", + "pip", + "pip3", + "pipx", + "prettier", + "pudb", + "pyenv", + "python", + "python3", + "railway", + "react-scripts", + "rust-analyzer", + "rustc", + "rustfmt", + "rustup", + "strip", + "swift", + "swiftc", + "trunk", + "ts-node", + "tsc", + "tsx", + "vite", + "vitest", + "wasm-bindgen", + "wasm-pack", + "xcodebuild", + "yarn" + ], + "script_commands": [ + "bun", + "npm", + "pnpm", + "yarn" + ], + "custom_commands": [], + "detected_stack": { + "languages": [ + "python", + "javascript", + "typescript", + "rust", + "php", + "java", + "kotlin", + "csharp", + "c", + "cpp", + "swift" + ], + "package_managers": [ + "yarn" + ], + "frameworks": [ + "react", + "vite", + "vitest", + "eslint", + "prettier" + ], + "databases": [], + "infrastructure": [], + "cloud_providers": [ + "railway" + ], + "code_quality_tools": [], + "version_managers": [ + "nvm", + "pyenv" + ] + }, + "custom_scripts": { + "npm_scripts": [ + "dev", + "preview:prod", + "preview:dev", + "preview:private", + "analyze", + "bump", + "build:web", + "build:packages", + "postbuild:packages", + "clean", + "clean:web", + "clean:packages", + "codemod:clear-assets-migration", + "deadcode", + "dev:web", + "dev:web:linked", + "dev:packages", + "dev:swap-widget", + "generate:all", + "generate:caip-adapters", + "generate:asset-data", + "generate:related-asset-index", + "generate:color-map", + "generate:tradable-asset-map", + "generate:thor-longtail-tokens", + "local-ci", + "lint", + "lint:fix", + "postinstall", + "release", + "scrape-walletconnect-dapps", + "test", + "test:web", + "test:packages", + "translations:count-words-invalidate-since", + "translations:update-path", + "type-check", + "type-check-watch" + ], + "make_targets": [], + "poetry_scripts": [], + "cargo_aliases": [], + "shell_scripts": [] + }, + "project_dir": "/Users/mini/Projects/web", + "created_at": "2026-01-21T16:42:42.608501", + "project_hash": "62212c8725a9ce3b1ff788c34711de24", + "inherited_from": "/Users/mini/Projects/web" +} \ No newline at end of file diff --git a/.auto-claude-status b/.auto-claude-status new file mode 100644 index 00000000000..8f769ade3d8 --- /dev/null +++ b/.auto-claude-status @@ -0,0 +1,25 @@ +{ + "active": true, + "spec": "010-clicking-off-of-view-wallet-in-create-wallet-flow-", + "state": "building", + "subtasks": { + "completed": 3, + "total": 6, + "in_progress": 1, + "failed": 0 + }, + "phase": { + "current": "Fix Import Wallet Flow Connection", + "id": null, + "total": 2 + }, + "workers": { + "active": 0, + "max": 1 + }, + "session": { + "number": 4, + "started_at": "2026-01-21T17:04:58.690509" + }, + "last_update": "2026-01-21T17:10:48.207264" +} \ No newline at end of file diff --git a/.claude_settings.json b/.claude_settings.json new file mode 100644 index 00000000000..2f707b1f21c --- /dev/null +++ b/.claude_settings.json @@ -0,0 +1,39 @@ +{ + "sandbox": { + "enabled": true, + "autoAllowBashIfSandboxed": true + }, + "permissions": { + "defaultMode": "acceptEdits", + "allow": [ + "Read(./**)", + "Write(./**)", + "Edit(./**)", + "Glob(./**)", + "Grep(./**)", + "Read(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Write(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Edit(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Glob(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Grep(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Read(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/.auto-claude/specs/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Write(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/.auto-claude/specs/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Edit(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/.auto-claude/specs/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", + "Read(/Users/mini/Projects/web/.auto-claude/**)", + "Write(/Users/mini/Projects/web/.auto-claude/**)", + "Edit(/Users/mini/Projects/web/.auto-claude/**)", + "Glob(/Users/mini/Projects/web/.auto-claude/**)", + "Grep(/Users/mini/Projects/web/.auto-claude/**)", + "Bash(*)", + "WebFetch(*)", + "WebSearch(*)", + "mcp__context7__resolve-library-id(*)", + "mcp__context7__get-library-docs(*)", + "mcp__graphiti-memory__search_nodes(*)", + "mcp__graphiti-memory__search_facts(*)", + "mcp__graphiti-memory__add_episode(*)", + "mcp__graphiti-memory__get_episodes(*)", + "mcp__graphiti-memory__get_entity_edge(*)" + ] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6be6cb15e17..ee3e012249a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ yarn-error.log* *.iml .idea/ .playwright-mcp/ + +# Auto Claude data directory +.auto-claude/ diff --git a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx index 6b1d2c323d4..9249f2f1d63 100644 --- a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx @@ -1,6 +1,6 @@ import { Button, Icon, VStack } from '@chakra-ui/react' import type { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' -import { useCallback, useRef } from 'react' +import { useCallback, useEffect, useRef } from 'react' import { IoIosCheckmarkCircle } from 'react-icons/io' import { useTranslate } from 'react-polyglot' import type { Location } from 'react-router-dom' @@ -83,6 +83,10 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { setTimeout(() => location.state?.vault?.revoke(), 500) }, [onClose, appDispatch, setWelcomeModal, handleWalletConnection, location.state?.vault]) + useEffect(() => { + handleWalletConnection() + }, [handleWalletConnection]) + return ( From 46b43d90ecd743a0fdd7d73a6c0862d70a02367b Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:04:41 +0100 Subject: [PATCH 5/7] fix: wallet import modal dismiss showing wallet --- .../routes/CreateWallet/CreateSuccess.tsx | 68 ++++++++++++------- .../routes/ImportWallet/ImportSuccess.tsx | 53 +++++++++++---- src/pages/ConnectWallet/MobileConnect.tsx | 55 +++++++-------- 3 files changed, 110 insertions(+), 66 deletions(-) diff --git a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx index b4e5a3f13e9..8c6aac86a29 100644 --- a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx @@ -1,6 +1,6 @@ import { Button, Icon, Text, VStack } from '@chakra-ui/react' import { useQueryClient } from '@tanstack/react-query' -import { useCallback, useEffect, useRef } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { IoIosCheckmarkCircle } from 'react-icons/io' import { useTranslate } from 'react-polyglot' import type { Location } from 'react-router-dom' @@ -34,11 +34,30 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { const { dispatch, getAdapter } = useWallet() const localWallet = useLocalWallet() const saveAttemptedRef = useRef(false) + const connectionAttemptedRef = useRef(false) + const [isConnecting, setIsConnecting] = useState(false) - const saveAndSelectWallet = useCallback(async () => { + const saveWallet = useCallback(async () => { if (saveAttemptedRef.current) return saveAttemptedRef.current = true + if (location.state?.vault?.label && location.state?.vault?.mnemonic) { + const wallet = await addWallet({ + label: location.state.vault.label, + mnemonic: location.state.vault.mnemonic, + }) + + if (wallet) { + await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) + wallet.revoke() + } + } + }, [location.state?.vault, queryClient]) + + const handleWalletConnection = useCallback(async () => { + if (connectionAttemptedRef.current) return + connectionAttemptedRef.current = true + if (location.state?.vault?.label && location.state?.vault?.mnemonic) { const wallet = await addWallet({ label: location.state.vault.label, @@ -83,40 +102,30 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { console.log(e) } } - await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) wallet.revoke() appDispatch(setWelcomeModal({ show: true })) } - }, [ - location.state?.vault, - dispatch, - getAdapter, - localWallet, - queryClient, - appDispatch, - setWelcomeModal, - ]) + }, [location.state?.vault, dispatch, getAdapter, localWallet, appDispatch, setWelcomeModal]) useEffect(() => { - saveAndSelectWallet() - }, [saveAndSelectWallet]) - - const handleViewWallet = useCallback(() => { - saveAndSelectWallet() - onClose() - }, [onClose, saveAndSelectWallet]) + saveWallet() + }, [saveWallet]) - const handleClose = useCallback(() => { - saveAndSelectWallet() - onClose() - appDispatch(setWelcomeModal({ show: true })) - }, [onClose, appDispatch, setWelcomeModal, saveAndSelectWallet]) + const handleViewWallet = useCallback(async () => { + setIsConnecting(true) + try { + await handleWalletConnection() + onClose() + } finally { + setIsConnecting(false) + } + }, [onClose, handleWalletConnection]) return ( - + @@ -134,7 +143,14 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { - diff --git a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx index 9249f2f1d63..0d7b2a5bc34 100644 --- a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx @@ -1,6 +1,7 @@ import { Button, Icon, VStack } from '@chakra-ui/react' import type { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' -import { useCallback, useEffect, useRef } from 'react' +import { useQueryClient } from '@tanstack/react-query' +import { useCallback, useEffect, useRef, useState } from 'react' import { IoIosCheckmarkCircle } from 'react-icons/io' import { useTranslate } from 'react-polyglot' import type { Location } from 'react-router-dom' @@ -32,12 +33,25 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { const { getAdapter, dispatch } = useWallet() const localWallet = useLocalWallet() const translate = useTranslate() - const hasConnectedRef = useRef(false) + const queryClient = useQueryClient() + const connectionAttemptedRef = useRef(false) + const refreshAttemptedRef = useRef(false) + const [isConnecting, setIsConnecting] = useState(false) + + const refreshWalletList = useCallback(async () => { + if (refreshAttemptedRef.current) return + refreshAttemptedRef.current = true + await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) + }, [queryClient]) + + useEffect(() => { + refreshWalletList() + }, [refreshWalletList]) const handleWalletConnection = useCallback(async () => { - if (hasConnectedRef.current) return + if (connectionAttemptedRef.current) return if (!location.state?.vault) return - hasConnectedRef.current = true + connectionAttemptedRef.current = true const adapter = await getAdapter(KeyManager.Mobile) if (!adapter) throw new Error('Native adapter not found') try { @@ -70,22 +84,28 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { type: WalletActions.SET_CONNECTOR_TYPE, payload: { modalType: KeyManager.Mobile, isMipdProvider: false }, }) + appDispatch(setWelcomeModal({ show: true })) } } catch (e) { console.log(e) } - }, [getAdapter, location.state?.vault, dispatch, localWallet]) + }, [getAdapter, location.state?.vault, dispatch, localWallet, appDispatch, setWelcomeModal]) + + const handleViewWallet = useCallback(async () => { + setIsConnecting(true) + try { + await handleWalletConnection() + onClose() + setTimeout(() => location.state?.vault?.revoke(), 500) + } finally { + setIsConnecting(false) + } + }, [onClose, handleWalletConnection, location.state?.vault]) const handleClose = useCallback(() => { - handleWalletConnection() onClose() - appDispatch(setWelcomeModal({ show: true })) setTimeout(() => location.state?.vault?.revoke(), 500) - }, [onClose, appDispatch, setWelcomeModal, handleWalletConnection, location.state?.vault]) - - useEffect(() => { - handleWalletConnection() - }, [handleWalletConnection]) + }, [onClose, location.state?.vault]) return ( @@ -112,7 +132,14 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { - diff --git a/src/pages/ConnectWallet/MobileConnect.tsx b/src/pages/ConnectWallet/MobileConnect.tsx index f9255936c28..fbd0b7285b8 100644 --- a/src/pages/ConnectWallet/MobileConnect.tsx +++ b/src/pages/ConnectWallet/MobileConnect.tsx @@ -14,6 +14,7 @@ import { Stack, } from '@chakra-ui/react' import { keyframes } from '@emotion/react' +import { useQuery as useReactQuery } from '@tanstack/react-query' import { AnimatePresence, motion } from 'framer-motion' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' @@ -33,7 +34,6 @@ import { SlideTransitionY } from '@/components/SlideTransitionY' import { RawText, Text } from '@/components/Text' import { WalletActions } from '@/context/WalletProvider/actions' import { listWallets } from '@/context/WalletProvider/MobileWallet/mobileMessageHandlers' -import type { RevocableWallet } from '@/context/WalletProvider/MobileWallet/RevocableWallet' import { useModal } from '@/hooks/useModal/useModal' import { useQuery } from '@/hooks/useQuery/useQuery' import { useWallet } from '@/hooks/useWallet/useWallet' @@ -67,10 +67,7 @@ const BodyText: React.FC = props => ( export const MobileConnect = () => { const { dispatch, state } = useWallet() const translate = useTranslate() - const [wallets, setWallets] = useState([]) - const [error, setError] = useState(null) const [hideWallets, setHideWallets] = useState(false) - const [isLoading, setIsLoading] = useState(true) const scaleFadeAnimation = `${scaleFade} 0.6s cubic-bezier(0.76, 0, 0.24, 1)` const hasWallet = Boolean(state.walletInfo?.deviceId) const navigate = useNavigate() @@ -78,6 +75,31 @@ export const MobileConnect = () => { const mobileWalletDialog = useModal('mobileWalletDialog') const [isWaitingForRedirection, setIsWaitingForRedirection] = useState(false) + const { + isLoading, + data: wallets = [], + error: queryError, + } = useReactQuery({ + queryKey: ['listWallets'], + staleTime: 0, + gcTime: 0, + retry: false, + refetchOnMount: true, + queryFn: listWallets, + }) + + const error = useMemo(() => { + if (queryError) { + return queryError instanceof Error + ? queryError.message + : 'walletProvider.shapeShift.load.error.fetchingWallets' + } + if (!wallets.length && !isLoading) { + return 'walletProvider.shapeShift.load.error.noWallet' + } + return null + }, [queryError, wallets.length, isLoading]) + const handleOpenCreateWallet = useCallback(() => { mobileWalletDialog.open({ defaultRoute: MobileWalletDialogRoutes.Create }) }, [mobileWalletDialog]) @@ -122,34 +144,13 @@ export const MobileConnect = () => { } }, [navigate, hasWallet, query, state, dispatch, setIsWaitingForRedirection]) - useEffect(() => { - if (!wallets.length) { - setIsLoading(true) // Set loading state to true when fetching wallets - ;(async () => { - try { - const vaults = await listWallets() - if (!vaults.length) { - setError('walletProvider.shapeShift.load.error.noWallet') - } else { - setWallets(vaults) - } - } catch (e) { - console.log(e) - setError('An error occurred while fetching wallets.') - } finally { - setIsLoading(false) // Set loading state to false when fetching is done - } - })() - } - }, [wallets]) - const handleToggleWallets = useCallback(() => { - setHideWallets(!hideWallets) // allow users with saved wallets to toggle between saved and create/import + setHideWallets(!hideWallets) }, [hideWallets]) useEffect(() => { if (!wallets.length && !isLoading) { - setHideWallets(true) // If they have no wallets, show the default create or import + setHideWallets(true) } }, [isLoading, wallets.length]) From 5b71c25defcb3f537f5805781ff78dc140880422 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:08:47 +0100 Subject: [PATCH 6/7] chore: remove autoclaude files and revert .gitignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes autoclaude configuration files that shouldn't be tracked in git: - .auto-claude-security.json - .auto-claude-status - .claude_settings.json Reverts .gitignore to remove autoclaude directory entry. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .auto-claude-security.json | 307 ------------------------------------- .auto-claude-status | 25 --- .claude_settings.json | 39 ----- .gitignore | 3 - 4 files changed, 374 deletions(-) delete mode 100644 .auto-claude-security.json delete mode 100644 .auto-claude-status delete mode 100644 .claude_settings.json diff --git a/.auto-claude-security.json b/.auto-claude-security.json deleted file mode 100644 index 49d630db104..00000000000 --- a/.auto-claude-security.json +++ /dev/null @@ -1,307 +0,0 @@ -{ - "base_commands": [ - ".", - "[", - "[[", - "ag", - "awk", - "basename", - "bash", - "bc", - "break", - "cat", - "cd", - "chmod", - "clear", - "cmp", - "column", - "comm", - "command", - "continue", - "cp", - "curl", - "cut", - "date", - "df", - "diff", - "dig", - "dirname", - "du", - "echo", - "egrep", - "env", - "eval", - "exec", - "exit", - "expand", - "export", - "expr", - "false", - "fd", - "fgrep", - "file", - "find", - "fmt", - "fold", - "gawk", - "gh", - "git", - "grep", - "gunzip", - "gzip", - "head", - "help", - "host", - "iconv", - "id", - "jobs", - "join", - "jq", - "kill", - "killall", - "less", - "let", - "ln", - "ls", - "lsof", - "man", - "mkdir", - "mktemp", - "more", - "mv", - "nl", - "paste", - "pgrep", - "ping", - "pkill", - "popd", - "printenv", - "printf", - "ps", - "pushd", - "pwd", - "read", - "readlink", - "realpath", - "reset", - "return", - "rev", - "rg", - "rm", - "rmdir", - "sed", - "seq", - "set", - "sh", - "shuf", - "sleep", - "sort", - "source", - "split", - "stat", - "tail", - "tar", - "tee", - "test", - "time", - "timeout", - "touch", - "tr", - "tree", - "true", - "type", - "uname", - "unexpand", - "uniq", - "unset", - "unzip", - "watch", - "wc", - "wget", - "whereis", - "which", - "whoami", - "xargs", - "yes", - "yq", - "zip", - "zsh" - ], - "stack_commands": [ - "ant", - "ar", - "cargo", - "cargo-audit", - "cargo-clippy", - "cargo-deny", - "cargo-dist", - "cargo-doc", - "cargo-edit", - "cargo-fmt", - "cargo-llvm-cov", - "cargo-make", - "cargo-miri", - "cargo-nextest", - "cargo-outdated", - "cargo-release", - "cargo-tarpaulin", - "cargo-update", - "cargo-watch", - "cargo-xtask", - "clang", - "clang++", - "cmake", - "composer", - "cross", - "dotnet", - "eslint", - "g++", - "gcc", - "gradle", - "gradlew", - "ipython", - "jar", - "java", - "javac", - "jupyter", - "kotlin", - "kotlinc", - "ld", - "make", - "maven", - "mdbook", - "meson", - "msbuild", - "mvn", - "ninja", - "nm", - "node", - "notebook", - "npm", - "npx", - "nuget", - "nvm", - "objdump", - "pdb", - "php", - "pip", - "pip3", - "pipx", - "prettier", - "pudb", - "pyenv", - "python", - "python3", - "railway", - "react-scripts", - "rust-analyzer", - "rustc", - "rustfmt", - "rustup", - "strip", - "swift", - "swiftc", - "trunk", - "ts-node", - "tsc", - "tsx", - "vite", - "vitest", - "wasm-bindgen", - "wasm-pack", - "xcodebuild", - "yarn" - ], - "script_commands": [ - "bun", - "npm", - "pnpm", - "yarn" - ], - "custom_commands": [], - "detected_stack": { - "languages": [ - "python", - "javascript", - "typescript", - "rust", - "php", - "java", - "kotlin", - "csharp", - "c", - "cpp", - "swift" - ], - "package_managers": [ - "yarn" - ], - "frameworks": [ - "react", - "vite", - "vitest", - "eslint", - "prettier" - ], - "databases": [], - "infrastructure": [], - "cloud_providers": [ - "railway" - ], - "code_quality_tools": [], - "version_managers": [ - "nvm", - "pyenv" - ] - }, - "custom_scripts": { - "npm_scripts": [ - "dev", - "preview:prod", - "preview:dev", - "preview:private", - "analyze", - "bump", - "build:web", - "build:packages", - "postbuild:packages", - "clean", - "clean:web", - "clean:packages", - "codemod:clear-assets-migration", - "deadcode", - "dev:web", - "dev:web:linked", - "dev:packages", - "dev:swap-widget", - "generate:all", - "generate:caip-adapters", - "generate:asset-data", - "generate:related-asset-index", - "generate:color-map", - "generate:tradable-asset-map", - "generate:thor-longtail-tokens", - "local-ci", - "lint", - "lint:fix", - "postinstall", - "release", - "scrape-walletconnect-dapps", - "test", - "test:web", - "test:packages", - "translations:count-words-invalidate-since", - "translations:update-path", - "type-check", - "type-check-watch" - ], - "make_targets": [], - "poetry_scripts": [], - "cargo_aliases": [], - "shell_scripts": [] - }, - "project_dir": "/Users/mini/Projects/web", - "created_at": "2026-01-21T16:42:42.608501", - "project_hash": "62212c8725a9ce3b1ff788c34711de24", - "inherited_from": "/Users/mini/Projects/web" -} \ No newline at end of file diff --git a/.auto-claude-status b/.auto-claude-status deleted file mode 100644 index 8f769ade3d8..00000000000 --- a/.auto-claude-status +++ /dev/null @@ -1,25 +0,0 @@ -{ - "active": true, - "spec": "010-clicking-off-of-view-wallet-in-create-wallet-flow-", - "state": "building", - "subtasks": { - "completed": 3, - "total": 6, - "in_progress": 1, - "failed": 0 - }, - "phase": { - "current": "Fix Import Wallet Flow Connection", - "id": null, - "total": 2 - }, - "workers": { - "active": 0, - "max": 1 - }, - "session": { - "number": 4, - "started_at": "2026-01-21T17:04:58.690509" - }, - "last_update": "2026-01-21T17:10:48.207264" -} \ No newline at end of file diff --git a/.claude_settings.json b/.claude_settings.json deleted file mode 100644 index 2f707b1f21c..00000000000 --- a/.claude_settings.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "sandbox": { - "enabled": true, - "autoAllowBashIfSandboxed": true - }, - "permissions": { - "defaultMode": "acceptEdits", - "allow": [ - "Read(./**)", - "Write(./**)", - "Edit(./**)", - "Glob(./**)", - "Grep(./**)", - "Read(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Write(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Edit(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Glob(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Grep(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Read(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/.auto-claude/specs/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Write(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/.auto-claude/specs/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Edit(/Users/mini/Projects/web/.auto-claude/worktrees/tasks/010-clicking-off-of-view-wallet-in-create-wallet-flow-/.auto-claude/specs/010-clicking-off-of-view-wallet-in-create-wallet-flow-/**)", - "Read(/Users/mini/Projects/web/.auto-claude/**)", - "Write(/Users/mini/Projects/web/.auto-claude/**)", - "Edit(/Users/mini/Projects/web/.auto-claude/**)", - "Glob(/Users/mini/Projects/web/.auto-claude/**)", - "Grep(/Users/mini/Projects/web/.auto-claude/**)", - "Bash(*)", - "WebFetch(*)", - "WebSearch(*)", - "mcp__context7__resolve-library-id(*)", - "mcp__context7__get-library-docs(*)", - "mcp__graphiti-memory__search_nodes(*)", - "mcp__graphiti-memory__search_facts(*)", - "mcp__graphiti-memory__add_episode(*)", - "mcp__graphiti-memory__get_episodes(*)", - "mcp__graphiti-memory__get_entity_edge(*)" - ] - } -} \ No newline at end of file diff --git a/.gitignore b/.gitignore index ee3e012249a..6be6cb15e17 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,3 @@ yarn-error.log* *.iml .idea/ .playwright-mcp/ - -# Auto Claude data directory -.auto-claude/ From ee3c614685089f714d5aa7e81de108e3f86215c0 Mon Sep 17 00:00:00 2001 From: NeOMakinG <14963751+NeOMakinG@users.noreply.github.com> Date: Tue, 27 Jan 2026 08:27:20 +0100 Subject: [PATCH 7/7] fix: fml --- .../routes/CreateWallet/CreateSuccess.tsx | 104 ++++++++++-------- .../routes/ImportWallet/ImportSuccess.tsx | 16 ++- src/pages/ConnectWallet/MobileConnect.tsx | 7 +- 3 files changed, 74 insertions(+), 53 deletions(-) diff --git a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx index 8c6aac86a29..f515afaee3d 100644 --- a/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/CreateWallet/CreateSuccess.tsx @@ -35,6 +35,7 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { const localWallet = useLocalWallet() const saveAttemptedRef = useRef(false) const connectionAttemptedRef = useRef(false) + const savedWalletRef = useRef> | null>(null) const [isConnecting, setIsConnecting] = useState(false) const saveWallet = useCallback(async () => { @@ -42,14 +43,19 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { saveAttemptedRef.current = true if (location.state?.vault?.label && location.state?.vault?.mnemonic) { - const wallet = await addWallet({ - label: location.state.vault.label, - mnemonic: location.state.vault.mnemonic, - }) - - if (wallet) { - await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) - wallet.revoke() + try { + const wallet = await addWallet({ + label: location.state.vault.label, + mnemonic: location.state.vault.mnemonic, + }) + + if (wallet) { + savedWalletRef.current = wallet + await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) + } + } catch (e) { + console.error('Failed to save wallet:', e) + saveAttemptedRef.current = false } } }, [location.state?.vault, queryClient]) @@ -58,52 +64,49 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { if (connectionAttemptedRef.current) return connectionAttemptedRef.current = true - if (location.state?.vault?.label && location.state?.vault?.mnemonic) { - const wallet = await addWallet({ - label: location.state.vault.label, - mnemonic: location.state.vault.mnemonic, - }) - - if (!wallet) { - return - } + const wallet = savedWalletRef.current + if (!wallet || !location.state?.vault?.mnemonic) { + connectionAttemptedRef.current = false + return + } + try { const adapter = await getAdapter(KeyManager.Mobile) const deviceId = wallet.id if (adapter && deviceId) { const { name, icon } = MobileConfig - try { - const walletInstance = await adapter.pairDevice(deviceId) - await walletInstance?.loadDevice({ mnemonic: location.state?.vault?.mnemonic ?? '' }) - - if (!(await walletInstance?.isInitialized())) { - await walletInstance?.initialize() - } - dispatch({ - type: WalletActions.SET_WALLET, - payload: { - wallet: walletInstance, - name, - icon, - deviceId, - meta: { label: location.state?.vault?.label }, - connectedType: KeyManager.Mobile, - }, - }) - dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) - dispatch({ - type: WalletActions.SET_CONNECTOR_TYPE, - payload: { modalType: KeyManager.Mobile, isMipdProvider: false }, - }) - - localWallet.setLocalWallet({ type: KeyManager.Mobile, deviceId }) - localWallet.setLocalNativeWalletName(location.state?.vault?.label ?? 'label') - } catch (e) { - console.log(e) + const walletInstance = await adapter.pairDevice(deviceId) + await walletInstance?.loadDevice({ mnemonic: location.state?.vault?.mnemonic ?? '' }) + + if (!(await walletInstance?.isInitialized())) { + await walletInstance?.initialize() } + dispatch({ + type: WalletActions.SET_WALLET, + payload: { + wallet: walletInstance, + name, + icon, + deviceId, + meta: { label: location.state?.vault?.label }, + connectedType: KeyManager.Mobile, + }, + }) + dispatch({ type: WalletActions.SET_IS_CONNECTED, payload: true }) + dispatch({ + type: WalletActions.SET_CONNECTOR_TYPE, + payload: { modalType: KeyManager.Mobile, isMipdProvider: false }, + }) + + localWallet.setLocalWallet({ type: KeyManager.Mobile, deviceId }) + localWallet.setLocalNativeWalletName(location.state?.vault?.label ?? 'label') + appDispatch(setWelcomeModal({ show: true })) } wallet.revoke() - appDispatch(setWelcomeModal({ show: true })) + savedWalletRef.current = null + } catch (e) { + console.error('Failed to connect wallet:', e) + connectionAttemptedRef.current = false } }, [location.state?.vault, dispatch, getAdapter, localWallet, appDispatch, setWelcomeModal]) @@ -111,6 +114,15 @@ export const CreateSuccess = ({ onClose }: CreateSuccessProps) => { saveWallet() }, [saveWallet]) + useEffect(() => { + return () => { + if (savedWalletRef.current) { + savedWalletRef.current.revoke() + savedWalletRef.current = null + } + } + }, []) + const handleViewWallet = useCallback(async () => { setIsConnecting(true) try { diff --git a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx index 0d7b2a5bc34..5e64512380e 100644 --- a/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx +++ b/src/components/MobileWalletDialog/routes/ImportWallet/ImportSuccess.tsx @@ -41,7 +41,12 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { const refreshWalletList = useCallback(async () => { if (refreshAttemptedRef.current) return refreshAttemptedRef.current = true - await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) + try { + await queryClient.invalidateQueries({ queryKey: ['listWallets'] }) + } catch (e) { + console.error('Failed to refresh wallet list:', e) + refreshAttemptedRef.current = false + } }, [queryClient]) useEffect(() => { @@ -52,9 +57,11 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { if (connectionAttemptedRef.current) return if (!location.state?.vault) return connectionAttemptedRef.current = true - const adapter = await getAdapter(KeyManager.Mobile) - if (!adapter) throw new Error('Native adapter not found') + try { + const adapter = await getAdapter(KeyManager.Mobile) + if (!adapter) throw new Error('Native adapter not found') + const deviceId = location.state.vault.id ?? '' const wallet = (await adapter.pairDevice(deviceId)) as NativeHDWallet const mnemonic = location.state.vault.mnemonic @@ -87,7 +94,8 @@ export const ImportSuccess = ({ onClose }: ImportSuccessProps) => { appDispatch(setWelcomeModal({ show: true })) } } catch (e) { - console.log(e) + console.error('Failed to connect wallet:', e) + connectionAttemptedRef.current = false } }, [getAdapter, location.state?.vault, dispatch, localWallet, appDispatch, setWelcomeModal]) diff --git a/src/pages/ConnectWallet/MobileConnect.tsx b/src/pages/ConnectWallet/MobileConnect.tsx index fbd0b7285b8..a3220cfcc7d 100644 --- a/src/pages/ConnectWallet/MobileConnect.tsx +++ b/src/pages/ConnectWallet/MobileConnect.tsx @@ -90,9 +90,10 @@ export const MobileConnect = () => { const error = useMemo(() => { if (queryError) { - return queryError instanceof Error - ? queryError.message - : 'walletProvider.shapeShift.load.error.fetchingWallets' + if (queryError instanceof Error) { + console.error('Failed to fetch wallets:', queryError.message) + } + return 'walletProvider.shapeShift.load.error.fetchingWallets' } if (!wallets.length && !isLoading) { return 'walletProvider.shapeShift.load.error.noWallet'