llms.txt
@mysten/sui v2.0 and a new dApp Kit are here! Check out the migration guide
Mysten Labs SDKs
MigrationsMigrate to 2.0

@mysten/sui

Migrate @mysten/sui from 1.x to 2.0 with gRPC clients, Core API, and BCS changes

Removal of SuiClient exports

The old SuiClient export has been removed from @mysten/sui/client. For application code, migrate to SuiGrpcClient and use top-level methods such as client.getObject(), client.listCoins(), and client.signAndExecuteTransaction().

Legacy JSON-RPC functionality moved to @mysten/sui/jsonRpc, but JSON-RPC APIs are deprecated in the Sui TypeScript SDK. Use the JSON-RPC exports only when maintaining code that still needs the old JSON-RPC method names or response shapes during migration.

Removed exports:

  • SuiClient (use SuiGrpcClient; legacy JSON-RPC code can use SuiJsonRpcClient)
  • SuiClientOptions (use SuiGrpcClientOptions; legacy JSON-RPC code can use SuiJsonRpcClientOptions)
  • isSuiClient (use isSuiGrpcClient, isSuiGraphQLClient, or legacy isSuiJsonRpcClient)
  • SuiTransport (legacy JSON-RPC code can use JsonRpcTransport)
  • SuiTransportRequestOptions (use JsonRpcTransportRequestOptions instead)
  • SuiTransportSubscribeOptions (removed; use the gRPC subscription service for streaming APIs)
  • SuiHTTPTransportOptions (use JsonRpcHTTPTransportOptions instead)
  • SuiHTTPTransport (use JsonRpcHTTPTransport instead)
  • getFullnodeUrl (pass the full node URL to SuiGrpcClient.baseUrl; legacy JSON-RPC code can use getJsonRpcFullnodeUrl)
  • All JSON-RPC types (now exported from @mysten/sui/jsonRpc)

Migration:

- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
+ import { SuiGrpcClient } from '@mysten/sui/grpc';

