Skip to content

Conversation

@tomiir
Copy link
Collaborator

@tomiir tomiir commented Sep 25, 2025

Description

Overview

This PR implements a significant architectural refactoring that moves account-related logic from AppKitBaseClient to ConnectionController and completely removes the connectionControllerClient abstraction layer. This change aligns with the AppKit stability improvements initiative and moves us closer to atomic state management.

🎯 Motivation

As outlined in the AppKit Refactor POC Findings & Recommendations, the current architecture has several issues:
Circular Dependencies: Controllers have circular deps through client abstractions
Tangled State: Multiple cross-controller dependencies make atomic updates impossible
Blurry Boundaries: State responsibilities are unclear between controllers
Proxy Pattern Anti-pattern: connectionControllerClient acts as unnecessary middleware

🔄 Changes Made

✅ Removed connectionControllerClient Completely

  • Eliminated the client abstraction layer that was creating circular dependencies
  • Direct controller-to-controller communication replaces client-mediated calls
  • Simplified the call chain: views → controllers → adapters (instead of views → controllers → client → adapters)

🏗️ Moved Account Logic to ConnectionController

The following methods were moved from AppKitBaseClient to ConnectionController:

Connection Management Methods:

  • connectExternal() - External wallet connection logic
  • reconnectExternal() - Reconnection handling
  • disconnect() - Disconnection flows
  • switchConnection() - Multi-wallet connection switching

Account Operations:

  • syncAccount() - Account synchronization
  • syncIdentity() - Identity/ENS resolution
  • updateBalance() - Balance updates

Provider execution

  • signMessage() - Message signing functionality
  • sendTransaction() - Transaction sending
  • estimateGas() - Gas estimation
  • writeContract() - Smart contract interactions
  • (new) request() - Generic RPC request. Removed specific namespace requests

Utility Methods:

  • parseUnits() / formatUnits() - Unit conversion utilities
  • getEnsAddress() / getEnsAvatar() - ENS resolution
  • checkInstalled() - Wallet installation checks

Updated Adapter Integration

Adapters now call ConnectionController methods directly instead of through client

  • Removed adapter dependency on connectionControllerClient
  • Simplified adapter initialization and connection flows

Type of change

  • Chore (non-breaking change that addresses non-functional tasks, maintenance, or code quality improvements)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Associated Issues

Closes APKT-3837

Checklist

  • Code in this PR is covered by automated tests (Unit tests, E2E tests)
  • My changes generate no new warnings
  • I have reviewed my own code
  • I have filled out all required sections
  • I have tested my changes on the preview link
  • Approver of this PR confirms that the changes are tested on the preview link

Note

Consolidates account and provider operations into ConnectionController, removes ConnectionControllerClient, and updates adapters, UI, tests, and examples to the new API.

  • Core/AppKit:
    • Migrate connection/account flows and provider ops (connectExternal, reconnectExternal, disconnect, switchConnection, syncAccount, syncIdentity, updateBalance, signMessage, sendTransaction, estimateGas, writeContract, request) into ConnectionController.
    • Remove ConnectionControllerClient; simplify call chain and update AppKitBaseClient, appkit-core, and universal adapter client.
    • Adjust controller exports, types, and utils (balance/ENS/units) to route through ConnectionController.
  • Adapters:
    • Update wagmi, ethers/ethers5, solana, bitcoin, polkadot, ton clients to call ConnectionController directly; refresh tests and mocks.
  • UI/Scaffold:
    • Update modal/views/widgets to consume new controller APIs (connect, networks, send/swap/receive flows).
  • Controllers:
    • Refactor ChainController, SendController, SwapController, BlockchainApiController to align with new responsibilities and API surface.
  • Tests:
    • Broad test updates across appkit, controllers, adapters, and scaffold-ui; add/adjust cases for connection, balance, send/estimate, ENS, smart sessions.
  • Examples/Packages:
    • Align example apps and package configs to new API surface; minor package.json updates across apps/examples/packages.

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

tomiir and others added 30 commits August 25, 2025 19:57
…m/appkit into chore/remove-account-controller
…m/appkit into chore/remove-account-controller
…m/appkit into chore/remove-account-controller
const namespaceNetworkId = ChainController.getNetworkData(chainNamespace)?.caipNetwork?.id
const syncAccountChainId = chainId || namespaceNetworkId

const caipNetworkId = `${chainNamespace}:${syncAccountChainId}` as const
Copy link

Choose a reason for hiding this comment

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

Bug: CAIP Network IDs Malformed by Missing Data

The caipNetworkId is constructed as a template literal with as const assertion, but when syncAccountChainId is undefined, it creates an invalid CAIP network ID like "eip155:undefined". This happens in the else branch at line 675 where syncAccountChainId might be undefined, leading to malformed CAIP network IDs being passed to ConnectionController.syncAccount.

Fix in Cursor Fix in Web

Copy link

@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.

Bug: Connection Persistence Broken

The setConnections method no longer persists connections to storage. The removed line StorageUtil.setConnections(connections, chainNamespace) was not replaced, and ConnectionController.setConnections only updates in-memory state without persisting to localStorage. This breaks reconnection functionality on page reload since connections won't be stored.

packages/appkit/src/client/appkit-base-client.ts#L1250-L1256

public setConnections: (typeof ConnectionController)['setConnections'] = (
connections,
chainNamespace
) => {
ConnectionController.setConnections(connections, chainNamespace)
}

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