Skip to main content

GetObject

Retrieve Object Data with High-Performance gRPC#

The GetObject method from the Ledger Service provides efficient access to Sui blockchain object data through gRPC. This method returns comprehensive object information including metadata, ownership, type information, and contents, with support for field masking to optimize response payloads.

Overview#

Objects are fundamental to Sui's architecture. Every piece of data on Sui exists as an object with a unique identifier, version, ownership model, and type definition. The GetObject gRPC method enables developers to query object state efficiently using binary Protocol Buffer serialization, offering significant performance advantages over JSON-RPC for high-throughput applications.

Key Features#

  • Field Masking: Request only necessary fields to minimize response size
  • Binary Serialization: Protocol Buffers provide compact, efficient data encoding
  • Type Safety: Strong typing through proto definitions eliminates runtime errors
  • Version Tracking: Access object version history and previous transactions
  • Ownership Information: Detailed ownership metadata including transfer capabilities

Method Signature#

Service: sui.rpc.v2beta2.LedgerService Method: GetObject Type: Unary RPC (single request, single response)

Parameters#

ParameterTypeRequiredDescription
object_idstringYesThe unique identifier of the Sui object (hex string with 0x prefix)
read_maskFieldMaskNoSpecifies which fields to include in the response

Field Mask Options#

The read_mask parameter accepts a paths array to specify which fields should be returned. Available paths include:

PathDescription
bcsBinary Canonical Serialization of the object
object_idObject's unique identifier
versionCurrent version number
digestCryptographic digest of object state
ownerOwnership information and permissions
object_typeType classification (module::struct)
has_public_transferWhether object can be transferred publicly
contentsObject data fields and values
previous_transactionDigest of the transaction that created/modified this version
storage_rebateStorage rebate amount in MIST

Example Object IDs#

0x5                                                              // System object
0x0000000000000000000000000000000000000000000000000000000000000002 // Sui system state

Response Structure#

The method returns an Object message with the following structure:

message Object {
bytes bcs = 1;
string object_id = 2;
uint64 version = 3;
string digest = 4;
Owner owner = 5;
string object_type = 6;
bool has_public_transfer = 7;
ObjectContents contents = 8;
string previous_transaction = 9;
uint64 storage_rebate = 10;
}

Owner Structure#

message Owner {
enum OwnerKind {
ADDRESS_OWNER = 0;
OBJECT_OWNER = 1;
SHARED = 2;
IMMUTABLE = 3;
}
OwnerKind kind = 1;
string address = 2; // Set for ADDRESS_OWNER and OBJECT_OWNER
uint64 initial_shared_version = 3; // Set for SHARED objects
}

Response Fields#

FieldTypeDescription
bcsbytesBinary Canonical Serialization data
object_idstringObject's unique identifier
versionuint64Current version number
digeststringObject state digest
ownerOwnerOwnership details
object_typestringFull type path (package::module::type)
has_public_transferboolPublic transfer capability
contentsObjectContentsStructured object data
previous_transactionstringTransaction digest that modified this object
storage_rebateuint64Storage rebate in MIST

Code Examples#

import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';

// Configuration
const ENDPOINT = 'api-sui-mainnet-full.n.dwellir.com';
const API_TOKEN = 'your_api_token_here';

// Load proto definition
const packageDefinition = protoLoader.loadSync(
'./protos/ledger.proto',
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
includeDirs: ['./protos']
}
);

const protoDescriptor = grpc.loadPackageDefinition(packageDefinition) as any;

// Create client with TLS
const credentials = grpc.credentials.createSsl();
const client = new protoDescriptor.sui.rpc.v2beta2.LedgerService(
ENDPOINT,
credentials
);

// Setup authentication
const metadata = new grpc.Metadata();
metadata.add('x-api-key', API_TOKEN);

// Query specific object
async function getObject(objectId: string): Promise<any> {
return new Promise((resolve, reject) => {
const request = {
object_id: objectId,
read_mask: {
paths: [
'object_id',
'version',
'digest',
'owner',
'object_type',
'has_public_transfer',
'previous_transaction',
'storage_rebate'
]
}
};

client.GetObject(request, metadata, (error: any, response: any) => {
if (error) {
console.error('GetObject error:', error.message);
reject(error);
return;
}

resolve(response);
});
});
}

// Example usage
async function main() {
try {
// Query the Sui system state object
const systemObject = await getObject('0x5');

console.log('Object Information:');
console.log('==================');
console.log('Object ID:', systemObject.object_id);
console.log('Version:', systemObject.version);
console.log('Type:', systemObject.object_type);
console.log('Digest:', systemObject.digest);
console.log('Storage Rebate:', systemObject.storage_rebate, 'MIST');

// Parse ownership
if (systemObject.owner) {
const ownerTypes = ['ADDRESS_OWNER', 'OBJECT_OWNER', 'SHARED', 'IMMUTABLE'];
console.log('Owner Type:', ownerTypes[systemObject.owner.kind]);

if (systemObject.owner.address) {
console.log('Owner Address:', systemObject.owner.address);
}
}

console.log('Public Transfer:', systemObject.has_public_transfer ? 'Yes' : 'No');
console.log('Previous Transaction:', systemObject.previous_transaction);
} catch (error) {
console.error('Failed to get object:', error);
}
}

