LunoKit EVM Compatibility Upgrade

Hi everyone,

LunoKit has been live for over six months and is already being used by multiple developer teams within the Polkadot ecosystem, including projects such as EnergyWeb, Fintradex, and Snowbridge.

Additionally, we have finalized LunoKit’s roadmap for 2026, focusing mainly on EVM account support. This will allow dApp developers to integrate both Substrate and EVM accounts through LunoKit, which we believe will be highly valuable for multi-chain teams and significantly reduce development costs.

If you are not familiar with the LunoKit project background, you can find more information here:
Luno-lab/LunoKit | DeepWiki or https://docs.lunolab.xyz/.

Below is our specific technical implementation plan. We welcome feedback on any aspect of this design, including architecture choices, state models, hooks, UX decisions, and potential risks.


1. Background and Motivation

As EVM-related entry points and tooling inside the Polkadot ecosystem continue to mature (including the upcoming PolkaHub), we expect more developers to deploy dApps using Solidity contracts within Polkadot. In these scenarios, EVM accounts often serve as the natural entry point, while Substrate accounts remain fundamental to the Polkadot ecosystem.

This is not a hypothetical requirement. Several production dApps in the ecosystem (e.g. Bifrost, Hydration) already support both Substrate and EVM accounts in real user flows, demonstrating that the dual-account model is practically useful.

Today, most teams implement this by assembling multiple SDKs, providers, and state systems at the application layer. This leads to duplicated effort, unclear security boundaries, inconsistent state handling, and high long-term maintenance costs.

Our goal is to move this complexity into the SDK layer and provide a standardized solution.


2. Overall Goal

The core goal of this upgrade is to build a Hybrid Core Architecture that natively supports both Substrate and EVM ecosystems, while providing a unified abstraction over heterogeneous account models, connectors, and interaction flows.

Specifically, we aim to:

  • Clearly distinguish Substrate and EVM at the type system level while exposing a unified API to applications
  • Provide consistent lifecycle behavior across connectors with explicit ecosystem boundaries
  • Establish a single source of truth for state and context-aware React Hooks
  • Deliver a unified UX and transaction model that closes the “write operation” loop

3. Hybrid Core Architecture

3.0 Architecture Evolution

Previously, @luno-kit/core was strictly a collection of Substrate C@luno-kitnnectors, capable of interacting only with Polkadot-native wallets.

Now, it integrates Substrate and EVM Connectors into a single system. By standardizing the interface, it allows Wagmi-based EVM connectors and native Substrate connectors to coexist and be managed uniformly, enabling developers to use wallets from both ecosystems side-by-side.

3.1 Extensible Chain Type System

At the core level, we introduce an Extensible Chain Type System based on ChainType discriminated unions.

This system distinguishes:

  • SubstrateAccount (ss58)
  • EvmAccount (0x)

and extends to:

  • SubstrateChain and EvmChain
  • Chain configuration, account context, and interaction capabilities

By leveraging TypeScript’s type narrowing, once developers branch on chainType (e.g. if (account.chainType === 'evm')), the compiler and IDE automatically infer the correct ecosystem-specific types, preventing cross-ecosystem misuse.

Dependencies:

TypeScript, Viem, Wagmi Core, Dedot


3.2 Polymorphic Connector Architecture

The connector layer follows a Polymorphic Connector Architecture based on the Adapter Pattern, with BaseConnector as a unified contract.

Two parallel implementations are provided:

  • SubstrateConnector

    Handles native Polkadot wallet connection and signing logic.

  • EvmConnector

    Acts as an adapter over standard Wagmi connectors (injected, MetaMask, WalletConnect, Safe), bridging them into LunoKit’s unified interface.

Inside EvmConnector, Wagmi APIs such as watchConnection are used to observe provider state changes, which are then translated into LunoKit-standard events (accountsChanged, disconnect) to keep connector state fully synchronized.

