gRPC Migration Cookbook
Each recipe pairs a JSON-RPC call with its gRPC replacement and explains the key differences. For the full method mapping and decision criteria, see the JSON-RPC Migration Guide. For gRPC concepts and setup, see What is gRPC? and Querying Data with gRPC.
JSON-RPC is deprecated. Migrate to either gRPC or GraphQL RPC before the week of July 27, 2026, when JSON-RPC is disabled on Sui Foundation mainnet full nodes. Full decommission, including code removal, is planned for mid-October 2026. For a method mapping, decision criteria, and the full timeline, see the JSON-RPC Migration Guide.
Refer to the list of RPC or data providers that have enabled gRPC on their full nodes or offer GraphQL RPC. Contact a provider directly to request access. If your RPC or data provider doesn’t yet support these data access methods, ask them to enable support or contact the Sui Foundation team on Discord, Telegram, or Slack for help.
Before you start
All gRPC examples use the @mysten/sui TypeScript SDK. Install the SDK with the following command:
$ npm install @mysten/sui
Create a client once and reuse it:
import { SuiGrpcClient } from '@mysten/sui/grpc';
const client = new SuiGrpcClient({
baseUrl: '<FULL_NODE_URL>',
network: 'mainnet',
});
For grpcurl and Buf CLI examples, replace <FULL_NODE_URL> with your provider's gRPC endpoint. See Querying Data with gRPC for setup details and language-specific client instructions for Go and Python.
Get a single object
Replace sui_getObject with LedgerService.GetObject. Use a field mask to request only the fields you need.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getObject",
"params": [
"0xOBJECT_ID",
{ "showContent": true, "showOwner": true }
]
}'
const { object } = await client.core.getObject({
objectId: '0xOBJECT_ID',
include: { content: true },
});
console.log('Owner:', object.owner);
console.log('Type:', object.type);
console.log('Content:', object.content);
$ grpcurl -d '{
"object_id": "0xOBJECT_ID",
"read_mask": { "paths": ["content", "owner"] }
}' <FULL_NODE_URL> sui.rpc.v2.LedgerService/GetObject
The gRPC call differs from the JSON-RPC call in the following ways:
- JSON-RPC uses the
showContentandshowOwnerbooleans. gRPC uses aread_maskwith field paths, or the SDK'sincludeparameter. - The SDK's
getObjectreturns{ object }directly. UsegetObjects(plural) for batch lookups, which returns{ objects: (Object | Error)[] }.
Batch-fetch objects
Replace sui_multiGetObjects with LedgerService.BatchGetObjects. The top-level read_mask applies to all objects in the batch.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_multiGetObjects",
"params": [
["0xOBJECT_A", "0xOBJECT_B", "0xOBJECT_C"],
{ "showContent": true }
]
}'
const { objects } = await client.core.getObjects({
objectIds: ['0xOBJECT_A', '0xOBJECT_B', '0xOBJECT_C'],
include: { content: true },
});
for (const obj of objects) {
if (obj instanceof Error) {
console.error('Failed to fetch:', obj.message);
} else {
console.log(obj.objectId, obj.content);
}
}
$ grpcurl -d '{
"requests": [
{ "object_id": "0xOBJECT_A" },
{ "object_id": "0xOBJECT_B" },
{ "object_id": "0xOBJECT_C" }
],
"read_mask": { "paths": ["content"] }
}' <FULL_NODE_URL> sui.rpc.v2.LedgerService/BatchGetObjects
The gRPC call differs from the JSON-RPC call in the following ways:
- The service respects only the top-level
read_mask. The service ignores any mask inside individual sub-requests. - The response returns objects in the same order as the request.
Get a transaction
Replace sui_getTransactionBlock with LedgerService.GetTransaction.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getTransactionBlock",
"params": [
"J4NvV5iQZQFm1xKPYv9ffDCCPW6cZ4yFKsCqFUiDX5L4",
{ "showEffects": true, "showEvents": true }
]
}'
const result = await client.core.getTransaction({
digest: 'J4NvV5iQZQFm1xKPYv9ffDCCPW6cZ4yFKsCqFUiDX5L4',
include: { effects: true, events: true },
});
if (result.$kind === 'Transaction') {
console.log('Status:', result.Transaction.effects?.status);
console.log('Events:', result.Transaction.events);
}
$ grpcurl -d '{
"digest": "J4NvV5iQZQFm1xKPYv9ffDCCPW6cZ4yFKsCqFUiDX5L4",
"read_mask": { "paths": ["effects", "events"] }
}' <FULL_NODE_URL> sui.rpc.v2.LedgerService/GetTransaction
The gRPC call differs from the JSON-RPC call in the following ways:
- JSON-RPC uses the
showEffectsandshowEventsbooleans. gRPC usesread_maskpaths or the SDK'sincludeparameter. - Digests are
Base58-encoded strings in both APIs.
Batch-fetch transactions
Replace sui_multiGetTransactionBlocks with LedgerService.BatchGetTransactions.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_multiGetTransactionBlocks",
"params": [
["DIGEST_A", "DIGEST_B"],
{ "showEffects": true, "showEvents": true }
]
}'
// Use the proto client directly for batch transaction lookups
const { response } = await client.ledgerService.batchGetTransactions({
digests: ['DIGEST_A', 'DIGEST_B'],
readMask: { paths: ['effects', 'events'] },
});
for (const tx of response.transactions) {
if (tx.result.oneofKind === 'transaction') {
const executed = tx.result.transaction;
console.log(executed.digest, executed.effects);
}
}
$ grpcurl -d '{
"digests": ["DIGEST_A", "DIGEST_B"],
"read_mask": { "paths": ["effects", "events"] }
}' <FULL_NODE_URL> sui.rpc.v2.LedgerService/BatchGetTransactions
The same read_mask rules apply as for batch objects: the service respects only the top-level mask.
Query events
JSON-RPC uses suix_queryEvents with filters such as MoveModule, MoveEventType, Sender, and Transaction. gRPC provides LedgerService.ListEvents for paginated, filtered historical queries and SubscriptionService.SubscribeEvents for live streaming with the same filters. You can also read events from a specific transaction.
Events from a known transaction
If you know the transaction digest, fetch the transaction with events included.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_queryEvents",
"params": [
{ "Transaction": "8NB8sXb4m9PJhCyLB7eVH4onqQWoFFzVUrqPoYUhcQe2" },
null, 50, false
]
}'
const result = await client.core.getTransaction({
digest: '8NB8sXb4m9PJhCyLB7eVH4onqQWoFFzVUrqPoYUhcQe2',
include: { events: true },
});
if (result.$kind === 'Transaction') {
for (const event of result.Transaction.events ?? []) {
console.log('Type:', event.eventType);
console.log('JSON:', event.json);
}
}
Live event streaming
Replace sui_subscribeEvent (WebSocket) with SubscriptionService.SubscribeEvents. The JSON-RPC WebSocket subscription APIs have been deprecated since mid-2024, so migrate any remaining WebSocket subscriptions to gRPC streaming. The server filters events before it sends them, so your client receives only matching events.
- JSON-RPC WebSocket (deprecated)
- gRPC (proto client)
- gRPC (Buf CLI)
// Old WebSocket subscription (no longer supported)
const ws = new WebSocket('wss://<FULL_NODE_URL>/websocket');
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'sui_subscribeEvent',
params: [{ MoveEventType: '<PACKAGE>::module::MyEvent' }],
}));
ws.onmessage = (msg) => console.log(JSON.parse(msg.data));
The @mysten/sui TypeScript SDK does not yet expose SubscribeEvents. Use the generated proto client directly until the SDK adds a wrapper. The grpcurl and Buf CLI examples on this page work today.
// Use the generated proto client directly
const stream = client.subscriptionService.subscribeEvents({
filter: {
terms: [{
literals: [{
eventType: { eventType: '<PACKAGE>::module::MyEvent' },
}],
}],
},
});
for await (const response of stream.responses) {
console.log('Matched event:', response.event);
}
$ buf curl --protocol grpc \
https://<FULL_NODE_URL>/sui.rpc.v2.SubscriptionService/SubscribeEvents \
-d '{
"filter": {
"terms": [{
"literals": [{
"event_type": { "event_type": "<PACKAGE>::module::MyEvent" }
}]
}]
}
}' \
--timeout 5m
The gRPC subscription differs from the JSON-RPC subscription in the following ways:
- JSON-RPC WebSocket subscriptions filtered events server-side, and have been deprecated since mid-2024. gRPC
SubscribeEventsalso filters server-side using anEventFilter, so your client receives only matching events. - Subscriptions always begin at the current tip of the chain and do not accept a resume point. To avoid missing data between a backfill and a subscription, open the subscription first, note the first
WatermarkfromSubscribeEvents, then backfill withLedgerService.ListEventsup to that watermark. After the backfill completes, begin consuming from the already-open subscription. See Subscriptions for streaming data. - For filtered historical event queries over a range, use
LedgerService.ListEventsor GraphQLQuery.events.
Query events over a checkpoint range
Use LedgerService.ListEvents to retrieve events matching an EventFilter across a range of checkpoints. This method replaces the paginated suix_queryEvents pattern.
- gRPC (proto client)
- gRPC (grpcurl)
The @mysten/sui TypeScript SDK does not yet expose ListEvents. Use the generated proto client directly until the SDK adds a wrapper, or use the Rust SDK, which supports ListEvents. The grpcurl example in the next tab works today.
// Use the generated proto client directly
const stream = client.ledgerService.listEvents({
startCheckpoint: BigInt(1000000),
endCheckpoint: BigInt(1000100),
filter: {
terms: [{
literals: [{
eventType: { eventType: '<PACKAGE>::module::MyEvent' },
}],
}],
},
options: { limit: 50 },
});
for await (const response of stream.responses) {
console.log('Event:', response.event);
}
$ grpcurl -d '{
"start_checkpoint": "1000000",
"end_checkpoint": "1000100",
"filter": {
"terms": [{
"literals": [{
"event_type": { "event_type": "<PACKAGE>::module::MyEvent" }
}]
}]
}
}' <FULL_NODE_URL> sui.rpc.v2.LedgerService/ListEvents
Stream checkpoints
Replace sui_getCheckpoints polling with SubscriptionService.SubscribeCheckpoints for a real-time, ordered stream, or LedgerService.ListCheckpoints for paginated queries over a checkpoint range.
- JSON-RPC polling (deprecated)
- gRPC (TypeScript SDK)
- gRPC (Buf CLI)
// Old polling pattern (inefficient and deprecated)
let cursor = null;
while (true) {
const res = await fetch('<FULL_NODE_URL>', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0', id: 1,
method: 'sui_getCheckpoints',
params: [cursor, 10, false],
}),
});
const { result } = await res.json();
for (const cp of result.data) {
console.log('Checkpoint:', cp.sequenceNumber);
cursor = cp.sequenceNumber;
}
if (!result.hasNextPage) await new Promise((r) => setTimeout(r, 1000));
}
const { responses } = client.subscriptionService.subscribeCheckpoints({
readMask: {
paths: ['sequenceNumber', 'digest', 'summary'],
},
});
for await (const response of responses) {
const cp = response.checkpoint;
console.log('Checkpoint:', cp?.sequenceNumber);
console.log('Timestamp:', cp?.summary?.timestamp);
console.log('Tx count:', cp?.summary?.totalNetworkTransactions);
}
$ buf curl --protocol grpc \
https://<FULL_NODE_URL>/sui.rpc.v2.SubscriptionService/SubscribeCheckpoints \
-d '{ "readMask": "sequenceNumber,digest,summary.timestamp" }' \
--timeout 5m
The gRPC stream differs from the JSON-RPC polling pattern in the following ways:
- You do not need a polling loop. The gRPC stream pushes checkpoints as they finalize.
- Use
LedgerService.ListCheckpointsto query a historical range of checkpoints, optionally filtered by aTransactionFilter. UseSubscriptionService.SubscribeCheckpointsfor live streaming from the current tip. - Subscriptions do not support resumption. To avoid gaps, open the subscription first, note the first
cursorfromSubscribeCheckpoints, then backfill missed checkpoints withListCheckpointsup to that cursor before you consume from the already-open stream. grpcurlsupports server-side streaming for theLedgerService.List*calls on this page. ForSubscriptionServicesubscriptions, which are indefinite streams, the Buf CLI or an SDK client provides better control over timeouts and reconnection.
Look up a single checkpoint
Replace sui_getCheckpoint with LedgerService.GetCheckpoint.
A full node serves only checkpoints within its retention window. If you query an old sequence number and receive NOT_FOUND, either use a more recent checkpoint or query the Archival Service instead.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_getCheckpoint",
"params": ["CHECKPOINT_SEQUENCE_NUMBER"]
}'
// Use the proto client directly. No Core API wrapper exists for checkpoint lookups.
const { response } = await client.ledgerService.getCheckpoint({
checkpointId: {
oneofKind: 'sequenceNumber',
sequenceNumber: BigInt('CHECKPOINT_SEQUENCE_NUMBER'),
},
readMask: { paths: ['digest', 'summary'] },
});
console.log('Digest:', response.checkpoint?.digest);
console.log('Timestamp:', response.checkpoint?.summary?.timestamp);
console.log('Total transactions:', response.checkpoint?.summary?.totalNetworkTransactions);
$ grpcurl -d '{
"sequence_number": "CHECKPOINT_SEQUENCE_NUMBER",
"read_mask": { "paths": ["digest", "summary"] }
}' <FULL_NODE_URL> sui.rpc.v2.LedgerService/GetCheckpoint
Get balances
Replace suix_getBalance and suix_getAllBalances with StateService.GetBalance and StateService.ListBalances.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
To query a single coin type, run the following command:
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getBalance",
"params": ["<ADDRESS>", "0x2::sui::SUI"]
}'
To query all coin types, run the following command:
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getAllBalances",
"params": ["<ADDRESS>"]
}'
// Single coin type
const { balance } = await client.core.getBalance({
owner: '<ADDRESS>',
coinType: '0x2::sui::SUI',
});
console.log('Total balance:', balance.balance);
console.log('Coin balance:', balance.coinBalance);
console.log('Address balance:', balance.addressBalance);
// All coin types
const { balances } = await client.core.listBalances({
owner: '<ADDRESS>',
});
for (const b of balances) {
console.log(b.coinType, b.balance);
}
To query a single coin type, run the following command:
$ grpcurl -d '{
"owner": "<ADDRESS>",
"coin_type": "0x2::sui::SUI"
}' <FULL_NODE_URL> sui.rpc.v2.StateService/GetBalance
To query all coin types, run the following command:
$ grpcurl -d '{
"owner": "<ADDRESS>"
}' <FULL_NODE_URL> sui.rpc.v2.StateService/ListBalances
gRPC separates coinBalance (coin objects) and addressBalance (accumulator). The balance field is the combined total. See Using Address Balances for reconciliation details.
List owned coins
Replace suix_getCoins and suix_getAllCoins with StateService.ListOwnedObjects filtered by coin type.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getCoins",
"params": ["<ADDRESS>", "0x2::sui::SUI", null, 50]
}'
// List SUI coin objects
const page = await client.core.listOwnedObjects({
owner: '<ADDRESS>',
type: '0x2::coin::Coin<0x2::sui::SUI>',
limit: 50,
});
for (const obj of page.objects) {
console.log('Coin:', obj.objectId);
}
// Paginate with the cursor from the previous response
if (page.hasNextPage) {
const nextPage = await client.core.listOwnedObjects({
owner: '<ADDRESS>',
type: '0x2::coin::Coin<0x2::sui::SUI>',
limit: 50,
cursor: page.cursor,
});
}
$ grpcurl -d '{
"owner": "<ADDRESS>",
"object_type": "0x2::coin::Coin<0x2::sui::SUI>"
}' <FULL_NODE_URL> sui.rpc.v2.StateService/ListOwnedObjects
The gRPC approach differs from the JSON-RPC approach in the following ways:
- There is no dedicated coin-listing RPC. Use
ListOwnedObjectswith aCoin<T>type filter. - To list coins of every type, filter by
0x2::coin::Coinwithout a type parameter. - For transaction building, prefer gas smashing or address-balance gas payments over manual coin selection.
List dynamic fields
Replace suix_getDynamicFields with StateService.ListDynamicFields.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getDynamicFields",
"params": ["0xPARENT_OBJECT_ID", null, 50]
}'
const page = await client.core.listDynamicFields({
parentId: '0xPARENT_OBJECT_ID',
limit: 50,
});
for (const field of page.dynamicFields) {
console.log('Name:', field.name);
console.log('Field ID:', field.fieldId);
}
$ grpcurl -d '{
"parent": "0xPARENT_OBJECT_ID"
}' <FULL_NODE_URL> sui.rpc.v2.StateService/ListDynamicFields
For suix_getDynamicFieldObject, derive the dynamic field's object ID locally from the parent ID and field name, then call LedgerService.GetObject. You do not need ListDynamicFields when you already know the field name.
Execute a transaction
Replace sui_executeTransactionBlock with TransactionExecutionService.ExecuteTransaction.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_executeTransactionBlock",
"params": [
"BASE64_TX_BYTES",
["BASE64_SIGNATURE"],
{ "showEffects": true }
]
}'
import { Transaction } from '@mysten/sui/transactions';
// Build and sign a transaction (see PTB docs for details)
const tx = new Transaction();
// ... add commands ...
const bytes = await tx.build({ client });
const { signature } = await keypair.signTransaction(bytes);
// Execute
const result = await client.core.executeTransaction({
transaction: bytes,
signatures: [signature],
include: { effects: true },
});
if (result.$kind === 'Transaction') {
console.log('Digest:', result.Transaction.digest);
console.log('Status:', result.Transaction.effects?.status);
}
The JSON-RPC unsafe_* builder methods, such as unsafe_moveCall and unsafe_transferObject, have no gRPC equivalent. Build transactions with programmable transaction blocks (PTBs) using the SDK, then submit the bytes. See Building PTBs and Signing and Sending Transactions.
Simulate a transaction (dry run)
Replace sui_dryRunTransactionBlock and sui_devInspectTransactionBlock with TransactionExecutionService.SimulateTransaction.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "sui_dryRunTransactionBlock",
"params": ["BASE64_TX_BYTES"]
}'
const result = await client.core.simulateTransaction({
transaction: txBytes,
include: { effects: true, events: true },
});
if (result.$kind === 'Transaction') {
console.log('Simulated status:', result.Transaction.effects?.status);
console.log('Simulated events:', result.Transaction.events);
}
Get reference gas price
Replace suix_getReferenceGasPrice with getReferenceGasPrice on the SDK, or call LedgerService.GetEpoch through grpcurl and read the reference_gas_price field.
- JSON-RPC (deprecated)
- gRPC (TypeScript SDK)
- gRPC (grpcurl)
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_getReferenceGasPrice",
"params": []
}'
const { referenceGasPrice } = await client.core.getReferenceGasPrice();
console.log('Reference gas price:', referenceGasPrice);
$ grpcurl -d '{ "read_mask": { "paths": ["reference_gas_price"] } }' \
<FULL_NODE_URL> sui.rpc.v2.LedgerService/GetEpoch
Resolve a SuiNS name
Replace JSON-RPC name resolution with NameService.LookupName and NameService.ReverseLookupName.
- JSON-RPC (deprecated)
- gRPC (grpcurl)
To resolve a name to an address, run the following command:
$ curl -X POST <FULL_NODE_URL> \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "suix_resolveNameServiceAddress",
"params": ["example.sui"]
}'
To resolve a name to an address, run the following command:
$ grpcurl -d '{ "name": "example.sui" }' \
<FULL_NODE_URL> sui.rpc.v2.NameService/LookupName
To resolve an address to a name, run the following command:
$ grpcurl -d '{ "address": "<ADDRESS>" }' \
<FULL_NODE_URL> sui.rpc.v2.NameService/ReverseLookupName
Common patterns
Reconnect a checkpoint stream
If the gRPC stream disconnects, backfill any missed checkpoints before you resubscribe:
let lastProcessed = 0n;
async function startStream() {
const { responses } = client.subscriptionService.subscribeCheckpoints({
readMask: { paths: ['sequenceNumber', 'transactions'] },
});
try {
for await (const response of responses) {
const seq = response.checkpoint?.sequenceNumber ?? 0n;
// Detect and backfill gaps
if (seq > lastProcessed + 1n && lastProcessed > 0n) {
for (let i = lastProcessed + 1n; i < seq; i++) {
const { response: missed } = await client.ledgerService.getCheckpoint({
checkpointId: { oneofKind: 'sequenceNumber', sequenceNumber: i },
readMask: { paths: ['transactions'] },
});
processCheckpoint(missed.checkpoint);
}
}
processCheckpoint(response.checkpoint);
lastProcessed = seq;
}
} catch (err) {
console.error('Stream disconnected, reconnecting...', err);
startStream(); // reconnect
}
}
Paginate through all owned objects
Use the cursor from each response to request the next page:
import type { SuiClientTypes } from '@mysten/sui';
let cursor: string | null = null;
do {
const page: SuiClientTypes.ListOwnedObjectsResponse = await client.core.listOwnedObjects({
owner: '<ADDRESS>',
limit: 50,
cursor,
});
for (const obj of page.objects) {
console.log(obj.objectId);
}
cursor = page.hasNextPage ? page.cursor : null;
} while (cursor);
Fall back to the Archival Store for pruned data
A full node returns NOT_FOUND for data outside its retention window. Fall back to the Archival Store for historical lookups:
import { SuiGrpcClient } from '@mysten/sui/grpc';
const fullNode = new SuiGrpcClient({
baseUrl: '<FULL_NODE_URL>',
network: 'mainnet',
});
const archive = new SuiGrpcClient({
baseUrl: 'https://archive.mainnet.sui.io:443',
network: 'mainnet',
});
async function getTransaction(digest: string) {
const result = await fullNode.core.getTransaction({
digest,
include: { effects: true },
});
if (result.$kind === 'Transaction') {
return result.Transaction;
}
// Data was pruned, so fall back to the Archival Store.
const archiveResult = await archive.core.getTransaction({
digest,
include: { effects: true },
});
if (archiveResult.$kind === 'Transaction') {
return archiveResult.Transaction;
}
throw new Error(`Transaction ${digest} not found in full node or archive`);
}