Okay, look. Every other "MetaMask Snaps" guide jumps straight into "install this, code that" without telling you Snaps aren't for regular users yet. You can't just grab the normal MetaMask and expect magic. Snaps are in beta ish mode, and honestly, most folks waste hours because they skip Flask. That's the developer version. Without it? You're toast. I usually tell friends: get Flask first, or don't bother.
Why does this matter? Regular MetaMask blocks snaps unless you're on the directory page, and even then, it's limited. Flask lets you play wild. Sound familiar? You've probably tried something, got stuck, rage quit. Not today.
Download it from the official site - search "MetaMask Flask" and hit the Chrome extension link. Install like any extension. Pin it. Unlock with a new wallet or import one. Don't use your main funds here. Testnet ETH only, like Sepolia.
Now, check if it's Flask. Open console in a blank tab: await ethereum.request({method: 'web3_clientVersion'}). See "flask" in there? Good. No? Wrong version. Update.
In my experience, this trips up 80% of newbies. Gas fees? Minimal, like 0.00001 ETH for snap installs. But you're not paying much yet.
Done. Five seconds. What's next?
Don't code yet. Try existing ones. Head to snaps.metamask.io. Directory's got 30+ snaps. Pick Wallet Guard - blocks shady txs.
ShapeShift? Same deal. Adds multichain. I use it for quick Solana peeks without swapping wallets. Fees? Network gas only, ~0.0005 ETH.
Potential issue: "Snap not found". Refresh Flask. Or toggle Developer Mode off/on. Fixes 90%.
Time to make one. Prerequisites: Node 20.11+, Yarn. VS Code. That's it.
Terminal. Run: npx @metamask/create snap my first snap. Name it whatever. Waits ~10-20 secs, installs deps. Might whine about scripts - yarn run allow scripts auto. Then yarn start.
Boom. Serves at localhost:8080 (snap) and :8000 (demo dapp). Open :8000 in Flask.
snap/src/index.ts: change "Hello" to "Yo, custom snap!".Super short first win. Feels good, right?
Thing is, snaps extend MetaMask. JSON RPC calls. Like wallet_invokeSnap to ping yours. Permissions in snap.manifest.json: tweak initialPermissions. Need homepage? Add "endowment:homepage". Restart yarn start.
| Permission | What It Does | When to Use |
|---|---|---|
| endowment:longRunning | Runs background tasks | Notifications, simulations |
| endowment:transaction insights | Analyzes txs | Wallet Guard style |
| snap_getBip44Entropy | Derives keys | Custom wallets (careful!) |
| endowment:display | Custom UI screens | Forms, dialogs |
Start minimal. I usually just grab "homepage" and "display". More later. Mismatch? Install fails. Check console: errors scream why.
Watched a dev stream this. Built a snap that fancy fies text - bold serif, strikethrough, medieval vibes. Inside MetaMask. No external sites. Here's how, step for step. Copied the vibe.
First, edit snap.manifest.json:
["endowment:homepage", "endowment:display"]Now snap/src/index.ts. Ditch default. Add JSX support - latest V12 stuff.
import type { OnRpcRequestHandler } from '@metamask/snaps types';
import { panel, text, heading } from "@metamask/snaps ui/jsx";
import { updateSnapUI } from "@metamask/snaps jsx"; // Maps for transforms
const boldSerifMap = {'a':'𝐀','b':'𝐁' / etc - fill from Unicode /};
const doubleStruckMap = {'a':'𝕒' / you get it /}; function transformText(input: string, map: Record<string,string>): string { return input.split('').map(char => map[char] || char).join('');
} export const onRpcRequest: OnRpcRequestHandler = async ({ origin, request }) => { switch (request.method) { case 'hello': return snap.request({ method: 'snap_dialog', params: { type: 'Alert', content: panel([ heading('Text Transformer'), text('Paste text below') ]) } }); case 'transform': const { text: inputText, style } = request.params; let map = boldSerifMap; // switch on style const result = transformText(inputText, map); // Update UI await updateSnapUI(snap.updateBlock('result', text(result))); return result; default: throw new Error('Method not found'); }
};
Demo dapp: add form. wallet_invokeSnap({ snapId: 'local:http://localhost:8080', request: { method: 'transform', params: {text: 'hello', style: 'bold'} } }).
Test: yarn start → demo → input "test" → transform. Medieval text pops in MetaMask UI. Copy paste to Twitter. Took 30 mins total.
Issue? "UI not updating". Check JSX imports. V12 needs @metamask/snaps jsx. yarn add it.
Console in background.html. Logs everything. Errors like "Permission denied"? Manifest mismatch. "Snap not installed"? Reconnect.
Hot reload fails sometimes. Kill yarn start, yarn start again. Gas for local? Zero - localhost.
In my experience, Chrome extensions page: reload Flask unpacked if packed. But don't pack yet.
Hook snaps into your site. Like Hedera snap tutorial.
ethereum.request({method: 'eth_requestAccounts'})await ethereum.request({ method: 'wallet_enable', params: { snaps: { [snapId]: {} } } })await ethereum.request({ method: 'wallet_invokeSnap', params: { snapId, request: { method: 'getEvmAddress' } } })Balances? Call getBalance. Fees ~0.000005 HBAR equiv. Create account by sending to EVM addr first.
Why bother? Users stay in MetaMask. No exports. Secure.
Local's fine for dev. For real: build site with install button. <a href="https://your site.com/snaps/your snap.zip">Install</a>. Host on IPFS or GitHub Pages.
Directory? Submit to snaps.metamask.io. Review process. Not instant.
Pro tip: shasum in manifest. Verify integrity. Users trust more.
No lists here. Just venting. Yarn versions mismatch - stick to LTS Node. Flask crashes on tab close? Restart browser. Permissions creep: audit json weekly. UI JSX breaks on old Flask - update to latest.
Multichain snaps? Add chainId perms. Gas sims eat ~0.001 ETH/testnet. Budget it.
Honestly, once you're in, it's addictive. Built a tx insights snap once - flags high fees pre sign. Saved me 50 bucks.
Want interactive forms? Export SnapComponent. Like:
export const InteractiveForm = () => ( <form id="transformer"> <input name="text" /> <button action="submit">Transform</button> </form>
);
Handle in onInput: if (event.type === 'form:submit') { / transform / }. Reinstall to see.
| Snaps | Extensions |
|---|---|
| Inside MetaMask sandbox | Separate popup |
| RPC extend | Full browser access |
| Permissions granular | All or nothing |
| Hot reload dev | Reload unpacked |
Snaps win for wallet stuff. Extensions for broad tools.
(