Skip to content

feat(gRPC)!: improve client ergonomics & read-mask discoverability#1147

Open
DaughterOfMars wants to merge 18 commits into
developfrom
feat/grpc-improvements
Open

feat(gRPC)!: improve client ergonomics & read-mask discoverability#1147
DaughterOfMars wants to merge 18 commits into
developfrom
feat/grpc-improvements

Conversation

@DaughterOfMars

Copy link
Copy Markdown
Contributor

Follow-up to the initial gRPC client landing (#1062). This PR sharpens the
high-level Rust gRPC API around two recurring rough edges — every read method
having to take an Option<ReadMask>, and callers having to know by convention
which XField namespace pairs with which method — and adds a handful of
examples that exercise the result.

Summary

  • Split every masked endpoint into a default-mask method + a _masked
    variant.
    client.get_objects(refs) uses the canonical default mask;
    client.get_objects_masked(refs, mask) takes a mask directly (no
    Option, no wrapper). Applied to all 17 masked methods across
    get_objects / get_objects_with_versions / get_transactions /
    get_service_info / get_epoch / get_checkpoint_* / stream_checkpoints*
    / list_owned_objects / list_dynamic_fields / get_coins /
    simulate_transaction(s) / execute_transaction(s).
  • Typed scoped read masks per endpoint. Each XField (e.g.
    ObjectField, TransactionField, EpochField, …) is now a typed
    Cow<'static, str> newtype instead of a bag of &str consts, and each
    masked endpoint accepts a paired XReadMask (ObjectReadMask,
    TransactionReadMask, …) via impl Into<…>. Call sites become:
    client.get_objects_masked([id], ObjectField::BCS).await?;
    client.get_objects_masked([id], [ObjectField::REFERENCE, ObjectField::BCS]).await?;
    No ReadMask::from(…) wrapper. Passing TransactionField::EFFECTS to
    get_objects_masked is now a compile error. Pre-computed mask constants
    in read_masks::* still flow through via From<&'static str> /
    From<String> escape hatches on each scoped mask.
  • New Client::get_coins(_masked) plus GetCoinsQuery builder in
    state/coins.rs — paginated coin listing with optional StructTag
    filter, returning iota_types::framework::Coin items (proto Object
    SDK Coin conversion happens internally).
  • CheckpointResponse accessors refactored to return SDK types directly.
    response.summary() / .signature() / .contents() now yield the
    deserialized SDK types; the proto variants are renamed to _grpc
    (summary_grpc, etc.). Same pattern as the executed_transactions /
    executed_transactions_grpc split.
  • Network constructors on Client: Client::new_localnet(),
    new_devnet(), new_testnet(), new_mainnet() plus pub-crate host
    constants.
  • TLS features forwarded from iota-sdk's grpc feature. Previously
    enabling iota-sdk/grpc pulled in iota-grpc-client with
    default-features = false, so Client::new_testnet() failed at runtime
    with "HTTPS requires the tls-ring feature". The grpc feature now
    forwards tls-ring + tls-native-roots.
  • Four new gRPC examples in crates/iota-sdk/examples/:
    chain_id_grpc, get_object_grpc, owned_objects_grpc,
    stream_checkpoints_grpc — the last has no GraphQL counterpart and
    exists specifically to showcase the streaming RPC.

Migration

This is a breaking change to the gRPC client surface. The mechanical
rewrite at call sites:

Before After
get_objects(refs, None) get_objects(refs)
get_objects(refs, Some(ReadMask::from(ObjectField::BCS))) get_objects_masked(refs, ObjectField::BCS)
get_objects(refs, Some(ReadMask::from(&[ObjectField::BCS, ObjectField::REFERENCE]))) get_objects_masked(refs, [ObjectField::BCS, ObjectField::REFERENCE])
cp.summary()?.summary()? cp.summary()?
cp.signature()?.signature()? cp.signature()?
cp.contents()?.contents()? cp.contents()?

XField::Y used to evaluate to &'static str; it's now an XField
struct. Use .as_str() if you need the underlying path string.

ReadMask<'_> is retained as a low-level string holder for advanced
composition but is no longer accepted by client methods directly — pass a
scoped mask (or a &str for the escape hatch) instead.

@DaughterOfMars DaughterOfMars requested a review from a team as a code owner May 13, 2026 14:36
Comment thread crates/iota-sdk-grpc-client/src/api/mod.rs Outdated
Comment thread crates/iota-sdk/examples/chain_id_grpc.rs Outdated
Comment thread crates/iota-sdk-grpc-types/src/read_mask_fields.rs
Comment thread crates/iota-sdk-grpc-client/src/api/state/coins.rs Outdated
Comment thread crates/iota-sdk-grpc-client/src/api/ledger/checkpoints.rs
Comment thread crates/iota-sdk-grpc-client/Cargo.toml Outdated
@Thoralf-M

Copy link
Copy Markdown
Member

Overall not sure if this PR is really worth it, just providing None for the read mask if not needed or finding the correct things to mask doesn't seem to be a big deal to me

@DaughterOfMars

Copy link
Copy Markdown
Contributor Author

Overall not sure if this PR is really worth it, just providing None for the read mask if not needed or finding the correct things to mask doesn't seem to be a big deal to me

I think it's a pretty big usability increase, if not for the extra helper fns than definitely for the read mask discoverability. Before you basically had no way to know what read masks to use other than reading the doc. Now it's implicit.

@DaughterOfMars DaughterOfMars linked an issue Jun 2, 2026 that may be closed by this pull request
@Thoralf-M Thoralf-M changed the title feat(gRPC): improve client ergonomics & read-mask discoverability feat(gRPC)!: improve client ergonomics & read-mask discoverability Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add additional grpc helper fns

2 participants