Skip to content

Commit d6053fd

Browse files
committed
feat: transaction subscriber and node services
1 parent 077daea commit d6053fd

27 files changed

+2231
-102
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/iota-core/src/subscription_handler.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,11 @@ impl EventSubscriber for SubscriptionHandler {
134134
) -> Box<dyn futures::Stream<Item = IotaEvent> + Send + Unpin> {
135135
Box::new(Box::pin(self.event_streamer.subscribe(filter)))
136136
}
137+
138+
fn subscribe_transactions(
139+
&self,
140+
filter: TransactionFilter,
141+
) -> Box<dyn futures::Stream<Item = IotaTransactionBlockEffects> + Send + Unpin> {
142+
Box::new(Box::pin(self.transaction_streamer.subscribe(filter)))
143+
}
137144
}

crates/iota-grpc-api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ tonic.workspace = true
2525
tracing.workspace = true
2626

2727
# internal dependencies
28+
fastcrypto.workspace = true
2829
iota-grpc-types.workspace = true
2930
iota-json-rpc-types.workspace = true
3031
iota-types.workspace = true

crates/iota-grpc-api/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ fn main() {
66
.compile_protos(
77
&[
88
"proto/common.proto",
9+
"proto/node.proto",
910
"proto/checkpoint.proto",
1011
"proto/event.proto",
12+
"proto/transaction.proto",
1113
],
1214
&["proto/"],
1315
)

crates/iota-grpc-api/proto/checkpoint.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ service CheckpointService {
1111
// Checkpoint operations
1212
rpc StreamCheckpoints (CheckpointStreamRequest) returns (stream Checkpoint);
1313
rpc GetEpochFirstCheckpointSequenceNumber (EpochRequest) returns (CheckpointSequenceNumberResponse);
14+
rpc GetLatestCheckpoint (GetLatestCheckpointRequest) returns (Checkpoint);
1415
}
1516

1617
message CheckpointStreamRequest {
@@ -28,6 +29,12 @@ message CheckpointSequenceNumberResponse {
2829
uint64 sequence_number = 1;
2930
}
3031

32+
// Get the latest checkpoint information
33+
message GetLatestCheckpointRequest {
34+
// If true, get the full CheckpointData (not just the summary).
35+
bool full = 1;
36+
}
37+
3138
message Checkpoint {
3239
uint64 sequence_number = 1;
3340
// Indicates whether bcs_data contains full CheckpointData (true) or just CertifiedCheckpointSummary (false)

crates/iota-grpc-api/proto/common.proto

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,47 @@ message Address {
1515
bytes address = 1;
1616
}
1717

18-
// 32-byte Transaction digest
19-
message TransactionDigest {
18+
// Generic 32-byte digest (used for transactions, objects, etc.)
19+
message Digest {
2020
bytes digest = 1;
2121
}
22+
23+
// Match all events (catch-all filter)
24+
message AllFilter {
25+
}
26+
27+
// Filter by address (sender, package, etc.)
28+
message AddressFilter {
29+
Address address = 1;
30+
}
31+
32+
// Filter by transaction digest
33+
message TransactionDigestFilter {
34+
Digest tx_digest = 1;
35+
}
36+
37+
// Filter by Move module (package + module)
38+
message MoveModuleFilter {
39+
Address package_id = 1; // Package ID
40+
string module = 2; // Module name
41+
}
42+
43+
// Filter by Move event type (package + module + event name)
44+
message MoveEventTypeFilter {
45+
Address package_id = 1; // Package ID
46+
string module = 2; // Module name
47+
string name = 3; // Event name
48+
}
49+
50+
// Filter by Move event module (package + module)
51+
message MoveEventModuleFilter {
52+
Address package_id = 1; // Package ID
53+
string module = 2; // Module name
54+
}
55+
56+
// Filter by Move function (package + module + function)
57+
message MoveFunctionFilter {
58+
Address package_id = 1; // Package ID
59+
optional string module = 2; // Module name (optional)
60+
optional string function = 3; // Function name (optional)
61+
}

crates/iota-grpc-api/proto/event.proto

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -28,58 +28,24 @@ message Event {
2828

2929
message EventID {
3030
uint64 event_seq = 1;
31-
iota.grpc.common.TransactionDigest tx_digest = 2;
31+
iota.grpc.common.Digest tx_digest = 2;
3232
}
3333

3434
// Rich event filter that supports gRPC event filtering
3535
message EventFilter {
3636
oneof filter {
37-
AllFilter all = 1;
38-
SenderFilter sender = 2;
39-
TransactionFilter transaction = 3;
40-
MoveModuleFilter move_module = 4;
41-
MoveEventTypeFilter move_event_type = 5;
42-
MoveEventModuleFilter move_event_module = 6;
37+
iota.grpc.common.AllFilter all = 1;
38+
iota.grpc.common.AddressFilter sender = 2;
39+
iota.grpc.common.TransactionDigestFilter transaction = 3;
40+
iota.grpc.common.MoveModuleFilter move_module = 4;
41+
iota.grpc.common.MoveEventTypeFilter move_event_type = 5;
42+
iota.grpc.common.MoveEventModuleFilter move_event_module = 6;
4343
TimeRangeFilter time_range = 7;
4444
}
4545
}
4646

47-
// Match all events (catch-all filter)
48-
message AllFilter {
49-
// Empty - matches all events
50-
}
51-
52-
// Filter by sender address
53-
message SenderFilter {
54-
iota.grpc.common.Address sender = 1; // Sender address
55-
}
56-
57-
// Filter by transaction digest
58-
message TransactionFilter {
59-
iota.grpc.common.TransactionDigest tx_digest = 1; // Transaction digest
60-
}
61-
62-
// Filter by transaction execution module (different from event definition module)
63-
message MoveModuleFilter {
64-
iota.grpc.common.Address package_id = 1; // Package ID
65-
string module = 2; // Module name
66-
}
67-
68-
// Filter by Move event type (package::module::event_name)
69-
message MoveEventTypeFilter {
70-
iota.grpc.common.Address package_id = 1; // Package ID
71-
string module = 2; // Module name (e.g., "request")
72-
string name = 3; // Event name (e.g., "RequestEvent")
73-
}
74-
75-
// Filter by package and module
76-
message MoveEventModuleFilter {
77-
iota.grpc.common.Address package_id = 1; // Package ID
78-
string module = 2; // Module name
79-
}
80-
8147
// Filter by timestamp range
8248
message TimeRangeFilter {
8349
uint64 start_time = 1; // Start time in milliseconds since epoch (inclusive)
8450
uint64 end_time = 2; // End time in milliseconds since epoch (exclusive)
85-
}
51+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright (c) 2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
syntax = "proto3";
5+
6+
package iota.grpc.node;
7+
8+
import "common.proto";
9+
10+
service NodeService {
11+
rpc ExecuteTransaction (ExecuteTransactionRequest) returns (ExecuteTransactionResponse);
12+
rpc GetObject (GetObjectRequest) returns (GetObjectResponse);
13+
}
14+
15+
// ExecuteTransaction
16+
message ExecuteTransactionRequest {
17+
// BCS serialized transaction data bytes
18+
bytes tx_bytes = 1;
19+
// List of signatures
20+
repeated bytes signatures = 2;
21+
// Options for specifying the content to be returned
22+
optional TransactionResponseOptions options = 3;
23+
// The request type
24+
optional ExecuteTransactionRequestType request_type = 4;
25+
}
26+
27+
message TransactionResponseOptions {
28+
bool show_input = 1;
29+
bool show_raw_input = 2;
30+
bool show_effects = 3;
31+
bool show_events = 4;
32+
bool show_object_changes = 5;
33+
bool show_balance_changes = 6;
34+
bool show_raw_effects = 7;
35+
}
36+
37+
enum ExecuteTransactionRequestType {
38+
WAIT_FOR_EFFECTS_CERT = 0;
39+
WAIT_FOR_LOCAL_EXECUTION = 1;
40+
}
41+
42+
message ExecuteTransactionResponse {
43+
// Transaction digest
44+
iota.grpc.common.Digest digest = 1;
45+
// Transaction data (if show_input or show_raw_input is true)
46+
optional iota.grpc.common.BcsData transaction = 2;
47+
// Raw transaction bytes (if show_raw_input is true)
48+
optional bytes raw_transaction = 3;
49+
// Transaction effects (if show_effects is true)
50+
optional iota.grpc.common.BcsData effects = 4;
51+
// Events (if show_events is true)
52+
repeated iota.grpc.common.BcsData events = 5;
53+
// Object changes (if show_object_changes is true)
54+
repeated iota.grpc.common.BcsData object_changes = 6;
55+
// Balance changes (if show_balance_changes is true)
56+
repeated iota.grpc.common.BcsData balance_changes = 7;
57+
// Timestamp when transaction was executed
58+
optional uint64 timestamp_ms = 8;
59+
// Whether the transaction was confirmed locally
60+
optional bool confirmed_local_execution = 9;
61+
// Checkpoint sequence number (if available)
62+
optional uint64 checkpoint = 10;
63+
// Error messages (if any)
64+
repeated string errors = 11;
65+
// Raw effects (if show_raw_effects is true)
66+
optional bytes raw_effects = 12;
67+
}
68+
69+
// GetObject - corresponds to REST API GetObject
70+
message GetObjectRequest {
71+
// Object ID to retrieve
72+
iota.grpc.common.Address object_id = 1;
73+
// Options for specifying the content to be returned
74+
optional ObjectDataOptions options = 2;
75+
}
76+
77+
message ObjectDataOptions {
78+
bool show_type = 1;
79+
bool show_owner = 2;
80+
bool show_previous_transaction = 3;
81+
bool show_display = 4;
82+
bool show_content = 5;
83+
bool show_bcs = 6;
84+
bool show_storage_rebate = 7;
85+
}
86+
87+
message GetObjectResponse {
88+
// Object data (if exists)
89+
optional ObjectData data = 1;
90+
// Error (if object doesn't exist or other error)
91+
optional ObjectError error = 2;
92+
}
93+
94+
message ObjectData {
95+
// Object ID
96+
iota.grpc.common.Address object_id = 1;
97+
// Object version
98+
uint64 version = 2;
99+
// Object digest
100+
iota.grpc.common.Digest digest = 3;
101+
// Object type (if show_type is true)
102+
optional string type = 4;
103+
// Object owner (if show_owner is true)
104+
optional string owner = 5;
105+
// Previous transaction digest (if show_previous_transaction is true)
106+
optional iota.grpc.common.Digest previous_transaction = 6;
107+
// Storage rebate (if show_storage_rebate is true)
108+
optional uint64 storage_rebate = 7;
109+
// Display fields (if show_display is true)
110+
optional iota.grpc.common.BcsData display = 8;
111+
// Parsed content data (if show_content is true)
112+
optional iota.grpc.common.BcsData content = 9;
113+
// BCS raw data (if show_bcs is true)
114+
optional iota.grpc.common.BcsData bcs = 10;
115+
}
116+
117+
message ObjectError {
118+
oneof error {
119+
NotExistsError not_exists = 1;
120+
DynamicFieldNotFoundError dynamic_field_not_found = 2;
121+
DeletedError deleted = 3;
122+
UnknownError unknown = 4;
123+
DisplayError display = 5;
124+
VersionNotFoundError version_not_found = 6;
125+
VersionTooHighError version_too_high = 7;
126+
}
127+
}
128+
129+
message NotExistsError {
130+
iota.grpc.common.Address object_id = 1;
131+
}
132+
133+
message DynamicFieldNotFoundError {
134+
iota.grpc.common.Address parent_object_id = 1;
135+
}
136+
137+
message DeletedError {
138+
iota.grpc.common.Address object_id = 1;
139+
uint64 version = 2;
140+
iota.grpc.common.Digest digest = 3;
141+
}
142+
143+
message UnknownError {
144+
optional string error_message = 1;
145+
}
146+
147+
message DisplayError {
148+
string error_message = 1;
149+
}
150+
151+
message VersionNotFoundError {
152+
iota.grpc.common.Address object_id = 1;
153+
uint64 asked_version = 2;
154+
}
155+
156+
message VersionTooHighError {
157+
iota.grpc.common.Address object_id = 1;
158+
uint64 asked_version = 2;
159+
uint64 latest_version = 3;
160+
}

0 commit comments

Comments
 (0)