Files
zeekay 7200114387 Merge upstream/dev (52 commits) + sweep yarn → pnpm
Upstream merge brings 52 commits from safe-global/safe-wallet-monorepo
into the luxfi/safe-wallet@dev fork.

Conflicts resolved:
- yarn.lock: deleted (we are on pnpm)
- apps/web/package.json: kept pnpm version + brand build scripts
  (build:safe / build:lux / build:hanzo) plus upstream's new
  generate-version.mjs step
- apps/mobile/.../Signer/appKit.ts: took upstream's import pattern
  for shared/projectId, shared/metadata, shared/mmkvStorageAdapter

Yarn sweep applied to 42 files (docs, github-actions, workflows, AGENTS,
specs, codemods, scripts, READMEs). Net result: zero yarn-* command
references anywhere outside node_modules.

  ❯ pnpm is the law in this fork. No yarn.
2026-05-27 03:25:16 -07:00

24 KiB

Tasks: Counterfactual Feature Refactor

Feature: 002-counterfactual-refactor
Branch: 002-counterfactual-refactor
Date: 2026-01-15
Spec: spec.md | Plan: plan.md

Overview

Breaking down the counterfactual feature refactoring into 84 actionable tasks across 5 categories. Tasks are ordered by execution sequence and priority.

Estimated Time: 5-6 hours total
Critical Path: Tasks 6-25 (file reorganization) → Tasks 26-74 (external imports) → Tasks 75-81 (verification)

Task Legend

  • [ ] - Not started
  • [~] - In progress
  • [x] - Complete
  • [!] - Blocked
  • [?] - Needs clarification

Category 1: Structural Setup (Non-Breaking)

Objective: Create all barrel files and new files without moving anything yet.
Time: ~15 minutes
Dependencies: None

Task 1: Create Root Barrel Files

  • Create apps/web/src/features/counterfactual/index.ts (empty)
  • Create apps/web/src/features/counterfactual/types.ts (empty)
  • Create apps/web/src/features/counterfactual/constants.ts (empty)

Acceptance: Files exist, type-check still passes


Task 2: Create Components Barrel

  • Create directory apps/web/src/features/counterfactual/components/ (if not exists)
  • Create apps/web/src/features/counterfactual/components/index.ts (empty)

Acceptance: Directory and barrel file exist


Task 3: Create Hooks Barrel

  • Create apps/web/src/features/counterfactual/hooks/index.ts (empty)

Acceptance: Barrel file exists in hooks directory


Task 4: Create Services Barrel

  • Create apps/web/src/features/counterfactual/services/index.ts (empty)

Acceptance: Barrel file exists in services directory


Task 5: Create Store Barrel

  • Create apps/web/src/features/counterfactual/store/index.ts (empty)

Acceptance: Barrel file exists in store directory


Checkpoint 1: Verify Structure Created

  • Run pnpm --filter @safe-global/web type-check
  • Verify exit code 0 (no errors from new empty files)

Acceptance: Type-check passes, structure ready for file moves


Category 2: File Reorganization (Breaking)

Objective: Move all files to correct locations and update internal imports.
Time: ~1 hour
Dependencies: Category 1 complete
WARNING: This phase breaks the build temporarily

Task 6: Move ActivateAccountButton Component

  • Create directory components/ActivateAccountButton/
  • Move ActivateAccountButton.tsx → components/ActivateAccountButton/index.tsx
  • Update imports within the file (relative paths)

Acceptance: File in new location with correct imports


Task 7: Move ActivateAccountFlow Component

  • Create directory components/ActivateAccountFlow/
  • Move ActivateAccountFlow.tsx → components/ActivateAccountFlow/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 8: Move CheckBalance Component

  • Create directory components/CheckBalance/
  • Move CheckBalance.tsx → components/CheckBalance/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 9: Move CounterfactualForm Component

  • Create directory components/CounterfactualForm/
  • Move CounterfactualForm.tsx → components/CounterfactualForm/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 10: Move CounterfactualHooks Component

  • Create directory components/CounterfactualHooks/
  • Move CounterfactualHooks.tsx → components/CounterfactualHooks/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 11: Move CounterfactualStatusButton Component

  • Create directory components/CounterfactualStatusButton/
  • Move CounterfactualStatusButton.tsx → components/CounterfactualStatusButton/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 12: Move CounterfactualSuccessScreen Component

  • Create directory components/CounterfactualSuccessScreen/
  • Move CounterfactualSuccessScreen.tsx → components/CounterfactualSuccessScreen/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 13: Move FirstTxFlow Component

  • Create directory components/FirstTxFlow/
  • Move FirstTxFlow.tsx → components/FirstTxFlow/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 14: Move LazyCounterfactual Component

  • Create directory components/LazyCounterfactual/
  • Move LazyCounterfactual.tsx → components/LazyCounterfactual/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 15: Move PayNowPayLater Component

  • Create directory components/PayNowPayLater/
  • Move PayNowPayLater.tsx → components/PayNowPayLater/index.tsx
  • Update imports within the file

