Joltsdk

jolt-sdk · TypeScript

Build apps that
borrow an identity.

Jolt applications do not own accounts. They ask the local Jolt daemon for a capability-scoped session that the user approves in Jolt Console, then publish signed content under the user's identity, read other identities' content, and exchange encrypted objects through recipient-controlled ingress. The SDK is the typed client for that contract.

01 / Install

One package. Four entry points.

yarn add jolt-sdk

The SDK also ships with every Jolt release as an installable tarball, if you prefer pinning to a release directly:

yarn add https://github.com/alexanderwanyoike/jolt/releases/latest/download/jolt-sdk.tgz
ImportWhat it is
jolt-sdkTypes, typed errors, and createJoltClient: tolerant, domain-shaped operations
jolt-sdk/transport-httpfetch-based transport for browsers and Node.js 18+
jolt-sdk/transport-tauriTauri invoke-based transport for desktop shells
jolt-sdk/testingcreateFakeJolt: a deterministic in-memory fake for tests

02 / Quick start

Session in, signed content out.

An app declares who it is and exactly what it wants to do. The daemon holds the request until the user approves it in Jolt Console; the app polls until the approval carries a bearer token, then every call is checked against the granted capabilities.

import { createJoltClient } from "jolt-sdk";
import { HttpTransport } from "jolt-sdk/transport-http";

let token = "";
const jolt = createJoltClient({
  transport: new HttpTransport({ daemonUrl: "http://127.0.0.1:9862" }),
  getSessionToken: () => token,
});

// 1. Ask for a scoped session; the user approves it in Jolt Console.
const status = await jolt.getStatus();
const request = await jolt.requestSession({
  appId: "myapp.local",
  appName: "My App",
  appOrigin: window.location.origin,
  identity: status.identity_address,
  capabilities: ["publish:/myapp/*", "resolve:public", "fetch:public"],
});

// 2. Poll until approved.
for (;;) {
  const s = await jolt.getSessionRequestStatus(request.request_id);
  if (s.session_token) { token = s.session_token; break; }
  await new Promise((r) => setTimeout(r, 1000));
}

// 3. Publish signed content and read it back, versioned and decoded.
await jolt.publishJson("/myapp/profile", { name: "Alice" });
const profile = await jolt.read(
  { identity: status.identity_address, path: "/myapp/profile" },
  (v) => (typeof v === "object" && v && "name" in v ? (v as { name: string }) : null)
);

Reads are tolerant: missing, unreachable, or undecodable content returns null instead of throwing, so one bad record never poisons an app projection. Failures from publishes and sends throw JoltApiError (the daemon answered with an error) or JoltTransportError (the daemon was unreachable); every operation accepts { signal, timeoutMs }.

03 / Transports

Same client. Two ways to the daemon.

Everything above the transport (operations, client, domain types) is identical in the browser, Node.js, and Tauri. Only the last hop changes.

HTTP · browser and Node.js

HttpTransport talks to the daemon over fetch. Point it at the daemon directly, or use HttpTransport.viteProxy() behind a dev-server proxy to dodge CORS.

import { HttpTransport } from "jolt-sdk/transport-http";

const transport = new HttpTransport({
  daemonUrl: "http://127.0.0.1:9862",
});
Tauri · desktop shells

Daemon calls go through audited Rust proxy commands, so the webview never needs network access. The tauri-plugin-jolt plugin ships those commands; wiring it up is three lines:

  1. 01
    Add the crate and register it:
    .plugin(tauri_plugin_jolt::init())
  2. 02
    Grant the jolt:default capability in your Tauri capabilities file.
  3. 03
    Construct the transport:
    new TauriTransport({ plugin: true })

04 / Testing

A whole daemon, faked in memory.

createFakeJolt returns a fully working JoltClient with no daemon and no network: publishes land in an in-memory store, reads resolve against it, sends are recorded, and incoming envelopes can be injected. Your tests exercise your schemas and flows, not HPKE.

import { createFakeJolt } from "jolt-sdk/testing";

const { client, sent, deliverIngress } = createFakeJolt("alice.jolt");
// client satisfies JoltClient and all of its sub-interfaces; sends are
// recorded in `sent`, and deliverIngress() injects incoming envelopes.

05 / Documentation

Where to go next.

API

Generated from TSDoc · four modules

SDK reference

Every exported class, interface, function, and type: the client and its sub-interfaces, typed operations, wire DTOs, both transports, and the testing fake.

01

Tutorial · Tauri + React

App development guide

Build Chirp, a minimal twitter-style app: scoped sessions, append records and timelines, follow requests over ingress, and tests against the fake.