Skip to content

Commit 707e542

Browse files
committed
init: transaction subscriber and node services
1 parent 91a9304 commit 707e542

26 files changed

+2003
-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, return full CheckpointData; if false, return just CertifiedCheckpointSummary
35+
bool is_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 (no filtering)
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 for events)
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 for transactions)
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: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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+
// Error type (e.g., "NotExists")
119+
string error_type = 1;
120+
// Object ID that caused the error
121+
iota.grpc.common.Address object_id = 2;
122+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (c) 2025 IOTA Stiftung
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
syntax = "proto3";
5+
6+
package iota.grpc.transactions;
7+
8+
import "common.proto";
9+
10+
// Transaction subscription service
11+
service TransactionService {
12+
rpc StreamTransactions (TransactionStreamRequest) returns (stream Transaction);
13+
}
14+
15+
// Request to stream transactions with optional filtering
16+
message TransactionStreamRequest {
17+
TransactionFilter filter = 1;
18+
}
19+
20+
// Transaction data structure
21+
message Transaction {
22+
iota.grpc.common.Digest transaction_digest = 1;
23+
iota.grpc.common.BcsData effects = 2;
24+
string effects_json = 3;
25+
}
26+
27+
// Rich transaction filter that supports gRPC transaction filtering
28+
message TransactionFilter {
29+
oneof filter {
30+
iota.grpc.common.AllFilter all = 1;
31+
CheckpointFilter checkpoint = 2;
32+
iota.grpc.common.MoveFunctionFilter move_function = 3;
33+
InputObjectFilter input_object = 4;
34+
ChangedObjectFilter changed_object = 5;
35+
iota.grpc.common.AddressFilter from_address = 6;
36+
iota.grpc.common.AddressFilter to_address = 7;
37+
FromAndToAddressFilter from_and_to_address = 8;
38+
iota.grpc.common.AddressFilter from_or_to_address = 9;
39+
TransactionKindFilter transaction_kind = 10;
40+
TransactionKindInFilter transaction_kind_in = 11;
41+
}
42+
}
43+
44+
// Filter by checkpoint sequence number
45+
message CheckpointFilter {
46+
uint64 checkpoint = 1;
47+
}
48+
49+
// Filter by input object ID
50+
message InputObjectFilter {
51+
iota.grpc.common.Address object_id = 1;
52+
}
53+
54+
// Filter by changed object ID (created, mutated, unwrapped)
55+
message ChangedObjectFilter {
56+
iota.grpc.common.Address object_id = 1;
57+
}
58+
59+
60+
// Filter by sender and recipient addresses
61+
message FromAndToAddressFilter {
62+
iota.grpc.common.Address from_address = 1;
63+
iota.grpc.common.Address to_address = 2;
64+
}
65+
66+
67+
// Filter by transaction kind
68+
message TransactionKindFilter {
69+
TransactionKind kind = 1;
70+
}
71+
72+
// Filter by transaction kinds (any of the specified kinds)
73+
message TransactionKindInFilter {
74+
repeated TransactionKind kinds = 1;
75+
}
76+
77+
// Transaction kinds
78+
enum TransactionKind {
79+
SYSTEM_TRANSACTION = 0;
80+
PROGRAMMABLE_TRANSACTION = 1;
81+
GENESIS = 2;
82+
CONSENSUS_COMMIT_PROLOGUE_V1 = 3;
83+
AUTHENTICATOR_STATE_UPDATE_V1 = 4;
84+
RANDOMNESS_STATE_UPDATE = 5;
85+
END_OF_EPOCH_TRANSACTION = 6;
86+
}
87+

0 commit comments

Comments
 (0)