LaWalletdocs
SDK

SDK Overview

Build your own webapp on top of your LaWallet instance — typed client, React hooks, nostr-first auth.

One package, two entry points, so anyone running a LaWallet instance can offer its features from their own webapp (usually on their own domain or subdomain):

  • @lawallet/sdk — a typed, framework-free client for the REST API. Works in the browser and in Node. Its only runtime dependency is nostr-tools.
  • @lawallet/sdk/react — a React provider + hooks built on that client: instance branding, nostr login, lightning-address claiming (with payment), NWC wallet binding, and live updates over SSE.
npm install @lawallet/sdk

React is an optional peer dependency, so a Node backend that imports the core client never pulls React into its dependency graph. Both entry points share one implementation, so a LaWalletError thrown by the core is the same class the hooks re-throw.

Everything is nostr-first: there are no accounts, no passwords and no session tokens. The user's Nostr key is their identity — every authenticated API request is a NIP-98 event signed by that key. See Authentication.

Where the SDK lives

The SDK is developed and published from its own repository, lawalletio/sdk — that is where issues, the runnable example apps and the agent skills live. This section documents how to use it against a LaWallet instance; it requires an instance running v2.6.0 or newer, which is when cross-origin access, the NIP-98 SSE token and the operator provisioning endpoint landed.

Quickstart

import { LaWalletClient, nsecSigner } from '@lawallet/sdk'

const wallet = new LaWalletClient({
  endpoint: 'https://wallet.example.com', // your instance's PUBLIC origin
  signer: nsecSigner('nsec1...')
})

// Instance discovery — public, no signature involved
const settings = await wallet.settings.get()
console.log(settings.community_name, settings.domain)

// First authenticated call materialises the user for this npub
const me = await wallet.users.me()

// Claim a lightning address (throws a 402 LaWalletError in paid mode —
// or use wallet.registration.claimAddress() to handle payment for you)
await wallet.addresses.create({ username: 'satoshi' })

The same client works in Node — pass the instance URL and a signer, nothing browser-specific is required. For live events in runtimes without a global EventSource, inject one via the EventSourceImpl option.

What the SDK covers

NamespaceEndpoints
settingsPublic instance settings — branding, domain, feature flags
usersme() — fetches (and on first contact creates) the current user
addressesList / get / create / update / remove / set-primary, invoices, availability
registrationPaid registration: invoice mint, LUD-21 verify, preimage claim, orchestration
remoteWalletsNWC connections: CRUD, server-minted LNCurl wallets, connection string, balance
lud16Public payment endpoints: resolve, request invoice, LUD-21 verify
nip05/.well-known/nostr.json lookups
eventsSSE subscription — change notifications for live UIs

Reads, writes, creation, updates and subscriptions all go through the same per-request signing model; if the signer can sign, the client can act.

Errors

Every non-2xx response throws a LaWalletError carrying the HTTP status, the server's code and optional details — branch on those instead of parsing messages:

import { LaWalletError } from '@lawallet/sdk'

try {
  await wallet.addresses.create({ username: 'satoshi' })
} catch (error) {
  if (error instanceof LaWalletError && error.status === 402) {
    // Paid registration — see the registration flow guide
  }
}

Cross-origin access

LaWallet instances serve their API with open CORS for exactly this use case: your webapp on app.your-domain.com can call wallet.your-domain.com directly from the browser. Authentication travels in the Authorization header (or, for SSE, a signed query token) — no cookies are involved.

Where next

On this page