Skip to content

Commit

Permalink
[indexer] add ability to use struct type filter for get_owned_objects (
Browse files Browse the repository at this point in the history
…MystenLabs#14639)

## Description 

This PR enables struct type and `MatchAny` struct type filters for
get_owned_objects method.

## Test Plan 

Tested locally.

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
  • Loading branch information
emmazzz authored Nov 2, 2023
1 parent 61428d1 commit 3c377e7
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ CREATE TABLE objects (
CREATE INDEX objects_owner ON objects (owner_type, owner_id) WHERE owner_type BETWEEN 1 AND 2 AND owner_id IS NOT NULL;
CREATE INDEX objects_coin ON objects (owner_id, coin_type) WHERE coin_type IS NOT NULL AND owner_type = 1;
CREATE INDEX objects_checkpoint_sequence_number ON objects (checkpoint_sequence_number);
CREATE INDEX objects_type ON objects (object_type);
8 changes: 6 additions & 2 deletions crates/sui-indexer/src/apis/governance_api_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ use cached::{proc_macro::cached, SizedCache};
use sui_json_rpc::{
api::GovernanceReadApiServer, governance_api::ValidatorExchangeRates, SuiRpcModule,
};
use sui_json_rpc_types::{DelegatedStake, EpochInfo, StakeStatus, SuiCommittee, ValidatorApys};
use sui_json_rpc_types::{
DelegatedStake, EpochInfo, StakeStatus, SuiCommittee, SuiObjectDataFilter, ValidatorApys,
};
use sui_open_rpc::Module;
use sui_types::{
base_types::{MoveObjectType, ObjectID, SuiAddress},
Expand Down Expand Up @@ -74,7 +76,9 @@ impl GovernanceReadApiV2 {
.inner
.get_owned_objects_in_blocking_task(
owner,
Some(MoveObjectType::staked_sui().to_string()),
Some(SuiObjectDataFilter::StructType(
MoveObjectType::staked_sui().into(),
)),
None,
// Allow querying for up to 1000 staked objects
1000,
Expand Down
9 changes: 1 addition & 8 deletions crates/sui-indexer/src/apis/indexer_api_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,10 @@ impl IndexerApiV2 {
limit: usize,
) -> RpcResult<ObjectsPage> {
let SuiObjectResponseQuery { filter, options } = query.unwrap_or_default();
if filter.is_some() {
// TODO: do we want to support this?
return Err(IndexerError::NotSupportedError(
"Indexer does not support querying owned objects with filters".into(),
)
.into());
}
let options = options.unwrap_or_default();
let objects = self
.inner
.get_owned_objects_in_blocking_task(address, None, cursor, limit + 1)
.get_owned_objects_in_blocking_task(address, filter, cursor, limit + 1)
.await?;
let mut objects = self
.inner
Expand Down
4 changes: 2 additions & 2 deletions crates/sui-indexer/src/apis/transaction_builder_api_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::indexer_reader::IndexerReader;
use async_trait::async_trait;
use move_core_types::language_storage::StructTag;
use sui_json_rpc::transaction_builder_api::TransactionBuilderApi;
use sui_json_rpc_types::{SuiObjectDataOptions, SuiObjectResponse};
use sui_json_rpc_types::{SuiObjectDataFilter, SuiObjectDataOptions, SuiObjectResponse};
use sui_transaction_builder::DataReader;
use sui_types::base_types::{ObjectID, ObjectInfo, SuiAddress};
use sui_types::object::Object;
Expand All @@ -33,7 +33,7 @@ impl DataReader for TransactionBuilderApiV2 {
.inner
.get_owned_objects_in_blocking_task(
address,
Some(object_type.to_canonical_string()),
Some(SuiObjectDataFilter::StructType(object_type)),
None,
50, // Limit the number of objects returned to 50
)
Expand Down
37 changes: 31 additions & 6 deletions crates/sui-indexer/src/indexer_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use std::{
};
use sui_json_rpc_types::{
AddressMetrics, CheckpointId, EpochInfo, EventFilter, MoveCallMetrics, MoveFunctionName,
NetworkMetrics, SuiEvent, SuiTransactionBlockResponse, TransactionFilter,
NetworkMetrics, SuiEvent, SuiObjectDataFilter, SuiTransactionBlockResponse, TransactionFilter,
};
use sui_json_rpc_types::{
Balance, Coin as SuiCoin, SuiCoinMetadata, SuiTransactionBlockEffects,
Expand Down Expand Up @@ -555,20 +555,45 @@ impl IndexerReader {
pub async fn get_owned_objects_in_blocking_task(
&self,
address: SuiAddress,
object_type: Option<String>,
filter: Option<SuiObjectDataFilter>,
cursor: Option<ObjectID>,
limit: usize,
) -> Result<Vec<StoredObject>, IndexerError> {
let object_types = Self::extract_struct_filters(filter)?;
self.spawn_blocking(move |this| {
this.get_owned_objects_impl(address, object_type, cursor, limit)
this.get_owned_objects_impl(address, object_types, cursor, limit)
})
.await
}

fn extract_struct_filters(
filter: Option<SuiObjectDataFilter>,
) -> Result<Option<Vec<String>>, IndexerError> {
if filter.is_none() {
return Ok(None);
}
match filter.unwrap() {
SuiObjectDataFilter::StructType (struct_tag ) => Ok(Some(vec![struct_tag.to_string()])),
SuiObjectDataFilter::MatchAny(filters) => {
filters.iter().map(|filter| {
match filter {
SuiObjectDataFilter::StructType (struct_tag ) => Ok(struct_tag.to_string()),
_ => Err(IndexerError::InvalidArgumentError(
"Invalid filter type. Only struct filters and MatchAny of struct filters are supported.".into(),
)),
}
}).collect::<Result<Vec<_>, _>>().map(Some)
}
_ => Err(IndexerError::InvalidArgumentError(
"Invalid filter type. Only struct filters and MatchAny of struct filters are supported.".into(),
)),
}
}

fn get_owned_objects_impl(
&self,
address: SuiAddress,
object_type: Option<String>,
object_types: Option<Vec<String>>,
cursor: Option<ObjectID>,
limit: usize,
) -> Result<Vec<StoredObject>, IndexerError> {
Expand All @@ -578,8 +603,8 @@ impl IndexerReader {
.filter(objects::dsl::owner_id.eq(address.to_vec()))
.limit(limit as i64)
.into_boxed();
if let Some(object_type) = object_type {
query = query.filter(objects::dsl::object_type.eq(object_type));
if let Some(object_types) = object_types {
query = query.filter(objects::dsl::object_type.eq_any(object_types));
}

if let Some(object_cursor) = cursor {
Expand Down

0 comments on commit 3c377e7

Please sign in to comment.