pocket
Build and contribute

Configuration and environment

What is configured at build time, what lives in the network table, and why contract addresses are configuration rather than constants.

Build-time variables

Three values are supplied at build time and never committed. Each one, when absent, makes the wallet report the feature as unconfigured rather than failing at a fetch.

# extension/.env
VITE_ARCHIVE_URL=http://127.0.0.1:8787
VITE_DEFINDEX_API_KEY=
VITE_DEFINDEX_VAULT=CCLV4H7WTLJQ7ATLHBBQV2WW3OINF3FOY5XZ7VPHZO7NH3D2ZS4GFSF6

Absent, the archive variable hides the private-history and rebuild controls, and either DeFindex variable makes yield report itself unconfigured. What each one holds.

.env is loaded by every build, development and production alike, so what you load always has these values. .env.production is loaded afterwards for a production build and overrides only what it sets.

The intended split: .env points at local services, and a release sets the deployed archive URL in .env.production.

A loopback address cannot ship

Release gate 6 fails a package containing a loopback address.

A loopback baked into a shipped extension points every user at their own machine, where nothing is listening. The failure would be silent and would look like the archive being down.

Aquarius, CCTP and the StellarExpert directory need no configuration. All three are keyless.

The network table

extension/src/core/config.ts holds one entry per network, and every endpoint in it was checked against the live network rather than recalled. Every field.

The mainnet entry exists and is complete except for confidential, which is empty until a mainnet deployment exists. Every consumer guards on that being empty and reports the private pocket unavailable rather than reading past the end, so enabling mainnet cannot silently point the private pocket at a testnet contract.

friendbotUrl is absent on mainnet by design, so the absence is a type-level fact rather than a URL that would fail at runtime.

Contract addresses are configuration, never constants

Testnet is wiped on resets, and confidential identities are per deployment, so a redeployment means every user re-registers. Hardcoding an address anywhere else would mean a second place to update and a silent failure when it was missed.

Each confidential entry carries four fields:

{
  token:      "CDMXZEFO…",  // the wrapper. Its address is baked into every key derived for it
  verifier:   "CBERRYPR…",  // shared across wrappers
  auditor:    "CDE5JETG…",  // shared across wrappers
  underlying: "CDLZFC3S…",  // the SEP-41 asset it holds
  symbol:     "XLM",
}

A wrapper binds exactly one underlying asset at construction, so private XLM and private USDC are two deployments, each with its own confidential identity.

Why prices come from a different network

Asset prices are always read from mainnet Horizon, whatever network the wallet is on, because testnet has no real market and a testnet price would be noise from a handful of test trades.

So the price module deliberately does not take the active network's Horizon URL: the two are different hosts with different jobs, and collapsing them would price a testnet balance off testnet's empty order book.

That is also why the manifest declares two Horizon hosts, and why the mainnet one is path-scoped to /trade_aggregations: it is the only endpoint the chart needs, it cannot submit anything, and nothing else on that host is reachable.

The mainnet refusal

Switching to mainnet is refused in three independent places:

  1. setNetwork throws with the reason
  2. the manifest declares no mainnet RPC host, so Chrome would refuse the traffic anyway
  3. the mainnet confidential list is empty, and every consumer guards on it

The setNetwork refusal is also checked twice, at the router and in the controller, because the value is assigned and then persisted: an unknown one would leave every later network lookup undefined and survive a restart, with no screen able to set it back.

The other two environments

The archive and the deployment scripts take their own variables. Both tables, and running an archive.

On this page