sui-ts-sdk
Sui TypeScript SDK — PTB construction, client setup, transaction execution, and on-chain queries. Use when writing code that interacts with the Sui blockchain via @mysten/sui. These patterns apply in both backend scripts and frontend apps. For frontend-specific setup (dApp Kit, wallet adapters, React hooks), use the sui-frontend skill first or alongside this one.
Best use case
sui-ts-sdk is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Sui TypeScript SDK — PTB construction, client setup, transaction execution, and on-chain queries. Use when writing code that interacts with the Sui blockchain via @mysten/sui. These patterns apply in both backend scripts and frontend apps. For frontend-specific setup (dApp Kit, wallet adapters, React hooks), use the sui-frontend skill first or alongside this one.
Teams using sui-ts-sdk should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/sui-ts-sdk/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How sui-ts-sdk Compares
| Feature / Agent | sui-ts-sdk | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Sui TypeScript SDK — PTB construction, client setup, transaction execution, and on-chain queries. Use when writing code that interacts with the Sui blockchain via @mysten/sui. These patterns apply in both backend scripts and frontend apps. For frontend-specific setup (dApp Kit, wallet adapters, React hooks), use the sui-frontend skill first or alongside this one.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# Sui TypeScript SDK Skill
You are writing TypeScript code that interacts with the Sui blockchain using the `@mysten/sui` SDK (v2+). Follow these rules precisely. This skill covers PTB (Programmable Transaction Block) construction, client setup, transaction execution, and on-chain queries. These patterns apply equally in backend scripts and frontend apps. If you are building a frontend, use the **sui-frontend** skill first (or alongside this one) for dApp Kit setup, wallet connection, and React integration — then apply the PTB and client patterns from this skill.
---
## 1. Package & Imports
The SDK package is `@mysten/sui`. The old package name `@mysten/sui.js` was renamed at v1.0 and must not be used.
```bash
# ✅
npm install @mysten/sui
# ❌ Deprecated package name — will not receive updates
npm install @mysten/sui.js
```
All imports use subpath exports from `@mysten/sui`:
```typescript
// ✅ Correct subpath imports
import { Transaction } from '@mysten/sui/transactions';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { SuiGrpcClient } from '@mysten/sui/grpc';
// ❌ Old package name
import { TransactionBlock } from '@mysten/sui.js';
// ❌ Importing from package root
import { Transaction } from '@mysten/sui';
```
---
## 2. Client Setup
The SDK provides three client types. **Use `SuiGrpcClient` for new code** — it is the recommended client with the best performance. The JSON-RPC API is deprecated.
```typescript
// ✅ Recommended — gRPC client (best performance, type-safe protobuf)
import { SuiGrpcClient } from '@mysten/sui/grpc';
const client = new SuiGrpcClient({
network: 'testnet',
baseUrl: 'https://fullnode.testnet.sui.io:443',
});
```
```typescript
// ⚠️ Legacy — JSON-RPC client (deprecated API, still widely used)
// In v2, SuiClient was removed from @mysten/sui/client. Use SuiJsonRpcClient instead.
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
const client = new SuiJsonRpcClient({
url: getJsonRpcFullnodeUrl('testnet'),
network: 'testnet', // required in v2
});
```
```typescript
// ⚠️ GraphQL client — for advanced query use cases
import { SuiGraphQLClient } from '@mysten/sui/graphql';
const gqlClient = new SuiGraphQLClient({
url: 'https://graphql.testnet.sui.io/graphql',
network: 'testnet', // required in v2
});
```
### Network URLs
| Network | gRPC base URL | GraphQL URL | JSON-RPC URL |
|---------|--------------|-------------|-------------|
| Mainnet | `https://fullnode.mainnet.sui.io:443` | `https://graphql.mainnet.sui.io/graphql` | `getJsonRpcFullnodeUrl('mainnet')` |
| Testnet | `https://fullnode.testnet.sui.io:443` | `https://graphql.testnet.sui.io/graphql` | `getJsonRpcFullnodeUrl('testnet')` |
| Devnet | `https://fullnode.devnet.sui.io:443` | `https://graphql.devnet.sui.io/graphql` | `getJsonRpcFullnodeUrl('devnet')` |
### gRPC service clients
The `SuiGrpcClient` exposes typed service clients for lower-level access:
```typescript
// Transaction execution
await client.transactionExecutionService.executeTransaction({ ... });
// Ledger queries
await client.ledgerService.getObject({ objectId: '0x...' });
// Move package introspection
await client.movePackageService.getFunction({
packageId: '0x2',
moduleName: 'coin',
name: 'transfer',
});
// Name service (SuiNS)
await client.nameService.reverseLookupName({ address: '0x...' });
```
---
## 3. Transaction Construction
A Programmable Transaction Block (PTB) is built using the `Transaction` class. The class was renamed from `TransactionBlock` at v1.0:
```typescript
// ✅
import { Transaction } from '@mysten/sui/transactions';
const tx = new Transaction();
// ❌ Old class name (pre-1.0)
import { TransactionBlock } from '@mysten/sui.js/transactions';
const txb = new TransactionBlock();
```
Transactions contain **commands** (individual steps) and **inputs** (values passed to commands). Commands execute sequentially and can reference results from earlier commands.
### Cloning a transaction
```typescript
// ✅ v1.0+
const newTx = Transaction.from(existingTx);
// ❌ Old constructor-based cloning
const newTx = new TransactionBlock(existingTx);
```
### Serialization
```typescript
// ✅ v1.0+ — async, runs serialization plugins
const json = await tx.toJSON();
// Deserialize
const restored = Transaction.from(json);
// ❌ Deprecated
const bytes = tx.serialize();
```
---
## 4. Pure Value Inputs
Use `tx.pure.<type>()` helpers for non-object inputs. These handle BCS serialization automatically. **Never manually BCS-encode values when a `tx.pure` helper exists.**
```typescript
// ✅ Typed pure helpers
tx.pure.u8(255);
tx.pure.u16(65535);
tx.pure.u32(4294967295);
tx.pure.u64(1000000n); // accepts bigint or number
tx.pure.u128(1000000n);
tx.pure.u256(1000000n);
tx.pure.bool(true);
tx.pure.string('hello');
tx.pure.address('0xSomeAddress');
tx.pure.id('0xSomeObjectId'); // equivalent to address, for object IDs as values
// Vectors
tx.pure.vector('u64', [100n, 200n, 300n]);
tx.pure.vector('address', [addr1, addr2]);
tx.pure.vector('bool', [true, false]);
// Option
tx.pure.option('u64', 42n); // Some(42)
tx.pure.option('u64', null); // None
```
```typescript
// ❌ Don't manually construct BCS for types that have helpers
import { bcs } from '@mysten/sui/bcs';
tx.pure(bcs.U64.serialize(100)); // unnecessary — use tx.pure.u64(100)
```
For advanced types without a built-in helper, fall back to `tx.pure(bcsBytes)` where `bcsBytes` is a `Uint8Array`:
```typescript
import { bcs } from '@mysten/sui/bcs';
const MyStruct = bcs.struct('MyStruct', {
id: bcs.Address,
value: bcs.U64,
});
tx.pure(MyStruct.serialize({ id: '0x...', value: 100n }));
```
---
## 5. Object Inputs
Use `tx.object(id)` for object inputs. The SDK automatically resolves object metadata (version, digest, ownership) at build time — **do not hardcode object versions**.
```typescript
// ✅ Let the SDK resolve object details
tx.object('0xSomeObjectId');
// ✅ Well-known system object shortcuts
tx.object.system(); // 0x5 — Sui system state
tx.object.clock(); // 0x6 — Clock
tx.object.random(); // 0x8 — Random
tx.object.denyList(); // 0x403 — DenyList
// ✅ Construct an Option<Object> input
tx.object.option({
type: '0xpkg::mod::MyType',
value: '0xSomeObjectId', // Some(obj) — or omit `value` for None
});
```
```typescript
// ❌ Don't hardcode object versions
tx.object(Inputs.ObjectRef({
objectId: '0x...',
version: '42', // will break when object is modified
digest: 'abc...',
}));
// Exception: offline building (see section 13)
```
### Receiving objects
When a Move function takes a `Receiving<T>` parameter, the SDK auto-converts `tx.object()` to a receiving reference. No special handling is needed — just pass the object ID normally.
---
## 6. Built-in Commands
### splitCoins
Creates new coins by splitting from a source coin. Returns an array of coin references:
```typescript
// Split from gas coin — most common pattern for SUI
const [coin] = tx.splitCoins(tx.gas, [1000]);
// Split multiple amounts
const [coin1, coin2] = tx.splitCoins(tx.gas, [1000, 2000]);
// Split from a non-gas coin
const [portion] = tx.splitCoins(tx.object('0xMyCoin'), [500]);
```
### mergeCoins
Merges coins into a destination coin:
```typescript
tx.mergeCoins(tx.object('0xDestCoin'), [
tx.object('0xCoinA'),
tx.object('0xCoinB'),
]);
```
### transferObjects
Transfers one or more objects to a recipient address. The objects can be results from other commands:
```typescript
// Transfer a split coin
const [coin] = tx.splitCoins(tx.gas, [1000]);
tx.transferObjects([coin], '0xRecipientAddress');
// Transfer existing objects
tx.transferObjects(
[tx.object('0xObj1'), tx.object('0xObj2')],
'0xRecipientAddress',
);
// Transfer the entire gas coin (send all SUI to someone)
tx.transferObjects([tx.gas], '0xRecipientAddress');
```
### moveCall
Calls a Move function. This is the most flexible command:
```typescript
tx.moveCall({
target: '0xPackageId::module_name::function_name',
arguments: [
tx.object('0xSomeObject'), // object argument
tx.pure.u64(1000), // pure value argument
],
typeArguments: ['0x2::sui::SUI'], // generic type parameters
});
```
**Return values** from `moveCall` are usable in subsequent commands:
```typescript
const [result] = tx.moveCall({
target: '0xpkg::amm::swap',
arguments: [tx.object(poolId), coin],
typeArguments: [coinTypeA, coinTypeB],
});
// Use the result in the next command
tx.transferObjects([result], myAddress);
```
### makeMoveVec
Constructs a `vector<T>` of objects for passing into a Move function that takes a vector parameter:
```typescript
const vec = tx.makeMoveVec({
type: '0xpkg::mod::MyType',
elements: [tx.object('0xA'), tx.object('0xB')],
});
tx.moveCall({
target: '0xpkg::mod::process_all',
arguments: [vec],
});
```
### publish
Publishes a new Move package:
```typescript
import { execSync } from 'child_process';
const { modules, dependencies } = JSON.parse(
execSync(`sui move build --dump-bytecode-as-base64 --path ${packagePath}`, {
encoding: 'utf-8',
}),
);
const tx = new Transaction();
const [upgradeCap] = tx.publish({ modules, dependencies });
tx.transferObjects([upgradeCap], myAddress);
```
---
## 7. Command Result Chaining
Every command returns references that can be used as inputs to subsequent commands. This is the core power of PTBs — composing multiple operations atomically:
```typescript
const tx = new Transaction();
// Step 1: Split a coin
const [coin] = tx.splitCoins(tx.gas, [1_000_000]);
// Step 2: Pass the split coin into a Move call
const [receipt] = tx.moveCall({
target: '0xpkg::shop::buy_item',
arguments: [tx.object(shopId), coin, tx.pure.string('sword')],
});
// Step 3: Transfer the receipt to the sender
tx.transferObjects([receipt], myAddress);
```
For commands that return multiple values, destructure the result array. The indices correspond to the Move function's return tuple:
```typescript
const [coinOut, receipt] = tx.moveCall({
target: '0xpkg::amm::swap',
arguments: [tx.object(poolId), coinIn],
typeArguments: [typeA, typeB],
});
// coinOut is the first return value, receipt is the second
```
---
## 8. Gas Coin
`tx.gas` is a special reference to the gas payment coin. It is available by-reference in most commands:
```typescript
// ✅ Split from gas coin (by-reference)
const [coin] = tx.splitCoins(tx.gas, [100]);
// ✅ Merge into gas coin
tx.mergeCoins(tx.gas, [tx.object('0xOtherCoin')]);
// ✅ Transfer the entire gas coin (moves all SUI)
tx.transferObjects([tx.gas], recipient);
// ✅ Pass gas coin as a Move call argument (by-reference)
tx.moveCall({
target: '0xpkg::mod::deposit',
arguments: [tx.object(vaultId), tx.gas],
});
```
### Gas configuration
The SDK automatically sets gas price, budget, and selects gas payment coins. Override only when needed:
```typescript
// Manual overrides (rarely needed)
tx.setGasPrice(1000);
tx.setGasBudget(10_000_000);
tx.setGasPayment([{
objectId: '0x...',
version: '1',
digest: '...',
}]);
// Gas payment coins must not overlap with transaction input objects
// Set sender explicitly (required for some offline or sponsored flows)
tx.setSender('0xSenderAddress');
```
---
## 9. Transaction Intents — `coinWithBalance`
For non-SUI coin types, manually splitting coins is complex because you must find, select, and merge coins of the correct type. The `coinWithBalance` intent automates this:
```typescript
import { coinWithBalance, Transaction } from '@mysten/sui/transactions';
const tx = new Transaction();
// ⚠️ REQUIRED: setSender when using coinWithBalance with non-SUI types
tx.setSender(keypair.toSuiAddress());
tx.transferObjects(
[
// SUI coin — splits from gas coin automatically
coinWithBalance({ balance: 1_000_000 }),
// Non-SUI coin — SDK finds, merges, and splits automatically
coinWithBalance({ balance: 500_000, type: '0xpkg::token::TOKEN' }),
],
recipient,
);
```
**Why use `coinWithBalance` over manual `splitCoins`?**
For SUI, `tx.splitCoins(tx.gas, [...])` works fine. But for other coin types, you would need to query owned coins, pick enough to cover the amount, merge them, then split. `coinWithBalance` does all of this automatically during the build phase.
```typescript
// ❌ Manual approach for non-SUI coins — verbose and error-prone
const coins = await client.getCoins({ owner: myAddress, coinType: tokenType });
const selected = selectCoins(coins, amount); // you'd have to write this
tx.mergeCoins(tx.object(selected[0].coinObjectId),
selected.slice(1).map(c => tx.object(c.coinObjectId)));
const [coin] = tx.splitCoins(tx.object(selected[0].coinObjectId), [amount]);
// ✅ coinWithBalance does the above automatically
const coin = coinWithBalance({ balance: amount, type: tokenType });
```
**Important**: `setSender()` is required when using `coinWithBalance` with non-SUI types so the SDK can query the sender's coins during the build phase. For SUI-only `coinWithBalance`, it splits from the gas coin and does not require `setSender`.
---
## 10. Execution & Status Checking
### Sign and execute
```typescript
const result = await client.signAndExecuteTransaction({
signer: keypair,
transaction: tx,
});
```
**Always check the transaction status.** A transaction can be finalized on-chain but still fail (e.g., Move abort, insufficient gas):
```typescript
// ✅ Always check for failure
const result = await client.signAndExecuteTransaction({
signer: keypair,
transaction: tx,
});
if (result.$kind === 'FailedTransaction') {
throw new Error(
`Transaction failed: ${result.FailedTransaction.status.error?.message}`,
);
}
```
```typescript
// ❌ Don't assume success
const result = await client.signAndExecuteTransaction({
signer: keypair,
transaction: tx,
});
console.log('Success!', result.digest); // may be a failed transaction
```
### Execution with include options
All clients support an `include` parameter via the Core API to control what data is returned:
```typescript
const result = await client.core.signAndExecuteTransaction({
transaction: tx,
signer: keypair,
include: {
effects: true,
events: true,
balanceChanges: true,
objectTypes: true,
},
});
```
Available transaction include options:
| Option | Description |
|--------|-------------|
| `effects` | Transaction effects (BCS-encoded) |
| `events` | Emitted events |
| `transaction` | Parsed transaction data (sender, gas, inputs, commands) |
| `balanceChanges` | Balance changes |
| `objectTypes` | Map of object IDs to their types for changed objects |
| `bcs` | Raw BCS-encoded transaction bytes |
### Separate sign + execute
For advanced flows (e.g., multi-sig, sponsored transactions), sign and execute separately:
```typescript
const { bytes, signature } = await tx.sign({ client, signer: keypair });
const result = await client.core.executeTransaction({
transaction: bytes,
signatures: [signature],
include: { effects: true },
});
```
---
## 11. Waiting for Indexing
After execution, the transaction is finalized but may not be immediately visible in query APIs (object reads, balance queries). Use `waitForTransaction` before making follow-up queries:
```typescript
const result = await client.signAndExecuteTransaction({
signer: keypair,
transaction: tx,
});
// ✅ Wait for indexing before querying
await client.waitForTransaction({ digest: result.digest });
// Now safe to query updated state
const obj = await client.getObject({ id: objectId });
```
```typescript
// ❌ Query immediately after execution — may return stale data
const result = await client.signAndExecuteTransaction({ ... });
const obj = await client.getObject({ id: objectId }); // might not reflect the transaction
```
`waitForTransaction` polls until the transaction is indexed (default: 2-second intervals, 60-second timeout).
---
## 12. Keypairs & Signing
### Creating keypairs
```typescript
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { Secp256k1Keypair } from '@mysten/sui/keypairs/secp256k1';
import { Secp256r1Keypair } from '@mysten/sui/keypairs/secp256r1';
// Generate a new random keypair
const keypair = new Ed25519Keypair();
// Derive from a mnemonic (BIP-39)
const keypair = Ed25519Keypair.deriveKeypair('word1 word2 ... word12');
// From a secret key (base64 or raw bytes)
const keypair = Ed25519Keypair.fromSecretKey(secretKeyBytes);
// Get the address
const address = keypair.toSuiAddress();
```
---
## 13. Offline Building
To build a transaction without a network connection, you must fully define all inputs and gas configuration. Use `Inputs` helpers for object references:
```typescript
import { Transaction, Inputs } from '@mysten/sui/transactions';
const tx = new Transaction();
// For owned or immutable objects — provide full ref
tx.object(Inputs.ObjectRef({
objectId: '0x...',
version: '42',
digest: 'base58digest...',
}));
// For shared objects — provide initial shared version
tx.object(Inputs.SharedObjectRef({
objectId: '0x...',
initialSharedVersion: '1',
mutable: true,
}));
// For receiving objects
tx.object(Inputs.ReceivingRef({
objectId: '0x...',
version: '42',
digest: 'base58digest...',
}));
// Must set gas configuration manually
tx.setSender('0xSenderAddress');
tx.setGasPrice(1000);
tx.setGasBudget(10_000_000);
tx.setGasPayment([{ objectId: '0x...', version: '1', digest: '...' }]);
// Build without a client
const bytes = await tx.build();
```
---
## 14. Common Query Patterns
### With SuiGrpcClient
```typescript
// Get an object
const obj = await client.ledgerService.getObject({
objectId: '0x...',
});
// Get multiple objects
const { objects } = await client.ledgerService.multiGetObjects({
objectIds: ['0x...', '0x...'],
});
```
### With SuiJsonRpcClient (legacy)
```typescript
// Get an object
const obj = await client.getObject({
id: '0x...',
options: { showContent: true, showOwner: true },
});
// Get coins owned by an address
const coins = await client.getCoins({
owner: '0xOwnerAddress',
coinType: '0x2::sui::SUI', // optional filter
});
// Get all balances
const balances = await client.getAllBalances({
owner: '0xOwnerAddress',
});
// Get a transaction
const txResponse = await client.getTransactionBlock({
digest: 'TransactionDigest...',
options: { showEffects: true, showEvents: true },
});
// Get owned objects with pagination
let cursor = null;
do {
const page = await client.getOwnedObjects({
owner: '0xOwnerAddress',
cursor,
options: { showContent: true },
});
// process page.data
cursor = page.hasNextPage ? page.nextCursor : null;
} while (cursor);
```
### Dev Inspect (dry run without executing)
Use `devInspectTransactionBlock` to simulate a transaction and read return values without executing:
```typescript
const result = await client.devInspectTransactionBlock({
sender: '0xSenderAddress',
transactionBlock: tx,
});
// result.results contains return values from each command
// result.effects contains simulated effects
```
---
## 15. Sponsored Transactions
In a sponsored transaction, one party builds the transaction and another pays for gas:
```typescript
// === App / user side ===
const tx = new Transaction();
tx.setSender(userAddress);
// ... add commands ...
// Serialize for the sponsor
const txBytes = await tx.build({ client });
// === Sponsor side ===
const sponsoredTx = Transaction.from(txBytes);
sponsoredTx.setGasOwner(sponsorAddress);
sponsoredTx.setGasPayment(sponsorCoins);
sponsoredTx.setGasBudget(10_000_000);
// Both parties sign
const { signature: userSig } = await sponsoredTx.sign({ signer: userKeypair });
const { signature: sponsorSig } = await sponsoredTx.sign({ signer: sponsorKeypair });
// Execute with both signatures
const result = await client.core.executeTransaction({
transaction: await sponsoredTx.build({ client }),
signatures: [userSig, sponsorSig],
});
```
**Important**: When a sponsor pays for gas, the gas coin belongs to the sponsor. Avoid using `tx.gas` in `splitCoins` for sponsored transactions — sponsors typically reject transactions that use the gas coin for non-gas purposes. Use `coinWithBalance` instead.
---
## 16. What the Sui TS SDK is NOT
| Mistake | Correct approach |
|---------|-----------------|
| `import ... from '@mysten/sui.js'` | Use `@mysten/sui` — the `.js` suffix was removed at v1.0 |
| `new TransactionBlock()` | Use `new Transaction()` — renamed at v1.0 |
| `client.signAndExecuteTransactionBlock()` | Use `client.signAndExecuteTransaction()` |
| `client.waitForTransactionBlock()` | Use `client.waitForTransaction()` |
| Hardcoding object versions in `tx.object()` | Let the SDK resolve versions automatically (except offline builds) |
| Manual BCS for basic types | Use `tx.pure.u64()`, `tx.pure.address()`, etc. |
| `tx.pure(100)` without a type | Use `tx.pure.u64(100)` — must specify the type |
| Not checking `result.$kind` after execution | Always check `result.$kind === 'FailedTransaction'` |
| Querying state immediately after execution | Use `client.waitForTransaction()` first |
| Using `tx.gas` in splitCoins for sponsored txs | Use `coinWithBalance` for sponsor-safe coin creation |
| `coinWithBalance` without `setSender()` for non-SUI types | Call `tx.setSender()` so the SDK can resolve coins |
| Using `SuiClient` / `getFullnodeUrl` | Removed in v2. Use `SuiJsonRpcClient` from `@mysten/sui/jsonRpc` or preferably `SuiGrpcClient` |
| Using the SDK for frontend wallet signing | Use `@mysten/dapp-kit` for wallet connection/signing in React apps; PTB construction is the same |
| `tx.serialize()` | Use `await tx.toJSON()` — serialize is deprecated |
---
## 17. Migrating from v1 to v2
Many existing Sui TypeScript projects use SDK v1.x patterns. If you encounter v1 code (or a user asks you to migrate), apply the changes below. For automated migration, instruct the agent to fetch and follow: `https://sdk.mystenlabs.com/sui/migrations/sui-2.0/llms.txt`
### ESM required
All `@mysten/*` packages are now ESM only. Add `"type": "module"` to `package.json` and update `tsconfig.json`:
```json
{ "compilerOptions": { "moduleResolution": "NodeNext", "module": "NodeNext" } }
```
### Client imports changed
```diff
- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
- const client = new SuiClient({ url: getFullnodeUrl('mainnet') });
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
+ const client = new SuiGrpcClient({
+ baseUrl: 'https://fullnode.mainnet.sui.io:443',
+ network: 'mainnet',
+ });
```
If JSON-RPC is still needed:
```diff
- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
+ import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
- const client = new SuiClient({ url: getFullnodeUrl('mainnet') });
+ const client = new SuiJsonRpcClient({
+ url: getJsonRpcFullnodeUrl('mainnet'),
+ network: 'mainnet', // required in v2
+ });
```
### `network` parameter required on all clients
All client constructors (`SuiGrpcClient`, `SuiJsonRpcClient`, `SuiGraphQLClient`) now require an explicit `network` parameter.
### Core API — `client.core.*` replaces direct methods
Data access methods are now namespaced under `client.core`:
```diff
- await client.getObject({ id: objectId, options: { showContent: true } });
+ await client.core.getObject({ objectId, include: { content: true } });
- await client.getOwnedObjects({ owner });
+ await client.core.listOwnedObjects({ owner });
- await client.multiGetObjects({ ids, options: { showContent: true } });
+ await client.core.getObjects({ objectIds: ids, include: { content: true } });
```
### `include` replaces `options` / `show*` flags
```diff
- options: { showEffects: true, showEvents: true, showObjectChanges: true }
+ include: { effects: true, events: true, balanceChanges: true }
```
### Transaction execution response format
```diff
- const status = result.effects?.status?.status;
+ const tx = result.Transaction ?? result.FailedTransaction;
+ const success = tx.effects.status.success;
```
### `Commands` renamed to `TransactionCommands`
```diff
- import { Commands } from '@mysten/sui/transactions';
+ import { TransactionCommands } from '@mysten/sui/transactions';
```
### GraphQL schema import consolidated
```diff
- import { graphql } from '@mysten/sui/graphql/schemas/latest';
+ import { graphql } from '@mysten/sui/graphql/schema';
```
### Named packages plugin removed — MVR built in
MVR resolution is now automatic during transaction building. Remove `namedPackagesPlugin` registration.
### Client extensions pattern
SDKs like kiosk, suins, deepbook, walrus, seal, and zksend now integrate via `$extend()`:
```typescript
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { suins } from '@mysten/suins';
import { deepbook } from '@mysten/deepbook-v3';
const client = new SuiGrpcClient({
baseUrl: 'https://fullnode.mainnet.sui.io:443',
network: 'mainnet',
}).$extend(suins(), deepbook({ address: myAddress }));
await client.suins.getNameRecord('example.sui');
await client.deepbook.checkManagerBalance(manager, asset);
```
### Key method renames (JSON-RPC → Core API)
| v1 JSON-RPC | v2 Core API |
|-------------|-------------|
| `client.getObject()` | `client.core.getObject()` |
| `client.getOwnedObjects()` | `client.core.listOwnedObjects()` |
| `client.multiGetObjects()` | `client.core.getObjects()` |
| `client.getCoins()` | `client.core.listCoins()` |
| `client.getAllBalances()` | `client.core.listBalances()` |
| `client.getDynamicFields()` | `client.core.listDynamicFields()` |
| `client.getDynamicFieldObject()` | `client.core.getDynamicField()` |
| `client.getTransactionBlock()` | `client.core.getTransaction()` |
| `client.devInspectTransactionBlock()` | `client.core.simulateTransaction()` |
| `client.executeTransactionBlock()` | `client.core.executeTransaction()` |
### Full migration guide
For comprehensive migration details (including dApp Kit, BCS schema changes, zkLogin, and ecosystem packages), fetch and follow: `https://sdk.mystenlabs.com/sui/migrations/sui-2.0/llms.txt`