main();

Use Cases#

1. Object Ownership Verification#

Verify ownership before performing operations:

async function verifyOwnership(objectId: string, expectedOwner: string): Promise<boolean> {
const object = await getObject(objectId);

if (object.owner.kind === 0) { // ADDRESS_OWNER
return object.owner.address === expectedOwner;
}

return false;
}

2. Object Version Tracking#

Monitor object version changes:

async function trackObjectVersions(objectId: string): Promise<void> {
const object = await getObject(objectId);

console.log('Current Version:', object.version);
console.log('Last Modified By:', object.previous_transaction);

// Store version for comparison
localStorage.setItem(`${objectId}_version`, object.version);
}

3. NFT Metadata Retrieval#

Efficiently query NFT objects:

async function getNFTMetadata(nftObjectId: string) {
const nft = await client.GetObject({
object_id: nftObjectId,
read_mask: {
paths: [
'object_id',
'object_type',
'owner',
'contents',
'has_public_transfer'
]
}
}, metadata);

return {
id: nft.object_id,
type: nft.object_type,
owner: nft.owner.address,
transferrable: nft.has_public_transfer,
metadata: nft.contents
};
}

4. Storage Cost Analysis#

Analyze storage costs across objects:

async function analyzeStorageCosts(objectIds: string[]): Promise<void> {
let totalRebate = 0;

for (const id of objectIds) {
const obj = await client.GetObject({
object_id: id,
read_mask: { paths: ['storage_rebate'] }
}, metadata);

totalRebate += parseInt(obj.storage_rebate);
}

console.log(`Total Storage Rebate: ${totalRebate / 1_000_000_000} SUI`);
}

Field Masking for Performance#

Field masking dramatically reduces response size and improves performance:

Full Response (No Field Mask)#

const request = { object_id: '0x5' };
// Response size: ~2.5 KB

Optimized Response (With Field Mask)#

const request = {
object_id: '0x5',
read_mask: {
paths: ['object_id', 'version', 'owner']
}
};
// Response size: ~150 bytes (94% reduction)

Performance Impact#

Fields RequestedResponse SizeParsing TimeBandwidth Saved
All (no mask)2.5 KB1.2 ms0%
8 fields800 bytes0.4 ms68%
3 fields150 bytes0.1 ms94%

Error Handling#

Handle common error scenarios:

async function safeGetObject(objectId: string) {
try {
const object = await getObject(objectId);
return { success: true, data: object };
} catch (error: any) {
switch (error.code) {
case grpc.status.NOT_FOUND:
return {
success: false,
error: 'Object not found. It may have been deleted or never existed.'
};

case grpc.status.INVALID_ARGUMENT:
return {
success: false,
error: 'Invalid object ID format. Ensure it\'s a valid hex string.'
};

case grpc.status.PERMISSION_DENIED:
return {
success: false,
error: 'Authentication failed. Check your API token.'
};

case grpc.status.DEADLINE_EXCEEDED:
return {
success: false,
error: 'Request timeout. The server took too long to respond.'
};

default:
return {
success: false,
error: `Unexpected error: ${error.message}`
};
}
}
}

Best Practices#

1. Use Field Masking#

Always specify only the fields you need:

// ✅ Good: Request only needed fields
const request = {
object_id: objectId,
read_mask: { paths: ['owner', 'version'] }
};

// ❌ Bad: Request all fields when you only need a few
const request = { object_id: objectId };

2. Implement Caching#

Cache object data to reduce API calls:

const objectCache = new Map();

async function getCachedObject(objectId: string, maxAge: number = 60000) {
const cached = objectCache.get(objectId);

if (cached && Date.now() - cached.timestamp < maxAge) {
return cached.data;
}

const object = await getObject(objectId);

objectCache.set(objectId, {
data: object,
timestamp: Date.now()
});

return object;
}

3. Handle Version Conflicts#

Check version numbers to avoid stale data:

async function updateObjectIfNewer(objectId: string, lastKnownVersion: number) {
const object = await client.GetObject({
object_id: objectId,
read_mask: { paths: ['version', 'digest'] }
}, metadata);

if (object.version > lastKnownVersion) {
console.log('Object updated:', {
oldVersion: lastKnownVersion,
newVersion: object.version,
digest: object.digest
});
return object;
}

return null; // No update needed
}

4. Batch Queries#

For multiple objects, use BatchGetObjects instead:

// ✅ Efficient: Single batch request
const response = await client.BatchGetObjects({
requests: objectIds.map(id => ({ object_id: id }))
}, metadata);

// ❌ Inefficient: Multiple individual requests
for (const id of objectIds) {
await client.GetObject({ object_id: id }, metadata);
}

Performance Considerations#

  • Field Masking: Reduces response size by up to 94%
  • Binary Serialization: 5-10x faster than JSON parsing
  • Connection Reuse: Keep gRPC channel open for multiple requests
  • Compression: Enable gRPC compression for large payloads
  • Caching: Cache immutable objects to avoid repeated queries

Need help with gRPC integration? Contact our support team or check the gRPC overview.