npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@capxul/sdk

v0.1.0-alpha.12

Published

Headless TypeScript client for Capxul's /v1/* HTTP contract.

Downloads

1,169

Readme

@capxul/sdk

Headless TypeScript client for Capxul — issue and accept stablecoin payments, manage organization treasuries, and orchestrate on-chain flows backed by audited custody contracts.

Alpha — 0.x is pre-release. APIs can change between alpha versions. Pin to an exact version (@capxul/[email protected]) and read the changelog before upgrading.

Install

pnpm add @capxul/sdk @capxul/sdk-react
# or: npm install @capxul/sdk @capxul/sdk-react

@capxul/sdk is the headless contract — flows, types, errors. The React-flavored entry point lives in @capxul/sdk-react. Pick:

  • Browser apps (recommended). Install both. Use <CapxulProvider config={{ mode: "publishable-key", publishableKey }}> from @capxul/sdk-react and the useMe / useCapxulStatus hooks. See that package's README for the lazy-DX example.
  • Server / CLI / scripts. Install only @capxul/sdk. Build a CapxulClient directly with your own auth and Convex adapters (see "Server-side construction" below).

Two-layer trust

Capxul splits the platform into two layers with different licenses:

| Layer | What it does | License | |---|---|---| | Custody (on-chain) | Safe v1.4.1 + ERC-4337 modules — every contract that holds, transfers, or signs over user funds | Open source, audited, in the Capxul GitHub repo | | Orchestration (this package) | Workflow logic, business rules, integration glue, the /v1/* HTTP client | Proprietary — see LICENSE |

You don't have to take our word for the parts that hold money — those contracts are open and auditable. The parts that orchestrate workflows on top are our product.

Quickstart (server / CLI)

import { createCapxulClient, createLocalSigner, tryCatch } from "@capxul/sdk";

const signer = createLocalSigner(process.env.CAPXUL_PRIVATE_KEY!);
const capxul = createCapxulClient({
  apiKey: process.env.CAPXUL_API_KEY!, // server-to-server partner key
  signer,
});

const [err, payment] = await tryCatch(
  capxul.payments.create({
    to: { email: "[email protected]" },
    amount: { value: "100", currency: "USD" },
  }),
);

if (err) {
  if (err.code === "INSUFFICIENT_BALANCE") {
    // narrow `err.code` to route the UI / reply
  }
  throw err;
}

console.log(payment.id);

Quickstart (browser via React)

See @capxul/sdk-react. The browser path uses a publishable key (cap_pk_…) and bootstraps runtime URLs lazily — no need to ship secrets to the client:

import { CapxulProvider, useMe, useCapxulStatus } from "@capxul/sdk-react";

<CapxulProvider
  config={{
    mode: "publishable-key",
    publishableKey: process.env.NEXT_PUBLIC_CAPXUL_PUBLISHABLE_KEY!,
  }}
>
  <App />
</CapxulProvider>;

Publishable-key transport

The browser transport accepts a publishable key, then lazily resolves runtime URLs by POSTing to /v1/client/bootstrap on the first auth or ensureRuntime() call. The successful backend response is intentionally small:

{ "authBaseUrl": "https://<deployment>.convex.site/api/auth", "convexUrl": "https://<deployment>.convex.cloud" }

The resolved runtime is cached for the lifetime of the transport. Concurrent callers share one bootstrap request, successful resolutions are reused, and failed bootstrap attempts reset so the next call can retry. Tests and non-default deployments can inject both fetchImpl and an absolute bootstrapUrl:

import { makeHttpTransport, CapxulError } from "@capxul/sdk";

const transport = makeHttpTransport({
  mode: "publishable-key",
  publishableKey: process.env.NEXT_PUBLIC_CAPXUL_PUBLISHABLE_KEY!,
  bootstrapUrl: "https://api.capxul.com/v1/client/bootstrap",
  fetchImpl: fetch,
});

await transport.ensureRuntime();

Local setup errors and backend bootstrap errors both use CapxulError, but carry different details.source values:

try {
  await transport.ensureRuntime();
} catch (error) {
  if (error instanceof CapxulError) {
    if (error.details?.source === "sdk-config") {
      // Missing or malformed local config, such as publishableKey or bootstrapUrl.
    }
    if (error.details?.source === "backend-bootstrap") {
      // Sanitized backend refusal, such as NOT_AUTHENTICATED or PERMISSION_DENIED.
    }
  }
}

Runtime proof status:

| Surface | Source support | Runtime proof | Status | |---|---|---|---| | SDK transport | makeHttpTransport({ mode: "publishable-key", publishableKey }) | packages/sdk/tests/unit/transport.test.ts proves config validation, singleflight bootstrap, retry after failure, lifecycle transitions, and sanitized backend errors. | Proven with mocked fetch | | React provider | CapxulProvider config={{ mode: "publishable-key", ... }} | packages/sdk-react/ops/proof/react-headless.test.tsx proves bootstrap before a real useMe() read through the provider and lazy Convex data client. | Proven with mocked fetch + headless React | | Reference CLI | bootstrap probe --mock --json | apps/reference-cli/scripts/agent-driver.ts phase 0 and the direct CLI command prove provider/bootstrap/auth ordering and sanitized output. | Proven locally; live endpoint remains manual-key gated |

Copy-paste local replication:

corepack pnpm --filter @capxul/sdk check-types
corepack pnpm --filter @capxul/sdk build
corepack pnpm --filter @capxul/sdk-react check-types
corepack pnpm --filter @capxul/sdk-react build
corepack pnpm --filter @capxul/reference-cli check-types
corepack pnpm --filter @capxul/reference-cli build
node apps/reference-cli/dist/cli.js bootstrap probe --mock --json

Run the SDK and React SDK builds before the reference CLI typecheck in a fresh checkout; the CLI depends on their generated declaration outputs.

Expected sanitized pass signal:

{"command":"bootstrap.probe","ok":true,"mode":"publishable-key","status":"ready","bootstrapRequests":1,"authRequests":1,"keyLengthClass":"provided","mocked":true}

Public surface (alpha)

capxul.auth          // sendOtp, verifyOtp, signOut, serviceTokenMint
capxul.me            // get, update — first-party caller identity
capxul.accounts      // create, retrieve, list
capxul.organizations // CRUD + members + payments + treasury
capxul.payments      // create, retrieve, list
capxul.invoices      // create, retrieve, list
capxul.withdrawals   // create, retrieve, list
capxul.documents     // KYC uploads, invoices, receipts, tax forms
capxul.flows.{auth, onboarding, provisioning} // XState v5 flows

Helpers:

  • tryCatch(promise) — error tuple [error, data]; routes on error.code (typed CapxulErrorCode union)
  • matchError, matchStatus, matchAction — exhaustive pattern matchers per CANON.md §4.44
  • Branded type constructors — toEmail, toAccountId, toOrganizationId, … — never cast raw strings

Error model

Every method returns a CapxulResult<T, Codes> tuple. Errors are instances of CapxulError with a typed code (narrowed per method).

const [err, account] = await tryCatch(capxul.me.get());

if (err) {
  switch (err.code) {
    case "PROFILE_NOT_FOUND": return router.push("/onboarding");
    case "NOT_AUTHENTICATED": return router.push("/login");
    default: throw err; // unhandled — bubble to the error boundary
  }
}

There is no second error type. Backend CapxulError → Convex serialization → SDK deserialization → frontend CapxulError — one class, 34 codes, end-to-end.

Telemetry (opt-out)

The SDK reports operational telemetry (operation IDs, latencies, correlation IDs, error codes) to Capxul. PII is never sent — events are scrubbed at the source. Disable by passing { telemetry: { enabled: false } } (coming in 0.2.0); current alpha sends only operational signals which Capxul Terms disclose explicitly.

License

Proprietary — see LICENSE. The orchestration code in this package is governed by the Capxul Terms of Service. The value-bearing custody contracts are open source — see "Two-layer trust" above.

Contact: [email protected]