Skip to content

Commit 70d35ce

Browse files
[WIP] support IAW auth tokens for EOA signing
1 parent 2e50f0b commit 70d35ce

File tree

14 files changed

+468
-11
lines changed

14 files changed

+468
-11
lines changed

Cargo.lock

Lines changed: 64 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/credentials.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
use serde::{Deserialize, Serialize};
2+
use thirdweb_core::auth::ThirdwebAuth;
3+
use thirdweb_core::iaw::AuthToken;
24
use vault_types::enclave::auth::Auth;
35

46
#[derive(Debug, Clone, Serialize, Deserialize)]
57
pub enum SigningCredential {
68
Vault(Auth),
9+
Iaw {
10+
auth_token: AuthToken,
11+
thirdweb_auth: ThirdwebAuth
12+
},
713
}

core/src/error.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use alloy::{
88
use schemars::JsonSchema;
99
use serde::{Deserialize, Serialize};
1010
use thirdweb_core::error::ThirdwebError;
11+
1112
use thiserror::Error;
1213
use twmq::error::TwmqError;
1314

@@ -206,6 +207,11 @@ pub enum EngineError {
206207
#[serde(rename_all = "camelCase")]
207208
VaultError { message: String },
208209

210+
#[schema(title = "Engine IAW Service Error")]
211+
#[error("Error interaction with IAW service: {message}")]
212+
#[serde(rename_all = "camelCase")]
213+
IawError { message: String },
214+
209215
#[schema(title = "RPC Configuration Error")]
210216
#[error("Bad RPC configuration: {message}")]
211217
RpcConfigError { message: String },
@@ -456,3 +462,11 @@ impl From<TwmqError> for EngineError {
456462
}
457463
}
458464
}
465+
466+
impl From<thirdweb_core::iaw::IAWError> for EngineError {
467+
fn from(error: thirdweb_core::iaw::IAWError) -> Self {
468+
EngineError::IawError {
469+
message: error.to_string(),
470+
}
471+
}
472+
}

core/src/signer.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use alloy::{
55
use schemars::JsonSchema;
66
use serde::{Deserialize, Serialize};
77
use serde_with::{DisplayFromStr, PickFirst, serde_as};
8+
use thirdweb_core::iaw::IAWClient;
89
use vault_sdk::VaultClient;
910
use vault_types::enclave::encrypted::eoa::MessageFormat;
1011

@@ -164,12 +165,13 @@ pub trait AccountSigner {
164165
#[derive(Clone)]
165166
pub struct EoaSigner {
166167
pub vault_client: VaultClient,
168+
pub iaw_client: IAWClient,
167169
}
168170

169171
impl EoaSigner {
170172
/// Create a new EOA signer
171-
pub fn new(vault_client: VaultClient) -> Self {
172-
Self { vault_client }
173+
pub fn new(vault_client: VaultClient, iaw_client: IAWClient) -> Self {
174+
Self { vault_client, iaw_client }
173175
}
174176
}
175177

@@ -196,12 +198,37 @@ impl AccountSigner for EoaSigner {
196198
)
197199
.await
198200
.map_err(|e| {
199-
tracing::error!("Error signing message with EOA: {:?}", e);
201+
tracing::error!("Error signing message with EOA (Vault): {:?}", e);
200202
e
201203
})?;
202204

203205
Ok(vault_result.signature)
204206
}
207+
SigningCredential::Iaw { auth_token, thirdweb_auth } => {
208+
// Convert MessageFormat to IAW MessageFormat
209+
let iaw_format = match format {
210+
MessageFormat::Text => thirdweb_core::iaw::MessageFormat::Text,
211+
MessageFormat::Hex => thirdweb_core::iaw::MessageFormat::Hex,
212+
};
213+
214+
let iaw_result = self
215+
.iaw_client
216+
.sign_message(
217+
auth_token,
218+
thirdweb_auth,
219+
message.to_string(),
220+
options.from,
221+
options.chain_id,
222+
Some(iaw_format),
223+
)
224+
.await
225+
.map_err(|e| {
226+
tracing::error!("Error signing message with EOA (IAW): {:?}", e);
227+
EngineError::from(e)
228+
})?;
229+
230+
Ok(iaw_result.signature)
231+
}
205232
}
206233
}
207234

@@ -218,12 +245,29 @@ impl AccountSigner for EoaSigner {
218245
.sign_typed_data(auth_method.clone(), typed_data.clone(), options.from)
219246
.await
220247
.map_err(|e| {
221-
tracing::error!("Error signing typed data with EOA: {:?}", e);
248+
tracing::error!("Error signing typed data with EOA (Vault): {:?}", e);
222249
e
223250
})?;
224251

225252
Ok(vault_result.signature)
226253
}
254+
SigningCredential::Iaw { auth_token, thirdweb_auth } => {
255+
let iaw_result = self
256+
.iaw_client
257+
.sign_typed_data(
258+
auth_token.clone(),
259+
thirdweb_auth.clone(),
260+
typed_data.clone(),
261+
options.from,
262+
)
263+
.await
264+
.map_err(|e| {
265+
tracing::error!("Error signing typed data with EOA (IAW): {:?}", e);
266+
EngineError::from(e)
267+
})?;
268+
269+
Ok(iaw_result.signature)
270+
}
227271
}
228272
}
229273
}

core/src/userop.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ impl UserOpSigner {
103103
}
104104
})?)
105105
}
106+
SigningCredential::Iaw { auth_token: _, thirdweb_auth: _ } => {
107+
// IAW doesn't support UserOp signing yet
108+
Err(EngineError::ValidationError {
109+
message: "IAW service does not support UserOperation signing".to_string(),
110+
})
111+
}
106112
}
107113
}
108114
}

