Mysten Labs SDKs
Migrations

Migrate to version 2.0

Migrating to @mysten/sui@2.0

BCS Schema Changes

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

ExecutionStatus: Failed → Failure

The transaction execution status variant has been renamed from Failed to Failure:

// Before
if (effects.status.$kind === 'Success') {
  // success
} else {
-  const error = effects.status.Failed.error;
+  const error = effects.status.Failure.error;
}

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

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);

UnchangedSharedKind → UnchangedConsensusKind

Transaction effects field renamed:

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

// Removed obsolete variants: MutateDeleted, ReadDeleted
// New variants added: MutateConsensusStreamEnded, ReadConsensusStreamEnded, Cancelled, PerEpochConfig

ZkLogin legacyAddress parameter is now required

The legacyAddress parameter is now required for all zkLogin address computation functions. In v1.x, this parameter had default values that varied by function, which could lead to confusion. You must now explicitly specify whether you want to use legacy address encoding.

Update all calls to zkLogin functions to include the legacyAddress parameter. To preserve existing behavior, use the following migrations:

// 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, was optional)
- toZkLoginPublicIdentifier(addressSeed, iss)
+ toZkLoginPublicIdentifier(addressSeed, iss, { legacyAddress: false })

ZkLogin Signature verification

In previous versions of the SDK, methods that verified ZkLogin signatures created a GraphQL client that used the GraphQL alpha to verify mainnet ZkLogin signatures. This default is being removed, as it was dependent on the GraphQL alpha endpoint, which is no longer available, and did not work for non-mainnet signatures.

You will now need to pass a client (GraphQL, GRPC, or JSON RPC) to any methods that verify ZkLogin signatures.

const client: SuiGraphQLClient | SuiGrpcClient | SuiJsonRpcClient;

verifyPersonalMessageSignature(message, signature, { client });
verifyTransactionSignature(txBytes, signature, { client });
parseSignature(signatureBytes, { client });

// For ZkLoginPublicIdentifier, the client is passed in when it it created
zkLoginPublicIdentifier = toZkLoginPublicIdentifier(seed, iss, { client, legacyAddress: false });
zkLoginPublicIdentifier.verifyPersonalMessage(message, signature);
zkLoginPublicIdentifier.verifyTransaction(transaction, signature);

Network is now required for GraphQL and JSON RPC clients

When creating a new SuiGraphQLClient or SuiJsonRpcClient, you must now provide a network parameter.

const client = new SuiGraphQLClient({
	url: 'https://...',
	network: 'mainnet', // or 'testnet', 'devnet', etc.
});
const client = new SuiJsonRpcClient({
	url: 'https://...',
	network: 'mainnet', // or 'testnet', 'devnet', etc.
});

Removal of SuiClient exports from @mysten/sui/client

The @mysten/sui/client export path has been removed. All JSON-RPC client functionality is now exported from @mysten/sui/jsonRpc.

The following exports have been removed from @mysten/sui/client:

  • SuiClient (use SuiJsonRpcClient instead)
  • SuiClientOptions (use SuiJsonRpcClientOptions instead)
  • isSuiClient (use isSuiJsonRpcClient instead)
  • SuiTransport (use JsonRpcTransport instead)
  • SuiTransportRequestOptions (use JsonRpcTransportRequestOptions instead)
  • SuiTransportSubscribeOptions (use JsonRpcTransportSubscribeOptions instead)
  • SuiHTTPTransportOptions (use JsonRpcHTTPTransportOptions instead)
  • SuiHTTPTransport (use JsonRpcHTTPTransport instead)
  • getFullnodeUrl (use getJsonRpcFullnodeUrl instead)
  • All JSON-RPC types (now exported from @mysten/sui/jsonRpc)

Migration:

Update all imports from @mysten/sui/client to @mysten/sui/jsonRpc and rename classes:

- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
+ import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';

- const client = new SuiClient({
-   url: getFullnodeUrl('devnet'),
+ const client = new SuiJsonRpcClient({
+   url: getJsonRpcFullnodeUrl('devnet'),
    network: 'devnet',
  });

Removal of reportTransactionEffects API

The sui:reportTransactionEffects wallet standard feature and associated hooks have been removed from both @mysten/wallet-standard and @mysten/dapp-kit.

The following APIs have been removed:

  • sui:reportTransactionEffects feature from wallet standard
  • useReportTransactionEffects hook from dapp-kit
  • reportTransactionEffects callback from useSignTransaction hook's return value
  • Automatic transaction effects reporting in useSignAndExecuteTransaction

For dApp developers:

If you were using useReportTransactionEffects:

- const { mutateAsync: reportTransactionEffects } = useReportTransactionEffects();
  const { effects } = await executePreSignedTransaction();
- reportTransactionEffects({ effects });

If you were using the reportTransactionEffects callback from useSignTransaction:

const {
	bytes,
	signature,
-	reportTransactionEffects
} = await signTransaction({
	transaction: new Transaction(),
});
const executeResult = await client.executeTransactionBlock({
	transactionBlock: bytes,
	signature,
});
- reportTransactionEffects(executeResult.rawEffects!);

For wallet developers:

Remove the sui:reportTransactionEffects feature implementation from your wallet.

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.

Migration:

- 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));

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 from types and classes.

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:

Update imports and remove Experimental_ prefixes:

- 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

GraphQL Schema Consolidation

The SDK now exports a single unified GraphQL schema instead of multiple versioned schemas. Now that the GraphQL API is more stable, there should always only be a single schema supported by the API.

Breaking changes:

The following versioned schema exports have been removed:

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

Migration:

Replace all versioned schema imports with the new unified schema export:

- 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, eliminating the need for the plugin-based approach.

Breaking changes:

The following have been 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

What's preserved:

  • Instance-level plugin methods (addSerializationPlugin, addBuildPlugin, addIntentResolver) remain available for other use cases like object caching
  • NamedPackagesOverrides type is now exported from @mysten/sui/client

How it works now:

MVR name resolution happens automatically during transaction building. When you build a transaction, the SDK will detect any .move names (like @org/package::module::Type) and resolve them using the client's MVR resolver before building the transaction bytes. No manual plugin registration is required.

Migration:

If you were using the global named packages plugin:

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

+ import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
+ import type { NamedPackagesOverrides } from '@mysten/sui/client';
+
+ // Configure MVR overrides when creating the client
+ const client = new SuiJsonRpcClient({
+   url: 'https://fullnode.mainnet.sui.io:443',
+   network: 'mainnet',
+   mvr: {
+     overrides: myOverrides,
+   },
+ });

If you were using the plugin with @mysten/mvr-static:

- import { Transaction, namedPackagesPlugin } from '@mysten/sui/transactions';
+ import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
+ import type { NamedPackagesOverrides } from '@mysten/sui/client';
  import { getMvrCache } from './mvr.ts';

- // Register plugin globally
- Transaction.registerGlobalSerializationPlugin(
-   'namedPackages',
-   namedPackagesPlugin({
-     url: 'https://mainnet.mvr.mystenlabs.com',
-     overrides: getMvrCache('mainnet'),
-   })
- );

+ // Configure client with MVR overrides
+ const client = new SuiJsonRpcClient({
+   url: 'https://fullnode.mainnet.sui.io:443',
+   network: 'mainnet',
+   mvr: {
+     overrides: getMvrCache('mainnet'),
+   },
+ });

The client will now automatically resolve .move names in transactions using the configured overrides or by querying the MVR API if no override is provided.

On this page