# Sphere SDK: a TypeScript wallet SDK for Unicity agents, with server-side custody

> Sphere SDK gives a TypeScript application BIP39 keys, a wallet-api payment rail and Nostr messaging in one package. The design puts token inventory on a backend, which is the trade-off worth understanding before you install it.

**unicity-sphere/sphere-sdk** — The SDK for autonomous economic agents. Give an agent an identity, a wallet, and the ability to find, negotiate with, and settle with other agents - peer-to-peer, with perfect privacy and ultra-fast finality

- Repository: https://github.com/unicity-sphere/sphere-sdk
- Website: https://unicity.ai
- Stars: 5,391 · Forks: 107
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/unicity-sphere-sphere-sdk

## What Sphere SDK is for, and who it is not for

Sphere SDK is a modular TypeScript library for Unicity wallet operations. The README describes it as an SDK for Unicity state transition network wallet operations, and the repository topics list ai-agents, blockchain and commerce. In practice it bundles four things an autonomous agent or a wallet client needs: key derivation, a payment rail, a messaging layer, and a way for a dApp to talk to a wallet.

The feature list is broader than the name suggests. Wallet management covers BIP39 and BIP32 derivation with optional PBKDF2 password encryption. Payments run over what the README calls the wallet-api vertical, with durable server-side intents and mailbox delivery. Payment requests, a signed intent bulletin board with semantic search, NIP-29 group chat, NIP-17 direct messages, HD multi-address derivation and a dApp Connect protocol are all in the same package.

The audience is narrow in one specific way. The README states plainly that custody is server-side: the wallet-api backend holds your token inventory, and your keys stay local. If your requirement is that the private keys and the tokens live in the same process, this SDK is not that. The README also notes that own-storage custody was rescinded and there is no local token store. That is a design decision, not a missing feature, and it shapes everything else in the library.

A second constraint is the recipient model. The send example requires the recipient to have a published identity, described as a chain pubkey, for example a registered Unicity ID. Without one, the call fails with INVALID_RECIPIENT. You cannot send to an arbitrary address you just generated.

## The two-layer provider model that trips up first-time setup

The most important thing to understand before writing code is that setup is two provider layers, not one. The README says this directly: createBrowserProviders and createNodeProviders build only the base, which supplies storage, transport and oracle. You must then attach the wallet-api transport config with createWalletApiProviders. Money moves only through the wallet-api vertical.

Skipping the second layer does not fail quietly. Sphere.init throws INVALID_CONFIG. That is a reasonable failure mode for a misconfiguration, and better than a wallet that initializes and then cannot send.

Nostr is the part people misread. The transport built by the base providers carries messaging and nametags only. The README is explicit that it does not move payments. If you have used Nostr-based wallet projects before, the mental model transfers only halfway here.

The README also documents a seam for testing. StoragePort and DeliveryPort in modules/payments-v2/ports.ts have wallet-api implementations, and the paymentsV2Transport key in the walletApi config lets a test or a custom host inject a whole replacement bundle. That is the extension point to look at if you want to run the SDK against a fake backend rather than the real one.

Network placement is a recurring source of INVALID_CONFIG. The network value is required on createBrowserProviders, in the walletApi config, and on Sphere.init, and all three must agree. Sphere.init resolves the payments composition and the token registry from its own network value, so a mismatch throws before any storage write happens.

## Installing Sphere SDK and sending a first certified transfer

The package is published on npm as @unicitylabs/sphere-sdk. The README gives a single install command with no peer dependency note for the base package, though the platform table marks ws as required for Node.js and IndexedDB storage as optional for the browser.

```bash
npm install @unicitylabs/sphere-sdk
```

The README's quick start is a four-step sequence. The first block builds the base providers. Note that network is required here and has no default, and that the testnet2 gateway key is described as public, not a secret.

```typescript
import { Sphere } from '@unicitylabs/sphere-sdk';
import { createBrowserProviders } from '@unicitylabs/sphere-sdk/impl/browser';
import { createWalletApiProviders } from '@unicitylabs/sphere-sdk/impl/shared/wallet-api';

const base = createBrowserProviders({
  network: 'testnet',
  oracle: { apiKey: 'sk_ddc3cfcc001e4a28ac3fad7407f99590' },
});
```

The second block attaches the wallet-api transport config. The README recommends persisting deviceId so the wallet does not re-authenticate on every launch.

```typescript
const providers = createWalletApiProviders(base, {
  baseUrl: 'https://wallet-api.unicity.network',
  network: 'testnet2',
  deviceId: 'my-stable-device-id',
});
```

Initialization auto-creates a wallet when none exists. If created is true, the README's example prints the generated mnemonic with the label SAVE THIS RECOVERY PHRASE. That output is the only copy the user gets from this call path.

```typescript
const { sphere, created, generatedMnemonic } = await Sphere.init({
  ...providers,
  autoGenerate: true,
});
if (created && generatedMnemonic) {
  console.log('SAVE THIS RECOVERY PHRASE:', generatedMnemonic);
}
```

The send call takes a decimal string amount, never a JavaScript number, and coinId accepts a symbol such as UCT that auto-resolves to its hex id. The status field is completed on success. A deliveryPending value of true is described in the README as normal rather than a failure: the spend is certified on chain but the recipient's mailbox delivery was deferred and lands on retry.

```typescript
const result = await sphere.payments.send({
  recipient: '@alice',
  amount: '1000000',
  coinId: 'UCT',
  memo: 'hello',
});
console.log(result.status);
```