- const client = new SuiClient({
-   url: getFullnodeUrl('devnet'),
+ const client = new SuiGrpcClient({
+   baseUrl: 'https://fullnode.devnet.sui.io:443',
    network: 'devnet',
  });

Network parameter required

When creating a new SuiGrpcClient, SuiGraphQLClient, or legacy SuiJsonRpcClient, provide a network parameter:

const grpcClient = new SuiGrpcClient({
	baseUrl: 'https://...',
	network: 'mainnet', // Required
});

const graphqlClient = new SuiGraphQLClient({
	url: 'https://...',
	network: 'mainnet', // Required
});

const jsonRpcClient = new SuiJsonRpcClient({
	url: 'https://...',
	network: 'mainnet', // Required
});

BCS schema changes

Several BCS schemas in @mysten/sui/bcs have been updated to align exactly with the Rust implementation. These changes affect serialization and deserialization of transaction effects and objects.

ExecutionStatus changes

BCS Schema (when parsing raw effects): The variant was renamed from Failed to Failure:

- effects.status.Failed.error
+ effects.status.Failure.error

Core API and top-level client methods (gRPC and GraphQL responses): Use a simplified structure with a success boolean:

// Top-level gRPC and GraphQL methods return this structure.
const result = await client.getTransaction({ digest, include: { effects: true } });
const tx = result.Transaction ?? result.FailedTransaction;

if (tx.effects.status.success) {
	// Transaction succeeded
} else {
	const error = tx.effects.status.error;
}

Object BCS schema changes

Several changes to object BCS schemas:

// Renamed Owner enum variant
const owner = {
-  ConsensusV2: { owner: addr, startVersion: 1 }
+  ConsensusAddressOwner: { startVersion: 1, owner: addr }
};

// Renamed Data enum variant
const data = {
-  MoveObject: { ... }
+  Move: { ... }
};

// Renamed exported schema
- import { ObjectBcs } from '@mysten/sui/bcs';
+ import { bcs } from '@mysten/sui/bcs';
- const bytes = ObjectBcs.serialize(obj);
+ const bytes = bcs.Object.serialize(obj);

This affects serialization. Any existing serialized data with ConsensusV2 will need to be re-serialized with the new ConsensusAddressOwner variant.

UnchangedSharedKind to UnchangedConsensusKind

Transaction effects field renamed:

// Field name change
- effects.unchangedSharedObjects
+ effects.unchangedConsensusObjects

Removed variants: MutateDeleted, ReadDeleted

New variants: MutateConsensusStreamEnded, ReadConsensusStreamEnded, Cancelled, PerEpochConfig

Experimental client API stabilization

The experimental client API has been stabilized and moved from @mysten/sui/experimental to @mysten/sui/client. All Experimental_ prefixes have been removed.

Breaking changes:

  • The @mysten/sui/experimental module has been removed
  • All Experimental_ prefixed types and classes have been renamed
  • Client types namespace changed from Experimental_SuiClientTypes to SuiClientTypes

Migration:

- import {
-   Experimental_BaseClient,
-   Experimental_CoreClient,
-   type Experimental_SuiClientTypes,
-   type Experimental_CoreClientOptions,
- } from '@mysten/sui/experimental';
+ import {
+   BaseClient,
+   CoreClient,
+   type SuiClientTypes,
+   type CoreClientOptions,
+ } from '@mysten/sui/client';

// Update class extensions
- class MyClient extends Experimental_CoreClient {
+ class MyClient extends CoreClient {
    async getObjects(
-     options: Experimental_SuiClientTypes.GetObjectsOptions,
-   ): Promise<Experimental_SuiClientTypes.GetObjectsResponse> {
+     options: SuiClientTypes.GetObjectsOptions,
+   ): Promise<SuiClientTypes.GetObjectsResponse> {
      // ...
    }
  }

Common renames:

Old NameNew Name
Experimental_BaseClientBaseClient
Experimental_CoreClientCoreClient
Experimental_SuiClientTypesSuiClientTypes
Experimental_CoreClientOptionsCoreClientOptions

Commands renamed to TransactionCommands

The Commands type exported from @mysten/sui/transactions has been renamed to TransactionCommands because Commands is a reserved keyword in React Native.

- import { Commands } from '@mysten/sui/transactions';
+ import { TransactionCommands } from '@mysten/sui/transactions';

- const coin = tx.add(Commands.SplitCoins(tx.gas, [tx.pure.u64(100)]));
+ const coin = tx.add(TransactionCommands.SplitCoins(tx.gas, [tx.pure.u64(100)]));

- tx.add(Commands.TransferObjects([coin], recipient));
+ tx.add(TransactionCommands.TransferObjects([coin], recipient));

GraphQL schema consolidation

The SDK now exports a single unified GraphQL schema instead of multiple versioned schemas.

Removed exports:

  • @mysten/sui/graphql/schemas/2024.1
  • @mysten/sui/graphql/schemas/2024.4
  • @mysten/sui/graphql/schemas/latest

Migration:

- import { graphql } from '@mysten/sui/graphql/schemas/latest';
- import { graphql } from '@mysten/sui/graphql/schemas/2024.4';
- import { graphql } from '@mysten/sui/graphql/schemas/2024.1';
+ import { graphql } from '@mysten/sui/graphql/schema';

Named packages plugin removed

The namedPackagesPlugin and global plugin registry APIs have been removed. MVR (Move Registry) resolution is now built directly into the core client.

Removed:

  • namedPackagesPlugin function
  • NamedPackagesPluginOptions type (from @mysten/sui/transactions)
  • Transaction.registerGlobalSerializationPlugin() static method
  • Transaction.unregisterGlobalSerializationPlugin() static method
  • Transaction.registerGlobalBuildPlugin() static method
  • Transaction.unregisterGlobalBuildPlugin() static method

How it works now:

MVR name resolution happens automatically during transaction building. The SDK detects .move names like @org/package::module::Type and resolves them using the client's MVR resolver.

Migration:

- import { Transaction, namedPackagesPlugin } from '@mysten/sui/transactions';
-
- Transaction.registerGlobalSerializationPlugin(
-   'namedPackages',
-   namedPackagesPlugin({
-     url: 'https://mainnet.mvr.mystenlabs.com',
-     overrides: myOverrides,
-   })
- );

+ import { SuiGrpcClient } from '@mysten/sui/grpc';
+
+ const client = new SuiGrpcClient({
+   baseUrl: 'https://fullnode.mainnet.sui.io:443',
+   network: 'mainnet',
+   mvr: {
+     overrides: myOverrides,
+   },
+ });

Transaction executors now accept any client

The transaction executor classes now accept any client implementing ClientWithCoreApi instead of requiring SuiJsonRpcClient specifically.

Affected classes:

  • CachingTransactionExecutor
  • SerialTransactionExecutor
  • ParallelTransactionExecutor

Breaking changes:

  • Constructor client parameter type changed from SuiJsonRpcClient to ClientWithCoreApi
  • Return type of executeTransaction() changed from the legacy { digest, effects, data } wrapper to a Core API TransactionResult discriminated union returned directly
  • The second parameter changed from JSON-RPC options to core API include options

Migration:

import { SerialTransactionExecutor } from '@mysten/sui/transactions';
- import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
+ import { SuiGrpcClient } from '@mysten/sui/grpc';

+ const client = new SuiGrpcClient({
+   baseUrl: 'https://fullnode.devnet.sui.io:443',
+   network: 'devnet',
+ });

const executor = new SerialTransactionExecutor({
-   client: jsonRpcClient,
+   client, // Any ClientWithCoreApi-compatible client
    signer,
});

const result = await executor.executeTransaction(tx);

// Accessing the transaction result now returned directly
- console.log(result.data.effects?.status.status);
+ const transaction = result.Transaction ?? result.FailedTransaction;
+ console.log(transaction.effects.status.success);

Include options have also changed:

- const result = await executor.executeTransaction(tx, {
-   showEffects: true,
-   showEvents: true,
- });
+ const result = await executor.executeTransaction(tx, {
+   effects: true,
+   events: true,
+ });

zkLogin changes

legacyAddress parameter required

The legacyAddress parameter is now required for all zkLogin address computation functions.

Migration (to preserve existing behavior):

// computeZkLoginAddressFromSeed (previous default: true)
- computeZkLoginAddressFromSeed(seed, iss)
+ computeZkLoginAddressFromSeed(seed, iss, true)

// jwtToAddress (previous default: false)
- jwtToAddress(jwt, userSalt)
+ jwtToAddress(jwt, userSalt, false)

// computeZkLoginAddress (previous default: false)
- computeZkLoginAddress({ claimName, claimValue, iss, aud, userSalt })
+ computeZkLoginAddress({ claimName, claimValue, iss, aud, userSalt, legacyAddress: false })

// toZkLoginPublicIdentifier (no previous default)
- toZkLoginPublicIdentifier(addressSeed, iss)
+ toZkLoginPublicIdentifier(addressSeed, iss, { legacyAddress: false })

Default transaction expiration

Transactions now default the expiration to the current epoch + 1 using ValidDuring when built with a client. This provides replay protection for all transactions without requiring explicit configuration.

To preserve the old behavior (no expiration), explicitly set the expiration to None:

const tx = new Transaction();
tx.setExpiration({ None: true });

On this page