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(())
}
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);
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);
}
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);
}
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);
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);
}
Query by sender
let events = sui
.event_api()
.query_events(
EventFilter::Sender(address),
None,
Some(100),
false,
)
.await?;
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);
}
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());
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);
Get checkpoint details
let checkpoint = sui
.read_api()
.get_checkpoint(checkpoint_id)
.await?;
println!("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);
Get chain identifier
let chain_id = sui
.read_api()
.get_chain_identifier()
.await?;
println!("Chain ID: {}", chain_id);
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;
}
}