@mysten/sui
Version:
Sui TypeScript API
400 lines (333 loc) • 11.9 kB
Markdown
# Migrating from JSON-RPC
> Migrate from JSON-RPC to the new Core API
This guide covers migrating from `SuiJsonRpcClient` to the new client APIs. The JSON-RPC API is
being deprecated in favor of `SuiGrpcClient` and `SuiGraphQLClient`.
> **Note:** We recommend using `SuiGrpcClient` for most operations and `SuiGraphQLClient` for
> complex queries like filtering transactions and events.
## Choosing a Client
| Client | Best For |
| ------------------ | --------------------------------------------------------------- |
| `SuiGrpcClient` | Most operations, SDK integrations, real-time data |
| `SuiGraphQLClient` | Complex queries, filtering transactions/events, historical data |
## Quick Migration to gRPC
For most use cases, migrate to `SuiGrpcClient`:
```diff
- import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
- const client = new SuiJsonRpcClient({
- url: getJsonRpcFullnodeUrl('mainnet'),
- network: 'mainnet',
- });
+ const client = new SuiGrpcClient({
+ baseUrl: 'https://fullnode.mainnet.sui.io:443',
+ network: 'mainnet',
+ });
```
Both clients use the same full node URLs, so you can use the same endpoint when migrating.
## Core API Methods
The gRPC client should work with almost all mysten SDKs as a drop in replacement for the JSON-RPC
client. When using the client directly, the methods and data returned will not be exactly the same
as what was available in JSON-RPC.
## Methods Replaced by Core API
These JSON-RPC methods have direct replacements in the core API:
| JSON-RPC Method | Core API Replacement |
| ---------------------------- | ------------------------------------------------- |
| `getCoins` | `listCoins` |
| `getAllCoins` | `listOwnedObjects` with `type: '0x2::coin::Coin'` |
| `getAllBalances` | `listBalances` |
| `getOwnedObjects` | `listOwnedObjects` |
| `multiGetObjects` | `getObjects` |
| `getDynamicFields` | `listDynamicFields` |
| `getDynamicFieldObject` | `getDynamicField` |
| `devInspectTransactionBlock` | `simulateTransaction` with `checksEnabled: false` |
| `dryRunTransactionBlock` | `simulateTransaction` |
| `getNormalizedMoveFunction` | `getMoveFunction` |
| `getMoveFunctionArgTypes` | `getMoveFunction` |
### Example: Migrating devInspectTransactionBlock
```diff
- const result = await jsonRpcClient.devInspectTransactionBlock({
- sender: '0xabc...',
- transactionBlock: tx,
- });
- const returnValues = result.results?.[0]?.returnValues;
+ const result = await client.core.simulateTransaction({
+ transaction: tx,
+ checksEnabled: false,
+ include: { commandResults: true },
+ });
+ const returnValues = result.commandResults?.[0]?.returnValues;
```
### Example: Migrating getOwnedObjects
```diff
- const { data } = await jsonRpcClient.getOwnedObjects({
- owner: '0xabc...',
- options: { showContent: true },
- });
+ const { objects } = await grpcClient.listOwnedObjects({
+ owner: '0xabc...',
+ include: { content: true },
+ });
```
## Methods Replaced by gRPC Services
These JSON-RPC methods can be replaced by calling gRPC service clients directly:
| JSON-RPC Method | gRPC Service Replacement |
| ----------------------------------- | --------------------------------- |
| `getCheckpoint` | `ledgerService.getCheckpoint` |
| `getCheckpoints` | `ledgerService.listCheckpoints` |
| `getLatestCheckpointSequenceNumber` | `ledgerService.getCheckpoint` |
| `getEpochs` | `ledgerService.listEpochs` |
| `getCurrentEpoch` | `ledgerService.getEpoch` |
| `getLatestSuiSystemState` | `ledgerService.getSystemState` |
| `getCommitteeInfo` | `ledgerService.getCommittee` |
| `getValidatorsApy` | `ledgerService.getValidators` |
| `getProtocolConfig` | `ledgerService.getProtocolConfig` |
| `getNormalizedMoveModule` | `movePackageService.getModule` |
| `getNormalizedMoveModulesByPackage` | `movePackageService.getPackage` |
| `getNormalizedMoveStruct` | `movePackageService.getStruct` |
| `resolveNameServiceAddress` | `nameService.lookupName` |
| `resolveNameServiceNames` | `nameService.reverseLookupName` |
### Example: Using gRPC Service Clients
```typescript
const client = new SuiGrpcClient({
baseUrl: 'https://fullnode.mainnet.sui.io:443',
network: 'mainnet',
});
// Get checkpoint information
const { response } = await client.ledgerService.getCheckpoint({
sequenceNumber: 12345n,
});
// Get current epoch
const { response: epoch } = await client.ledgerService.getEpoch({});
// Get Move module information
const { response: module } = await client.movePackageService.getModule({
packageId: '0x2',
moduleName: 'coin',
});
// Resolve SuiNS name
const { response: address } = await client.nameService.lookupName({
name: 'example.sui',
});
```
## Methods Requiring GraphQL
Some JSON-RPC methods don't have gRPC equivalents and require using `SuiGraphQLClient` instead:
| JSON-RPC Method | GraphQL Alternative |
| --------------------------- | ---------------------------------- |
| `queryTransactionBlocks` | `transactions` query |
| `multiGetTransactionBlocks` | `multiGetTransactionEffects` query |
| `queryEvents` | `events` query |
| `getCoinMetadata` | `coinMetadata` query |
| `getTotalSupply` | `coinMetadata` query |
| `getStakes` | `address.stakedSuis` query |
| `getStakesByIds` | `multiGetObjects` query |
| `tryGetPastObject` | Historical object queries |
| `getNetworkMetrics` | Use indexer |
| `getAddressMetrics` | Use indexer |
| `getMoveCallMetrics` | Use indexer |
### Setting Up GraphQL Client
```typescript
const graphqlClient = new SuiGraphQLClient({
url: 'https://sui-mainnet.mystenlabs.com/graphql',
network: 'mainnet',
});
```
### Querying Transactions
Replace `queryTransactionBlocks` with a GraphQL query:
```typescript
const result = await graphqlClient.query({
query: `
query QueryTransactions($sender: SuiAddress, $first: Int, $after: String) {
transactions(
first: $first
after: $after
filter: { sentAddress: $sender }
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
digest
effects {
status
epoch { epochId }
}
}
}
}
`,
variables: {
sender: '0xabc...',
first: 10,
},
});
```
**Available transaction filters:**
- `sentAddress` - Filter by sender address
- `affectedAddress` - Filter by any address involved in the transaction
- `affectedObject` - Filter by object ID that was affected
- `function` - Filter by Move function called (e.g., `0x2::coin::transfer`)
- `kind` - Filter by transaction kind (`SYSTEM` or `PROGRAMMABLE`)
- `atCheckpoint` / `beforeCheckpoint` / `afterCheckpoint` - Filter by checkpoint
### Querying Events
Replace `queryEvents` with a GraphQL query:
```typescript
const result = await graphqlClient.query({
query: `
query QueryEvents($type: String, $first: Int, $after: String) {
events(
first: $first
after: $after
filter: { type: $type }
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
transactionModule {
package { address }
name
}
sender { address }
contents {
type { repr }
bcs
}
}
}
}
`,
variables: {
type: '0x2::coin::CoinCreated',
first: 10,
},
});
```
**Available event filters:**
- `type` - Filter by event type (package, package::module, or full type)
- `module` - Filter by emitting module
- `sender` - Filter by transaction sender
- `atCheckpoint` / `beforeCheckpoint` / `afterCheckpoint` - Filter by checkpoint
### Fetching Multiple Transactions
Replace `multiGetTransactionBlocks` with a GraphQL query:
```typescript
const result = await graphqlClient.query({
query: `
query MultiGetTransactions($digests: [String!]!) {
multiGetTransactionEffects(keys: $digests) {
transaction {
digest
transactionBcs
}
status
epoch { epochId }
}
}
`,
variables: {
digests: ['digest1', 'digest2', 'digest3'],
},
});
```
### Querying Historical Objects
Replace `tryGetPastObject` with a GraphQL query specifying a version:
```typescript
const result = await graphqlClient.query({
query: `
query GetObjectAtVersion($id: SuiAddress!, $version: UInt53!) {
object(address: $id, version: $version) {
address
version
digest
asMoveObject {
contents {
type { repr }
bcs
}
}
}
}
`,
variables: {
id: '0x123...',
version: 42,
},
});
```
### Querying Coin Metadata
Replace `getCoinMetadata` and `getTotalSupply` with a GraphQL query:
```typescript
const result = await graphqlClient.query({
query: `
query GetCoinMetadata($coinType: String!) {
coinMetadata(coinType: $coinType) {
name
symbol
description
decimals
iconUrl
supply
}
}
`,
variables: {
coinType: '0x2::sui::SUI',
},
});
```
### Querying Staked SUI
Replace `getStakes` with a GraphQL query:
```typescript
const result = await graphqlClient.query({
query: `
query GetStakes($owner: SuiAddress!) {
address(address: $owner) {
stakedSuis {
nodes {
principal
stakeActivationEpoch
estimatedReward
contents {
bcs
}
}
}
}
}
`,
variables: {
owner: '0xabc...',
},
});
```
## Response Format Differences
The gRPC client uses the core API response format, which differs from JSON-RPC responses. See the
[@mysten/sui migration guide](/sui/migrations/sui-2.0/sui#transaction-executors-now-accept-any-client)
for details on the new response format.
Key differences:
```diff
// Transaction result access
- const status = result.effects?.status?.status;
+ const tx = result.Transaction ?? result.FailedTransaction;
+ const status = tx.effects.status.success;
// Include options
- { showEffects: true, showEvents: true }
+ { effects: true, events: true }
```
## Client Extensions
Client extensions work the same way with both clients:
```typescript
const client = new SuiGrpcClient({
baseUrl: 'https://fullnode.mainnet.sui.io:443',
network: 'mainnet',
}).$extend(deepbook({ address: myAddress }), suins());
// Use extended functionality
await client.deepbook.checkManagerBalance(manager, asset);
await client.suins.getName('0xabc...');
```
## See Also
- [SuiGrpcClient Documentation](/sui/clients/grpc) - Full gRPC client documentation
- [SuiGraphQLClient Documentation](/sui/clients/graphql) - GraphQL client documentation
- [Core API](/sui/clients/core) - Transport-agnostic API methods
- [gRPC Overview](https://docs.sui.io/concepts/data-access/grpc-overview) - Sui gRPC API
documentation