Acceptance: File in new location with correct imports


Task 16: Move useCounterfactualBalances Hook

  • Move useCounterfactualBalances.ts → hooks/useCounterfactualBalances.ts
  • Update imports within the file

Acceptance: File in hooks directory with correct imports


Task 17: Move and Rename utils.ts

  • Move utils.ts → services/counterfactualUtils.ts
  • Update imports within the file to reflect new location
  • Rename to services/safeDeployment.ts for clarity (post-implementation improvement)
  • Update all internal imports to use new name

Acceptance: File renamed to better reflect its purpose (Safe deployment operations), all imports updated

Note: Originally renamed to counterfactualUtils.ts during initial refactoring. Subsequently improved to safeDeployment.ts during validation as the file specifically contains Safe deployment and activation business logic, not generic utilities.


Task 18: Move useDeployGasLimit Test

  • Create directory hooks/__tests__/
  • Move __tests__/useDeployGasLimit.test.ts → hooks/__tests__/useDeployGasLimit.test.ts
  • Update imports within test file

Acceptance: Test colocated with source in hooks/tests/


Task 19: Move and Rename utils Test

  • Create directory services/__tests__/
  • Move __tests__/utils.test.ts → services/__tests__/counterfactualUtils.test.ts
  • Update imports within test file
  • Rename to safeDeployment.test.ts to match source file (post-implementation)

Acceptance: Test colocated with renamed source file


Task 20: Remove Empty tests Directory

  • Delete empty __tests__/ directory from feature root

Acceptance: Directory removed, tests relocated


Task 20.1: Split Shared CSS Module (Post-Implementation Fix)

  • Split styles.module.css into component-specific CSS modules
  • Create components/CounterfactualStatusButton/styles.module.css
  • Create components/PayNowPayLater/styles.module.css
  • Delete shared styles.module.css from feature root
  • Verify type-check and build still pass

Acceptance: Each component has its own CSS module, no shared styles at root

Note: This task was added during implementation validation when the build revealed that styles.module.css was not moved with the components during Tasks 11 and 15.


Checkpoint 2: Verify Internal Imports

  • Run pnpm --filter @safe-global/web type-check | grep counterfactual
  • Fix any remaining internal import errors within counterfactual feature
  • Verify no internal counterfactual errors (only external import errors expected)

Acceptance: Internal imports within feature all resolve correctly


Category 3: Public API Definition (Breaking Externally)

Objective: Create types, constants, feature flag hook, and populate barrel files.
Time: ~1 hour
Dependencies: Category 2 complete

Task 21: Extract Types to types.ts

  • Extract all TypeScript interfaces from store/undeployedSafesSlice.ts
  • Extract interfaces from services/counterfactualUtils.ts
  • Add to types.ts: UndeployedSafe, UndeployedSafesState, UndeployedSafeStatus, ReplayedSafeProps, UndeployedSafeProps
  • Re-export types from @safe-global/utils: PayMethod, PendingSafeStatus
  • Update source files to import from ../types

Acceptance: All counterfactual types centralized in types.ts


Task 22: Extract Constants to constants.ts

  • Extract CF_TX_GROUP_KEY from services/counterfactualUtils.ts
  • Add to constants.ts
  • Update source files to import from ../constants

Acceptance: Constants centralized, source files updated


Task 23: Create Feature Flag Hook

  • Create hooks/useIsCounterfactualEnabled.ts
  • Implement: return useHasFeature(FEATURES.COUNTERFACTUAL)
  • Add JSDoc documentation
  • Return type: boolean | undefined

Acceptance: Hook exists, correctly checks feature flag


Task 24: Populate Components Barrel

  • Edit components/index.ts
  • Export all 10 components (ActivateAccountButton, ActivateAccountFlow, CheckBalance, CounterfactualForm, CounterfactualHooks, CounterfactualStatusButton, CounterfactualSuccessScreen, FirstTxFlow, LazyCounterfactual, PayNowPayLater)
  • Add comment: "Internal exports - not exposed from feature root"

Acceptance: All components exported from components/index.ts


Task 25: Populate Hooks Barrel

  • Edit hooks/index.ts
  • Export useIsCounterfactualEnabled (public)
  • Add comment documenting internal-only hooks (not exported)

Acceptance: Feature flag hook exported, internal hooks documented


Task 26: Populate Services Barrel

  • Edit services/index.ts
  • Export all from counterfactualUtils: export * from './counterfactualUtils'
  • Export all from safeCreationEvents: export * from './safeCreationEvents'

Acceptance: All service functions exported


