How to Understand the Code Flow of Wand Enhancer: A Complete Technical Guide

Wand Enhancer bridges a .NET WPF patcher with an Electron web-panel through a three-stage pipeline that extracts ASAR archives, injects bridge scripts, and establishes WebSocket communication on port 3223.

To understand the code flow of Wand Enhancer, you must trace how the k1tbyte/Wand-Enhancer repository coordinates between its C# WPF frontend and TypeScript Electron backend. The architecture follows a clear sequence: the WPF application initializes the UI, the patcher modifies the target ASAR bundle, and the Electron renderer establishes bidirectional IPC with the injected bridge.

Stage 1: Application Startup and WPF Initialization

The execution begins in the .NET layer where the WPF application sets up global handlers and presents the main interface.

Entry Point and Global Setup

In WandEnhancer/Program.cs, the Main method serves as the single entry point. It instantiates a WPF App class, configures global exception handlers, and launches MainWindow. This ensures that any unhandled exceptions in the patching process are captured before the UI renders.

View-Model Architecture

The MainWindowVm.cs file in WandEnhancer/View/MainWindow/ implements the view-model pattern that drives all user interactions. It maintains the log list displayed in the UI and handles commands such as Patch and Launch Remote Panel. When a user initiates a patch, the view-model coordinates the transition from UI interaction to file system operations.

Stage 2: ASAR Extraction and Patching

Once the user clicks Patch, the flow shifts from the WPF layer to low-level ASAR manipulation using the embedded AsarSharp library.

Extraction Logic

The patcher utilizes AsarSharp/Utils/NativeMethods.cs to extract resources/app.asar from the target Wand installation. The extraction process creates a temporary directory structure where the archive contents are unpacked for manipulation. According to the source code, the extractor handles both the packed ASAR and its unpacked counterpart directories.

Script Injection and Configuration

After extraction, the patcher copies web-panel/dist/bridge.cjs into the extracted ASAR under the remote-panel/ folder. It also copies the default renderer scripts from web-panel/dist/renderer-scripts/ into remote-panel/renderer-scripts/.

Custom user scripts specified in PatchConfig.CustomScriptPaths are injected at this stage as well. This configuration allows users to extend functionality without modifying core bridge files. The patching logic then repacks the modified directory back into resources/app.asar.

Stage 3: Electron Bridge and Remote UI Communication

With the patched ASAR in place, the Electron side initializes and establishes the communication layer between the Wand client and the remote web interface.

Bridge Constants and Protocol

The bridge runtime configuration resides in web-panel/bridge/src/constants.ts. This file defines the WebSocket port (3223), HTTP/WS endpoints, and IPC channel names used throughout the application. Port alignment is critical: the C# side assumes the bridge listens on port 3223, so any modification must be synchronized in this constants file.

Message contracts are strictly typed through web-panel/protocol/messages.ts and validated via web-panel/protocol/validation.ts. The JSON schema in web-panel/protocol/web-contract.json serves as the authoritative reference for all WebSocket payloads.

Renderer Scripts and IPC

Upon launch, the Electron panel loads web-panel/bridge/scripts/default/installed-apps-sync.js. This default renderer script performs three essential functions:

  • Subscribes to Wand’s IPC services to monitor installed games
  • Builds a snapshot of the current game library
  • Handles remote commands via the remote_command channel

The script communicates with the WPF backend through the ipcRenderer module, forwarding game-status events and executing play/stop commands received from the remote UI.

Critical Implementation Details

Several architectural constraints govern how components interact across the stack.

  • Port Alignment: The C# patcher and TypeScript bridge must agree on port 3223 as defined in constants.ts. Mismatches break the WebSocket connection.

  • Development Guards: All mock data is wrapped in import.meta.env.DEV checks, ensuring production builds exclude demonstration content.

  • Storage Abstraction: Direct localStorage access is prohibited in favor of web-panel/src/shared/storage.ts, which centralizes JSON serialization and error handling.

  • Pro Activation: Pro-state patches rewrite three service methods and the Redux reducer within the ASAR patch pipeline, as documented in AGENTS.md, to maintain subscription flags across language changes.

Code Examples

The following snippets demonstrate the transition points between architecture layers.

Starting a patch from the WPF UI (C#):

// Inside MainWindowVm.cs – invoked by the “Patch” button
public async Task PatchAsync()
{
    var extractor = new AsarSharp.AsarExtractor();
    await extractor.ExtractAllAsync(@"resources/app.asar", @"temp/extracted");
    // Copy bridge and scripts (pseudo-code, actual copy logic lives in PatchVectorsPopup)
    File.Copy(@"web-panel/dist/bridge.cjs", @"temp/extracted/remote-panel/bridge.cjs", true);
    // Re-pack the ASAR
    await extractor.PackAsync(@"temp/extracted", @"resources/app.asar");
}

Subscribing to installed apps in the renderer (TypeScript):

import { ipcRenderer } from 'electron';
import { sendMessage } from '../bridge';
import type { GameSnapshot } from '../protocol/messages';

ipcRenderer.on('wand-remote-installed-apps', (_event, apps: GameSnapshot[]) => {
  // Update UI store
  store.dispatch({ type: 'SET_INSTALLED_APPS', payload: apps });
});

// Request a fresh snapshot on start-up
sendMessage('hello', { request: 'installed_apps' });

Sending a remote play command:

// From the UI when the user clicks “Play”
sendMessage('remote_command', {
  command: 'play',
  gameId: selectedGame.id,
});

Summary

  • Entry Point: Program.cs initializes the WPF application and global exception handlers.
  • View-Model: MainWindowVm.cs coordinates UI actions and delegates patching operations.
  • ASAR Manipulation: AsarSharp/Utils/NativeMethods.cs handles extraction and repacking of the target archive.
  • Script Injection: Bridge files and custom scripts are copied into remote-panel/ during the patch phase.
  • Communication Layer: The bridge uses constants.ts (port 3223) and web-contract.json for typed message exchange.
  • Renderer Logic: installed-apps-sync.js manages game state synchronization and remote command execution.
  • Storage: All persistence flows through web-panel/src/shared/storage.ts rather than direct localStorage access.

Frequently Asked Questions

What is the entry point for the Wand Enhancer application?

The execution begins in WandEnhancer/Program.cs, where the Main method creates the WPF App instance, configures global exception handlers, and opens MainWindow. This serves as the bridge between the operating system and the WPF view-model architecture.

How does the patcher modify the Wand client ASAR archive?

The patcher uses AsarSharp/Utils/NativeMethods.cs to extract resources/app.asar, copies web-panel/dist/bridge.cjs and renderer scripts into a remote-panel/ subdirectory, and repacks the archive. Custom scripts from PatchConfig.CustomScriptPaths are also injected during this process.

Which file defines the WebSocket port for the remote panel?

The port is defined in web-panel/bridge/src/constants.ts as 3223. This value must remain synchronized with the C# side expectations; changing it requires updates in both the TypeScript bridge configuration and the WPF patcher logic.

Where should I store configuration data in the web panel?

All localStorage operations must route through web-panel/src/shared/storage.ts. This abstraction layer handles JSON serialization and prevents direct access to the browser storage API, ensuring consistent data handling across the application.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →