Skip to content

fix: preserve imported token migrations#5989

Open
samholmes wants to merge 1 commit intodevelopfrom
sam/migrate-fix-zano
Open

fix: preserve imported token migrations#5989
samholmes wants to merge 1 commit intodevelopfrom
sam/migrate-fix-zano

Conversation

@samholmes
Copy link
Copy Markdown
Contributor

@samholmes samholmes commented Mar 30, 2026

Imported token migrations were losing their parent wallet context between wallet creation and the migration flow, which made token migrations disappear or crash before users could review them.

Track the created wallet ids during import completion and carry the parent wallet metadata into the migration payload so imported tokens reach the migration scenes as first-class assets.

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Requirements

If you have made any visual changes to the GUI. Make sure you have:

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Note

Medium Risk
Adjusts how migration payloads are constructed after wallet import/creation, which can affect which assets appear (and their metadata) in the migration flow. Logic is localized to CreateWalletCompletionScene, but mistakes could cause missing/incorrect migration entries or crashes.

Overview
Fixes imported token migrations by rebuilding handleMigrate to include only successfully created wallets plus all imported token items, instead of mapping raw newWalletItems.

The migration payload now derives each item’s createWalletId, walletType, and displayName by resolving the correct parent wallet (handling PLACEHOLDER_WALLET_ID and existing-wallet createWalletIds) so token migrations retain their parent context when navigating to migrateWalletCalculateFee.

Written by Cursor Bugbot for commit 11a010a. This will update automatically on new commits. Configure here.


Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: PluginId-keyed map loses wallets sharing same plugin
    • Changed createdWalletIdsByPluginId to key by unique item.key instead of pluginId, preventing wallet ID overwrites when multiple wallets share the same pluginId.

Create PR

Or push these changes by commenting:

@cursor push 14928f7cff
Preview (14928f7cff)
diff --git a/src/components/scenes/CreateWalletCompletionScene.tsx b/src/components/scenes/CreateWalletCompletionScene.tsx
--- a/src/components/scenes/CreateWalletCompletionScene.tsx
+++ b/src/components/scenes/CreateWalletCompletionScene.tsx
@@ -56,8 +56,9 @@
   const defaultIsoFiat = useSelector(state => state.ui.settings.defaultIsoFiat)
 
   const [done, setDone] = React.useState(false)
-  const [createdWalletIdsByPluginId, setCreatedWalletIdsByPluginId] =
-    React.useState<Record<string, string>>({})
+  const [createdWalletIdsByKey, setCreatedWalletIdsByKey] = React.useState<
+    Record<string, string>
+  >({})
 
   const { newWalletItems, newTokenItems } = React.useMemo(
     () => splitCreateWalletItems(createWalletList),
@@ -157,13 +158,12 @@
       }
 
       // Save the created wallets
-      const newCreatedWalletIdsByPluginId: Record<string, string> = {}
+      const newCreatedWalletIdsByKey: Record<string, string> = {}
       walletResults.forEach((result, index) => {
         if (!result.ok) return
-        newCreatedWalletIdsByPluginId[newWalletItems[index].pluginId] =
-          result.result.id
+        newCreatedWalletIdsByKey[newWalletItems[index].key] = result.result.id
       })
-      setCreatedWalletIdsByPluginId(newCreatedWalletIdsByPluginId)
+      setCreatedWalletIdsByKey(newCreatedWalletIdsByKey)
 
       setDone(true)
       return () => {}
@@ -264,7 +264,8 @@
 
       return {
         ...createWallet,
-        createWalletId: createdWalletIdsByPluginId[pluginId] ?? '',
+        createWalletId:
+          createdWalletIdsByKey[parentWalletItem?.key ?? key] ?? '',
         walletType: parentWalletItem?.walletType ?? createWallet.walletType,
         displayName:
           parentWalletItem == null

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

The migration handler only included mainnet wallet items,
so imported tokens were excluded from the migration flow.
Token items need their parent wallet resolved to carry the
correct createWalletId into the downstream migration scenes.
@samholmes samholmes force-pushed the sam/migrate-fix-zano branch from e9c9336 to 11a010a Compare March 30, 2026 23:56
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

}
const migrateWalletList: MigrateWalletItem[] = [
...successfulNewWalletItems,
...newTokenItems
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfiltered token items with failed parents break migration

High Severity

newTokenItems are spread into the migration list without filtering for parent wallet success. When a parent wallet creation fails, tokens with PLACEHOLDER_WALLET_ID won't find a parentWalletItem in successfulNewWalletItems, resulting in wallet being undefined and createWalletId falling back to ''. In MigrateWalletCalculateFeeScene, the useAsyncEffect processes all items and does currencyWallets[createWalletId] followed by an unguarded destructuring of .currencyInfo, which throws a TypeError on undefined — breaking the entire migration flow for all items, not just the failed ones.

Additional Locations (1)
Fix in Cursor Fix in Web

const parentWalletItem =
createWallet.walletType != null
? createWallet
: createWalletIds[0] === PLACEHOLDER_WALLET_ID
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unchecked array index on createWalletIds[0]

Low Severity

createWalletIds[0] is accessed multiple times without verifying the array has elements. The createWalletIds variable is initialized via createWallet.createWalletIds ?? [], so it can be an empty array, making createWalletIds[0] undefined. While the comparisons happen to degrade gracefully here, this violates the check-array-bounds rule and makes the intent unclear.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants