pocket
Build and contribute

Build and run

Building the extension, the contracts and the archive, and what the vendoring step does before every build.

Four workspaces, each with its own dependencies. The extension is the one you need to run a wallet.

If you only want to use Pocket rather than work on it, take a prebuilt release instead: install it.

extension/    the wallet
contracts/    three Rust Soroban contracts
indexer/      the durable event archive
scripts/      release gates and the infrastructure check

The extension

cd extension
npm install
npm run build          # vendors, then builds into .output/chrome-mv3

Load extension/.output/chrome-mv3 through chrome://extensions with Developer mode on, using Load unpacked.

CommandDoes
npm run devvendors, then runs the WXT dev server
npm run buildvendors, then produces the unpacked package
npm run zippackages the build
npm run checkthe gate: types, lint, and both test tiers
npm run linteslint, prettier and types
npm run formatprettier, writing

The vendoring step

npm run vendor runs before every build and dev start, and copies three things into the package:

ScriptBrings in
vendor-bb.mjsthe bb.js prebuilt browser bundle
vendor-srs.mjsthe Aztec Ignition reference string, sha256-pinned
vendor-circuits.mjsthe six compiled circuits and their verification keys

Manifest V3 forbids remotely hosted code, so everything the extension executes has to be in the package. bb.js in particular must not go through the bundler: its browser build declares a top-level export that collides with a bundler runtime and spawns its worker from an ignored URL, so bundled it resolves the worker to a chunk that does not exist and proving hangs forever with no error.

Token logos are vendored separately and committed, by npm run vendor:icons. A logo is a trust signal and a swapped one is a phishing aid, so it is reviewed in a diff rather than re-fetched silently, and the ordinary build stays offline.

The circuits come from the upstream clone under resources/upstream/. Without it, vendor-circuits.mjs stops and says so.

The contracts

cd contracts
stellar contract build        # target: wasm32v1-none
cargo test
cargo fmt --check
node deploy.mjs               # writes resources/deployment-<network>.json

Deployment order matters: the verifier and the auditor registry must exist before the token wrapper, because the wrapper's constructor binds both permanently.

Adding a second asset reuses both and deploys only a new wrapper:

UNDERLYING=<SAC contract id> SYMBOL=USDC node add-asset.mjs

Both Rust dependencies are pinned to a git revision rather than a branch, so an upstream force-push cannot change what gets built. Bumping either revision is a protocol change and requires reproducing the verification keys.

The archive

cd indexer
npm install
npm test
npx tsc --noEmit

CONTRACT_ID=C… npm run backfill
DB_PATH=pocket-archive.db PORT=8787 npm start

Running an archive.

The pre-commit hook

.githooks/pre-commit runs across every workspace:

cd extension && npm run check
cd indexer   && npx tsc --noEmit && npx vitest run
cd contracts && cargo fmt --check

Enable it with:

git config core.hooksPath .githooks

Note what it does not cover: the browser tiers. npm run check is types, lint and the two vitest configs, and Playwright appears in neither. The browser suite runs at release gate 7 against the built package.

Toolchain pins

The proving toolchain is pinned to nargo 1.0.0-beta.11 and bb 0.87.0, and that is a protocol constraint rather than a preference: the Soroban verifier hardcodes bb 0.87's proof layout, and bb 5.x cannot read beta.11's compiled circuit format.

Upgrading is a protocol migration that requires replacing the on-chain verifier first, which means every user re-registers. What cannot be changed.

TypeScript is pinned to 6.0.3 because the eslint TypeScript plugin peers below 6.1.

Release gate 1 checks both proving pins, reading --version from the binaries rather than from a lockfile.

On this page