Client generation
Generate TypeScript, Kotlin, Python, Go, C, and off-chain Rust clients from one Hopper manifest.
hopper client gen --ts <manifest.json>-> TypeScript SDKhopper 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 clienthopper 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>Argsinterface for typed arguments - An
<InstructionName>Accountsinterface for required accounts - A
create<InstructionName>Instruction(args, accounts, programId)function that returns aTransactionInstruction
Events
Each event gets:
- A TypeScript interface with typed fields
- A
decode<Name>Event(data: Buffer): <Name>Eventfunction
Kotlin Generation
Kotlin generation is implemented today. The generator emits a file-marked
bundle targeting org.sol4k primitives:
Types.ktwith header and discriminator helpersAccounts.ktwith data classes and decodersInstructions.ktwith typed argument/account classes and buildersEvents.ktwith 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
decodeclassmethods 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, andInstructiontransport-neutral structs- typed account structs and
Decode<Name>helpers that verifyLAYOUT_ID - typed
<Instruction>Args/<Instruction>Accountsstructs Build<Instruction>Instructionhelpers 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
HopperPubkeytypes hopper_decode_<layout>account decoders that verifyLAYOUT_IDhopper_build_<instruction>_datapayload buildershopper_<instruction>_account_metasaccount metadata helpers- event decoders and explicit
HopperClientErrorreturn 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.
