A MetaMask Snap that turns your MetaMask into a full wallet for the dungeon-1 Cosmos chain. Derive a dungeon1... address from your existing MetaMask seed, view your $DGN balance, sign messages, and send DGN — all without leaving MetaMask.
Built for the Dungeon platform — DEX, NFT Marketplace, Kosmic Quest, and Cosmos validator services.
Slice-by-slice build status. Each slice shipped with green tests.
| RPC method | Status | Description |
|---|---|---|
dungeon_getAccount |
shipped | Returns { address, pubkey } derived via SLIP-44 coin type 118. |
dungeon_getBalance |
shipped | Queries live DGN balance from api.dungeongames.io. |
dungeon_showAccount |
shipped | Displays an info dialog with address + balance. |
dungeon_signArbitrary |
shipped | Raw SHA256 message signing. Returns 64-byte compact secp256k1 signature. |
dungeon_signADR036 |
shipped | Keplr-compatible ADR-036 message signing. Same shape, signs over the canonical sign doc. |
dungeon_buildSendTx |
shipped | Builds + signs a MsgSend tx without broadcasting. Returns { txBytes, accountNumber, sequence, signature }. |
dungeon_sendTokens |
shipped | Signs and broadcasts a MsgSend tx via the LCD. Returns { txhash, code, rawLog }. |
dungeon_swapAndBridgeToCard |
not implemented | Skip Router cross-chain "Spend my DGN" flow. Blocked on Skip chain-registry PR. |
# install deps + initial build
yarn install
yarn workspace dungeon-snap build
# run the test suite (rebuilds bundle then runs jest)
yarn workspace dungeon-snap test
# start local Snap server on http://localhost:8080
yarn workspace dungeon-snap serve
# in another shell, run the companion site
yarn workspace site startOpen MetaMask Flask, point your browser at http://localhost:8000, and click Connect to install the local Snap.
// Install the snap (user prompts once)
await window.ethereum.request({
method: 'wallet_requestSnaps',
params: { 'npm:dungeon-snap': {} },
});
// Get the user's dungeon-1 address
const { address, pubkey } = await window.ethereum.request({
method: 'wallet_invokeSnap',
params: {
snapId: 'npm:dungeon-snap',
request: { method: 'dungeon_getAccount' },
},
});
// Send 1 DGN
const { txhash } = await window.ethereum.request({
method: 'wallet_invokeSnap',
params: {
snapId: 'npm:dungeon-snap',
request: {
method: 'dungeon_sendTokens',
params: { recipient: 'dungeon1...', amount: '1000000', memo: 'hi' },
},
},
});packages/snap— the Snap itself. Bundles todist/bundle.js(~290KB).packages/site— companion Gatsby site for manual smoke-testing.- Key derivation:
@metamask/key-treeoversnap_getBip32Entropy(pathm/44'/118'/0'/0/0). - Crypto:
@noble/hashes(SHA256, RIPEMD160) +@noble/secp256k1(ECDSA sign). - Bech32:
@cosmjs/encodingfordungeonprefix encoding. - Protobuf:
cosmjs-typesforMsgSend,TxBody,AuthInfo,SignDoc,TxRaw. - Why NOT
@cosmjs/crypto: its transitive dep@noble/curvesships a method named.eval, which MetaMask's SES sandbox rejects via regex. Use@metamask/key-tree+@noble/hashes+@noble/secp256k1instead.
The flagship "Spend my DGN" flow swaps DGN → USDC on the Dungeon DEX, bridges to Linea via Axelar GMP, and leaves the funds spendable with MetaMask Card. This requires Skip Router to support dungeon-1.
Unblock path:
- Submit a chain-registry PR to skip-mev/networks for dungeon-1 with its IBC channels to Axelar.
- Wait for Skip to deploy support for dungeon-1.
- Wire up
@skip-go/clientin this Snap. Thedungeon_swapAndBridgeToCardmethod already exists with a clear error pointing here.
- Chain ID:
dungeon-1 - SLIP-44 coin type:
118(standard Cosmos) - Bech32 prefix:
dungeon - Native denom:
udgn(1 DGN = 1,000,000 udgn) - LCD endpoint:
https://api.dungeongames.io - Min gas price: 0.05 udgn/gas
- Snap defaults: gas 200,000 + fee 14,000 udgn (0.014 DGN) per send
13 tests, all green via yarn workspace dungeon-snap test:
- Derives a valid
dungeon1bech32 address - Derivation is deterministic
- Balance fetches from live LCD
- ADR-036 + raw-sha256 signing produce 64-byte low-S signatures
- Signing is deterministic (RFC6979)
- User-reject paths throw clean errors
- Send rejects invalid bech32, zero amounts, and user-cancels
- Send surfaces "account does not exist" cleanly for unfunded test wallets
tools/play-snap-agent.cjs is an automated smoke runner. It launches Chrome with MetaMask Flask loaded, drives the companion site through every smoke action, auto-clicks Flask approval popups, screenshots each step, and (with --review) sends the screenshot reel to Claude Sonnet for visual bug-flagging.
- Download MetaMask Flask Chrome zip from the GitHub releases — look for
metamask-flask-chrome-<version>-flask.0.zip. - Extract to
.flask-extension/at the repo root (somanifest.jsonis at.flask-extension/manifest.json). - Start the snap server in one terminal:
yarn workspace dungeon-snap serve. - Start the companion site in another:
yarn workspace site start. - Run the agent:
node tools/play-snap-agent.cjs. - On the first run, you'll need to onboard Flask (set password, import/create a test seed). The profile is saved to
~/.dungeon-snap-flask-profile/and reused on subsequent runs.
node tools/play-snap-agent.cjs # headed, no AI review
node tools/play-snap-agent.cjs --review # adds Claude Sonnet vision pass
node tools/play-snap-agent.cjs --headless # CI mode
Outputs land in ai-reports/play-session/<timestamp>/: screenshots + session.log + vision-review.md (if --review).
MIT — see LICENSE.