Task 27: Populate Store Barrel

  • Edit store/index.ts
  • Export all from undeployedSafesSlice: export * from './undeployedSafesSlice'

Acceptance: Slice, actions, and selectors exported


Task 28: Populate Root index.ts (Public API)

  • Edit index.ts at feature root
  • Export types: UndeployedSafe, UndeployedSafesState, UndeployedSafeStatus, UndeployedSafeProps, ReplayedSafeProps
  • Export feature flag hook: useIsCounterfactualEnabled
  • Export store: slice, actions, selectors
  • Export services: all service functions
  • Export constants: CF_TX_GROUP_KEY
  • No default export (feature has no single main component)

Acceptance: Public API complete per contracts/public-api.ts


Checkpoint 3: Verify Public API

  • Run pnpm --filter @safe-global/web type-check
  • Expect many external import errors (49 files not updated yet)
  • Verify feature's public API exports are type-correct

Acceptance: Public API defined, ready for external import updates


Category 4: External Import Updates (Critical Path)

Objective: Update all 49 external files to import from @/features/counterfactual only.
Time: ~2-3 hours
Dependencies: Category 3 complete

Priority 1: Redux Store (CRITICAL)

Task 29: Update store/slices.ts

  • Change export * from '@/features/counterfactual/store/undeployedSafesSlice'
  • To use named exports from public API for store-only code
  • Run type-check to verify store exports resolve

Acceptance: Redux store imports only store-related exports (slice, actions, selectors) using named exports from public API

Implementation:

export {
  undeployedSafesSlice,
  addUndeployedSafe,
  addUndeployedSafes,
  updateUndeployedSafeStatus,
  removeUndeployedSafe,
  selectUndeployedSafes,
  selectUndeployedSafe,
  selectUndeployedSafesByAddress,
  selectIsUndeployedSafe,
} from '@/features/counterfactual'

Note: Cannot use export * from '@/features/counterfactual' as it would pollute store namespace with components/hooks/services. Cannot use export * from '@/features/counterfactual/store' as it violates no-restricted-imports ESLint rule. Named exports from public API is the correct approach.


Priority 2: Transaction Flows (Core Functionality)

Task 30: Update components/tx-flow/actions/Counterfactual.tsx

  • Replace deep imports with @/features/counterfactual
  • Import only needed exports from public API
  • Run type-check

Acceptance: Imports from public API only


Task 31: Update components/tx-flow/actions/Execute/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 32: Update components/tx-flow/actions/Sign/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 33: Update components/tx-flow/actions/ExecuteThroughRole/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 34: Update components/tx-flow/actions/Batching/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 35: Update components/tx-flow/features/BalanceChanges.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 36: Update components/tx-flow/features/ExecuteCheckbox.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 37: Update components/tx-flow/TxFlowProvider.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Checkpoint 4: Verify Transaction Flows

  • Run pnpm --filter @safe-global/web type-check
  • Verify no errors in tx-flow files

Acceptance: Transaction flow imports all resolve


Priority 3: Safe Creation (Activation Flows)

Task 38: Update components/new-safe/create/steps/StatusStep/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Import components, hooks, utils from public API
  • Run type-check

Acceptance: Imports from public API only


Task 39: Update components/new-safe/create/steps/ReviewStep/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 40: Update components/new-safe/create/steps/StatusStep/StatusMessage.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 41: Update components/new-safe/create/steps/StatusStep/useUndeployedSafe.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 42: Update components/new-safe/create/logic/index.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Checkpoint 5: Verify Safe Creation

  • Run pnpm --filter @safe-global/web type-check
  • Verify no errors in new-safe/create files

Acceptance: Safe creation imports all resolve


Priority 4: Feature Integrations (My Accounts)

Task 43: Update features/myAccounts/components/AccountItems/SingleAccountItem.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 44: Update features/myAccounts/components/AccountItems/MultiAccountItem.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 45: Update features/myAccounts/components/AccountInfoChips/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: Feature Integrations (Multichain)

Task 46: Update features/multichain/utils/utils.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 47: Update features/multichain/hooks/useSafeCreationData.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 48: Update features/multichain/components/CreateSafeOnNewChain/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: Loadables & Hooks

Task 49: Update hooks/loadables/useLoadSafeInfo.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 50: Update hooks/loadables/useLoadBalances.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 51: Update hooks/loadables/useTrustedTokenBalances.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 52: Update hooks/loadables/tests/useLoadBalances.test.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 53: Update hooks/coreSDK/useInitSafeCoreSDK.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 54: Update hooks/coreSDK/safeCoreSDK.ts

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: UI Components (Sidebar)

Task 55: Update components/sidebar/SidebarHeader/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 56: Update components/sidebar/NewTxButton/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: UI Components (Dashboard)

Task 57: Update components/dashboard/FirstSteps/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: UI Components (Balances)

