MetaMask Snap for Swarm postage: buy stamps and upload to a Bee node from inside the wallet, plus a minimal Next.js page that only installs the Snap.
The interactive UI lives in snap/ (Snap custom UI / JSX). The previous full web dApp was removed; the install site under src/app/ is intentionally tiny.
| Path | Role |
|---|---|
snap/ |
Snap bundle: onInstall, home page, buy flow, stamps, upload, settings |
src/app/ |
Install page: wallet_requestSnaps only |
backend/ |
Bee proxy + signature checks (unchanged contract with Snap) |
contracts/, deploy/, scripts/ |
Gnosis contracts and Hardhat tooling |
misc/ |
Optional maintenance scripts (registry export, etc.) |
docs/ |
Legacy guides for the old pre-Snap UI — kept as reference only |
- Node 20+
- MetaMask with Snaps (stable channel supports published Snaps; Flask for local dev)
# Root + Snap dependencies
npm install
npm run snap:install
# Terminal 1 — Snap: dev server for the bundle on 8080 + rebuilds on change
# (`snap:dev` and `snap:watch` are the same; `cd snap` also has `dev` and `watch`)
npm run snap:dev
# Terminal 2 — website that calls wallet_requestSnaps (Next.js, not the Snap file host)
npm run dev- 8080 — Snap only:
snap:devalready starts the server MetaMask needs. You do not runservein addition, unless you switch workflow to “serve the lastdist/” vianpm run snap:buildthennpm run snap:serve(same port — pick one process). - 3000 — install page only: root
npm run devis the Next.js site at http://localhost:3000 with the Install button. It does not host the Snap; MetaMask still loads the bundle from 8080. - Local id:
local:http://localhost:8080(seesrc/app/page.tsxandsnap/snap.config.ts). - Optional —
npm run backend:dev(seebackend/README.md).
- Snap server must be running — the install page does not host the bundle. Keep
npm run snap:dev(or, after a build,npm run snap:serve) in another terminal. Openhttp://localhost:8080in a browser to confirm the server responds. If you seeEADDRINUSEon 8080, stop the other process using that port or changeserver.portinsnap/snap.config.tsand set the same value inNEXT_PUBLIC_SNAP_IDfor the Next app. - Many different Snaps fail in MetaMask: usually a MetaMask or browser issue, not this repo. Try: restart the browser, update the extension, or a clean profile.
- Production — set
NEXT_PUBLIC_SNAP_ID=npm:@beesnap/snapandNEXT_PUBLIC_SNAP_VERSIONto the published Snap version (see Publishing new versions below).
Two things ship separately: the Snap (npm; MetaMask downloads it by id + version) and the install page (static files under out/ after a production build, then zip or rsync to your host).
Before a directory / allowlist submission, MetaMask expects a clean bundle: no console.* in shipped code, no unused manifest permissions, and a run of Snapper (npx @sayfer_io/snapper --path ./snap from the repo root). Many Snapper findings are low-severity style; triage high-severity items. Obvious false positives (e.g. Content-Type: application/json flagged as a “secret”) can be explained in your submission.
- Bump the version — Use the same semver in
snap/package.jsonand insnap/snap.manifest.json(version). Optionally runnpm installinsidesnap/sopackage-lock.jsonstays in sync. - Build — From the repo root:
npm run snap:build(orcd snap && npm run build). This compilessnap/dist/bundle.jsand fixessnap.manifest.jsonif the bundleshasumis out of date. - Commit — Commit the version bumps, manifest, and any lockfile changes so the tree matches what you publish.
- Publish —
cd snap && npm publish --access public. Scoped packages need--access public. If npm enforces 2FA, pass a one-time password:npm publish --access public --otp=<code>. - Check — Confirm the new version appears on npmjs.com/package/@beesnap/snap.
The install UI lives in src/app/. For production, next.config.mjs enables output: 'export', so next build writes a static site into out/ (that directory is gitignored).
-
Point the build at the Snap you want users to install —
wallet_requestSnapsuses the id and version baked in at build time (src/app/page.tsx). Set:NEXT_PUBLIC_SNAP_ID=npm:@beesnap/snapNEXT_PUBLIC_SNAP_VERSION=<same semver as on npm>(must match the version you published, or MetaMask may refuse / install the wrong build).
Put these in
.env.production.localat the repo root (Next loads it for production builds), or export them for a one-off build, e.g.
NEXT_PUBLIC_SNAP_ID=npm:@beesnap/snap NEXT_PUBLIC_SNAP_VERSION=0.1.6 npm run build. -
Build — From the repo root:
npm run build. Verifyout/index.htmland the_nextassets exist. -
Package for upload — Example:
cd out && zip -r ../beesnap-install-site.zip .(the zip name is gitignored at the repo root) then upload the zip to your server and unpack into the web root, or syncout/directly (rsync, CI artifact, etc.) wherever you serve the install link (often alongside nginx / beeport; seebackend/README.md).
Whenever you release a new Snap version on npm, repeat this install-site flow with the updated NEXT_PUBLIC_SNAP_VERSION so the published page requests the new build.
- Derives a dedicated account from the user’s recovery phrase via
snap_getEntropy(seesnap/src/lib/wallet.tsfor the fixed salt). - Buy storage with Relay: pay from several EVM chains, settle on Gnosis; Gnosis (xDAI) is the chain where the stamp and registry live.
- Home shows native balances on the same “pay from” networks as the buy dropdown.
- View storage, upload with Swarm/ Bee APIs, and view upload history (Snap state).
Limits (real platform constraints) are still true: e.g. no fine-grained upload progress in Snap fetch, and very large files are impractical.
See snap/snap.manifest.json initialPermissions. The Snap does not use endowment:ethereum-provider for the user’s main MetaMask account — it signs and sends from the Snap-derived key over allowed RPC URLs.
The Bee proxy, registry, and Sushi/Relay paths the Snap uses are the same family as the original app. Details: backend/README.md, contracts/README.md.
Project metadata is in the root package.json. For issues, use the linked GitHub tracker.