Incoming transfers arrive while the wallet runs, through a mailbox drain and a wake socket. A batch or CLI application that does not stay resident can call receive() explicitly, and a transfer:incoming event fires with the sender's nametag. To check balances, sphere.payments.assets() returns the current set.

## Where Sphere SDK breaks: delivery, recipients and custody

The deliveryPending field is the failure mode most likely to be misread in production. A transfer can be certified on chain and still not be in the recipient's hands, because the mailbox delivery was deferred. The README attributes this to a full inbox or a transition, and says it will land on retry. If your application treats a non-failed status as final settlement, you will report money as received when the recipient cannot yet see it. The event and receive() paths are how you observe the actual arrival.

The recipient requirement is the second hard edge. Sending to a nametag that has no published chain pubkey fails with INVALID_RECIPIENT. An agent that wants to pay a freshly generated counterparty cannot do so until that counterparty registers an identity somewhere the chain can see. This is a design consequence of certified on-chain settlement, not a bug, but it rules out the pay-anyone flow that plain address-based chains allow.

Custody is the third. The README states the backend holds inventory and there is no local token store. That means the wallet-api deployment is in the trust path for availability and for the inventory record. Keys staying local protects signing, not the tokens. If your threat model requires self-custody of the asset itself, this SDK is the wrong tool and no configuration flag changes that.

Finally, the API surface is young. The package.json in the repository declares version 0.17.1, the releases list shows v0.8.0 in May 2026 and v0.2.4 in February 2026, and the README documents that own-storage custody was rescinded. A rescinded custody model is a breaking change to how anyone who adopted an earlier version would have to build. Expect that kind of movement before 1.0.

## Sphere SDK against a plain Nostr client or a direct chain integration

The closest comparison in this repository is the SDK against its own Nostr transport. A plain Nostr client gives you NIP-17 direct messages and NIP-29 groups, and Sphere SDK includes both. The difference is everything around them: key derivation, the oracle and trust base, the wallet-api rail, and the certified transfer flow. If messaging is all you need, a Nostr library is smaller and has no wallet-api dependency. If you need an agent to hold and move value, the messaging library gives you nothing for that.

The other comparison is a direct integration with the Unicity token engine and gateway. The repository layout includes a token-engine directory and a separate exports entry for ./token-engine, and .env.example points at the testnet2 gateway and a trust base JSON that declares the network id. Going direct means you own the state transition submission, the trust base handling and the mailbox protocol yourself. Sphere SDK wraps that into Sphere.init plus a payments object, at the cost of the provider model described above and the version churn that comes with a 0.x package.

There is no equivalent comparison to draw against a mainstream wallet SDK, because the wallet-api rail and the Unicity trust base are specific to this network. A reader looking for a general-purpose multi-chain SDK will not find that here.

## Licence, maintenance and the cost of a 0.x upgrade

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. Nothing in the repository suggests additional terms, but the licence file itself is the authority, not this description. This is not legal advice.

The repository is not archived, and the last push was on 2026-09-10, which is recent. The release history is less uniform: v0.8.0 is dated 2026-05-29 and v0.2.4 is dated 2026-02-11, while package.json declares 0.17.1. The version numbers in package.json and in the releases list do not line up in an obvious sequence, so treat the releases list as a summary rather than a complete changelog and read CHANGELOG.md in the repository for the real history.

The upgrade cost is concentrated in the provider wiring. Because network must agree across three call sites, and because the walletApi config carries baseUrl and deviceId, a version bump that changes the provider composition is a change to your initialization code, not just a dependency line. The INVALID_CONFIG throw is the safety net. Keep the initialization in one module so a breaking change is a single edit, and pin the version rather than tracking latest if you ship to users.

## Conclusion

Adopt Sphere SDK if you are building a TypeScript client that needs an identity, a wallet and a payment rail against a Unicity wallet-api deployment you control or trust, and you accept that token inventory lives on that backend. Do not adopt it if you need self-custody of tokens, a stable API surface, or a payment rail that works without a wallet-api server. Before writing code, verify three things: that your target network id matches across createBrowserProviders, createWalletApiProviders and Sphere.init, that your recipients have published identities on chain, and that your storage adapter survives a process restart, because deviceId and recovery phrase are what you will need after a crash.

## FAQ

### What is the purpose of the Sphere SDK?

It is a modular TypeScript SDK for Unicity wallet operations, covering BIP39 and BIP32 key derivation, wallet-api payments, payment requests, an intent bulletin board, Nostr messaging and a dApp Connect protocol.

### Does Sphere SDK move payments over Nostr?

No. The README states that Nostr carries messaging and nametags only and does not move payments; transfers are certified on chain by the token engine and deposited into the recipient's wallet-api mailbox.

### Why does Sphere.init throw INVALID_CONFIG?

The network value is required on the base provider builder, in the walletApi config, and on Sphere.init, and the three must agree. A missing or disagreeing network throws before any storage write.

### Does Sphere SDK hold tokens locally?

No. The README says custody is server-side, the wallet-api backend holds the token inventory, keys stay local, and own-storage custody was rescinded so there is no local token store.

## Sources

- [License: MIT](https://github.com/unicity-sphere/sphere-sdk/blob/main/LICENSE)
- [Project website](https://unicity.ai)
- [README](https://github.com/unicity-sphere/sphere-sdk/blob/main/README.md)
- [Releases](https://github.com/unicity-sphere/sphere-sdk/releases)
- [unicity-sphere/sphere-sdk on GitHub](https://github.com/unicity-sphere/sphere-sdk)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/unicity-sphere-sphere-sdk
