Skip to content
hopper
Get started
Operations / client-generation

Client generation

Generate TypeScript, Kotlin, Python, Go, C, and off-chain Rust clients from one Hopper manifest.

  • hopper client gen --ts <manifest.json> -> TypeScript SDK
  • hopper client gen --kt <manifest.json> -> Kotlin SDK (org.sol4k)
  • hopper client gen --py <manifest.json> -> Python SDK (stdlib-only)
  • hopper client gen --go <manifest.json> -> Go SDK (stdlib-only)
  • hopper client gen --c <manifest.json> -> C header-only client
  • hopper compile --emit rust-client <manifest.json> -> Rust off-chain SDK

Hopper 0.2.1 generates TypeScript, Kotlin, Python, Go, C header-only, and off-chain Rust clients, plus Codama-shaped JSON and Anchor-shaped IDL JSON for downstream tooling. Account readers in every generated language assert the 8-byte Hopper LAYOUT_ID fingerprint before decoding fields.

Copyable generated-client flows

Write all generated artifacts to files during release verification:

hopper compile --emit ts --package hopper-token-2022-vault --out target/clients/vault.ts --force
hopper compile --emit kt --package hopper-token-2022-vault --out target/clients/Vault.kt --force
hopper compile --emit py --package hopper-token-2022-vault --out target/clients/vault_client.py --force
hopper compile --emit go --package hopper-token-2022-vault --out target/clients/vault_client.go --force
hopper compile --emit c --package hopper-token-2022-vault --out target/clients/vault_client.h --force
hopper compile --emit rust-client --package hopper-token-2022-vault --out target/clients/vault_client.rs --force

Generate user-facing surfaces from the same manifest:

hopper actions gen --program examples/hopper-token-2022-vault/hopper.manifest.json --out target/actions
hopper mobile gen --program examples/hopper-token-2022-vault/hopper.manifest.json --target kotlin --out target/mobile-kotlin
hopper mobile gen --program examples/hopper-token-2022-vault/hopper.manifest.json --target react-native --out target/mobile-rn
hopper test-gen security --program examples/hopper-token-2022-vault/hopper.manifest.json --out target/security_matrix.rs

Every command above consumes the manifest. That keeps account layout identity, instruction tags, client decoders, Actions route scaffolds, mobile binding stubs, and generated security test matrices on the same source of truth.

Motivation

Anchor wins social adoption because people know how to get from "program" to "client." Hopper needs a clean answer.

The client generator reads a Hopper ProgramManifest and emits typed SDKs that frontends, bots, scripts, and tests can drop into their project. All generated account decoders assert the 8-byte LAYOUT_ID fingerprint before reading fields, so stale clients fail closed instead of silently mis-decoding account bytes.

TypeScript Generation

What it generates

=== types.ts ===
=== accounts.ts ===
=== instructions.ts ===
=== events.ts ===
=== index.ts ===

The CLI prints a file-marked bundle to stdout. Each section can be split into its own file, or consumed by a generation pipeline.

Type mapping

Hopper canonical type TypeScript type Encoding
u8 number 1 byte LE
u16 number 2 bytes LE
u32 number 4 bytes LE
u64 bigint 8 bytes LE
u128 bigint 16 bytes LE
i8 number 1 byte LE signed
i16 number 2 bytes LE signed
i32 number 4 bytes LE signed
i64 bigint 8 bytes LE signed
bool boolean 1 byte (0/1)
Pubkey PublicKey 32 bytes
[u8; N] Uint8Array N bytes

Account decoders

Each account type gets:

  • A TypeScript interface with typed fields
  • A decode<Name>(data: Buffer): <Name> function
  • A discriminator constant for account identification

Instruction builders

Each instruction gets:

  • An <InstructionName>Args interface for typed arguments
  • An <InstructionName>Accounts interface for required accounts
  • A create<InstructionName>Instruction(args, accounts, programId) function that returns a TransactionInstruction

Events

Each event gets:

  • A TypeScript interface with typed fields
  • A decode<Name>Event(data: Buffer): <Name>Event function

Kotlin Generation

Kotlin generation is implemented today. The generator emits a file-marked bundle targeting org.sol4k primitives:

  • Types.kt with header and discriminator helpers
  • Accounts.kt with data classes and decoders
  • Instructions.kt with typed argument/account classes and builders
  • Events.kt with event data classes and decoders

Encoding and decoding use explicit little-endian ByteBuffer operations, so the generated Kotlin stays close to Hopper's wire model.

Python Generation

Python generation emits a single stdlib-only module:

  • dataclasses for account layouts and events
  • decode classmethods that verify layout identity first
  • segment-aware field readers for partial account inspection
  • build_<instruction> helpers that return raw instruction-data bytes

The generated module intentionally does not pick a Solana transport library. Callers can pass the emitted bytes to solders, solana-py, or their own RPC stack.

Go Generation

Go generation emits a single stdlib-only package with:

  • Pubkey, AccountMeta, and Instruction transport-neutral structs
  • typed account structs and Decode<Name> helpers that verify LAYOUT_ID
  • typed <Instruction>Args / <Instruction>Accounts structs
  • Build<Instruction>Instruction helpers with discriminator-prefixed data
  • event structs and decoders keyed by event tag

The generated package deliberately avoids choosing a Go Solana SDK. Callers can adapt the emitted Instruction into their RPC or transaction-building library.

C Generation

C generation emits a single header-style client with:

  • fixed-width integer and HopperPubkey types
  • hopper_decode_<layout> account decoders that verify LAYOUT_ID
  • hopper_build_<instruction>_data payload builders
  • hopper_<instruction>_account_metas account metadata helpers
  • event decoders and explicit HopperClientError return codes

The header is dependency-light (stdint.h, stdbool.h, stddef.h, string.h) and leaves transaction transport to the embedding application.

Rust Client Generation

hopper compile --emit rust-client emits an off-chain Rust client using Solana SDK types. It is separate from hopper compile --emit rust, which emits the lowered Hopper runtime preview for auditing macro expansion, accessors, and offset paths.

Usage

# Generate from manifest JSON
hopper client gen --ts @my-program.manifest.json

# Generate Kotlin client bundle
hopper client gen --kt @my-program.manifest.json

# Generate Python client module
hopper client gen --py @my-program.manifest.json

# Generate Go client package
hopper client gen --go @my-program.manifest.json

# Generate C client header
hopper client gen --c @my-program.manifest.json

# Generate off-chain Rust client
hopper compile --emit rust-client @my-program.manifest.json

# Generate from piped manifest
hopper schema export --manifest | hopper client gen --ts -

Architecture

ProgramManifest
  ├─ hopper-schema::clientgen::TsClientGen
  │    ├─ types.ts
  │    ├─ accounts.ts
  │    ├─ instructions.ts
  │    ├─ events.ts
  │    └─ index.ts
  ├─ hopper-schema::clientgen::KtClientGen
  │    ├─ Types.kt
  │    ├─ Accounts.kt
  │    ├─ Instructions.kt
  │    └─ Events.kt
  ├─ hopper-schema::python_client::PyClientGen
  │    └─ <program>_client.py
  ├─ hopper-schema::go_client::GoClientGen
  │    └─ client.go
  ├─ hopper-schema::c_client::CClientGen
  │    └─ client.h
  └─ hopper-schema::rust_client::RsClientGen
       └─ client.rs

The generator operates on ProgramManifest directly. It does NOT parse JSON. The CLI is responsible for loading the manifest; the generator formats TypeScript, Kotlin, Python, Go, C, and Rust output bundles.