This allows applications to manage fundamentally different wallet systems through the same lifecycle interface (connect, disconnect, getAccounts).


3.3 Factory Extraction & Instance Backfilling

To resolve lifecycle conflicts between Wagmi Config and LunoKit’s traditional static configuration model, we introduce Factory Extraction & Instance Backfilling with a lazy binding approach:

  1. During initialization, only Wagmi connector factory functions are extracted from user config
  2. Wagmi Config is constructed
  3. Active connector instances are backfilled into LunoKit’s EvmConnector container
  4. LunoKit centrally manages these instances while staying aligned with Wagmi’s internal state

This preserves Wagmi’s native behavior while enabling unified connector management.


3.4 Configuration System v2

The createConfig entry point is upgraded to Configuration System v2, allowing developers to define both Substrate and EVM parameters within a single configuration object.

Internally, parameters are routed automatically, and Wagmi’s createConfig is invoked to activate EVM connectivity, removing the need to maintain multiple configuration systems.


4. Reactive State Sync & Hooks

4.0 React Architecture Evolution

Previously, the React hooks were tightly coupled to Substrate. They could only return Polkadot-specific data and had no awareness of other ecosystems.

Now, the hooks are Context-Aware. By introducing a namespace mechanism, the same hook (e.g., useAccount) can intelligently switch contexts, retrieving data from either Substrate or EVM storage based on the user’s request or the currently active wallet.

4.1 Bi-directional State Synchronization

To prevent UI desynchronization when users manually switch networks or disconnect wallets (e.g. in MetaMask), LunoKit establishes a Single Source of Truth internally.

  • EVM state is subscribed via Wagmi React Hooks
  • State changes are propagated into the LunoKit Store
  • activeNamespace is maintained at the Store level to ensure a single active ecosystem and avoid concurrent state conflicts

4.2 Intelligent Hooks Layer

The Hooks layer is built using a combination of the Strategy Pattern and Factory Pattern.

  • Core hooks such as useAccount and useBalance accept an optional namespace parameter
  • When specified, hooks return ecosystem-specific state
  • When omitted, hooks automatically fall back to the current activeNamespace

Aggregated hooks such as useAccounts provide unified views across Substrate and EVM accounts.


4.3 Ecosystem-Specific & Unified Hooks

  • A unified chain info abstraction hides differences between EVM (Number) and Substrate (Genesis Hash) identifiers
  • Substrate-specific hooks (e.g. useSs58Format, usePapi) are preserved and enhanced
  • Context Guards ensure safe defaults or development-time warnings when these hooks are used outside their intended ecosystem

4.4 Unified Transaction Facade

Unified write-operation entry points such as useSendTransaction and useSignMessage are provided.

Routing is determined by the provided namespace or defaults to the active context:

  • EVM: Wagmi Hooks, following the Hash → Receipt flow
  • Substrate: Dedot Extrinsics, handling Ready → InBlock → Finalized lifecycle

A unified Promise-based interface and status callbacks are exposed to applications.


5. Unified UX & Transaction Model

5.0 UX Evolution

Previously, the UI and transaction logic were exclusive to Polkadot, forcing developers to build separate flows for Ethereum.

Now, it offers a Unified Facade. The connect modal seamlessly groups wallets from both ecosystems.

5.1 Multi-Ecosystem Connect Modal

The ConnectModal is redesigned with grouped rendering, clearly separating Polkadot and EVM wallets based on connector configuration.

The modal is tightly bound to activeNamespace, allowing context-aware transitions during the connection flow.


5.2 Context Switching & Session Recovery

A “switch chain = switch account” model is implemented using layered persistence:

  • Substrate: LunoKit persists the last active connector ID and non-sensitive account identifiers
  • EVM: Wagmi Storage is reused

When switching between ecosystems, the system attempts silent session recovery to reduce repetitive connection steps.


6. UI Design

This design draft provides only the main component parts, not all of them.

4 Likes