Skip to content

Commit 1235cdb

Browse files
bingyanglinmuXxer
authored andcommitted
feat: gRPC proto files
1 parent 5576ddd commit 1235cdb

File tree

12 files changed

+969
-92
lines changed

12 files changed

+969
-92
lines changed

crates/iota-grpc-client/src/event.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use anyhow::anyhow;
55
use futures::{Stream, StreamExt};
6-
use iota_grpc_types::v0::events as grpc_events;
6+
use iota_grpc_types::v0::{common as grpc_common, events as grpc_events};
77
use iota_json_rpc_types::{BcsEvent, IotaEvent};
88
use iota_types::{
99
base_types::{IotaAddress, ObjectID, TransactionDigest},
@@ -55,7 +55,7 @@ impl EventClient {
5555
}
5656

5757
/// Deserialize event data from BCS bytes.
58-
fn deserialize_event(event: &grpc_events::Event) -> anyhow::Result<IotaEvent> {
58+
fn deserialize_event(event: &grpc_common::Event) -> anyhow::Result<IotaEvent> {
5959
let event_id = event
6060
.event_id
6161
.as_ref()
@@ -76,20 +76,24 @@ impl EventClient {
7676
.as_ref()
7777
.ok_or_else(|| anyhow!("Missing sender"))?;
7878

79-
let bcs_data = event
79+
let bcs_wrapper = event
8080
.event_data
8181
.as_ref()
8282
.ok_or_else(|| anyhow!("Missing event data"))?;
8383

84+
let bcs_data = bcs_wrapper
85+
.value
86+
.as_ref()
87+
.ok_or_else(|| anyhow!("Missing BCS data value"))?;
88+
8489
// Parse the StructTag from string
8590
let type_tag: StructTag = event
8691
.type_name
8792
.parse()
8893
.map_err(|e| anyhow!("Failed to parse type tag: {e}"))?;
8994

90-
// Parse the JSON
91-
let parsed_json: serde_json::Value = serde_json::from_str(&event.parsed_json)
92-
.map_err(|e| anyhow!("Failed to parse JSON: {e}"))?;
95+
// We only provide BCS data; parsed_json is left empty for now
96+
let parsed_json = serde_json::json!({});
9397

9498
Ok(IotaEvent {
9599
id: EventID {

crates/iota-grpc-server/src/event_service.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl EventGrpcService {
4040
#[tonic::async_trait]
4141
impl grpc_events::event_service_server::EventService for EventGrpcService {
4242
type StreamEventsStream =
43-
std::pin::Pin<Box<dyn futures::Stream<Item = Result<grpc_events::Event, Status>> + Send>>;
43+
std::pin::Pin<Box<dyn futures::Stream<Item = Result<grpc_common::Event, Status>> + Send>>;
4444

4545
async fn stream_events(
4646
&self,
@@ -82,7 +82,7 @@ impl grpc_events::event_service_server::EventService for EventGrpcService {
8282
);
8383

8484
// Convert to protobuf Event
85-
let proto_event = grpc_events::Event::from(&event);
85+
let proto_event = grpc_common::Event::from(&event);
8686

8787
yield proto_event;
8888
}
@@ -106,7 +106,7 @@ fn create_event_filter(proto_filter: &grpc_events::EventFilter) -> Result<EventF
106106
match &proto_filter.filter {
107107
Some(Filter::All(_)) => Ok(EventFilter::All(vec![])),
108108
Some(Filter::Sender(f)) => {
109-
let sender = parse_iota_address(&f.sender, "Sender address")?;
109+
let sender = parse_iota_address(&f.address, "Sender address")?;
110110
Ok(EventFilter::Sender(sender))
111111
}
112112
Some(Filter::Transaction(f)) => {
@@ -174,7 +174,7 @@ fn parse_iota_address(
174174
}
175175

176176
fn parse_tx_digest(
177-
digest: &Option<grpc_common::TransactionDigest>,
177+
digest: &Option<grpc_common::Digest>,
178178
field_name: &str,
179179
) -> Result<TransactionDigest, Status> {
180180
let digest = digest

crates/iota-grpc-server/tests/event_e2e.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ const CLOCK_ACCESS_FUNCTION: &str = "access";
2121
// Event type names
2222
const NFT_MINTED_EVENT: &str = "NFTMinted";
2323

24-
// JSON field names for event validation
25-
const OBJECT_ID_FIELD: &str = "object_id";
26-
const CREATOR_FIELD: &str = "creator";
27-
const NAME_FIELD: &str = "name";
28-
2924
async fn setup_test_cluster() -> (TestCluster, EventClient, ObjectID, ObjectID) {
3025
let localhost = local_ip_utils::localhost_for_testing();
3126
let grpc_port = local_ip_utils::get_available_port(&localhost);
@@ -102,7 +97,7 @@ async fn test_event_filtering_and_bcs_serialization() {
10297
// Client 1: AllFilter - should receive all events
10398
let mut all_client = event_client.clone();
10499
let all_filter = grpc_events::EventFilter {
105-
filter: Some(Filter::All(grpc_events::AllFilter {})),
100+
filter: Some(Filter::All(grpc_common::AllFilter {})),
106101
};
107102
let mut all_stream = all_client
108103
.stream_events(all_filter)
@@ -112,8 +107,8 @@ async fn test_event_filtering_and_bcs_serialization() {
112107
// Client 2: SenderFilter - should receive only events from sender_1
113108
let mut sender_client = event_client.clone();
114109
let sender_filter = grpc_events::EventFilter {
115-
filter: Some(Filter::Sender(grpc_events::SenderFilter {
116-
sender: Some(grpc_common::Address {
110+
filter: Some(Filter::Sender(grpc_common::AddressFilter {
111+
address: Some(grpc_common::Address {
117112
address: sender_1.to_vec(),
118113
}),
119114
})),
@@ -126,7 +121,7 @@ async fn test_event_filtering_and_bcs_serialization() {
126121
// Client 3: MoveEventTypeFilter - should receive only NFT events
127122
let mut nft_client = event_client.clone();
128123
let nft_filter = grpc_events::EventFilter {
129-
filter: Some(Filter::MoveEventType(grpc_events::MoveEventTypeFilter {
124+
filter: Some(Filter::MoveEventType(grpc_common::MoveEventTypeFilter {
130125
package_id: Some(grpc_common::Address {
131126
address: nft_package_id.to_vec(),
132127
}),
@@ -272,12 +267,6 @@ async fn test_event_filtering_and_bcs_serialization() {
272267
);
273268
assert!(!event.bcs.bytes().is_empty(), "BCS data must be valid");
274269

275-
// Verify JSON structure for BCS deserialization
276-
let parsed_json = &event.parsed_json;
277-
assert!(parsed_json.get(OBJECT_ID_FIELD).is_some());
278-
assert!(parsed_json.get(CREATOR_FIELD).is_some());
279-
assert!(parsed_json.get(NAME_FIELD).is_some());
280-
281270
nft_events.push(event);
282271

283272
if nft_events.len() >= 3 {
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) 2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
syntax = "proto3";
5+
6+
package iota.grpc.v0.coin;
7+
8+
import "common.proto";
9+
10+
// Coin service provides access to coin-related data such as coins owned by an
11+
// address, balances, and coin metadata.
12+
service CoinService {
13+
// Get coins of a specific type owned by an address
14+
rpc GetCoins (GetCoinsRequest) returns (GetCoinsResponse);
15+
16+
// Get all coins owned by an address (all coin types)
17+
rpc GetAllCoins (GetAllCoinsRequest) returns (GetAllCoinsResponse);
18+
19+
// Get balance for a specific coin type
20+
rpc GetBalance (GetBalanceRequest) returns (GetBalanceResponse);
21+
22+
// Get all balances across all coin types
23+
rpc GetAllBalances (GetAllBalancesRequest) returns (GetAllBalancesResponse);
24+
25+
// Get coin metadata
26+
rpc GetCoinMetadata (GetCoinMetadataRequest) returns (GetCoinMetadataResponse);
27+
}
28+
29+
message GetCoinsRequest {
30+
// The owner's IOTA address
31+
iota.grpc.v0.common.Address owner = 1;
32+
33+
// Optional type name for the coin (e.g., 0x2::iota::IOTA)
34+
// Defaults to "0x2::iota::IOTA" if not specified
35+
optional string coin_type = 2;
36+
37+
// The maximum number of items to return per page
38+
// Default: 50, Max: 1000
39+
optional uint32 page_size = 3;
40+
41+
// Opaque pagination token from previous response
42+
// Token is BCS-encoded and should be treated as opaque by clients
43+
optional iota.grpc.v0.common.BcsData page_token = 4;
44+
}
45+
46+
message GetCoinsResponse {
47+
// List of coin objects
48+
repeated iota.grpc.v0.common.CoinInfo data = 1;
49+
50+
// Token for next page. If omitted, no more pages exist.
51+
// This is an opaque BCS-encoded token
52+
optional iota.grpc.v0.common.Bcs next_page_token = 2;
53+
}
54+
55+
message GetAllCoinsRequest {
56+
// The owner's IOTA address
57+
iota.grpc.v0.common.Address owner = 1;
58+
59+
// The maximum number of items to return per page
60+
// Default: 50, Max: 1000
61+
optional uint32 page_size = 2;
62+
63+
// Opaque pagination token from previous response
64+
// Token is BCS-encoded and should be treated as opaque by clients
65+
optional iota.grpc.v0.common.BcsData page_token = 3;
66+
}
67+
68+
message GetAllCoinsResponse {
69+
// List of coin objects
70+
repeated iota.grpc.v0.common.CoinInfo data = 1;
71+
72+
// Token for next page. If omitted, no more pages exist.
73+
// This is an opaque BCS-encoded token
74+
optional iota.grpc.v0.common.Bcs next_page_token = 2;
75+
}
76+
77+
// GetBalance - Return the total coin balance for one coin type
78+
message GetBalanceRequest {
79+
// The owner's IOTA address
80+
iota.grpc.v0.common.Address owner = 1;
81+
82+
// Optional type name for the coin (e.g., 0x2::iota::IOTA)
83+
// Defaults to "0x2::iota::IOTA" if not specified
84+
optional string coin_type = 2;
85+
}
86+
87+
message GetBalanceResponse {
88+
iota.grpc.v0.common.BalanceInfo balances = 1;
89+
}
90+
91+
// GetAllBalances - Return the total coin balance for all coin types
92+
message GetAllBalancesRequest {
93+
// The owner's IOTA address
94+
iota.grpc.v0.common.Address owner = 1;
95+
}
96+
97+
message GetAllBalancesResponse {
98+
// List of balances for all coin types
99+
repeated iota.grpc.v0.common.BalanceInfo balances = 1;
100+
}
101+
102+
// GetCoinMetadata - Return metadata for a coin
103+
message GetCoinMetadataRequest {
104+
// Type name for the coin (e.g., 0x2::iota::IOTA)
105+
string coin_type = 1;
106+
}
107+
108+
message GetCoinMetadataResponse {
109+
// BCS-encoded iota_types::coin::CoinMetadata
110+
optional iota.grpc.v0.common.Bcs metadata = 1;
111+
}

0 commit comments

Comments
 (0)