Unicity AgentSphere: a wallet UI pinned to one SDK build
A Web3 wallet and agent platform for the Unicity network - crypto wallet, DMs, group chat, and marketplace.
At a glance
- What is it?
- Unicity AgentSphere is a private React 19 and Vite front end that puts Unicity wallet operations, Nostr DMs, NIP-29 group chat and iframe-loaded dApps into one tabbed UI. Every wallet call runs through a pinned @unicitylabs/sphere-sdk build, the Docker defaults aim at staging, and a link in a DM can open an arbitrary site inside the wallet surface.
- Who is it for?
- Use Sphere if you work inside Unicity Labs' own stack and can stand up a second backend at a wallet-api instance. Pass on it for a fork, an auditable build, or a subpath deployment: the package is private, version 0.0.0, has no releases, defaults to staging hosts, and accepts deep-linked iframes without a documented allowlist.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 16 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- unicity-sphere/sphere9,629 ★ · -92
| Repository | 2026-09-10 | 2026-11-13 |
|---|---|---|
| unicity-sphere/sphere | 9.7k | 9.6k |
-92 Stars in the last 64 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Every wallet call routes through the pinned @unicitylabs/sphere-sdk 0.18.0
All wallet work is delegated to @unicitylabs/sphere-sdk, which covers L3, Nostr and IPFS and is pinned to 0.19.2 in package.json with no caret in front of it. On top of it sits src/sdk/, a hand-written React adapter of 24 files. hooks/core holds useSphere, useWalletStatus, useIdentity, useNametag, useSphereEvents and useIpfsSync. hooks/payments holds useTokens, useBalance, useAssets, useTransfer and useTransactionHistory. hooks/comms holds useSendDM and usePaymentRequests, with a utils folder for format helpers. What that arrangement costs you is ownership. The bridge packages, @unicitylabs/bridge-core and @unicitylabs/bridge-plugin, are pinned as well, at 0.2.0. package.json carries `"private": true` and version 0.0.0, and the repository has no GitHub releases, so there is no upstream tag to diff against. A key rotation or a wallet defect inside the SDK cannot be patched here; you would change the pin and rebuild.
A fresh clone serves the UI but has no backend behind the ASSET path
Sphere asks for Node.js 20+, and the documented setup is three lines:
npm install
cp .env.example .env # Configure environment variables
npm run dev # Start dev server at http://localhost:5173The file that cp copies is not self-sufficient. VITE_SPHERE_API_URL points at http://localhost:3001 for the marketplace, installed apps and auth, and VITE_WALLET_API_URL is set to the relative value /wallet-api. The dev and preview proxy forwards relative values to WALLET_API_PROXY_TARGET, which defaults to http://127.0.0.1:3000, the port used by the wallet-api repository's own compose stack. So after npm run dev you have a running front end at http://localhost:5173 with no server-side inventory custody, no mailbox delivery and no payment requests, while DMs and nametags stay on Nostr. A script named run-sphere.sh sits at the repository root, but the quick start never says what it launches or whether it covers that second service.
Subscriptions and paid plans are wired but shipped switched off
Two features are present in code and disabled in the configuration that ships. docker-compose.yml sets `SUBSCRIPTION_ENABLED: "false"` and `PAID_PLANS_ENABLED: "false"`. The Dockerfile explains why they cannot follow the normal route: the image bakes `__RUNTIME_*__` placeholders that deploy/runtime-config.sh rewrites at container start, but the VITE_ subscription flags get no placeholder on purpose, because Rollup prunes every `if (FLAG)` against a baked literal at build time. They reach the browser through window.__SPHERE_RUNTIME_CONFIG__ instead, written into /runtime-config.js at start, and the gateway URL needs no configuration because it is derived from the SDK's per-network aggregator gateway in src/config/subscription.ts. Credential handling is the sharp edge: AGGREGATOR_API_KEY is required only while subscriptions are off, and with SUBSCRIPTION_ENABLED=false the container refuses to start without it, yet the compose file ships a value inline. Switch the flag to "true" and the per-wallet SGW key replaces AGGREGATOR_API_KEY, which is then ignored.
One docker command and every request lands on Unicity staging
The Docker path is a single command:
docker compose up # Runs on port 3010It builds an nginx image tagged sphere-frontend, publishes 3010 on port 80 and sets restart to unless-stopped. Its own comment says the defaults below point a local run at staging, and the values agree: SPHERE_API_URL is https://quest-api.staging.unicity.network, WALLET_API_URL is https://wallet-api.staging.unicity.network, DEV_PORTAL_URL is https://developers.staging.unicity.network/ and REQUIRE_WALLET_API is "true". Two consequences follow for anyone testing locally. Transfers and payments you exercise are recorded against staging services rather than the network you intend to ship, and state-transition traffic goes through the aggregator with a key that .env.example describes as the testnet2 value, not a secret, with mainnet required to use a real secret set only in the deploy env. Promoting that inline compose value as is ships a published testnet credential.
A unicity-connect link in a DM becomes an in-wallet iframe
A received message can offer to load a remote site inside the wallet. A dApp builds a URL, replaces `https://` with `unicity-connect://` and sends it as a DM. The markdown parser detects the scheme in plain text, in `[text](unicity-connect://...)` and in `<a href="unicity-connect://...">`, then renders a DeepLinkButton dropdown. Open in Sphere navigates to `/agents/custom?url=<httpsUrl>`, loading the target as an iframe agent, while Open in browser opens the resolved http(s) URL through window.open. Conversion happens in deepLinkToHttps inside src/utils/deepLinkHandler.ts, which also holds a global click handler registry, and useDeepLinkNavigation in DashboardLayout registers the Sphere-side handler. What is missing is any documented gate on that path: no allowlist, no origin check, and no approval step like the ConnectionApprovalModal that the Connect protocol uses for iframe and popup connections. Since the destination is the same iframe route external dApps use, a link from a DM counterparty, not only from a dApp you approved, can place an arbitrary page inside the wallet.
Three agent types, one hardcoded relay, no manifest for custom ones
Agents are tabs, and the list has three entries: Messages, private DM over Nostr; Group Chat, NIP-29 group messaging; and Sphere Agents, which load any external dApp by custom URL. The NIP-29 side covers public and private groups with invite codes, real-time delivery over WebSocket, group discovery, join and leave, unread tracking, and a dedicated Zooid relay at wss://sphere-relay.unicity.network. Two ceilings are worth naming. That relay is a single named address, so aiming group chat at a different relay or self-hosting it is not something this project documents, and a group that loses that host has no documented fallback. A custom-URL agent is loaded by URL, and the README documents no manifest or declared scopes for it, so it does not say what a loaded agent may reach. Adding a fourth type means editing src/config/activities.ts, which is source code, so the tab set cannot be reshaped by configuration.
Turning a wallet module off means deleting a folder and rebuilding
Optional wallet features are removed at the filesystem level. Modules live in `src/modules/<name>/`, are discovered by folder, and the stated procedure is to delete a folder to remove the feature. The bridge, which handles external assets coming in, is one of them, and docs/WALLET-MODULES.md is the reference for the rest. Runtime knobs are narrower: VITE_WELCOME_AGENT_NAMETAG=kbbot sets the welcome DM agent nametag, VITE_WELCOME_DELAY_MS=4000 delays that DM, and SSL_CERT_PATH, HMR_HOST and BASE_PATH cover dev server HTTPS, remote HMR and the deployment base path. The day-to-day commands are the standard six:
npm run dev # Development server
npm run build # TypeScript compile + Vite production build
npm run preview # Preview production build
npm run lint # ESLint
npm run test # Vitest watch mode
npm run test:run # Vitest single runBecause removal is a folder deletion, no environment can disable a feature at runtime, and Vite inlines VITE_* at build time, which is why the Dockerfile bakes __RUNTIME_*__ placeholders and rewrites them at container start. BASE_PATH is baked as / in the Dockerfile because Vite rewrites both asset URLs and the router basename from it, which means the same image cannot also be served from a subpath.
Editorial conclusion
Use Sphere if you work inside Unicity Labs' own stack and can stand up a second backend at a wallet-api instance. Pass on it for a fork, an auditable build, or a subpath deployment: the package is private, version 0.0.0, has no releases, defaults to staging hosts, and accepts deep-linked iframes without a documented allowlist.
Frequently asked questions
What does Unicity AgentSphere include out of the box?
A Unicity crypto wallet with token transfers, balance tracking, incoming payment notifications and @nametag names, plus three agent tabs: DMs over Nostr, NIP-29 group chat, and external dApps loaded by custom URL as iframes. QR codes, wallet switching, seed phrase management and real-time market data are also listed.
How do I start Unicity AgentSphere locally?
With Node.js 20+, run npm install, copy .env.example to .env, then npm run dev, which serves http://localhost:5173. The copied .env points the ASSET path at a relative /wallet-api that the dev proxy forwards to WALLET_API_PROXY_TARGET, defaulting to http://127.0.0.1:3000.
Why does the Unicity AgentSphere container refuse to start without an aggregator key?
The compose file sets SUBSCRIPTION_ENABLED to "false", and its comment states that with subscriptions off the container refuses to start unless AGGREGATOR_API_KEY is present. Turning subscriptions on replaces that key with a per-wallet SGW key, and the shipped value is then ignored.
Can Unicity AgentSphere serve the wallet from a subpath?
Not from the image it builds. The Dockerfile keeps BASE_PATH=/ baked in because Vite rewrites asset URLs and the router basename from it, so a subpath deployment needs a rebuild. Vite inlines VITE_ variables at build time, which is why the image bakes __RUNTIME_*__ placeholders that are rewritten at container start.
What happens when a unicity-connect link arrives in a Unicity AgentSphere DM?
The markdown parser renders it as a DeepLinkButton. Open in Sphere navigates to /agents/custom?url=<httpsUrl> and loads the target as an iframe agent, while Open in browser opens the resolved http(s) URL in a new tab. The docs list no allowlist or origin check on that path.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/unicity-sphere-sphere)Star history chart for your README
[](https://hysenlabs.com/projects/unicity-sphere-sphere)Was this useful?