Skip to content

fix: preserve imported token migrations#5989

Merged
samholmes merged 2 commits intodevelopfrom
sam/migrate-fix-zano
Apr 7, 2026
Merged

fix: preserve imported token migrations#5989
samholmes merged 2 commits 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

High Risk
Changes transaction-building and broadcast paths for wallet migration and private-key sweep flows, including new bundled makeMaxSpend handling; mistakes could impact fee calculation, asset selection, or token enable/disable behavior during fund transfers.

Overview
Ensures imported token migrations retain their parent wallet context by building migrateWalletList from successfully created wallets and attaching matching tokens with the correct createWalletId in CreateWalletCompletionScene.

Updates migration and sweep fee calculation to use wallet-provided otherMethods.makeMaxSpend when available, marking token rows as "Included" (new string_included) and treating bundled tokens differently from the mainnet fee row.

Adjusts completion flows to handle bundled max-spend behavior (including passing sweep selection metadata and enabling tokens when token transfers are implicitly included in the mainnet transaction).

Reviewed by Cursor Bugbot for commit 4bfced1. Bugbot is set up for automated code reviews on this repo. 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.

@samholmes samholmes force-pushed the sam/migrate-fix-zano branch from e9c9336 to 11a010a Compare March 30, 2026 23:56
@samholmes samholmes force-pushed the sam/migrate-fix-zano branch from 11a010a to b4ec9dc Compare April 4, 2026 01:03
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: Double successCount increment in makeMaxSpend path
    • Removed the redundant successCount++ at line 278 to make both makeMaxSpend and legacy paths increment successCount consistently only once per successful bundle.

Create PR

Or push these changes by commenting:

@cursor push a855b7e9e0
Preview (a855b7e9e0)
diff --git a/src/components/scenes/MigrateWalletCalculateFeeScene.tsx b/src/components/scenes/MigrateWalletCalculateFeeScene.tsx
--- a/src/components/scenes/MigrateWalletCalculateFeeScene.tsx
+++ b/src/components/scenes/MigrateWalletCalculateFeeScene.tsx
@@ -274,8 +274,6 @@
                     item.tokenId == null ? txFee : 'included'
                   )
                 }
-
-                successCount++
               } catch (e: any) {
                 for (const key of bundlesFeeTotals.keys()) {
                   const insufficientFundsError =

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

@samholmes samholmes force-pushed the sam/migrate-fix-zano branch from b4ec9dc to 36ad35f Compare April 6, 2026 23:26
@samholmes samholmes force-pushed the sam/migrate-fix-zano branch from 36ad35f to 1cae140 Compare April 7, 2026 00:41
@samholmes samholmes enabled auto-merge April 7, 2026 00:44
@samholmes samholmes disabled auto-merge April 7, 2026 00:44
Motivation: keep token migrations bundled with their parent wallet so
multi-asset chains like Zano do not split into separate wallet bundles.
This also enables the makeMaxSpend migration path to run as a single
routine for a wallet bundle while preserving the per-asset fallback.
Enable the sweep private key scenes to use a single multi-asset spend when
memory wallets expose makeMaxSpend, matching migrate wallet behavior.

This keeps token selection and post-sweep token enabling consistent when a
single transaction represents multiple assets, while preserving the legacy
per-asset fallback for wallets without the method.
@samholmes samholmes force-pushed the sam/migrate-fix-zano branch from 1cae140 to 4bfced1 Compare April 7, 2026 00:49
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.

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit 4bfced1. Configure here.

type MakeMaxSpendMethod = (params: {
tokenIds?: Array<string | null>
spendTargets: Array<{ publicAddress: string }>
}) => Promise<EdgeTransaction>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicated MakeMaxSpendMethod type across three files

Low Severity

MakeMaxSpendMethod is independently defined in three files with slightly different shapes — the completion scene variant adds an optional metadata field while the other two omit it. Having three copies risks drift and makes updating the contract error-prone. A single shared definition (with metadata optional) would be cleaner.

Additional Locations (2)
Fix in Cursor Fix in Web

Triggered by project rule: Bugbot Review Rules

Reviewed by Cursor Bugbot for commit 4bfced1. Configure here.

@samholmes samholmes enabled auto-merge April 7, 2026 01:01
@samholmes samholmes merged commit 1eef8ba into develop Apr 7, 2026
4 checks passed
@samholmes samholmes deleted the sam/migrate-fix-zano branch April 7, 2026 01:18
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