Skip to content

Commit a75f550

Browse files
committed
fixed a bunch of ser-and-deserialization errors in requests and responses
1 parent fb37552 commit a75f550

File tree

5 files changed

+448
-21
lines changed

5 files changed

+448
-21
lines changed

src/hyperwallet_client/mod.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ pub mod types;
1010
pub use types::{
1111
Balance, BuildAndSignUserOperationForPaymentRequest, BuildAndSignUserOperationResponse,
1212
ChainId, CheckTbaOwnershipResponse, CreateNoteResponse, CreateWalletRequest,
13-
CreateWalletResponse, DeleteWalletRequest, DeleteWalletResponse, ErrorCode,
13+
CreateWalletResponse, DeleteWalletRequest, DeleteWalletResponse, Eip712Data, ErrorCode,
1414
ExecuteViaTbaResponse, ExportWalletRequest, ExportWalletResponse, GetBalanceRequest,
1515
GetBalanceResponse, GetTokenBalanceRequest, GetTokenBalanceResponse, GetWalletInfoRequest,
1616
GetWalletInfoResponse, HandshakeConfig, HandshakeStep, HyperwalletMessage, HyperwalletRequest,
1717
HyperwalletResponse, HyperwalletResponseData, ImportWalletRequest, ImportWalletResponse,
18-
ListWalletsResponse, Operation, OperationCategory, OperationError, PaymasterConfig,
19-
ProcessAddress, ProcessPermissions, RenameWalletRequest, SendEthRequest, SendEthResponse,
20-
SendTokenRequest, SendTokenResponse, SessionId, SessionInfo, SpendingLimits,
18+
ListWalletsResponse, MessageType, Operation, OperationCategory, OperationError,
19+
PaymasterConfig, ProcessAddress, ProcessPermissions, RenameWalletRequest, SendEthRequest,
20+
SendEthResponse, SendTokenRequest, SendTokenResponse, SessionId, SessionInfo, SpendingLimits,
2121
SubmitUserOperationResponse, TxReceipt, UnlockWalletResponse, UpdatableSetting,
2222
UserOperationHash, UserOperationReceiptResponse, WalletAddress,
2323
};
@@ -47,10 +47,11 @@ pub enum HyperwalletClientError {
4747

4848
/// Performs the full handshake and registration protocol with the Hyperwallet service.
4949
pub fn initialize(config: HandshakeConfig) -> Result<SessionInfo, HyperwalletClientError> {
50+
const CLIENT_PROTOCOL_VERSION: &str = "0.1.0";
5051
let client_name = config.client_name.expect("Client name is required");
5152

5253
let hello_step = types::HandshakeStep::ClientHello(types::ClientHello {
53-
client_version: "0.1.0".to_string(),
54+
client_version: CLIENT_PROTOCOL_VERSION.to_string(),
5455
client_name,
5556
});
5657
let hello_message = types::HyperwalletMessage {
@@ -71,8 +72,11 @@ pub fn initialize(config: HandshakeConfig) -> Result<SessionInfo, HyperwalletCli
7172
}
7273
};
7374

74-
let supported_operations = match welcome_step {
75-
types::HandshakeStep::ServerWelcome(server_welcome) => server_welcome.supported_operations,
75+
let (server_version, supported_operations) = match welcome_step {
76+
types::HandshakeStep::ServerWelcome(server_welcome) => (
77+
server_welcome.server_version,
78+
server_welcome.supported_operations,
79+
),
7680
_ => {
7781
return Err(HyperwalletClientError::ServerError(
7882
types::OperationError::internal_error(
@@ -82,6 +86,19 @@ pub fn initialize(config: HandshakeConfig) -> Result<SessionInfo, HyperwalletCli
8286
}
8387
};
8488

89+
// Basic protocol version negotiation: require matching major version
90+
let client_major = CLIENT_PROTOCOL_VERSION
91+
.split('.')
92+
.next()
93+
.unwrap_or(CLIENT_PROTOCOL_VERSION);
94+
let server_major = server_version.split('.').next().unwrap_or(&server_version);
95+
if client_major != server_major {
96+
return Err(HyperwalletClientError::VersionMismatch {
97+
client: CLIENT_PROTOCOL_VERSION.to_string(),
98+
server: server_version,
99+
});
100+
}
101+
85102
for required_op in &config.required_operations {
86103
if !supported_operations.contains(required_op) {
87104
return Err(HyperwalletClientError::ServerError(types::OperationError {
@@ -120,14 +137,12 @@ pub fn initialize(config: HandshakeConfig) -> Result<SessionInfo, HyperwalletCli
120137

121138
// Extract SessionInfo using pattern matching
122139
match complete_step {
123-
types::HandshakeStep::Complete(complete_handshake) => {
124-
Ok(types::SessionInfo {
125-
server_version: "0.1.0".to_string(), //lol, server should send it's version
126-
session_id: complete_handshake.session_id,
127-
registered_permissions: complete_handshake.registered_permissions,
128-
initial_chain_id: config.initial_chain_id,
129-
})
130-
}
140+
types::HandshakeStep::Complete(complete_handshake) => Ok(types::SessionInfo {
141+
server_version,
142+
session_id: complete_handshake.session_id,
143+
registered_permissions: complete_handshake.registered_permissions,
144+
initial_chain_id: config.initial_chain_id,
145+
}),
131146
_ => Err(HyperwalletClientError::ServerError(
132147
types::OperationError::internal_error(
133148
"Expected Complete handshake step, received different step",

src/hyperwallet_client/serde_impls.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ impl<'a> Deserialize<'a> for wit::OperationError {
240240
if details.is_some() {
241241
return Err(de::Error::duplicate_field("details"));
242242
}
243-
details = Some(map.next_value()?);
243+
// Accept Option<String>: null -> None
244+
details = map.next_value()?;
244245
}
245246
}
246247
}

src/hyperwallet_client/serde_response_impls.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Proper serde implementations for request/response types
22

33
use crate::hyperware::process::hyperwallet as wit;
4-
use serde::de::{self, MapAccess, Visitor};
4+
// no direct use of serde::de; rely on derives and serde_json where necessary
55
use serde::ser::SerializeStruct;
66
use serde::{Deserialize, Serialize};
77

@@ -13,10 +13,13 @@ impl Serialize for wit::ImportWalletRequest {
1313
where
1414
S: serde::Serializer,
1515
{
16-
let mut state = serializer.serialize_struct("ImportWalletRequest", 3)?;
16+
let field_count = if self.password.is_some() { 3 } else { 2 };
17+
let mut state = serializer.serialize_struct("ImportWalletRequest", field_count)?;
1718
state.serialize_field("name", &self.name)?;
1819
state.serialize_field("private_key", &self.private_key)?;
19-
state.serialize_field("password", &self.password)?;
20+
if let Some(ref pwd) = self.password {
21+
state.serialize_field("password", pwd)?;
22+
}
2023
state.end()
2124
}
2225
}
@@ -106,9 +109,12 @@ impl Serialize for wit::ExportWalletRequest {
106109
where
107110
S: serde::Serializer,
108111
{
109-
let mut state = serializer.serialize_struct("ExportWalletRequest", 2)?;
112+
let field_count = if self.password.is_some() { 2 } else { 1 };
113+
let mut state = serializer.serialize_struct("ExportWalletRequest", field_count)?;
110114
state.serialize_field("wallet_id", &self.wallet_id)?;
111-
state.serialize_field("password", &self.password)?;
115+
if let Some(ref pwd) = self.password {
116+
state.serialize_field("password", pwd)?;
117+
}
112118
state.end()
113119
}
114120
}

0 commit comments

Comments
 (0)