@ducat-unit/wallet-snap 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,165 +1,78 @@
1
- # Ducat MetaMask Snap
1
+ # Ducat Snap
2
2
 
3
- `@ducat-unit/wallet-snap` is the Ducat Bitcoin account and signing Snap for MetaMask. It derives deterministic mainnet, signet, and mutinynet Bitcoin accounts from the user's MetaMask Secret Recovery Phrase, keeps private keys inside MetaMask, and exposes a narrow Ducat JSON-RPC API to approved Ducat frontend origins.
3
+ A MetaMask snap for Bitcoin accounts and signing in the [Ducat](https://ducatprotocol.com) protocol.
4
4
 
5
- The Ducat web app remains the user action surface. Users create, deposit, borrow, repay, withdraw, swap, liquidate, and repossess in the web app; the Snap handles account discovery, MetaMask confirmations, message signing, PSBT signing, batch signing, transfer signing, recent action state, notifications, and Snap Home.
5
+ It derives Bitcoin accounts from the user's MetaMask Secret Recovery Phrase, keeps the keys
6
+ inside MetaMask, and exposes a small JSON-RPC API to the Ducat web app for message signing,
7
+ PSBT signing, and simple transfers. The web app drives everything the user does — borrow,
8
+ repay, withdraw, and so on — and the snap handles account discovery and the MetaMask
9
+ confirmation prompts.
6
10
 
7
- ## Release Candidate Status
11
+ > Mainnet, signet, and mutinynet are supported. Local development against regtest needs a
12
+ > dev build (see below).
8
13
 
9
- - Package candidate: `@ducat-unit/wallet-snap@0.1.9`
10
- - Snap ID: `npm:@ducat-unit/wallet-snap`
11
- - Proposed Snap name: `Ducat`
12
- - Audit candidate tag: `audit-candidate-0.1.9-20260617-release-0.1.9`
13
- - Audit candidate commit: tag target for `audit-candidate-0.1.9-20260617-release-0.1.9`
14
- - GitHub verification: `Verify Ducat Snap`
15
- - Manifest source shasum: `u1SC4s8yatFtFEE1IbLPvx2irYCtR/WOm0PtAx81qUs=`
16
- - Package candidate digest evidence: `RELEASE_EVIDENCE.md`
14
+ ## What are snaps?
17
15
 
18
- Launch scope:
16
+ Snaps let developers extend MetaMask with capabilities it doesn't ship by default — like
17
+ support for non-EVM chains. They run in an isolated environment with a limited set of
18
+ permissions. See the [MetaMask Snaps docs](https://docs.metamask.io/snaps/) for more.
19
19
 
20
- - Networks: `mainnet`, `signet`, and `mutinynet`
21
- - Mainnet: enabled in this audit candidate
22
- - Derivation paths:
23
- - sats mainnet: `m/84'/0'/0'/0/0`, P2WPKH `bc1q...`, compressed 33-byte public key
24
- - runes mainnet: `m/86'/0'/0'/0/0`, P2TR `bc1p...`, x-only 32-byte internal public key
25
- - vault mainnet: `m/86'/0'/0'/0/1`, P2TR `bc1p...`, x-only 32-byte internal public key
26
- - sats testnet: `m/84'/1'/0'/0/0`, P2WPKH `tb1q...`, compressed 33-byte public key
27
- - runes testnet: `m/86'/1'/0'/0/0`, P2TR `tb1p...`, x-only 32-byte internal public key
28
- - vault testnet: `m/86'/1'/0'/0/1`, P2TR `tb1p...`, x-only 32-byte internal public key
20
+ ## RPC methods
29
21
 
30
- ## Install
31
-
32
- ```bash
33
- npm ci
34
22
  ```
35
-
36
- Recommended local edit gate:
37
-
38
- ```bash
39
- npm run type-check
40
- npm test -- --runInBand
41
- npm run build
42
- npm run manifest
43
- npm run harness:accounts
44
- npm run harness:smoke-signing
23
+ ducat_getAccounts({ network })
24
+ ducat_getCapabilities()
25
+ ducat_getHomeState({ network })
26
+ ducat_signMessage({ network, address, message })
27
+ ducat_signPsbt({ network, psbt, signInputs, context })
28
+ ducat_signBatch({ network, entries, context })
29
+ ducat_sendTransfer({ network, address, amountSats, feeRate })
30
+ ducat_clearRecentActions()
45
31
  ```
46
32
 
47
- Full release gate:
33
+ Only the Ducat app origins below are allowed to call these:
48
34
 
49
- ```bash
50
- npm run verify:release
51
35
  ```
52
-
53
- `verify:release` runs type checking, Jest, build, manifest regeneration, MetaMask simulation harness checks, production dependency audit, Snapper, release metadata verification, release manifest verification, and `npm pack --dry-run`.
54
-
55
- ## Run Locally
56
-
57
- Serve the local Snap:
58
-
59
- ```bash
60
- npm run serve
36
+ https://app.ducatprotocol.com
37
+ https://dev.app.ducatprotocol.com
38
+ https://staging.app.ducatprotocol.com
61
39
  ```
62
40
 
63
- The local Snap is served at:
41
+ `localhost` and preview deployments are intentionally not in the published manifest — a local
42
+ process or a hijacked preview subdomain should never be able to drive mainnet signing. For
43
+ local QA, build with the dev origins/regtest flags (`DUCAT_SNAP_DEV_ORIGINS`,
44
+ `DUCAT_SNAP_DEV_REGTEST`); those are stripped from the published build.
64
45
 
65
- ```text
66
- http://localhost:8080
67
- ```
68
-
69
- For local frontend testing:
46
+ ## Development
70
47
 
71
48
  ```bash
72
- NEXT_PUBLIC_DUCAT_SNAP_ID="local:http://localhost:8080"
73
- NEXT_PUBLIC_DUCAT_SNAP_VERSION=""
49
+ npm ci
50
+ npm run build # mm-snap build -> dist/bundle.js
51
+ npm run manifest # regenerate the manifest shasum
52
+ npm run serve # serve the snap at http://localhost:8080
74
53
  ```
75
54
 
76
- For the published Snap:
55
+ Before opening a PR:
77
56
 
78
57
  ```bash
79
- NEXT_PUBLIC_DUCAT_SNAP_ID="npm:@ducat-unit/wallet-snap"
80
- NEXT_PUBLIC_DUCAT_SNAP_VERSION="^0.1.9"
58
+ npm run type-check
59
+ npm test
60
+ npm run verify:harness # MetaMask simulation harness (accounts, signing, BitVM3)
81
61
  ```
82
62
 
83
- Allowed HTTPS Ducat origins in the published mainnet manifest:
63
+ Point the frontend at the local build with `NEXT_PUBLIC_DUCAT_SNAP_ID="local:http://localhost:8080"`,
64
+ or at the published package with `NEXT_PUBLIC_DUCAT_SNAP_ID="npm:@ducat-unit/wallet-snap"`.
84
65
 
85
- - `https://app.ducatprotocol.com`
86
- - `https://dev.app.ducatprotocol.com`
87
- - `https://staging.app.ducatprotocol.com`
66
+ ## Security
88
67
 
89
- The published manifest authorizes only stable, org-controlled HTTPS Ducat origins. Local development (`http://localhost`) and ephemeral, re-registerable preview deployments (`*.vercel.app`) are deliberately excluded so a local process or a taken-over preview subdomain can never drive mainnet signing; use a separate, unpublished dev manifest for local Snap QA. The release verifier rejects localhost, non-HTTPS, wildcard, duplicate, or unknown origins in the shipped manifest.
68
+ Keys, child keys, WIFs, and raw entropy never leave the snap. Only derived Ducat accounts are
69
+ signed for, only the explicit `signInputs` indexes are signed, and every signing path requires a
70
+ MetaMask confirmation. Frontend-supplied context is treated as untrusted display metadata — the
71
+ parsed PSBT is the source of truth for what's actually signed. Taproot vault inputs must carry a
72
+ Ducat cosign tapleaf whose control block recomputes to the prevout output key.
90
73
 
91
- ## JSON-RPC API
74
+ The third-party security audit (Sayfer) is in [`docs/audit.pdf`](docs/audit.pdf).
92
75
 
93
- - `ducat_getAccounts({ network })`
94
- - `ducat_getCapabilities()`
95
- - `ducat_signMessage({ network, address, message })`
96
- - `ducat_signPsbt({ network, psbt, signInputs, context })`
97
- - `ducat_signBatch({ network, entries, context })`
98
- - `ducat_sendTransfer({ network, address, amountSats, feeRate })`
99
- - `ducat_getHomeState({ network })`
100
- - `ducat_clearRecentActions()`
76
+ ## License
101
77
 
102
- ## User Confirmation Surface
103
-
104
- MetaMask confirmations are action-specific and structured:
105
-
106
- - Message signing shows the Ducat action label, origin, network, account, BIP322 signature type, message length, message fingerprint, and copyable message body.
107
- - PSBT signing shows the Ducat action label, origin, network, summary rows, signed input details, output details, fee, warnings, and Ducat app metadata.
108
- - Batch signing shows transaction count, all-or-nothing semantics, total fee, per-transaction summaries, and warning count.
109
- - Simple BTC transfer shows amount, estimated fee, `You pay`, change, sender, recipient, selected UTXOs, and broadcast endpoint.
110
- - Snap Home shows last connected network, copyable BTC/UNIT/vault addresses, public balance and vault lookups when available, recent action state, approved HTTPS Ducat app links, and local development routes.
111
-
112
- Errors returned to the frontend include a stable `code`, user-facing `message`, and diagnostic `details` for expanded debugging.
113
-
114
- ## Security Model
115
-
116
- - Private keys, child private keys, WIFs, and raw entropy never leave the Snap.
117
- - The Snap requests Bitcoin mainnet and testnet BIP32 entropy paths: `m/84'/0'`, `m/86'/0'`, `m/84'/1'`, and `m/86'/1'`.
118
- - Mainnet requests use Bitcoin mainnet addresses, transaction parsing, and broadcast endpoints; signet and mutinynet requests use Bitcoin testnet parameters.
119
- - Unauthorized origins cannot invoke the Snap RPC API.
120
- - Only explicit `signInputs` indexes are signed.
121
- - Signing is restricted to derived Ducat Snap accounts.
122
- - Message, PSBT, batch, and transfer signing require MetaMask confirmation.
123
- - Frontend context is treated as untrusted display metadata. Parsed PSBT data is the signing source of truth.
124
- - Snap state stores recent Ducat action metadata only.
125
-
126
- Taproot script-path inputs must include a Ducat cosign tapleaf and control-block data that recomputes to the prevout P2TR output key. The tapleaf must place the derived Ducat vault key in the client slot, and the client and guard pubkeys must be distinct. The Snap rejects uncommitted script-path inputs, client/guard key collapse, and generic leaves even when a leaf contains the derived vault key.
127
-
128
- ## Audit And Submission Packet
129
-
130
- Primary audit documents:
131
-
132
- - `AUDITOR_HANDOFF.md`
133
- - `AUDIT_SCOPE.md`
134
- - `RELEASE_EVIDENCE.md`
135
- - `INTERNAL_SECURITY_REVIEW.md`
136
- - `DEPENDENCY_AUDIT.md`
137
- - `SNAPPER_REVIEW.md`
138
-
139
- Submission documents:
140
-
141
- - `submission/README.md`
142
- - `submission/ALLOWLIST_SUBMISSION.md`
143
- - `submission/EXTERNAL_GATES.md`
144
- - `submission/metamask-directory.json`
145
- - `submission/fixtures/README.md`
146
- - `submission/e2e/README.md`
147
- - `submission/screenshots/README.md`
148
-
149
- The source, package, metadata, and local verification evidence are ready for external audit handoff. MetaMask directory submission still requires the third-party audit report, final screenshots, demo video, real transaction fixtures, final E2E evidence, and project-owned support/escalation details listed in `submission/EXTERNAL_GATES.md`.
150
-
151
- ## Useful Commands
152
-
153
- ```bash
154
- npm run type-check
155
- npm test -- --runInBand
156
- npm run build
157
- npm run manifest
158
- npm run verify:harness
159
- npm run verify:release
160
- npm run verify:metadata
161
- npm run verify:release-manifest
162
- npm run verify:submission-ready
163
- npm run audit:prod
164
- npm run pack:dry-run
165
- ```
78
+ See [LICENSE](LICENSE).