Skip to content

Commit f8b13bb

Browse files
committed
move all routes
1 parent 332f726 commit f8b13bb

File tree

4 files changed

+97
-128
lines changed

4 files changed

+97
-128
lines changed

server/src/http/routes/contract_encode.rs

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// 8:12 PM - COLOCATION: Contract Encode Operations
22

3-
use aide::{axum::IntoApiResponse, transform::TransformOperation};
43
use alloy::{hex, primitives::ChainId};
5-
use axum::{extract::State, http::StatusCode, response::Json};
4+
use axum::{
5+
extract::State,
6+
http::StatusCode,
7+
response::{IntoResponse, Json},
8+
};
69
use engine_core::error::EngineError;
710
use futures::future::join_all;
811
use schemars::JsonSchema;
@@ -20,7 +23,7 @@ use crate::http::{
2023
// ===== REQUEST/RESPONSE TYPES =====
2124

2225
/// Options for encoding contract function calls
23-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
2427
#[serde(rename_all = "camelCase")]
2528
pub struct EncodeOptions {
2629
/// The blockchain network ID to encode for
@@ -30,7 +33,7 @@ pub struct EncodeOptions {
3033
}
3134

3235
/// Request to encode contract function calls
33-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
36+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
3437
#[serde(rename_all = "camelCase")]
3538
pub struct EncodeRequest {
3639
/// Configuration options for encoding
@@ -45,19 +48,20 @@ pub struct EncodeRequest {
4548
///
4649
/// Each result can either be successful (containing the encoded transaction data)
4750
/// or failed (containing detailed error information).
48-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
51+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
4952
#[serde(untagged)]
5053
pub enum EncodeResultItem {
5154
Success(EncodeResultSuccessItem),
5255
Failure(EncodeResultFailureItem),
5356
}
5457

5558
/// Successful result from a contract encode operation
56-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
59+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
5760
#[serde(rename_all = "camelCase")]
5861
pub struct EncodeResultSuccessItem {
5962
/// Always true for successful operations
6063
#[schemars(with = "bool")]
64+
#[schema(value_type = bool)]
6165
pub success: serde_bool::True,
6266
/// The contract address that would be called
6367
pub target: String,
@@ -73,24 +77,25 @@ pub struct EncodeResultSuccessItem {
7377
}
7478

7579
/// Failed result from a contract encode operation
76-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
80+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
7781
pub struct EncodeResultFailureItem {
7882
/// Always false for failed operations
7983
#[schemars(with = "bool")]
84+
#[schema(value_type = bool)]
8085
pub success: serde_bool::False,
8186
/// Detailed error information describing what went wrong
8287
pub error: EngineError,
8388
}
8489

8590
/// Collection of results from multiple contract encode operations
86-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
91+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
8792
pub struct EncodeResults {
8893
/// Array of results, one for each input contract call
8994
pub results: Vec<EncodeResultItem>,
9095
}
9196

9297
/// Response from the contract encode endpoint
93-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
98+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
9499
pub struct EncodeResponse {
95100
/// Container for all encode operation results
96101
pub result: EncodeResults,
@@ -150,12 +155,29 @@ impl EncodeResultItem {
150155

151156
// ===== ROUTE HANDLER =====
152157

158+
#[utoipa::path(
159+
post,
160+
operation_id = "encodeContract",
161+
path = "/encode/contract",
162+
tag = "Read",
163+
request_body(content = EncodeRequest, description = "Encode contract request", content_type = "application/json"),
164+
responses(
165+
(status = 200, description = "Successfully encoded contract calls", body = EncodeResponse, content_type = "application/json"),
166+
),
167+
params(
168+
("x-thirdweb-client-id" = Option<String>, Header, description = "Thirdweb client ID, passed along with the service key"),
169+
("x-thirdweb-service-key" = Option<String>, Header, description = "Thirdweb service key, passed when using the client ID"),
170+
("x-thirdweb-secret-key" = Option<String>, Header, description = "Thirdweb secret key, passed standalone"),
171+
)
172+
)]
173+
/// Encode Contract
174+
///
153175
/// Encode contract function calls without execution
154176
pub async fn encode_contract(
155177
State(state): State<EngineServerState>,
156178
OptionalRpcCredentialsExtractor(rpc_credentials): OptionalRpcCredentialsExtractor,
157179
EngineJson(request): EngineJson<EncodeRequest>,
158-
) -> Result<impl IntoApiResponse, ApiEngineError> {
180+
) -> Result<impl IntoResponse, ApiEngineError> {
159181
let auth: Option<ThirdwebAuth> = rpc_credentials.map(|creds| match creds {
160182
engine_core::chain::RpcCredentials::Thirdweb(auth) => auth,
161183
});
@@ -203,33 +225,3 @@ pub async fn encode_contract(
203225
}),
204226
))
205227
}
206-
207-
// ===== DOCUMENTATION =====
208-
209-
pub fn encode_contract_docs(op: TransformOperation) -> TransformOperation {
210-
op.id("encodeContract")
211-
.description(
212-
"Encode contract function calls without execution.\n\n\
213-
This endpoint prepares contract function calls and returns the encoded \
214-
transaction data without executing them. This is useful for:\n\
215-
- Preparing transaction data for later execution\n\
216-
- Debugging contract interactions\n\
217-
- Building complex transaction batches\n\
218-
- Integration with external signing systems\n\n\
219-
## Features\n\
220-
- Encode multiple contract calls in one request\n\
221-
- Automatic ABI resolution or use provided ABIs\n\
222-
- Returns function selector, call data, and metadata\n\
223-
- Detailed error information for each failed encoding\n\n\
224-
## Authentication\n\
225-
- Optional: Same as read endpoint for ABI resolution",
226-
)
227-
.summary("Encode contract call data")
228-
.response_with::<200, Json<EncodeResponse>, _>(|res| {
229-
res.description("Successfully encoded contract calls")
230-
})
231-
.response_with::<400, Json<ErrorResponse>, _>(|res| {
232-
res.description("Bad request - invalid parameters")
233-
})
234-
.tag("Contract Operations")
235-
}

server/src/http/routes/contract_read.rs

Lines changed: 34 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
// 8:12 PM - COLOCATION: Contract Read Operations
22

3-
use aide::{axum::IntoApiResponse, transform::TransformOperation};
43
use alloy::dyn_abi::FunctionExt;
54
use alloy::primitives::{Address, ChainId, address};
65
use alloy::providers::RootProvider;
76
use alloy::{
87
providers::Provider, rpc::types::eth::TransactionRequest as AlloyTransactionRequest, sol,
98
sol_types::SolCall,
109
};
11-
use axum::{extract::State, http::StatusCode, response::Json};
10+
use axum::{
11+
extract::State,
12+
http::StatusCode,
13+
response::{IntoResponse, Json},
14+
};
1215
use engine_core::{
1316
chain::{Chain, ChainService},
1417
defs::AddressDef,
@@ -52,7 +55,7 @@ const MULTICALL3_DEFAULT_ADDRESS: Address = address!("0xcA11bde05977b36311670288
5255
// ===== REQUEST/RESPONSE TYPES =====
5356

5457
/// Options for reading from smart contracts
55-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
58+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
5659
#[serde(rename_all = "camelCase")]
5760
pub struct ReadOptions {
5861
/// The blockchain network ID to read from
@@ -63,13 +66,15 @@ pub struct ReadOptions {
6366
/// which is deployed on most networks
6467
#[serde(default = "default_multicall_address")]
6568
#[schemars(with = "AddressDef")]
69+
#[schema(value_type = AddressDef)]
6670
pub multicall_address: Address,
6771
/// Optional address to use as the caller for view functions
6872
///
6973
/// This can be useful for functions that return different values
7074
/// based on the caller's address or permissions
7175
#[serde(skip_serializing_if = "Option::is_none")]
7276
#[schemars(with = "Option<AddressDef>")]
77+
#[schema(value_type = Option<AddressDef>)]
7378
pub from: Option<Address>,
7479
}
7580

@@ -78,7 +83,7 @@ fn default_multicall_address() -> Address {
7883
}
7984

8085
/// Request to read from multiple smart contracts
81-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
86+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
8287
#[serde(rename_all = "camelCase")]
8388
pub struct ReadRequest {
8489
/// Configuration options for the read operation
@@ -94,18 +99,19 @@ pub struct ReadRequest {
9499
/// Each result can either be successful (containing the function return value)
95100
/// or failed (containing detailed error information). The `success` field
96101
/// indicates which case applies.
97-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
102+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
98103
#[serde(untagged)]
99104
pub enum ReadResultItem {
100105
Success(ReadResultSuccessItem),
101106
Failure(ReadResultFailureItem),
102107
}
103108

104109
/// Successful result from a contract read operation
105-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
110+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
106111
pub struct ReadResultSuccessItem {
107112
/// Always true for successful operations
108113
#[schemars(with = "bool")]
114+
#[schema(value_type = bool)]
109115
pub success: serde_bool::True,
110116
/// The decoded return value from the contract function
111117
///
@@ -115,10 +121,11 @@ pub struct ReadResultSuccessItem {
115121
}
116122

117123
/// Failed result from a contract read operation
118-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
124+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
119125
pub struct ReadResultFailureItem {
120126
/// Always false for failed operations
121127
#[schemars(with = "bool")]
128+
#[schema(value_type = bool)]
122129
pub success: serde_bool::False,
123130
/// Detailed error information describing what went wrong
124131
///
@@ -128,7 +135,7 @@ pub struct ReadResultFailureItem {
128135
}
129136

130137
/// Collection of results from multiple contract read operations
131-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
138+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
132139
pub struct ReadResults {
133140
/// Array of results, one for each input contract call
134141
///
@@ -137,7 +144,7 @@ pub struct ReadResults {
137144
}
138145

139146
/// Response from the contract read endpoint
140-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
147+
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
141148
pub struct ReadResponse {
142149
/// Container for all read operation results
143150
pub result: ReadResults,
@@ -179,12 +186,29 @@ impl ReadResultItem {
179186

180187
// ===== ROUTE HANDLER =====
181188

189+
#[utoipa::path(
190+
post,
191+
operation_id = "readContract",
192+
path = "/read/contract",
193+
tag = "Read",
194+
request_body(content = ReadRequest, description = "Read contract request", content_type = "application/json"),
195+
responses(
196+
(status = 200, description = "Successfully read contract data", body = ReadResponse, content_type = "application/json"),
197+
),
198+
params(
199+
("x-thirdweb-client-id" = Option<String>, Header, description = "Thirdweb client ID, passed along with the service key"),
200+
("x-thirdweb-service-key" = Option<String>, Header, description = "Thirdweb service key, passed when using the client ID"),
201+
("x-thirdweb-secret-key" = Option<String>, Header, description = "Thirdweb secret key, passed standalone"),
202+
)
203+
)]
204+
/// Read Contract
205+
///
182206
/// Read from multiple smart contracts using multicall
183207
pub async fn read_contract(
184208
State(state): State<EngineServerState>,
185209
OptionalRpcCredentialsExtractor(rpc_credentials): OptionalRpcCredentialsExtractor,
186210
EngineJson(request): EngineJson<ReadRequest>,
187-
) -> Result<impl IntoApiResponse, ApiEngineError> {
211+
) -> Result<impl IntoResponse, ApiEngineError> {
188212
let auth: Option<ThirdwebAuth> = rpc_credentials.and_then(|creds| match creds {
189213
engine_core::chain::RpcCredentials::Thirdweb(auth) => Some(auth),
190214
});
@@ -355,44 +379,3 @@ fn process_multicall_result(
355379
}
356380
}
357381

358-
// ===== DOCUMENTATION =====
359-
360-
pub fn read_contract_docs(op: TransformOperation) -> TransformOperation {
361-
op.id("readContract")
362-
.description(
363-
"Read from multiple smart contracts using multicall.\n\n\
364-
This endpoint allows you to efficiently call multiple read-only contract functions \
365-
in a single request. All calls are batched using the Multicall3 contract for \
366-
optimal gas usage and performance.\n\n\
367-
## Features\n\
368-
- Batch multiple contract calls in one request\n\
369-
- Automatic ABI resolution or use provided ABIs\n\
370-
- Support for function names, signatures, or full function declarations\n\
371-
- Detailed error information for each failed call\n\
372-
- Preserves original parameter order in results\n\n\
373-
## Authentication\n\
374-
- Optional: Provide `x-thirdweb-secret-key` or `x-thirdweb-client-id` + `x-thirdweb-service-key`\n\
375-
- If provided, will be used for ABI resolution from verified contracts\n\n\
376-
## Error Handling\n\
377-
- Individual call failures don't affect other calls\n\
378-
- Each result includes success status and detailed error information\n\
379-
- Preparation errors (ABI resolution, parameter encoding) are preserved\n\
380-
- Execution errors (multicall failures) are clearly identified"
381-
)
382-
.summary("Batch read contract functions")
383-
.response_with::<200, Json<ReadResponse>, _>(|res| {
384-
res.description("Successfully read contract data")
385-
.example(ReadResponse {
386-
result: ReadResults {
387-
results: vec![],
388-
},
389-
})
390-
})
391-
.response_with::<400, Json<ErrorResponse>, _>(|res| {
392-
res.description("Bad request - invalid parameters or chain ID")
393-
})
394-
.response_with::<500, Json<ErrorResponse>, _>(|res| {
395-
res.description("Internal server error")
396-
})
397-
.tag("Contract Operations")
398-
}

0 commit comments

Comments
 (0)