Instance-based Sanctum browser SDK (SanctumDK) designed for predictable lifecycle behavior and stronger developer ergonomics.
- No global mutable runtime state
- Explicit client lifecycle (
destroy) - Typed event subscriptions (no global callback overwrite)
- Single-flight token refresh with deterministic reauth handling
- Closed-shadow widget boundary (host apps cannot style or inspect internals)
npm install sanctum-dkimport { createSanctumDK } from 'sanctum-dk';
const client = createSanctumDK({
url: 'https://auth.shock.network',
websocketUrl: 'wss://auth.shock.network'
});
const offToken = client.events.onTokenChange((token) => {
console.log('Token changed', token);
});
const offAuthState = client.events.onAuthStateChanged((state) => {
console.log('Auth state', state);
});
client.widget.mount({
containerId: 'sanctum-widget',
theme: 'system'
});
const pubkey = await client.api.getPublicKey();
console.log(pubkey);
offToken();
offAuthState();
await client.destroy();Creates an isolated client instance. Multiple instances can exist without sharing state.
Config:
url(required)websocketUrl(optional, derived fromurlif omitted)storageAdapter(optional)tokenDataAdapter(optional)getClientKey(optional)
getPublicKey()getRelays()signEvent(eventJsonString)encrypt(plaintext, pubkey)decrypt(ciphertext, pubkey)createAuthHeader(url, method, body?)
getTokenData()setTokenData(tokensData)clear()
mount({ containerId, theme?, openAuthWindow?, showLogoutButton? })setTheme(theme)unmount()
Widget internals run inside a closed shadow root and are intentionally not customizable.
onTokenChange(handler)onTokensUpdated(handler)onReauthRequired(({ reason }) => ...)onAuthStateChanged(handler)
All event APIs return unsubscribe.
SanctumDKErrorErrorCode
Most API methods throw SanctumDKError on failure.
createSanctumDK(...)is synchronous wiring (no network calls).client.widget.mount(...)attaches DOM listeners, starts the widget auth flow when the user clicks connect, and updates UI based on session/events.client.destroy()is the instance-level teardown:- unmounts/destroys the widget (future
widget.mount(...)on the same instance will throw) - clears all event handlers registered through
client.events - does not clear persisted tokens/session storage (use
client.session.clear()for logout)
- unmounts/destroys the widget (future
The client always routes these errors through the same reauth path:
REFRESH_TOKEN_EXPIREDREFRESH_TOKEN_INVALIDREFRESH_TOKEN_REPLAYEDGRANT_REVOKED
Reauth path:
- token storage cleared
onReauthRequiredemitted- API call throws
SanctumDKErrorwithrecoverable=false
npm install
npm run build
npm run test
npm run serve