The swap card in the toolbar. Same public API as the web app, no keys, no backend of its own.
- Swap — live quote (refreshed every 30 s while open), DarkRoute fee and tier, all-in cost vs mid, address book chips, then "Get deposit address" → the one-time deposit address with QR, memo and the deposit-window countdown. On EVM chains, "Send with wallet" opens the app's pay page so a browser wallet sends the exact amount.
- Orders — every order created here or opened on app.darkroute.exchange is tracked in this browser. The badge counts orders still moving (red when one needs you: short deposit, or a window in its last hour). One notification per state change; click it to open the order page. The site's own address book and recent orders are picked up when you visit it.
- Send here with DarkRoute — select any wallet address on any page, right-click. The popup opens with the recipient filled and the receive token picked for that chain.
- Address bar —
dark 0.1 eth usdc(chain hints:usdc@base,eth:arbitrum). - Keyboard —
Alt+Shift+Dopens the card. - Tier — sign in on the app once (Sign in ↗ in the header); the session cookie rides along with host permission, so the $DARK tier applies in the popup too.
Plain JavaScript, ES modules, Manifest V3. No build step.
chrome://extensions→ enable Developer mode → Load unpacked → pick thisextension/folder.- Pin it. Quotes come from
https://app.darkroute.exchange.
| permission | used for |
|---|---|
storage |
tracked orders, address book, last pair — local to this browser, never sent anywhere |
alarms |
the 30 s status poll behind the badge |
contextMenus |
"Send here with DarkRoute" on selected text |
notifications |
one notice when an order settles, refunds, fails or is short |
host app.darkroute.exchange |
the API, and the content script that picks up orders and the address book from the site |
omnibox and commands are manifest keys, not permissions. No <all_urls>, no analytics, no
remote config. Privacy policy: https://darkroute.exchange/extension/privacy
node extension/test/run.mjs # rules parity with app/lib/fee.ts, address detection, omnibox parser, badge, manifest, hygiene
node extension/test/e2e.mjs # headless Chromium with the extension loaded: live quote, picker, tracker, QR, badge, prefill
node extension/test/shots.mjs # 2× popup renders for the /extension page + 1280×800 store frames
node extension/pack.mjs # web/public/darkroute-extension.zip + web/content/extension.json (version, size, sha256)Extension e2e must run in Playwright's own Chromium: branded Google Chrome ≥137 ignores --load-extension.
vendor/qrcode.min.js is the qrcode npm package (MIT, vendor/qrcode.LICENSE.txt) bundled once:
node_modules/.bin/esbuild app/node_modules/qrcode/lib/browser.js --bundle --format=iife --global-name=QRCode --minify --target=chrome120 --outfile=extension/vendor/qrcode.min.jslib/rules.js carries ADDRESS_RULES copied from app/lib/fee.ts; test/run.mjs fails if they drift.
node extension/pack.mjs writes the zip the landing page serves. Web Store listing copy and the
dashboard answers are in store/listing.md. Not submitted yet — beta = the zip, loaded unpacked.