Signer API
Overview
This page describes how to setup interaction with the signer iframe from the main app and what methods are available.
Communication (MessageChannel)
The signer communicates with the main app using the Channel Messaging API. This provides a direct, two-way communication pipe between the main app and the iframe, bypassing the overhead and noise of window.postMessage broadcasting.
Setup Flow
- Initialization: The main app creates a
MessageChanneland sends the message{ type: 'connect' }withport2to the signer iframe viapostMessage. - Connection: The signer listens for the
connectevent, grabs the port, and sets up its listeners. - Ready: The signer sends a
{ type: 'ready' }message back to the main app to signal it's ready to accept requests.
Proxy Pattern
The consumer (main app) uses a Proxy to interact with the signer. Instead of manually constructing postMessage payloads, the consumer code looks like this:
// Consumer side
await signer.signTransaction(txData);
Under the hood, the Proxy intercepts this call and converts it into a structured message:
{
"requestId": "unique-id",
"method": "signTransaction",
"args": [txData]
}
The signer receives this, resolves the method using the build-generated loader, executes it, and sends back the result.
Build System & Module Configs
The signer uses a custom build process (powered by scripts/build.ts) to discover and register modules. This allows for granular control over what gets included in the final bundle, especially for different build targets (e.g., online vs offline).
Entry Point Generation
During the build process, the script:
- Scans the
srcdirectory for allmodule.config.tsfiles. - Filters them based on the current
BUILD_TARGET(e.g., excluding online-only modules for offline builds). - Generates a central entry point at
src/services/safeService.ts.
This generated file contains a loadSafeServiceMethod function with a giant switch statement that maps method names to dynamic imports:
// Generated by scripts/build.ts
export async function loadSafeServiceMethod(moduleName: string) {
switch (moduleName) {
case "signTransaction": {
return import("./safeSigner/signTransaction");
}
// ... other modules
default: {
throw new Error(`Module ${moduleName} not found`);
}
}
}
This generation step ensures that only the modules relevant to the current build target are included, and that the runtime can resolve method names to file paths without needing a manual registry.
Every functional module in the signer must have a module.config.ts file.
👉 See the Module Integration Guide for step-by-step instructions.
Runtime & Dynamic Imports
To keep the signer lightweight, we do not bundle all logic into a single large file. Instead, we use dynamic imports.
On-Demand Loading
When the main app requests a method (e.g., signTransaction), the signer:
- Receives the request via
MessagePort. - Calls
loadSafeServiceMethod('signTransaction'). - The generated switch statement triggers a
import('./safeSigner/modules/signTransaction/signTransaction'). - The browser fetches the chunk containing that specific module.
This means the initial iframe load is very fast because it only contains the minimal main.ts and communication logic. Heavy cryptographic libraries or complex UI flows are loaded only when needed.
Caching
Once a module is loaded, its methods are cached in safeServiceCache (in src/main.ts). Subsequent calls to the same method use the cached version, avoiding repeated network requests or module resolution overhead.
Methods
Please refer to the specific method implementation for the details.
| Method | Description |
|---|---|
signDeltaOrder | Sign a cross-chain order. |
signTransaction | Sign a transaction. |
addAccounts | Add accounts to a wallet. |
addAddressToAddressBook | Add an entry to a portfolio address book. |
editAddressBookEntry | Edit an entry in a portfolio address book. |
removeAddressFromAddressBook | Remove an entry from a portfolio address book. |
createWallet | Create a new portfolio wallet. |
removeWallet | Remove a wallet from a portfolio. |
importWallet | Import a wallet to a portfolio. |
exportWallet | Export a wallet without secrets. |
renameWallet | Rename a wallet. |
setWalletPassword | Set the wallet password. |
importOfflineWallet | Import an offline wallet to a portfolio. |
showMnemonicGrid | Visually show a grid with mnemonic inputs. |
hideMnemonicGrid | Visually hide a rendered mnemonic grid. |
deriveAddressListSelectively | Derive address items for every passed entry. |
changeEncryptionType | Change a portfolio and all its entities encryption type. |
exitPortfolio | Exit a portfolio. |
backupPortfolio | Backup a portfolio. |
removePortfolio | Remove a portfolio. |
renamePortfolio | Rename a portfolio. |
getPortfolioPublicView | Get a portfolio without secrets. |
importToken | Import a token to an account. |
removeAccounts | Remove accounts from a wallet. |
setPortfolioPassword | Set the portfolio password. |
removeWalletAsset | Remove an asset from an account. |
renameAccount | Rename an account. |
syncAllBalance | Update accounts balances. |
updateAccountList | Save/remove a wallet accounts list. |
showAutoSign | Show the auto sign checkbox on auth forms. |
showLoginForm | Show the login form. |
submitLoginForm | Submit the login form. |
showRestoreForm | Show the restore form. |
submitRestoreForm | Submit the restore form. |
showSignUpForm | Show the sign up form. |
submitSignUpForm | Submit the sign up form. |
showChangePasswordForm | Show the change password form. |
submitChangePasswordForm | Submit the change password form. |
destroyVisibleForm | Destroy the currently rendered form. |
showImportInputPK | Show the private key input. |
submitImportAccount | Import an account by reading the private key input. |
validationImportInputPK | Validate the private key input. |
setupPasswordModal | Setup and render the password modal. |
setupPasteMnemonicTextFormWords | Change the mnemonic inputs length of the currently rendered mnemonic grid. |
showPasteMnemonicTextForm | Setup and render the mnemonic grid along with mnemonic words. |
validatePasteMnemonicForm | Validate the mnemonic grid. |
showReadOnlyMnemonicForm | Setup and render the readonly mnemonic grid along with mnemonic words. |
resetMnemonicState | Reset the mnemonic grid state. |
showDecryptedMnemonic | Show the decrypted from a QR mnemonic. |
showEncryptedInfo | Show the placeholder for the secure data. |
showDecryptedInfo | Decrypt and display the secure data. |
copyDecryptedInfo | Copy the decrypted secure data to the clipboard. |
showEncryptedMnemonicQr | Show the wallet mnemonic encrypted QR code. |
getMnemonicQr | Get the wallet mnemonic encrypted QR code src. |
setupQrDecryptFormRecoveryPhraseField | Render the textarea with a hidden with dots recovery phrase. |
showQrDecryptFormPasswordField | Render the password input for the QR decrypt form. |
submitQrDecryptForm | Submit the QR decrypt form and save the decrypted phrase in memory. |
validateQrDecryptForm | Validate the QR decrypt form. |
copyQrDecryptFormRecoveryPhrase | Copy the decrypted phrase to the clipboard. |
submitQrEncryptForm | Submit the QR encrypt form. |
showQrEncryptForm | Show the QR encrypt form. |
setLayoutMode | Set the theme. |