Task 58: Update components/balances/AssetsTable/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: UI Components (Settings)

Task 59: Update components/settings/PushNotifications/GlobalPushNotifications.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 60: Update components/settings/DataManagement/index.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Task 61: Update components/settings/DataManagement/ImportDialog.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Priority 4: Pages

Task 62: Update pages/_app.tsx

  • Replace deep imports with @/features/counterfactual
  • Run type-check

Acceptance: Imports from public API only


Checkpoint 6: Verify All External Imports

  • Run pnpm --filter @safe-global/web type-check
  • Verify exit code 0 (all imports resolve)
  • No counterfactual-related errors

Acceptance: Type-check passes completely


Category 5: Verification (Gate Before Commit)

Objective: Verify zero behavioral changes, proper code splitting, full compliance.
Time: ~30 minutes
Dependencies: Category 4 complete

Task 75: Run Type Check

  • Execute pnpm --filter @safe-global/web type-check
  • Verify exit code 0
  • Verify zero errors

Acceptance: Type-check passes completely


Task 76: Run Linting

  • Execute pnpm --filter @safe-global/web lint
  • Verify zero no-restricted-imports warnings for counterfactual
  • Fix any warnings if they exist

Acceptance: Lint passes, zero warnings


Task 77: Run Unit Tests

  • Execute pnpm --filter @safe-global/web test
  • Verify 100% pass rate
  • All counterfactual tests pass
  • No test modifications needed (except import paths)

Acceptance: All tests pass (100%)


Task 78: Build Application

  • Execute pnpm --filter @safe-global/web build
  • Verify build succeeds
  • No build errors

Acceptance: Build completes successfully


Task 79: Verify Bundle Code Splitting

  • Check .next/static/chunks/ for counterfactual chunks
  • Verify counterfactual code is in separate chunks
  • Verify not in main bundle

Acceptance: Code splitting verified


Task 80: Manual QA - Activate Account Flow

  • Create undeployed Safe (prediction)
  • Click "Activate Account" button
  • Verify deployment transaction submits
  • Verify status updates correctly
  • Verify flow works identically to before

Acceptance: Activate account flow works


Task 81: Manual QA - Pay Later Flow

  • Create undeployed Safe
  • Create first transaction
  • Verify Safe + transaction deployed together
  • Verify status updates correctly
  • Verify flow works identically to before

Acceptance: Pay later flow works


Task 82: Manual QA - Pending Notifications

  • With pending counterfactual Safe
  • Verify notification banner appears
  • Verify status chip shows correct state
  • Verify notifications work identically to before

Acceptance: Pending notifications work


Checkpoint 7: All Verification Passed

  • All checks pass (type, lint, test, build, bundle)
  • All manual QA scenarios work
  • Ready to commit

Acceptance: Refactoring verified, zero behavioral changes


Category 6: Commit & Review

Objective: Create atomic commit, push, create PR.
Time: ~30 minutes
Dependencies: Category 5 complete

Task 83: Create Atomic Commit

  • Review all changes: git status, git diff --stat
  • Stage all counterfactual changes
  • Stage external import updates
  • Create semantic commit with comprehensive message
  • Reference spec: Ref: specs/002-counterfactual-refactor

Acceptance: Single atomic commit created


Task 84: Push and Create PR

  • Push branch: git push origin 002-counterfactual-refactor
  • Create PR with comprehensive description
  • Include verification checklist in PR body
  • Link to spec and plan
  • Wait for CI to pass

Acceptance: PR created, CI passing


Summary Statistics

Total Tasks: 85
Completed: 83 / 85
In Progress: 0
Blocked: 0

By Category

Category Tasks Est. Time Status
1. Structural Setup 6 15 min ✅ Complete
2. File Reorganization 16 1 hour ✅ Complete
3. Public API Definition 8 1 hour ✅ Complete
4. External Import Updates 47 2-3 hours ✅ Complete
5. Verification 7 30 min ✅ Complete
6. Commit & Review 2 30 min ⏳ Ready

Critical Path: Tasks 29 → 30-37 → 38-42 → 43-62 → 75-82 → 83-84

Progress Tracking

Track progress by updating task checkboxes:

  • Change [ ] to [x] when complete
  • Change [ ] to [~] when in progress
  • Change [ ] to [!] if blocked

Completion Criteria

Automated implementation complete (83/85 tasks):

  • ✅ All file operations (28) completed
  • ✅ All external imports (49) updated
  • ✅ Type-check passes (0 errors)
  • ✅ All public API tasks complete
  • ✅ CSS modules split and colocated with components
  • ⏳ Manual QA passed - needs user testing (Tasks 80-82)
  • ⏳ PR created and CI passing - ready to create (Tasks 83-84)

Implementation Status: ✅ Refactoring complete - Ready for manual QA, commit, and PR creation