> For the complete documentation index, see [llms.txt](https://whitepaper.litho.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://whitepaper.litho.ai/docs/api-reference/sdk-reference.md).

# SDK Reference

The Lithosphere TypeScript SDK ships as two layered packages:

* **`@lithosphere/blockchain-core`** — low-level primitives: network registry, typed ABIs (LEP-100, WLITHO, LITHONative), `LithoError` + `ErrorCode`, and shared types. Zero runtime dependencies — safe to include in browser bundles.
* **`@lithosphere/sdk`** — high-level `LithoClient` with retry/backoff, balance helpers, and transaction polling. Depends on `blockchain-core` for ABIs and types; built on raw `fetch` so it works in Node 18+ and modern browsers without a transitive viem/ethers/web3 dep.

For contract **writes** and signing, pair the SDK with viem or ethers — the ABIs exported here plug directly into both.

## Install

```bash
pnpm add @lithosphere/sdk
# pulls @lithosphere/blockchain-core transitively
```

## Quickstart — read the head block in 30 seconds

```ts
import { LithoClient } from '@lithosphere/sdk';

const client = new LithoClient('mainnet');
const height = await client.getBlockNumber();
console.log(`Lithosphere head block: ${height}`);
```

Run it: save as `head.ts`, `pnpm tsx head.ts`. Should print the current block height against `https://rpc.litho.ai` in under one second.

## Quickstart — balance lookup with proper error handling

```ts
import { LithoClient, LithoError, ErrorCode } from '@lithosphere/sdk';

const client = new LithoClient('mainnet');

try {
  const { formatted, symbol } = await client.getBalance(
    '0x22d279d24f0b7ca5d49c5a7a7f032da416f72387',
  );
  console.log(`${formatted} ${symbol}`);
} catch (err) {
  if (err instanceof LithoError) {
    switch (err.code) {
      case ErrorCode.INVALID_ADDRESS:
        console.error('Bad address format');
        break;
      case ErrorCode.RPC_TIMEOUT:
        console.error('RPC took too long — retry or switch endpoints');
        break;
      case ErrorCode.RATE_LIMITED:
        console.error('Rate limit hit — back off');
        break;
      default:
        console.error('Unexpected:', err.message);
    }
  }
}
```

## Quickstart — LEP-100 token balance via viem

```ts
import { LEP100_ABI, NETWORKS } from '@lithosphere/sdk';
import { createPublicClient, http } from 'viem';

const viemClient = createPublicClient({
  transport: http(NETWORKS.mainnet.rpcUrl),
});

const balance = await viemClient.readContract({
  address: '0xtoken-contract-here...',
  abi: LEP100_ABI,
  functionName: 'balanceOf',
  args: ['0xholder-address-here...'],
});

console.log(`Balance: ${balance}`);
```

***

## `LithoClient`

### Constructor

```ts
new LithoClient(rpcUrlOrNetwork: string | NetworkName, config?: ClientConfig)
```

`rpcUrlOrNetwork` is either a registered network name (`'mainnet'`, `'staging'`, `'devnet'`, `'local'`) or a fully-qualified http(s) RPC URL.

`config` (optional):

```ts
interface ClientConfig {
  chainId?: number;                      // only needed for custom RPCs
  timeout?: number;                      // per-request ms (default 30_000)
  retry?: { count: number; delay: number };  // default {3, 250}
}
```

Retry uses exponential backoff: `delay * 2^attempt`. Only retries on transient failures (`NETWORK_ERROR`, `RPC_TIMEOUT`, `RATE_LIMITED`). JSON-RPC errors (invalid params, contract reverts) fail immediately — retrying won't help.

### Methods

| Method                                                                  | Signature                              | Notes                                                                              |
| ----------------------------------------------------------------------- | -------------------------------------- | ---------------------------------------------------------------------------------- |
| `getChainId()`                                                          | `Promise<number>`                      | Returns the configured chainId without calling RPC when known.                     |
| `getBlockNumber()`                                                      | `Promise<number>`                      | Current head block as decimal.                                                     |
| `getBalance(addr, opts?)`                                               | `Promise<AccountBalance>`              | Native LITHO balance with `formatted` (decimal string) and `balance` (bigint wei). |
| `getTransaction(hash)`                                                  | `Promise<TransactionResponse \| null>` | Returns `null` for unknown hash.                                                   |
| `getTransactionReceipt(hash)`                                           | `Promise<TransactionReceipt \| null>`  | Returns `null` while pending.                                                      |
| `waitForTransaction(hash, confirmations?, timeoutMs?, pollIntervalMs?)` | `Promise<TransactionReceipt>`          | Throws `LithoError(TIMEOUT)` if not confirmed within the budget.                   |
| `getNetworkConfig()`                                                    | `NetworkConfig \| null`                | The registered NetworkConfig that matches this client's RPC URL.                   |

All return types are exported from `@lithosphere/sdk` (re-exported from `@lithosphere/blockchain-core`).

***

## `NETWORKS` registry

```ts
import { NETWORKS } from '@lithosphere/sdk';

console.log(NETWORKS.mainnet);
// {
//   name: 'mainnet',
//   isPublic: true,
//   rpcUrl: 'https://rpc.litho.ai',
//   lcdUrl: 'https://api.litho.ai',
//   cosmosRpcUrl: 'https://rpc.litho.ai',
//   explorerUrl: 'https://makalu.litho.ai',
//   chainId: 700777,
//   cosmosChainId: 'lithosphere_700777-2',
//   bech32Prefix: 'litho',
//   currency: { name: 'Lithosphere', symbol: 'LITHO', decimals: 18, denom: 'ulitho' },
// }
```

The `mainnet`, `staging`, and `devnet` profiles currently all point at the live Makalu testnet (there is no separate mainnet chain yet — see [chain-parameters.md](/docs/network/chain-parameters.md)). The `local` profile targets `http://localhost:8545`.

***

## Errors

Every failure path throws `LithoError` with a typed `code`. `instanceof LithoError` and `switch (err.code)` are the supported patterns.

```ts
enum ErrorCode {
  UNKNOWN = 'UNKNOWN',
  NETWORK_ERROR = 'NETWORK_ERROR',
  NETWORK_NOT_FOUND = 'NETWORK_NOT_FOUND',
  INVALID_CHAIN_ID = 'INVALID_CHAIN_ID',
  RPC_TIMEOUT = 'RPC_TIMEOUT',
  RATE_LIMITED = 'RATE_LIMITED',
  TIMEOUT = 'TIMEOUT',
  INVALID_ADDRESS = 'INVALID_ADDRESS',
  INVALID_PARAMETER = 'INVALID_PARAMETER',
  TRANSACTION_FAILED = 'TRANSACTION_FAILED',
  INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS',
  CONTRACT_ERROR = 'CONTRACT_ERROR',
}
```

Underlying causes are preserved on `err.cause` (standard ES2022 `Error.cause`).

***

## Typed ABIs

Three exports cover the contracts that ship with Lithosphere:

```ts
import { LEP100_ABI, WLITHO_ABI, LITHONATIVE_ABI } from '@lithosphere/sdk';
```

A versioned bundle of every compiled contract (ABI + bytecode + deployedBytecode + link references + a summary `index.json`) is uploaded by the `Contract Artifacts (ABI + bytecode)` job in `ci-contracts.yaml` as the `contract-abis` workflow artifact. Useful for deployment automation, on-chain verification tooling, and SDK consumers who want predictable addresses across networks. Grab the latest via:

```bash
gh run download <run-id> -n contract-abis -D ./contract-artifacts
ls contract-artifacts/   # index.json + per-contract .abi.json / .bytecode.json / .full.json
```

A machine-readable copy of the api's GraphQL schema is checked in at [`schema.graphql`](https://github.com/KaJLabs/lithosphere/blob/main/docs/api-reference/schema.graphql) — drop it into your GraphQL client of choice for typed access. CI's `Schema Sync Check` job re-prints `src/schema.ts` and fails if the artifact drifts, so the committed file is always a faithful representation of what `/graphql` actually serves.

These are JSON ABIs vendored at `Makalu/packages/blockchain-core/src/abis/`. The contract artifacts in `Makalu/contracts/artifacts/` are the source of truth — drift between the two is blocked at CI time by the `abi-sync-check` job in `ci-contracts.yaml`. To re-sync after a contract change:

```bash
cd Makalu/contracts
pnpm run sync-abis
git add ../packages/blockchain-core/src/abis/
```

For tight viem / abitype inference, re-assert as `const` at the call site:

```ts
const abi = LEP100_ABI as const;
```

For most callers the default typing is sufficient — `viem.readContract` and `ethers.Contract` both accept the wider `Abi` type.

***

## Project scaffolding

`create-litho-app` remains the fastest path from zero to a working project:

```bash
npx create-litho-app my-dapp
```

The CLI scaffolds an SDK-consuming starter that imports `@lithosphere/sdk` out of the box. The `sdk` template in this monorepo (`Makalu/templates/sdk-template/`, package name `@lithosphere/sdk-template`) is the source-of-truth for that scaffold and is intentionally **not** published to npm — it's copied into the new project on `create-litho-app` invocation.

***

## Examples

* [Hardhat example](/docs/developers/examples/hardhat-example.md) — call contracts via Hardhat scripts
* [Foundry example](/docs/developers/examples/foundry-example.md) — solc + foundry test runner
* [ethers.js example](/docs/developers/examples/ethers-example.md) — read + sign transactions in Node
* [wagmi example](/docs/developers/examples/wagmi-example.md) — full Next.js + wagmi setup

***

## Versioning

This SDK follows semver:

* **Patch** — bug fixes only, no API changes.
* **Minor** — additive (new methods / networks / types).
* **Major** — breaking changes (reserved for v1.0.0+).

See the [release process](/docs/governance/release-process.md) for the publish workflow and `CHANGELOG.md` in each package directory for the history.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://whitepaper.litho.ai/docs/api-reference/sdk-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
