ENC Wallet Extension
The ENC Wallet Extension is a Chrome (MV3) browser extension that custodies a user's ENC
identity and signs on behalf of apps — so an app never touches the private key. It's a BIP-39
seed-phrase HD wallet (an ENC Schnorr identity plus an EVM address) that injects a window.enc
provider any ENC web app connects to through a standard Connect-Wallet flow. It's also
NIP-07-compatible (mirrored as window.nostr).
This is the delegated-custody signer in ENC's identity model: the
identity_priv stays inside the extension; the page asks it to sign, derive, or encrypt and
gets results back — never the key.
Connecting from an app
// the provider is injected on page load; wait for it if it isn't there yet
if (!window.enc) await new Promise(r => window.addEventListener('encReady', r, { once: true }))
const { approved, pubKey, evmAddress } = await window.enc.connect() // first call shows an approval popup
if (approved) console.log('ENC identity:', pubKey) // x-only 32-byte hexOnce connected, signing and encryption calls run without a popup (the user approved the
origin); only connect() and sendTransaction() prompt.
The window.enc provider
Connection & accounts
| Method | Returns | Notes |
|---|---|---|
connect() | { approved, pubKey, evmAddress } | approval popup on first use |
getPublicKey() | string | x-only 32-byte hex (the ENC identity) |
getEvmAddress() | string | cached 0x… address |
isConnected() | boolean | |
getAccounts() | { accounts: [{ index, pubKey, evmAddress }] } | HD-derived accounts |
switchAccount(index) | { pubKey, evmAddress } | emits accountChanged |
getVersion() | string |
Signing (no popup)
const sig = await window.enc.signSchnorr(hashHex) // BIP-340 over a 32-byte hash → signature hexThis is how an app gets a commit signed: build the commit hash, ask the extension to
signSchnorr it, and attach the signature. The key never leaves the extension.
Session keys (no popup)
const { session, sessionPriv, expires } = await window.enc.createSession(7200) // secondsA short-lived session key for WebSocket auth — see the session model.
ECDH & encryption (no popup)
const shared = await window.enc.ecdh(peerPubHex) // 32-byte hex
const key = await window.enc.deriveKey(shared, 'enc:dm:a-b') // HKDF → 32-byte hex
const ct = await window.enc.encrypt(key, 'secret') // XChaCha20-Poly1305 → base64
const pt = await window.enc.decrypt(key, ct)The same primitives as @enc-protocol/core, but computed inside
the extension against the custodied key.
EVM transactions (popup confirm)
const { hash } = await window.enc.sendTransaction({ to, amount, memo }) // shows a confirmation popupEvents
window.enc.on('connect', ({ pubKey, evmAddress }) => {})
window.enc.on('disconnect', () => {})
window.enc.on('accountChanged', ({ pubKey, accountIndex }) => {})Seed import
exportSeed() returns the 12-word mnemonic — used by an app's "import this wallet" flow so the
same identity is available to the in-app SDK.
Install for development
The extension ships as a built zip. To run it locally:
- Build the zip (
yarn build) and unzip it somewhere stable. - Open
chrome://extensions, enable Developer Mode, click Load unpacked, and select the extractedextension-chrome/folder. - Reload any open ENC app — the Connect-Wallet row should now show the extension as available.
The content script injects window.enc on every page, so any ENC web app can detect and
connect to it.
See also
- Building with the SDK — pair the signer with the client SDK
- Identity & custody ·
corecrypto