server/configuration/server_base.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ thirdweb:
99
paymaster: bundler.thirdweb-dev.com
1010
vault: https://d2w4ge7u2axqfk.cloudfront.net
1111
abi_service: https://contract.thirdweb.com/abi/
12+
iaw_service: https://embedded-wallet.thirdweb-dev.com
1213
secret: read_from_env
1314
client_id: read_from_env
1415

server/configuration/server_production.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ thirdweb:
99
paymaster: bundler.thirdweb.com
1010
vault: https://d145tet905juug.cloudfront.net # override in env
1111
abi_service: https://contract.thirdweb.com/abi/ # override in env
12+
iaw_service: https://embedded-wallet.thirdweb.com # override in env
1213
secret: read_from_env
1314
client_id: read_from_env
1415

server/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub struct ThirdwebUrls {
5151
pub vault: String,
5252
pub paymaster: String,
5353
pub abi_service: String,
54+
pub iaw_service: String,
5455
}
5556

5657
impl Default for ServerConfig {

server/src/http/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl ApiEngineError {
6767
_ => StatusCode::INTERNAL_SERVER_ERROR,
6868
},
6969
EngineError::VaultError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
70+
EngineError::IawError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
7071
EngineError::BundlerError { .. } => StatusCode::BAD_REQUEST,
7172
EngineError::PaymasterError { .. } => StatusCode::BAD_REQUEST,
7273
EngineError::ValidationError { .. } => StatusCode::BAD_REQUEST,

server/src/http/extractors.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,61 @@ where
9292
type Rejection = ApiEngineError;
9393

9494
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
95+
// Check for IAW credentials first (x-wallet-token)
96+
if let Some(wallet_token) = parts
97+
.headers
98+
.get("x-wallet-token")
99+
.and_then(|v| v.to_str().ok())
100+
{
101+
// Extract ThirdwebAuth for billing purposes
102+
let thirdweb_auth = if let Some(secret_key) = parts
103+
.headers
104+
.get("x-thirdweb-secret-key")
105+
.and_then(|v| v.to_str().ok())
106+
{
107+
ThirdwebAuth::SecretKey(secret_key.to_string())
108+
} else {
109+
// Try client ID and service key combination
110+
let client_id = parts
111+
.headers
112+
.get("x-thirdweb-client-id")
113+
.and_then(|v| v.to_str().ok())
114+
.ok_or_else(|| {
115+
ApiEngineError(EngineError::ValidationError {
116+
message: "Missing x-thirdweb-client-id header when using IAW".to_string(),
117+
})
118+
})?;
119+
120+
let service_key = parts
121+
.headers
122+
.get("x-thirdweb-service-key")
123+
.and_then(|v| v.to_str().ok())
124+
.ok_or_else(|| {
125+
ApiEngineError(EngineError::ValidationError {
126+
message: "Missing x-thirdweb-service-key header when using IAW".to_string(),
127+
})
128+
})?;
129+
130+
ThirdwebAuth::ClientIdServiceKey(thirdweb_core::auth::ThirdwebClientIdAndServiceKey {
131+
client_id: client_id.to_string(),
132+
service_key: service_key.to_string(),
133+
})
134+
};
135+
136+
return Ok(SigningCredentialsExtractor(SigningCredential::Iaw {
137+
auth_token: wallet_token.to_string(),
138+
thirdweb_auth,
139+
}));
140+
}
141+
142+
// Fall back to Vault credentials
95143
let vault_access_token = parts
96144
.headers
97145
.get("x-vault-access-token")
98146
.and_then(|v| v.to_str().ok())
99147
.ok_or_else(|| {
100148
ApiEngineError(EngineError::ValidationError {
101-
message: "Missing x-vault-access-token header".to_string(),
149+
message: "Missing x-vault-access-token or x-wallet-token header".to_string(),
102150
})
103151
})?;
104152

server/src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::sync::Arc;
22

33
use engine_core::{signer::EoaSigner, userop::UserOpSigner};
4-
use thirdweb_core::{abi::ThirdwebAbiServiceBuilder, auth::ThirdwebAuth};
4+
use thirdweb_core::{abi::ThirdwebAbiServiceBuilder, auth::ThirdwebAuth, iaw::IAWClient};
55
use thirdweb_engine::{
66
chains::ThirdwebChainService,
77
config,
@@ -38,10 +38,13 @@ async fn main() -> anyhow::Result<()> {
3838
rpc_base_url: config.thirdweb.urls.rpc,
3939
});
4040

41+
let iaw_client = IAWClient::new(&config.thirdweb.urls.iaw_service)?;
42+
tracing::info!("IAW client initialized");
43+
4144
let signer = Arc::new(UserOpSigner {
4245
vault_client: vault_client.clone(),
4346
});
44-
let eoa_signer = Arc::new(EoaSigner { vault_client });
47+
let eoa_signer = Arc::new(EoaSigner::new(vault_client, iaw_client));
4548

4649
let queue_manager =
4750
QueueManager::new(&config.redis, &config.queue, chains.clone(), signer.clone()).await?;

thirdweb-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7-
alloy = { version = "1.0.9", features = ["json-abi"] }
7+
alloy = { version = "1.0.9", features = ["json-abi", "consensus", "dyn-abi", "eips", "eip712"] }
88
moka = { version = "0.12.10", features = ["future"] }
99
reqwest = "0.12.18"
1010
schemars = "0.8.22"

0 commit comments

Comments
 (0)