Skip to content

Commit 70dd5e2

Browse files
committed
signing routes compiling
1 parent ed8f549 commit 70dd5e2

File tree

6 files changed

+133
-48
lines changed

6 files changed

+133
-48
lines changed

aa-core/src/signer.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use alloy::{
24
dyn_abi::TypedData,
35
hex::FromHex,
@@ -44,15 +46,15 @@ const ERC6492_MAGIC_SUFFIX: [u8; 32] =
4446

4547
/// Builder for creating SmartAccountSigner with computed address and factory pattern detection
4648
pub struct SmartAccountSignerBuilder<C: Chain> {
47-
eoa_signer: EoaSigner,
49+
eoa_signer: Arc<EoaSigner>,
4850
credentials: SigningCredential,
4951
options: SmartAccountSigningOptions,
5052
chain: C,
5153
}
5254

5355
impl<C: Chain + Clone> SmartAccountSignerBuilder<C> {
5456
pub fn new(
55-
eoa_signer: EoaSigner,
57+
eoa_signer: Arc<EoaSigner>,
5658
credentials: SigningCredential,
5759
options: SmartAccountSigningOptions,
5860
chain: C,
@@ -142,7 +144,7 @@ pub struct SmartAccountSigner<C: Chain> {
142144
options: SmartAccountSigningOptions,
143145
credentials: SigningCredential,
144146
chain: C,
145-
eoa_signer: EoaSigner,
147+
eoa_signer: Arc<EoaSigner>,
146148
smart_account: DeterminedSmartAccount,
147149
init_calldata: Vec<u8>,
148150
supports_712_factory: bool,

core/src/signer.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ use vault_sdk::VaultClient;
1010
use vault_types::enclave::encrypted::eoa::MessageFormat;
1111

1212
use crate::{
13-
chain::Chain,
14-
credentials::{self, SigningCredential},
13+
credentials::SigningCredential,
1514
defs::AddressDef,
1615
error::EngineError,
1716
execution_options::aa::{EntrypointAndFactoryDetails, EntrypointAndFactoryDetailsDeserHelper},
@@ -65,9 +64,11 @@ pub struct SmartAccountSigningOptions {
6564
pub enum SigningOptions {
6665
/// Standard EOA (Externally Owned Account) signing
6766
#[serde(rename = "eoa")]
67+
#[schema(title = "EOA Signing Options")]
6868
Eoa(EoaSigningOptions),
6969
/// Smart Account signing with advanced signature patterns
7070
#[serde(rename = "smart_account")]
71+
#[schema(title = "Smart Account Signing Options")]
7172
SmartAccount(SmartAccountSigningOptions),
7273
}
7374

server/src/http/routes/sign_message.rs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,52 @@
1-
// Sign Message Operations
2-
3-
use alloy::primitives::{Address, ChainId};
41
use axum::{
52
extract::State,
63
http::StatusCode,
74
response::{IntoResponse, Json},
85
};
6+
use engine_aa_core::signer::SmartAccountSignerBuilder;
97
use engine_core::{
10-
error::EngineError,
11-
signer::{EoaSigner, SigningOptions, SmartAccountSigningOptions},
8+
chain::ChainService,
129
credentials::SigningCredential,
10+
error::EngineError,
11+
signer::{AccountSigner, SigningOptions},
1312
};
14-
use engine_aa_core::signer::{SmartAccountSigner, SmartAccountSignerBuilder};
1513
use futures::future::join_all;
1614
use schemars::JsonSchema;
1715
use serde::{Deserialize, Serialize};
18-
use thirdweb_core::auth::ThirdwebAuth;
1916
use vault_types::enclave::encrypted::eoa::MessageFormat;
2017

2118
use crate::http::{
2219
error::ApiEngineError,
2320
extractors::{EngineJson, SigningCredentialsExtractor},
2421
server::EngineServerState,
25-
types::ErrorResponse,
2622
};
2723

2824
// ===== REQUEST/RESPONSE TYPES =====
29-
30-
/// Options for signing messages
31-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
32-
#[serde(rename_all = "camelCase")]
33-
pub struct SignOptions {
34-
/// Configuration options for signing
35-
#[serde(flatten)]
36-
pub signing_options: SigningOptions,
37-
}
38-
3925
/// Individual message to sign
40-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
26+
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
4127
#[serde(rename_all = "camelCase")]
4228
pub struct MessageInput {
4329
/// The message to sign
4430
pub message: String,
4531
/// Message format (text or hex)
4632
#[serde(default = "default_message_format")]
33+
#[schema(value_type = MessageFormatDef)]
4734
pub format: MessageFormat,
4835
}
4936

37+
#[derive(Serialize, Deserialize, Debug, Clone, Copy, utoipa::ToSchema)]
38+
#[serde(rename_all = "lowercase")]
39+
pub enum MessageFormatDef {
40+
Text,
41+
Hex,
42+
}
43+
5044
/// Request to sign messages
51-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
45+
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
5246
#[serde(rename_all = "camelCase")]
5347
pub struct SignMessageRequest {
5448
/// Configuration options for signing
55-
pub sign_options: SignOptions,
49+
pub signing_options: SigningOptions,
5650
/// List of messages to sign
5751
pub params: Vec<MessageInput>,
5852
}
@@ -177,7 +171,12 @@ pub async fn sign_message(
177171
) -> Result<impl IntoResponse, ApiEngineError> {
178172
// Process all messages in parallel
179173
let sign_futures = request.params.iter().map(|message_input| {
180-
sign_single_message(&state, &signing_credential, &request.sign_options.signing_options, message_input)
174+
sign_single_message(
175+
&state,
176+
&signing_credential,
177+
&request.signing_options,
178+
message_input,
179+
)
181180
});
182181

183182
let results: Vec<SignResultItem> = join_all(sign_futures).await;
@@ -201,7 +200,8 @@ async fn sign_single_message(
201200
let result = match signing_options {
202201
SigningOptions::Eoa(eoa_options) => {
203202
// Direct EOA signing
204-
state.eoa_signer
203+
state
204+
.eoa_signer
205205
.sign_message(
206206
eoa_options.clone(),
207207
&message_input.message,
@@ -232,7 +232,10 @@ async fn sign_single_message(
232232
}
233233
}
234234
Err(e) => Err(EngineError::ValidationError {
235-
message: format!("Failed to get chain {}: {}", smart_account_options.chain_id, e),
235+
message: format!(
236+
"Failed to get chain {}: {}",
237+
smart_account_options.chain_id, e
238+
),
236239
}),
237240
}
238241
}
@@ -246,4 +249,4 @@ async fn sign_single_message(
246249

247250
fn default_message_format() -> MessageFormat {
248251
MessageFormat::Text
249-
}
252+
}

server/src/http/routes/sign_typed_data.rs

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
// Sign Typed Data Operations
22

3-
use alloy::{dyn_abi::TypedData, primitives::Address};
3+
use alloy::dyn_abi::TypedData;
44
use axum::{
55
extract::State,
66
http::StatusCode,
77
response::{IntoResponse, Json},
88
};
9+
use engine_aa_core::signer::SmartAccountSignerBuilder;
910
use engine_core::{
10-
error::EngineError,
11-
signer::{EoaSigner, SigningOptions, SmartAccountSigningOptions},
11+
chain::ChainService,
1212
credentials::SigningCredential,
13+
defs::{AddressDef, U256Def},
14+
error::EngineError,
15+
signer::{AccountSigner, SigningOptions},
1316
};
14-
use engine_aa_core::signer::{SmartAccountSigner, SmartAccountSignerBuilder};
1517
use futures::future::join_all;
1618
use schemars::JsonSchema;
1719
use serde::{Deserialize, Serialize};
18-
use thirdweb_core::auth::ThirdwebAuth;
20+
use serde_json::Value;
1921

2022
use crate::http::{
2123
error::ApiEngineError,
2224
extractors::{EngineJson, SigningCredentialsExtractor},
2325
server::EngineServerState,
24-
types::ErrorResponse,
2526
};
2627

2728
// ===== REQUEST/RESPONSE TYPES =====
@@ -36,15 +37,55 @@ pub struct SignOptions {
3637
}
3738

3839
/// Request to sign typed data
39-
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
40+
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
4041
#[serde(rename_all = "camelCase")]
4142
pub struct SignTypedDataRequest {
4243
/// Configuration options for signing
4344
pub sign_options: SignOptions,
4445
/// List of typed data to sign
46+
#[schema(value_type = Vec<TypedDataDef>)]
4547
pub params: Vec<TypedData>,
4648
}
4749

50+
#[derive(utoipa::ToSchema)]
51+
pub struct TypedDataDef {
52+
/// Signing domain metadata. The signing domain is the intended context for
53+
/// the signature (e.g. the dapp, protocol, etc. that it's intended for).
54+
/// This data is used to construct the domain separator of the message.
55+
pub domain: TypedDataDomainDef,
56+
57+
/// The custom types used by this message.
58+
#[schema(rename = "types")]
59+
pub resolver: Value,
60+
61+
/// The type of the message.
62+
#[schema(rename = "primaryType")]
63+
pub primary_type: String,
64+
65+
/// The message to be signed.
66+
pub message: serde_json::Value,
67+
}
68+
69+
#[derive(utoipa::ToSchema)]
70+
pub struct TypedDataDomainDef {
71+
pub name: Option<String>,
72+
73+
/// The current major version of the signing domain. Signatures from
74+
/// different versions are not compatible.
75+
pub version: Option<String>,
76+
77+
/// The EIP-155 chain ID. The user-agent should refuse signing if it does
78+
/// not match the currently active chain.
79+
pub chain_id: Option<U256Def>,
80+
81+
/// The address of the contract that will verify the signature.
82+
pub verifying_contract: Option<AddressDef>,
83+
84+
/// A disambiguating salt for the protocol. This can be used as a domain
85+
/// separator of last resort.
86+
pub salt: Option<String>,
87+
}
88+
4889
/// Result of a single typed data signing operation
4990
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, utoipa::ToSchema)]
5091
#[serde(untagged)]
@@ -165,7 +206,12 @@ pub async fn sign_typed_data(
165206
) -> Result<impl IntoResponse, ApiEngineError> {
166207
// Process all typed data in parallel
167208
let sign_futures = request.params.iter().map(|typed_data| {
168-
sign_single_typed_data(&state.userop_signer, &signing_credential, &request.sign_options.signing_options, typed_data)
209+
sign_single_typed_data(
210+
&state,
211+
&signing_credential,
212+
&request.sign_options.signing_options,
213+
typed_data,
214+
)
169215
});
170216

171217
let results: Vec<SignResultItem> = join_all(sign_futures).await;
@@ -181,26 +227,53 @@ pub async fn sign_typed_data(
181227
// ===== HELPER FUNCTIONS =====
182228

183229
async fn sign_single_typed_data(
184-
signer: &Signer,
230+
state: &EngineServerState,
185231
signing_credential: &SigningCredential,
186232
signing_options: &SigningOptions,
187233
typed_data: &TypedData,
188234
) -> SignResultItem {
189-
let params = TypedDataSignerParams {
190-
credentials: signing_credential.clone(),
191-
typed_data: typed_data.clone(),
192-
signing_options: signing_options.clone(),
235+
let result = match signing_options {
236+
SigningOptions::Eoa(eoa_options) => {
237+
// Direct EOA signing
238+
state
239+
.eoa_signer
240+
.sign_typed_data(eoa_options.clone(), typed_data, signing_credential.clone())
241+
.await
242+
}
243+
SigningOptions::SmartAccount(smart_account_options) => {
244+
// Smart account signing via builder
245+
match state.chains.get_chain(smart_account_options.chain_id) {
246+
Ok(chain) => {
247+
match SmartAccountSignerBuilder::new(
248+
state.eoa_signer.clone(),
249+
signing_credential.clone(),
250+
smart_account_options.clone(),
251+
chain,
252+
)
253+
.build()
254+
.await
255+
{
256+
Ok(smart_signer) => smart_signer.sign_typed_data(typed_data).await,
257+
Err(e) => Err(e),
258+
}
259+
}
260+
Err(e) => Err(EngineError::ValidationError {
261+
message: format!(
262+
"Failed to get chain {}: {}",
263+
smart_account_options.chain_id, e
264+
),
265+
}),
266+
}
267+
}
193268
};
194269

195-
let result = signer.sign_typed_data(params).await;
196-
197270
match result {
198271
Ok(signature) => {
199272
// Convert typed data to JSON string for signed_data field
200273
let signed_data = serde_json::to_string(typed_data)
201274
.unwrap_or_else(|_| "Failed to serialize typed data".to_string());
202275
SignResultItem::success(signature, signed_data)
203-
},
276+
}
204277
Err(e) => SignResultItem::failure(e),
205278
}
206-
}
279+
}

server/src/http/server.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ impl EngineServer {
5858
.routes(routes!(
5959
crate::http::routes::transaction::cancel_transaction
6060
))
61+
.routes(routes!(crate::http::routes::sign_message::sign_message))
62+
.routes(routes!(
63+
crate::http::routes::sign_typed_data::sign_typed_data
64+
))
6165
.layer(cors)
6266
.layer(TraceLayer::new_for_http())
6367
.with_state(state);

server/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ async fn main() -> anyhow::Result<()> {
3838
rpc_base_url: config.thirdweb.urls.rpc,
3939
});
4040

41-
let signer = Arc::new(UserOpSigner { vault_client });
41+
let signer = Arc::new(UserOpSigner {
42+
vault_client: vault_client.clone(),
43+
});
4244
let eoa_signer = Arc::new(EoaSigner { vault_client });
4345

4446
let queue_manager =

0 commit comments

Comments
 (0)