> ## Documentation Index
> Fetch the complete documentation index at: https://docs.molpha.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Overview

> Install @molpha/sdk and request verifiable data from backends, agents, and custom applications.

[`@molpha/sdk`](https://www.npmjs.com/package/@molpha/sdk) is the recommended way to integrate Molpha from TypeScript. `MolphaSDK` wires the gateway client and the Solana client together behind a single wallet, and the package also ships framework-agnostic EVM/Starknet [argument builders](/sdk/reference).

For AI agent workflows in Cursor, Claude Desktop, or Codex, use the [Molpha MCP server](/mcp/molpha-mcp) — it wraps this SDK behind typed MCP tools. For the fastest path by audience, see the [Backend quickstart](/quickstarts/backend) or [AI agent quickstart](/quickstarts/ai-agents).

## What you can build

| Workflow                    | SDK path                                                             |
| --------------------------- | -------------------------------------------------------------------- |
| Request one signed payload  | `sdk.gateway.requestSignedData(...)`                                 |
| Maintain a Solana feed      | Derive `feedId`, then `sdk.requestAndSubmit(...)`                    |
| Read a maintained feed      | `sdk.solana.readFeed(feedId)`                                        |
| Verify directly in Rust     | Use `molpha-verifier` with registry/node data                        |
| Call EVM/Starknet verifiers | `buildEvmVerifierArgs(result)` / `buildStarknetVerifierArgs(result)` |

## Installation

Install the package along with the Solana peer dependencies (required for `MolphaSDK` / `MolphaSolanaClient`):

<Tabs>
  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add @molpha/sdk @anchor-lang/core bn.js
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={null}
    npm install @molpha/sdk @anchor-lang/core bn.js
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add @molpha/sdk @anchor-lang/core bn.js
    ```
  </Tab>
</Tabs>

* **ESM, browser-first**, with `"sideEffects": false`
* **Tree-shakeable Solana path** — gateway-only or read-only apps that skip the Solana imports can tree-shake the Anchor-heavy path entirely
* **Node.js `>=20.19.0`**
* Node-only helpers (e.g. `walletFromKeypairFile`) live under the `@molpha/sdk/utils` subpath so they never enter browser bundles

`@anchor-lang/core` provides the Anchor `Wallet` / `Connection` types the Solana client expects. `bn.js` is used by the Solana / Anchor path. The SDK pulls in `@solana/kit` and `@noble/*` as direct dependencies — you do not need `@solana/web3.js`, `@coral-xyz/anchor`, or `@solana/spl-token` for the consumer flow.

## Initialize

```ts theme={null}
import { web3 } from "@anchor-lang/core";
import { MolphaSDK } from "@molpha/sdk";
import { walletFromKeypairFile } from "@molpha/sdk/utils";

const sdk = new MolphaSDK({
  connection: new web3.Connection("https://api.devnet.solana.com", "confirmed"),
  wallet: walletFromKeypairFile("~/.config/solana/id.json"),
});
```

By default the SDK talks to `https://dev-gateway.molpha.io/`. Override with `endpoints` (string or array for failover):

```ts theme={null}
import { DEFAULT_GATEWAY_ENDPOINT } from "@molpha/sdk";

const sdk = new MolphaSDK({
  connection,
  wallet,
  endpoints: [DEFAULT_GATEWAY_ENDPOINT, "https://backup.example.com"],
});
```

`walletFromKeypairFile` is Node.js-only. In the browser, pass a [`MolphaWallet`](/sdk/reference#molphawallet) backed by a wallet adapter:

```ts theme={null}
import type { MolphaWallet } from "@molpha/sdk";

const wallet: MolphaWallet = {
  publicKey: adapter.publicKey,
  signTransaction: (tx) => adapter.signTransaction(tx),
  signAllTransactions: (txs) => adapter.signAllTransactions(txs),
  signAuthMessage: async (msg) => new Uint8Array(await adapter.signMessage(msg)),
};
```

<Warning>
  Gateway execution requires a real Ed25519 `authSig`. Keypair-backed wallets (`walletFromKeypairFile`) derive auth from `Wallet.payer` automatically. Browser adapters should provide `signAuthMessage`. The gateway rejects all-zero signatures.
</Warning>

## Facade surface

| Member                                                            | Purpose                                                                                                                                       |
| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `sdk.requestAndSubmit(feedId, { apiConfig, signaturesRequired })` | Run a gateway round against the current registry version and submit the signed result to Solana in one call. Returns `{ result, signature }`. |
| `sdk.gateway`                                                     | The [gateway client](/sdk/gateway-api): `requestSignedData`, `prepareContext`, …                                                              |
| `sdk.solana`                                                      | The Solana client (below): `getPlan`, `subscribe`, `extendSubscription`, `submitDataUpdate`, `readFeed`, `getRegistrySelectionConfig`, …      |

`requestAndSubmit` is equivalent to:

```ts theme={null}
const result = await sdk.gateway.requestSignedData({
  feedId,
  apiConfig,
  signaturesRequired,
});
const { signature } = await sdk.solana.submitDataUpdate(result);
```

## Solana client (`sdk.solana`)

All methods target the Molpha program (`MoLFGDpFoVnQgwbkTNScKPohCxhbfd61JjFrnotuwzh` on devnet); PDAs are derived internally from the documented seeds.

### Plans and subscriptions

```ts theme={null}
import { PlanType } from "@molpha/sdk";

const plan = await sdk.solana.getPlan(PlanType.Basic);

const { pricePaid } = await sdk.solana.subscribe(PlanType.Basic, {
  maxPriceUsdc: plan.subscriptionPrice,
});

// Renew for another period (same maxPriceUsdc safety bound)
await sdk.solana.extendSubscription({
  maxPriceUsdc: plan.subscriptionPrice,
});
```

`maxPriceUsdc` is a safety bound: the transaction aborts if the on-chain price is higher than what the user approved. The SDK currently exports `PlanType.Basic` (`0`). On-chain plan ordinals remain `Basic = 0`, `Standard = 1`, `Professional = 2`, `Enterprise = 3`.

### Derive a feed ID

```ts theme={null}
import { deriveApiConfigHash, deriveFeedIdString } from "@molpha/sdk";

const signaturesRequired = 3;
const apiConfigHash = deriveApiConfigHash(apiConfig);
const feedId = deriveFeedIdString(
  wallet.publicKey.toBytes(),
  apiConfigHash,
  signaturesRequired,
);
```

There is no separate create instruction. The first successful `submitDataUpdate` creates the Solana `Feed` account if it does not exist. Settlement writes round receipts only.

### Request

```ts theme={null}
// Optional: fetch registry + nodes once, then reuse across rounds
const context = await sdk.gateway.prepareContext(feedId);

const result = await sdk.gateway.requestSignedData({
  feedId,
  apiConfig,
  signaturesRequired,
  context,
});
```

Live gateway rounds return `fresh: true`. Gateway execution is authenticated via `signAuthMessage` (or a keypair-derived signer); the HTTP gateway rejects all-zero `authSig` values.

For private APIs, pass `encrypt: { secrets: { ... } }` — `MolphaSDK` authenticates gateway node keys against on-chain Node accounts before encrypting. See the [SDK gateway API](/sdk/gateway-api).

### Submission and reads

```ts theme={null}
// Verify + write the signed result to the Feed account
const { signature } = await sdk.solana.submitDataUpdate(result);

// Read the finalized on-chain feed account (bytes + metadata)
const feed = await sdk.solana.readFeed(feedId);
console.log(feed?.value, feed?.canonicalTimestamp);
```

`feed.value` is the on-chain byte array (`number[]`), not the human-readable `DataUpdateResult.value` string. Decode it per your feed schema (see [Read and verify](/guides/read-and-verify)).

`submit_data_update` is permissionless on-chain — the program re-verifies the aggregate signature on every write and only accepts a value whose `canonical_timestamp` is strictly greater than the stored one.

### Direct verification

For Solana, use one of two paths:

* submit through `submitDataUpdate`, then read the `Feed` account;
* verify directly in Rust with `molpha-verifier`.

For EVM and Starknet, build verifier arguments with the helpers in [SDK Reference](/sdk/reference).
