Querying Objects
Get owned objects
use sui_sdk::SuiClientBuilder;
use sui_sdk::rpc_types::SuiObjectDataOptions;
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let sui = SuiClientBuilder::default().build_testnet().await?;
let address = /* your address */;
let objects = sui
.read_api()
.get_owned_objects(
address,
None, // query filter
None, // cursor for pagination
Some(50), // limit
)
.await?;
for obj in objects.data {
println!("Object: {:?}", obj);
}
Ok(())
}
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
const client = new SuiClient({ url: getFullnodeUrl('testnet') });
const address = '0x...';
const objects = await client.getOwnedObjects({
owner: address,
options: {
showType: true,
showContent: true,
},
});
console.log('Objects:', objects.data);
Get specific object
let object_id: ObjectID = "0x...".parse()?;
let object = sui
.read_api()
.get_object_with_options(
object_id,
SuiObjectDataOptions {
show_type: true,
show_owner: true,
show_content: true,
show_display: true,
show_bcs: true,
show_storage_rebate: true,
show_previous_transaction: true,
},
)
.await?;
println!("Object: {:?}", object);
const objectId = '0x...';
const object = await client.getObject({
id: objectId,
options: {
showType: true,
showOwner: true,
showContent: true,
showDisplay: true,
},
});
console.log('Object:', object.data);
Querying Coins
Get coin balances
let balance = sui
.coin_read_api()
.get_balance(address, None) // None = SUI
.await?;
println!("Balance: {}", balance.total_balance);
// Get all coin types
let all_balances = sui
.coin_read_api()
.get_all_balances(address)
.await?;
for bal in all_balances {
println!("{}: {}", bal.coin_type, bal.total_balance);
}
const balance = await client.getBalance({
owner: address,
coinType: '0x2::sui::SUI',
});
console.log('Balance:', balance.totalBalance);
// Get all balances
const allBalances = await client.getAllBalances({
owner: address,
});
allBalances.forEach(b => {
console.log(`${b.coinType}: ${b.totalBalance}`);
});
Get individual coins
let coins = sui
.coin_read_api()
.get_coins(address, None, None, None)
.await?;
for coin in coins.data {
println!("Coin {} = {}", coin.coin_object_id, coin.balance);
}
const coins = await client.getCoins({
owner: address,
coinType: '0x2::sui::SUI',
});
coins.data.forEach(coin => {
console.log(`${coin.coinObjectId}: ${coin.balance}`);
});
Querying Transactions
Get transaction details
use sui_sdk::rpc_types::SuiTransactionBlockResponseOptions;
let tx = sui
.read_api()
.get_transaction_with_options(
digest,
SuiTransactionBlockResponseOptions {
show_input: true,
show_effects: true,
show_events: true,
show_object_changes: true,
show_balance_changes: true,
show_raw_input: false,
show_raw_effects: false,
},
)
.await?;
println!("Transaction: {:?}", tx);
const tx = await client.getTransactionBlock({
digest: txDigest,
options: {
showInput: true,
showEffects: true,
showEvents: true,
showObjectChanges: true,
showBalanceChanges: true,
},
});
console.log('Transaction:', tx);
Query transactions
// Get transactions for an address
const txs = await client.queryTransactionBlocks({
filter: {
FromAddress: address,
},
options: {
showEffects: true,
},
limit: 50,
});
// Get transactions that changed an object
const objTxs = await client.queryTransactionBlocks({
filter: {
ChangedObject: objectId,
},
});
Querying Events
Query by event type
use sui_sdk::rpc_types::EventFilter;
let events = sui
.event_api()
.query_events(
EventFilter::MoveEventType(
"0x2::coin::Deposit".parse()?
),
None, // cursor
Some(50), // limit
false, // descending
)
.await?;
for event in events.data {
println!("Event: {:?}", event);
}
const events = await client.queryEvents({
query: {
MoveEventType: '0xPACKAGE::module::EventType',
},
limit: 50,
});
console.log('Events:', events.data);
Query by sender
let events = sui
.event_api()
.query_events(
EventFilter::Sender(address),
None,
Some(100),
false,
)
.await?;
const events = await client.queryEvents({
query: {
Sender: address,
},
limit: 100,
});
Dynamic Fields
Get dynamic fields
let parent_id: ObjectID = "0x...".parse()?;
let fields = sui
.read_api()
.get_dynamic_fields(parent_id, None, None)
.await?;
for field in fields.data {
println!("Field: {:?}", field);
// Get field value
let field_obj = sui
.read_api()
.get_dynamic_field_object(parent_id, field.name)
.await?;
println!("Value: {:?}", field_obj);
}
const fields = await client.getDynamicFields({
parentId: objectId,
});
for (const field of fields.data) {
console.log('Field:', field);
const fieldObj = await client.getDynamicFieldObject({
parentId: objectId,
name: field.name,
});
console.log('Value:', fieldObj);
}
Pagination
Paginate through objects
let mut cursor = None;
let mut all_objects = Vec::new();
loop {
let response = sui
.read_api()
.get_owned_objects(address, None, cursor, Some(50))
.await?;
all_objects.extend(response.data);
if !response.has_next_page {
break;
}
cursor = response.next_cursor;
}
println!("Total objects: {}", all_objects.len());
let cursor = null;
const allObjects = [];
while (true) {
const response = await client.getOwnedObjects({
owner: address,
cursor,
limit: 50,
});
allObjects.push(...response.data);
if (!response.hasNextPage) break;
cursor = response.nextCursor;
}
console.log('Total objects:', allObjects.length);
Filtering Objects
Filter by type
const objects = await client.getOwnedObjects({
owner: address,
filter: {
StructType: '0xPACKAGE::module::TypeName',
},
});
Filter by package
const objects = await client.getOwnedObjects({
owner: address,
filter: {
Package: packageId,
},
});
Checkpoint Queries
Get latest checkpoint
let latest = sui
.read_api()
.get_latest_checkpoint_sequence_number()
.await?;
println!("Latest checkpoint: {}", latest);
const latest = await client.getLatestCheckpointSequenceNumber();
console.log('Latest checkpoint:', latest);
Get checkpoint details
let checkpoint = sui
.read_api()
.get_checkpoint(checkpoint_id)
.await?;
println!("Checkpoint: {:?}", checkpoint);
const checkpoint = await client.getCheckpoint({
id: checkpointId,
});
console.log('Checkpoint:', checkpoint);
Protocol Information
Get protocol config
let config = sui
.read_api()
.get_protocol_config(None)
.await?;
println!("Max tx gas: {}", config.max_tx_gas);
println!("Protocol version: {}", config.protocol_version);
const config = await client.getProtocolConfig();
console.log('Protocol version:', config.protocolVersion);
Get chain identifier
let chain_id = sui
.read_api()
.get_chain_identifier()
.await?;
println!("Chain ID: {}", chain_id);
const chainId = await client.getChainIdentifier();
console.log('Chain ID:', chainId);
Best Practices
1. Use pagination for large datasets
// Good: Paginate
let cursor = null;
while (true) {
const page = await client.getOwnedObjects({
owner: address,
cursor,
limit: 50,
});
// Process page
if (!page.hasNextPage) break;
cursor = page.nextCursor;
}
2. Request only needed data
// Good: Only request what you need
const objects = await client.getOwnedObjects({
owner: address,
options: {
showType: true, // Only type, not full content
},
});
3. Cache expensive queries
const cache = new Map();
async function getCachedBalance(address: string) {
if (cache.has(address)) {
const { balance, timestamp } = cache.get(address);
if (Date.now() - timestamp < 10000) { // 10s cache
return balance;
}
}
const balance = await client.getBalance({ owner: address });
cache.set(address, { balance, timestamp: Date.now() });
return balance;
}
4. Handle errors gracefully
async function safeGetObject(objectId: string) {
try {
return await client.getObject({ id: objectId });
} catch (error) {
console.error(`Failed to fetch object ${objectId}:`, error);
return null;
}
}