Phase 8 — SDKs & Developer Experience Portal
Status: ~65% (2026-05-11). A real, layered TypeScript SDK ships in
Makalu/packages/, the developer portal has end-to-end usage examples, and the npm publish workflow is wired tag-gated with provenance. OpenAPI / GraphQL schema auto-generation is deferred.
What this phase covers
The phase goal from the work plan: "Dev can call a contract on devnet in under 10 minutes using the portal guide." Coming into this phase that wasn't possible — @lithosphere/blockchain-core was 100% empty stubs (export {} + a VERSION constant), and the only working client code was buried inside the create-litho-app template, not a published runtime package.
Leaving the phase: two layered npm packages, four runnable example apps in the docs, and a release workflow that can publish to npm with provenance attestations the moment an NPM_TOKEN secret is set.
What we built
Two layered packages
@lithosphere/blockchain-core
Low-level primitives — network registry, typed ABIs, LithoError + ErrorCode, shared types. Zero runtime deps, browser-safe.
Makalu/packages/blockchain-core/
12
@lithosphere/sdk
High-level client — LithoClient with retry/backoff, balance helpers, transaction polling. Re-exports blockchain-core so consumers install one package.
Makalu/packages/sdk/
17
The split is deliberate: anyone building tooling for Lithosphere (e.g. a block explorer, a wallet, an indexer) depends on blockchain-core for ABIs and network constants without pulling in a runtime client. Application code depends on sdk and gets everything in one install.
Both ship dual ESM + CJS (tsup) with .d.ts for ESM and CJS contexts, work in Node 18+ and modern browsers, and use raw fetch — no transitive viem/ethers/web3 dependency on the runtime path. For contract writes and signing, pair the SDK with viem or ethers; the typed ABIs (LEP100_ABI, WLITHO_ABI, LITHONATIVE_ABI) plug into both libraries directly.
LithoClient — what it gives you
LithoClient — what it gives youimport { LithoClient, LithoError, ErrorCode } from '@lithosphere/sdk';
const client = new LithoClient('mainnet');
const { formatted, symbol } = await client.getBalance('0x22d...387');
console.log(`${formatted} ${symbol}`);getChainId()
Promise<number>
Avoids an RPC call when chainId is known from the registry.
getBlockNumber()
Promise<number>
Current head, decimal.
getBalance(addr, opts?)
Promise<AccountBalance>
Native LITHO, formatted + balance (bigint wei).
getTransaction(hash)
Promise<TransactionResponse | null>
null for unknown hash.
getTransactionReceipt(hash)
Promise<TransactionReceipt | null>
null while pending.
waitForTransaction(hash, confirmations?, timeoutMs?, pollIntervalMs?)
Promise<TransactionReceipt>
Throws LithoError(TIMEOUT) past budget.
getNetworkConfig()
NetworkConfig | null
The registry entry matching the client's RPC URL.
Retry behaviour: every RPC call goes through exponential backoff (delay * 2^attempt, default {count: 3, delay: 250}), and retries only on transient failures (NETWORK_ERROR, RPC_TIMEOUT, RATE_LIMITED). Bad params, invalid addresses, and contract reverts fail immediately — retrying won't help.
Errors: every failure path throws LithoError with a typed code. instanceof LithoError + switch (err.code) is the supported pattern. The underlying cause is preserved on err.cause (ES2022 Error.cause).
NETWORKS registry
NETWORKS registryFour profiles ship: mainnet, staging, devnet, local. Today the first three all resolve to the live Makalu testnet (there's no separate mainnet chain yet — see docs/network/chain-parameters.md), so choose the profile based on intent of the code path (production vs CI staging vs local hardhat fork). local targets http://localhost:8545.
Documentation portal updates
Rewrote from "Work in Progress" to a full reference: install, three runnable quickstarts, complete method table, errors enum, ABI exports, scaffolding pointer, versioning policy.
New. Next.js 14 + wagmi + viem setup using NETWORKS to derive the wagmi chain config, with a connect button, balance display, and LEP-100 transfer call wired through useWriteContract.
New. Node + ethers v6 reading native + token balances, signing a native transfer, and using LithoClient.waitForTransaction for confirmation polling.
New. NPM_TOKEN setup, semver policy for the SDK, dry-run procedure, rollback.
Surfaces the new examples + release process.
The wagmi and ethers samples are deliberately end-to-end runnable — copy file, pnpm install, set env, run. That's the "<10 min to call a contract" promise from the phase spec.
Tag-gated npm publish workflow
.github/workflows/release.yaml now syncs both packages' package.json versions from the tag, builds + tests both, packs tarballs for the GitHub Release, and publishes both to npm with --provenance attestations:
The job is NPM_TOKEN-aware: if the secret isn't set, it emits a non-fatal warning and skips publish — so the first release won't fail just because the secret hasn't been added yet. The GitHub Release tarball publication still goes through. Provenance attestations show up as a "verified" badge on the npm package page linking back to the Actions run.
@lithosphere/sdk-template rename
@lithosphere/sdk-template renameMakalu/templates/sdk-template/ was previously also named @lithosphere/sdk, which collided with the new package. Renamed to @lithosphere/sdk-template (private: true). It remains the source-of-truth for the create-litho-app scaffold — not published to npm, copied at scaffold time.
How to use what was built
Install (once published):
Quickstart — read the head block:
Quickstart — read a LEP-100 balance via viem:
Cutting a release:
Full walkthrough in release-process.md.
Why it matters
Closes the "<10 min to call a contract" acceptance criterion. Before this phase the only path was "clone the monorepo, find the template, copy client.ts out of it." Now:
pnpm add @lithosphere/sdk, copy a 5-line snippet from sdk-reference.md, done.Decouples downstream from the live chain endpoints. Anyone who hard-codes
rpc.litho.aiin their code ships breakage on the next endpoint move. TheNETWORKSregistry is the one place to update.Typed errors are recoverable errors. A wallet UI can distinguish "RPC is slow, show a spinner" (
RPC_TIMEOUT) from "user typed a bad address" (INVALID_ADDRESS) from "back off, you're being rate-limited" (RATE_LIMITED). GenericErrordoesn't carry that information.Browser-safe by construction.
blockchain-corehas zero runtime deps,sdkonly usesfetch. Bundling either into a frontend is one tree-shake away from the smallest possible footprint — no Node polyfills, no Buffer-shim drama.Provenance attestations. The published packages carry a cryptographically verifiable link back to the Actions run that built them. Supply-chain hardening at zero ongoing cost.
Files & commits
Makalu/packages/blockchain-core/
Rebuilt from stubs: src/networks.ts, src/errors.ts, src/types.ts, src/abis/{LEP100,WLITHO,LITHONative}.json, src/index.ts, tsup.config.ts, __tests__/networks.test.ts.
Makalu/packages/sdk/
New package: src/client.ts, src/index.ts, __tests__/client.test.ts, tsup.config.ts, README.md, CHANGELOG.md.
Makalu/templates/sdk-template/package.json
Renamed to @lithosphere/sdk-template, private: true.
.github/workflows/release.yaml
Added publish_npm job, updated smoke test to assert canonical SDK exports.
docs/api-reference/sdk-reference.md
Rewritten from placeholder.
docs/developers/examples/wagmi-example.md
New.
docs/developers/examples/ethers-example.md
New.
docs/governance/release-process.md
New.
_sidebar.md
Added new example + release-process entries.
Commit: 4701d55 (the entire layered SDK + docs + publish wiring landed together).
Deferred work
OpenAPI / GraphQL schema auto-generation. The api service exposes both REST and GraphQL today but the schemas aren't auto-published. Tracked separately — it's a Phase 9-ish observability concern more than an SDK one.
create-litho-apptemplate refresh. The template still pre-dates the published SDK; updating its scaffold topnpm add @lithosphere/sdkinstead of copyingclient.tsis a small follow-up.Cosmos LCD / REST helpers. v0.1 of the SDK is EVM-only. Cosmos-side helpers (delegations, governance, validators) are a Cosmos-aware add-on package, not a v0.1 deliverable.
First actual npm release. The workflow is ready;
NPM_TOKENneeds to land in repo secrets and someone needs to push the firstv0.1.0tag.
Last updated