This monorepo contains two main components:
- The Vultisig Desktop Application (Windows and Linux)
- The Vultisig Extension Browser Extension - A Chrome extension for bridging your Vultisig vaults to dApps
This project uses Wails. Please refer to https://wails.io/docs/gettingstarted/installation/ for installation instructions.
Vultisig under Linux requires libwebkit2gtk-4.0-dev. Install it with:
sudo apt update
sudo apt install libwebkit2gtk-4.0-devTo run the desktop application in development mode:
yarn dev:desktopThe startup receipt prints separate Wails, Vite, and local mediator URLs. Open the Wails URL; the Vite server does not have the required Wails-injected scripts. The primary checkout defaults to ports 34115, 5173, and 18080. Linked worktrees receive stable, isolated ports and a worktree-local development database automatically.
To build the desktop app dist:
yarn build:desktopFor Ubuntu 24.4 users who can't find libwebkit2gtk-4.0-dev:
- Add
deb http://gb.archive.ubuntu.com/ubuntu jammy mainto/etc/apt/sources.list - Run
sudo apt update && sudo apt install libwebkit2gtk-4.0-dev
Vultisig Extension is a Chrome extension similar to MetaMask but much safer. It does not store any critical information such as private keys or passwords. Instead, it acts as a bridge that allows you to connect your Vultisig app to DeFi applications, enabling you to interact with them and sign transactions securely on your devices.
You only need to import public keys and vault information into Vultisig Extension. Unlike MetaMask, if someone hacks your Chrome or the extension, they cannot execute transactions without your approval on your Vultisig devices, as they only have access to public information.
Before building Vultisig Extension, ensure you have the following installed:
Node.js(version 18.10.0 or later)yarn(for managing packages)
To run the Vultisig Extension extension in development mode:
yarn dev:extensionTo build the regular Vultisig extension:
yarn build:extensionThe Vultisig artifact is written to clients/extension/dist.
To build the Station extension:
yarn build:extension:stationThe Station artifact is written independently to
clients/extension/dist-station. Building one flavor does not replace the
other.
- Open Chrome and navigate to
chrome://extensions - Enable "Developer mode" (top-right corner)
- Click "Load unpacked" and select
clients/extension/distfor Vultisig orclients/extension/dist-stationfor Station. - Verify the extension card says
Vultisig ExtensionorStation Wallet, note its extension ID, and reload the exact directory selected above before reviewing UI. - The extension should now be installed and ready to use.
For details on integrating Vultisig Extension with your project, see the Integration Guide.
This project depends on multiple packages from the vultisig-sdk monorepo, published individually on npm:
@vultisig/sdk— main SDK@vultisig/core-chain— blockchain/chain utilities@vultisig/core-config— configuration@vultisig/core-mpc— multi-party computation@vultisig/lib-utils— shared utilities
CI also runs a non-blocking compatibility check against the SDK main branch to catch integration issues early.
Since vultisig-sdk is a monorepo, yarn link won't work due to peer dependency conflicts. A script is provided that builds the SDK, packs all packages into tarballs, and overrides them via resolutions:
./scripts/use-local-sdk.sh /path/to/vultisig-sdkThis will build the SDK, pack all shared packages, add resolutions to package.json, and run yarn install.
To restore npm versions:
git checkout package.json yarn.lock
yarn installProduction builds always use npm-published SDK versions. Before releasing, ensure all @vultisig/* dependencies in package.json point to stable npm versions, not git references or local links.
This codebase uses domain-driven organization - files are grouped by business purpose rather than technical type.
❌ Avoid: Dumping everything in generic folders like core/ui/components
✅ Follow: Place files based on their business domain. For example, ReshareVaultPage goes in core/ui/mpc/keygen/reshare/ because:
core/- shared across projectsui/- user interface codempc/- multi-party computation domainkeygen/- key generation subdomainreshare/- specific reshare functionality
This makes code easier to find, understand, and maintain by keeping related functionality together.
When adding new code, choose the appropriate top-level folder based on abstraction level:
lib/ - Pure, reusable code that could work in any project
- Zero dependencies on Vultisig business logic
- Examples: UI components, utilities
- Think: "Could I copy this to a completely different project?"
core/ - Vultisig-specific business logic shared across clients
- Contains domain knowledge about vaults, MPC, chains, etc.
- Shared between desktop and extension clients
- Examples: vault management, MPC protocols, chain integrations
clients/ - Application-specific code for each platform
clients/desktop/- Desktop app UI and platform-specific codeclients/extension/- Browser extension UI and Chrome APIs- Should import from
core/andlib/, not the other way around
Rule of thumb: Code flows from abstract (lib/) → domain-specific (core/) → application-specific (clients/).
Inside each feature or domain folder, organize files by their technical purpose:
config.ts - Shared constants and configuration
- Feature-specific constants that might be reused
- Default values, enums, static configurations
- Example:
core/ui/passcodeEncryption/core/config.tsfor passcode-related constants
state/ - React state management organized by entity
- One subfolder per data entity being managed
- Example:
state/mpcServerType/contains hooks and providers forMpcServerType - Include both the hook and provider in the same folder
core/ - Pure business logic for this feature
- Types, interfaces, classes, utility functions
- No React dependencies - pure TypeScript/JavaScript
- Example:
core/ui/chain/coin/addCustomToken/coreThis includes functions for adding custom tokens based on a specified chain, serving as the foundational logic for this feature.
queries/ - React Query queries for data fetching
- GET operations, data fetching hooks
- Organized by entity or API endpoint
- File names don't need the full hook name (e.g.,
coinBalance.tsinstead ofuseCoinBalanceQuery.ts)
mutations/ - React Query mutations for data modification
- POST, PUT, DELETE operations
- State-changing operations
- File names don't need the full hook name (e.g.,
changePasscode.tsinstead ofuseChangePasscodeMutation.ts)
Note: No /components folder needed - most files are already components, and non-component code goes into the folders above.