# Extensions The hdwalletv1 protocol supports optional extensions that let wallets and dapps negotiate additional capabilities beyond the core sign-transaction flow. Extensions are backward-compatible: existing wallets and dapps that don't know about extensions continue to work unchanged. ## How extensions work Extensions use three mechanisms, all of which are optional and additive: ### 1. Session extensions field Wallets advertise supported extensions in the `wallet_ready` handshake via an `extensions` field on the `Hdwalletv1Session` object: ```typescript interface Hdwalletv1Session { paths: PathXpub[]; extensions?: Record; } ``` Each key in `extensions` is an extension name. Its **presence** indicates the wallet supports that extension. The value carries extension-specific handshake data, or `{}` if no data is needed. Example: ```json { "paths": [ { "name": "receive", "xpub": "xpub6..." }, { "name": "change", "xpub": "xpub6..." }, { "name": "defi", "xpub": "xpub6..." } ], "extensions": { "bip352": {}, "decrypt": { "public_key": "02abc...", "scheme": "ecies" } } } ``` ### 2. Additional path names `PathName` is an open string type. Wallets may include paths beyond the well-known `receive`/`change`/`defi` set. Extension-defined paths are carried in the standard `paths` array: ```json { "paths": [ { "name": "receive", "xpub": "xpub6..." }, { "name": "change", "xpub": "xpub6..." }, { "name": "stealth_scan", "xpub": "xpub6..." }, { "name": "stealth_spend", "xpub": "xpub6..." } ], "extensions": { "bip352": {} } } ``` Dapps should ignore path names they do not recognize. The standard pubkey derivation logic (`DappPubkeyStateManager`) automatically skips unknown paths. ### 3. Custom message actions Extensions may define new message action strings beyond the well-known set. Custom messages follow the standard `ProtocolMessage` shape (`action` + `time`) and use the existing relay transport. Convention for request/response operations: ```typescript // Request (dapp → wallet): { action: "_request", sequence: number, time: number, ...params } // Response (wallet → dapp): { action: "_response", sequence: number, time: number, ...result } ``` The `sequence` field ties responses to requests, matching the pattern used by `sign_transaction_request`/`sign_transaction_response`. **Wallet side**: custom messages are emitted via the `"message"` event on `WalletConnectionManager`: ```typescript manager.on("message", (connectionId, msg) => { if (msg.action === "decrypt_request") { // handle decrypt request } }); ``` **Dapp side**: all messages (including custom ones) are emitted via the `"messagereceived"` event on `DappConnectionManager`: ```typescript manager.on("messagereceived", (msg) => { if (msg.action === "decrypt_response") { // handle decrypt response } }); ``` ## Implementing an extension (wallet side) Wallets advertise extensions by implementing optional methods on `WalletAdapter`: ```typescript interface WalletAdapter { // ... core methods ... /** Additional paths to include in the session (e.g. stealth_scan). */ getAdditionalPaths?(): PathXpub[]; /** Extension data for the session handshake. */ getExtensions?(): Record; } ``` Example: ```typescript const adapter: WalletAdapter = { // ... core implementation ... getAdditionalPaths() { return [ { name: "stealth_scan", xpub: deriveScanXpub() }, { name: "stealth_spend", xpub: deriveSpendXpub() }, ]; }, getExtensions() { return { "bip352": {} }; }, }; ``` Wallets that don't implement these methods produce the same session as before (receive/change/defi paths only, no extensions field). ## Discovering extensions (dapp side) Dapps check for extension support after receiving `wallet_ready`: ```typescript manager.on("walletready", (msg) => { const session = msg.session["hdwalletv1"] as Hdwalletv1Session; if (session.extensions?.bip352) { const scanPath = session.paths.find(p => p.name === "stealth_scan"); // enable stealth address features } else { // show: "Stealth payments require a wallet that supports BIP352" } }); ``` Dapps should degrade gracefully when an extension is absent. If a feature requires an extension the wallet doesn't support, inform the user rather than failing silently. ## Known extensions No extensions are standardized yet. The following are under discussion: | Extension name | Purpose | Status | |---------------|---------|--------| | `bip352` | BIP352 silent/stealth payments. Adds `stealth_scan` and `stealth_spend` paths. | Proposed | | `bip47_rpa` | BIP47 reusable payment addresses. Adds `rpa` path and payment code data. | Proposed | | `decrypt` | Dapp-side encrypted storage. Wallet provides a public key; dapp encrypts data for storage and sends `decrypt_request` messages when the data is needed. | Proposed | See the discussions and specifications for each extension as they are formalized.