> For the complete documentation index, see [llms.txt](/llms.txt)

# Sui TypeScript Codegen

Generate type-safe TypeScript bindings from onchain Sui Move packages.



The `@mysten/codegen` package automatically generates type-safe TypeScript code from your Move
packages, enabling seamless interaction with your smart contracts from TypeScript applications.

<Callout type="warn">
  This package is currently in development and might have breaking changes.
</Callout>

## Features

* **Type-safe Move calls**: Generate TypeScript functions with full type safety for calling your
  Move functions
* **BCS type definitions**: Automatic BCS struct definitions for parsing onchain data
* **Auto-completion**: IDE support with intelligent code completion for Move function arguments
* **Package resolution**: Support for both MVR-registered packages and local packages

## Installation

Install the codegen package as a dev dependency:

```sh npm2yarn
npm install -D @mysten/codegen
```

## Quick start

### Step 1: Create a configuration file

Create a `sui-codegen.config.ts` file in your project root:

```typescript
import type { SuiCodegenConfig } from '@mysten/codegen';

const config: SuiCodegenConfig = {
	output: './src/contracts',
	packages: [
		{
			package: '@local-pkg/counter',
			path: './move/counter',
		},
	],
};

export default config;
```

### Step 2: Generate TypeScript code

Add a script to your `package.json`:

```json
{
	"scripts": {
		"codegen": "sui-ts-codegen generate"
	}
}
```

Then run:

```bash
pnpm codegen
```

This generates TypeScript code in your configured output directory (for example, `./src/contracts`).

## Configuration options

The `SuiCodegenConfig` type supports the following options:

| Option                         | Type                   | Default | Description                                                                                                                                                           |
| ------------------------------ | ---------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `output`                       | `string`               | -       | The directory where generated code will be written                                                                                                                    |
| `packages`                     | `PackageConfig[]`      | -       | Array of Move packages to generate code for                                                                                                                           |
| `prune`                        | `boolean`              | `true`  | When enabled, only generates code for the main package and omits dependency modules (dependency types referenced by included types are still generated under `deps/`) |
| `generateSummaries`            | `boolean`              | `true`  | Automatically run `sui move summary` before generating code. Creates a `package_summaries` directory in your Move package which can be added to `.gitignore`          |
| `generate`                     | `GenerateOptions`      | -       | Default [generate options](#the-generate-option) (types, functions) for all packages                                                                                  |
| `importExtension`              | `'.js' \| '.ts' \| ''` | `'.js'` | File extension used in generated import statements                                                                                                                    |
| `includePhantomTypeParameters` | `boolean`              | `false` | Include [phantom type parameters](#phantom-types) as function arguments in generated BCS types                                                                        |

### Package configuration

Each entry in the `packages` array configures a Move package to generate code from. Packages can be
local (from source) or onchain (fetched from a network).

#### Local packages

| Option        | Type                     | Required | Description                                               |
| ------------- | ------------------------ | -------- | --------------------------------------------------------- |
| `package`     | `string`                 | yes      | Package identifier (for example, `@local-pkg/my-package`) |
| `path`        | `string`                 | yes      | Path to the Move package directory                        |
| `packageName` | `string`                 | no       | Custom name for generated code directory                  |
| `generate`    | `PackageGenerateOptions` | no       | Control what gets generated from this package             |

```typescript
{
  package: '@local-pkg/my-package',
  path: './move/my-package',
}
```

#### Onchain packages

For packages already deployed onchain, generate code directly from a package ID or MVR name without
needing local source code:

| Option        | Type                     | Required | Description                                   |
| ------------- | ------------------------ | -------- | --------------------------------------------- |
| `package`     | `string`                 | yes      | Package ID or MVR name                        |
| `packageName` | `string`                 | yes      | Name for the generated code directory         |
| `network`     | `'mainnet' \| 'testnet'` | yes      | Network to fetch the package from             |
| `generate`    | `PackageGenerateOptions` | no       | Control what gets generated from this package |

```typescript
{
  package: '0xabf837e98c26087cba0883c0a7a28326b1fa3c5e1e2c5abdb486f9e8f594c837',
  packageName: 'pyth',
  network: 'testnet',
}
```

## The `generate` option

The `generate` option controls what code is produced. It can be set at the global level (as a
default for all packages), at the per-package level, and at the per-module level. More specific
settings override less specific ones.

When no `generate` option is set, everything is generated (all types and functions). Package-level
`types` and `functions` also default to `true`. In the record form of `modules`, per-module `types`
and `functions` default to `false`, so you opt in to exactly what you need from each module. Use
`true` as a shorthand to include everything from a module with package-level defaults.

At the **global** and **package** levels, `types` and `functions` only accept boolean values (or an
object for `functions`). Name-based filtering with `string[]` is only available at the **module**
level inside the record form of `modules`, where the filter applies unambiguously to a single
module.

```typescript
// Global or package level
generate: {
  types: true | false,
  functions: true | false | { private: boolean | 'entry' },
  modules: string[] | Record<string, true | { types?, functions? }>,  // package-level only
}

// Module level (inside the record form of modules)
modules: {
  my_module: true,  // shorthand for "include everything"
  other_module: {
    types: true | false | string[],
    functions: true | false | string[] | { private: boolean | 'entry' },
  }
}
```

### Types

Controls which BCS type definitions (structs and enums) are generated:

* `true`: generate all types
* `false`: skip type generation
* `string[]`: generate only the listed types by name (module level only)

### Functions

Controls which Move function wrappers are generated:

* `true`: generate all public functions and private entry functions
* `false`: skip function generation
* `string[]`: generate only the listed functions by name; includes private functions (module level
  only)
* `{ private: 'entry' }`: generate public functions plus private entry functions
* `{ private: true }`: generate all functions including private
* `{ private: false }`: only generate public functions

### Modules

Controls which modules from the package are included. Only available at the package level, not at
the global level.

* Not set (default): include all modules
* `string[]`: only include the listed modules
* `Record<string, true | { types?, functions? }>`: only include the listed modules, with per-module
  overrides for `types` and `functions`. Use `true` as a shorthand to include everything from a
  module with package-level defaults

### Examples

Only generate code from specific modules of the Sui framework:

```typescript
{
  package: '0x0000000000000000000000000000000000000000000000000000000000000002',
  packageName: '0x2',
  network: 'testnet',
  generate: {
    modules: ['kiosk', 'kiosk_extension', 'transfer_policy'],
  },
}
```

Only generate a single type from a dependency (functions are omitted automatically because
`generate` is configured and `functions` is not specified):

```typescript
{
  package: '0xabf837e98c26087cba0883c0a7a28326b1fa3c5e1e2c5abdb486f9e8f594c837',
  packageName: 'pyth',
  network: 'testnet',
  generate: {
    modules: {
      state: { types: ['State'] },
    },
  },
}
```

Generate specific types and functions from individual modules:

```typescript
{
  package: '@local-pkg/my-package',
  path: './move/my-package',
  generate: {
    modules: {
      token: {
        types: ['Token', 'TokenMetadata'],
        functions: ['mint', 'burn', 'transfer'],
      },
      admin: {
        types: true,
        functions: ['initialize'],
      },
    },
  },
}
```

Generate all types but include all private functions for a local package:

```typescript
{
  package: '@local-pkg/my-package',
  path: './move/my-package',
  generate: {
    functions: { private: true },
  },
}
```

### Dependency pruning

The global `prune` option (default: `true`) controls whether dependency packages are included in the
output. Even when pruning is enabled, dependency types referenced by your included types are still
generated under `deps/`:

```
src/contracts/
├── mypackage/
│   ├── module_a.ts
│   ├── module_b.ts
│   └── deps/
│       └── 0x2/
│           └── balance.ts     # Auto-included dependency type
└── utils/
    └── index.ts               # Shared utilities (always generated)
```

Set `prune: false` to generate all dependency modules with their full types and functions.

## Phantom types

In Move, phantom type parameters are type parameters that only appear at the type level and don't
affect the runtime data layout of a struct. For example, `Balance<T>` has a phantom type parameter
`T` that indicates the coin type, but the actual serialized data only contains a `u64` value:

```move
public struct Balance<phantom T> has store {
    value: u64,
}
```

### Default behavior

By default, codegen excludes phantom type parameters from the generated BCS type functions because
they don't affect serialization. The generated type is a constant rather than a function:

```typescript
export const Balance = new MoveStruct({
	name: `${$moduleName}::Balance<phantom T>`,
	fields: {
		value: bcs.u64(),
	},
});
```

This works correctly for parsing onchain data because phantom types don't change the binary layout.

<Callout type="info">
  With the default behavior, phantom parameters appear as literals in the type name (for example,
  `Balance<phantom T>`). These names are useful for debugging but are not valid onchain type tags. If
  you need valid type names with resolved phantom parameters, enable `includePhantomTypeParameters`.
</Callout>

### Including phantom type parameters

If you need the phantom type parameters as function arguments (for example, to preserve type
information for other tooling), enable `includePhantomTypeParameters`:

```typescript
const config: SuiCodegenConfig = {
	output: './src/contracts',
	includePhantomTypeParameters: true,
	packages: [
		// ...
	],
};
```

With this option enabled, phantom type parameters become function arguments:

```typescript
export function Balance<T extends BcsType<any>>(T: T) {
	return new MoveStruct({
		name: `${$moduleName}::Balance<${T.name}>` as const,
		fields: {
			value: bcs.u64(),
		},
	});
}
```

## Using generated code

### Calling Move functions

The generated code provides type-safe functions for calling Move functions:

```typescript
import { Transaction } from '@mysten/sui/transactions';
import * as counter from './contracts/counter/counter';

// Increment a counter
const tx = new Transaction();
tx.add(
	counter.increment({
		arguments: {
			counter: '0x123...', // Counter object ID
		},
	}),
);
```

### Parsing BCS data

Use generated BCS types to parse onchain object data. Fetch the object with
`include: { content: true }` and pass `object.content` to the generated type's `.parse()` method:

```typescript
import { Counter as CounterStruct } from './contracts/counter/counter';

async function readCounter(client: ClientWithCoreApi, id: string) {
	const { object } = await client.core.getObject({
		objectId: id,
		include: { content: true },
	});

	// Parse the Move struct fields from BCS content
	const parsed = CounterStruct.parse(object.content);
	console.log('Counter value:', parsed.value);
	console.log('Counter owner:', parsed.owner);

	return parsed;
}
```

<Callout type="warn">
  Always use `content`, not `objectBcs`, when parsing with generated types. The `objectBcs` field
  contains a full object envelope with additional metadata that will cause parsing to fail. See the
  [Core API docs](/sui/clients/core#objectbcs) for details.
</Callout>

## Client configuration

### Using with MVR (Move Version Registry)

If your package is registered on MVR, the generated code works without additional configuration.

### Local packages

For local packages using `@local-pkg/*` identifiers, configure your client with package overrides:

```typescript
import { SuiGrpcClient } from '@mysten/sui/grpc';

const client = new SuiGrpcClient({
	network: 'testnet',
	baseUrl: 'https://fullnode.testnet.sui.io:443',
	mvr: {
		overrides: {
			packages: {
				'@local-pkg/counter': '0xYOUR_PACKAGE_ID',
			},
		},
	},
});
```

### With dApp Kit

Configure package overrides when creating your dApp Kit instance:

```typescript
import { createDAppKit } from '@mysten/dapp-kit-core';
import { SuiGrpcClient } from '@mysten/sui/grpc';

const GRPC_URLS = {
	testnet: 'https://fullnode.testnet.sui.io:443',
};

const PACKAGE_IDS = {
	testnet: {
		counter: '0xYOUR_PACKAGE_ID',
	},
};

const dAppKit = createDAppKit({
	networks: ['testnet'],
	createClient: (network) => {
		return new SuiGrpcClient({
			network,
			baseUrl: GRPC_URLS[network],
			mvr: {
				overrides: {
					packages: {
						'@local-pkg/counter': PACKAGE_IDS[network].counter,
					},
				},
			},
		});
	},
});
```

## Related resources

* [create-dapp](/dapp-kit/getting-started/create-dapp) - Bootstrap a working app with codegen
  already configured
* [Sui Move documentation](https://docs.sui.io/concepts/sui-move-concepts)
* [BCS documentation](/bcs)
* [Transaction building](/sui/transaction-building/basics)
* [dApp Kit](/dapp-kit)
