Skip to content

Commit eaa9799

Browse files
committed
spending limits added to wit
1 parent a75f550 commit eaa9799

File tree

6 files changed

+267
-6
lines changed

6 files changed

+267
-6
lines changed

hyperware-wit/hyperwallet:sys-v0.wit

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ interface hyperwallet {
165165
export-wallet(export-wallet-request),
166166
list-wallets,
167167
get-wallet-info(get-wallet-info-request),
168+
set-wallet-limits(set-wallet-limits-request),
168169

169170
// Ethereum Operations
170171
send-eth(send-eth-request),
@@ -256,6 +257,7 @@ interface hyperwallet {
256257
get-wallet-info(get-wallet-info-response),
257258
get-balance(get-balance-response),
258259
get-token-balance(get-token-balance-response),
260+
set-wallet-limits(set-wallet-limits-response),
259261

260262
// Transactions
261263
send-eth(send-eth-response),
@@ -311,6 +313,12 @@ interface hyperwallet {
311313
wallet-id: string,
312314
}
313315

316+
/// Set wallet-level spending limits
317+
record set-wallet-limits-request {
318+
wallet-id: string,
319+
limits: wallet-spending-limits,
320+
}
321+
314322
record get-balance-request {
315323
wallet-id: string,
316324
}
@@ -541,6 +549,13 @@ interface hyperwallet {
541549
total: u64,
542550
}
543551

552+
/// Response for setting wallet limits
553+
record set-wallet-limits-response {
554+
success: bool,
555+
wallet-id: string,
556+
message: string,
557+
}
558+
544559
record wallet {
545560
address: wallet-address,
546561
name: option<string>,

src/hyperwallet_client/api.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use super::types::{
22
self, Balance, BuildAndSignUserOperationForPaymentRequest, BuildAndSignUserOperationResponse,
33
CreateWalletRequest, ExportWalletResponse, GetTokenBalanceResponse, HyperwalletMessage,
44
HyperwalletRequest, ImportWalletRequest, ListWalletsResponse, PaymasterConfig,
5-
RenameWalletRequest, SendEthRequest, SendTokenRequest, SessionId, TxReceipt,
6-
UnlockWalletRequest, UserOperationReceiptResponse, Wallet,
5+
RenameWalletRequest, SendEthRequest, SendTokenRequest, SessionId, SetWalletLimitsRequest,
6+
SetWalletLimitsResponse, TxReceipt, UnlockWalletRequest, UserOperationReceiptResponse, Wallet,
77
};
88
use super::HyperwalletClientError;
99
use crate::wallet;
@@ -206,6 +206,28 @@ pub fn rename_wallet(
206206
}
207207
}
208208

209+
pub fn set_wallet_limits(
210+
session_id: &SessionId,
211+
wallet_id: &str,
212+
limits: types::WalletSpendingLimits,
213+
) -> Result<SetWalletLimitsResponse, HyperwalletClientError> {
214+
let message = build_message(
215+
session_id,
216+
HyperwalletRequest::SetWalletLimits(SetWalletLimitsRequest {
217+
wallet_id: wallet_id.to_string(),
218+
limits,
219+
}),
220+
);
221+
222+
let response = super::send_message(message)?;
223+
match response.data {
224+
Some(types::HyperwalletResponseData::SetWalletLimits(resp)) => Ok(resp),
225+
_ => Err(HyperwalletClientError::ServerError(
226+
types::OperationError::internal_error("Missing SetWalletLimits response data"),
227+
)),
228+
}
229+
}
230+
209231
// === TRANSACTIONS ===
210232

211233
pub fn send_eth(
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use crate::hyperware::process::hyperwallet as wit;
2+
use serde::de::{self};
3+
use serde::ser::Serialize;
4+
use serde::Deserialize;
5+
6+
// Create a macro to generate stub implementations for request/response types
7+
macro_rules! impl_stub_serde {
8+
($type:ty, $name:literal) => {
9+
impl Serialize for $type {
10+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
11+
where
12+
S: serde::ser::Serializer,
13+
{
14+
// For now, serialize as debug representation
15+
let json_val = serde_json::json!({
16+
"type": $name,
17+
"data": format!("{:?}", self)
18+
});
19+
json_val.serialize(serializer)
20+
}
21+
}
22+
23+
impl<'a> Deserialize<'a> for $type {
24+
fn deserialize<D>(deserializer: D) -> Result<$type, D::Error>
25+
where
26+
D: serde::de::Deserializer<'a>,
27+
{
28+
// The hyperwallet service is sending the response wrapped in a debug format
29+
// We need to deserialize the actual JSON payload
30+
let val = serde_json::Value::deserialize(deserializer)?;
31+
32+
// Try normal JSON deserialization first
33+
match serde_json::from_value(val.clone()) {
34+
Ok(result) => Ok(result),
35+
Err(_) => {
36+
// If that fails, it might be wrapped in the debug format
37+
// For now, we can't parse debug format strings back to structs
38+
// This is a fundamental issue with the hyperwallet service
39+
Err(de::Error::custom(format!(
40+
"{} cannot be deserialized from debug format. The hyperwallet service needs to be fixed to return proper JSON.",
41+
$name
42+
)))
43+
}
44+
}
45+
}
46+
}
47+
};
48+
}
49+
50+
// Request types
51+
impl_stub_serde!(
52+
wit::UpdateSpendingLimitsRequest,
53+
"UpdateSpendingLimitsRequest"
54+
);
55+
impl_stub_serde!(wit::ImportWalletRequest, "ImportWalletRequest");
56+
impl_stub_serde!(wit::DeleteWalletRequest, "DeleteWalletRequest");
57+
impl_stub_serde!(wit::RenameWalletRequest, "RenameWalletRequest");
58+
impl_stub_serde!(wit::ExportWalletRequest, "ExportWalletRequest");
59+
impl_stub_serde!(wit::GetWalletInfoRequest, "GetWalletInfoRequest");
60+
impl_stub_serde!(wit::SendEthRequest, "SendEthRequest");
61+
impl_stub_serde!(wit::SendTokenRequest, "SendTokenRequest");
62+
impl_stub_serde!(wit::ApproveTokenRequest, "ApproveTokenRequest");
63+
impl_stub_serde!(wit::GetBalanceRequest, "GetBalanceRequest");
64+
impl_stub_serde!(wit::GetTokenBalanceRequest, "GetTokenBalanceRequest");
65+
impl_stub_serde!(wit::CallContractRequest, "CallContractRequest");
66+
impl_stub_serde!(wit::SignTransactionRequest, "SignTransactionRequest");
67+
impl_stub_serde!(wit::SignMessageRequest, "SignMessageRequest");
68+
impl_stub_serde!(
69+
wit::BuildAndSignUserOperationForPaymentRequest,
70+
"BuildAndSignUserOperationForPaymentRequest"
71+
);
72+
impl_stub_serde!(
73+
wit::SubmitUserOperationRequest,
74+
"SubmitUserOperationRequest"
75+
);
76+
impl_stub_serde!(
77+
wit::GetUserOperationReceiptRequest,
78+
"GetUserOperationReceiptRequest"
79+
);
80+
impl_stub_serde!(
81+
wit::GetTransactionHistoryRequest,
82+
"GetTransactionHistoryRequest"
83+
);
84+
impl_stub_serde!(wit::EstimateGasRequest, "EstimateGasRequest");
85+
86+
// Response types
87+
impl_stub_serde!(wit::UnlockWalletResponse, "UnlockWalletResponse");
88+
impl_stub_serde!(wit::CreateWalletResponse, "CreateWalletResponse");
89+
impl_stub_serde!(wit::ImportWalletResponse, "ImportWalletResponse");
90+
impl_stub_serde!(wit::DeleteWalletResponse, "DeleteWalletResponse");
91+
impl_stub_serde!(wit::ExportWalletResponse, "ExportWalletResponse");
92+
impl_stub_serde!(wit::ListWalletsResponse, "ListWalletsResponse");
93+
impl_stub_serde!(wit::GetWalletInfoResponse, "GetWalletInfoResponse");
94+
impl_stub_serde!(wit::GetBalanceResponse, "GetBalanceResponse");
95+
impl_stub_serde!(wit::GetTokenBalanceResponse, "GetTokenBalanceResponse");
96+
impl_stub_serde!(wit::SendEthResponse, "SendEthResponse");
97+
impl_stub_serde!(wit::SendTokenResponse, "SendTokenResponse");
98+
impl_stub_serde!(wit::BuildAndSignUserOperationResponse,"BuildAndSignUserOperationResponse");
99+
impl_stub_serde!(wit::SubmitUserOperationResponse,"SubmitUserOperationResponse");
100+
impl_stub_serde!(wit::UserOperationReceiptResponse,"UserOperationReceiptResponse");
101+
102+
// Other request types
103+
impl_stub_serde!(wit::GetTransactionReceiptRequest,"GetTransactionReceiptRequest");
104+
impl_stub_serde!(wit::BuildUserOperationRequest, "BuildUserOperationRequest");
105+
impl_stub_serde!(wit::SignUserOperationRequest, "SignUserOperationRequest");
106+
impl_stub_serde!(wit::BuildAndSignUserOperationRequest,"BuildAndSignUserOperationRequest");
107+
impl_stub_serde!(wit::EstimateUserOperationGasRequest,"EstimateUserOperationGasRequest");
108+
impl_stub_serde!(wit::ConfigurePaymasterRequest, "ConfigurePaymasterRequest");
109+
impl_stub_serde!(wit::ExecuteViaTbaRequest, "ExecuteViaTbaRequest");
110+
impl_stub_serde!(wit::CheckTbaOwnershipRequest, "CheckTbaOwnershipRequest");
111+
impl_stub_serde!(wit::SetupTbaDelegationRequest, "SetupTbaDelegationRequest");
112+
impl_stub_serde!(wit::CreateNoteRequest, "CreateNoteRequest");
113+
impl_stub_serde!(wit::ReadNoteRequest, "ReadNoteRequest");
114+
impl_stub_serde!(wit::ResolveIdentityRequest, "ResolveIdentityRequest");
115+
impl_stub_serde!(wit::SetupDelegationRequest, "SetupDelegationRequest");
116+
impl_stub_serde!(wit::VerifyDelegationRequest, "VerifyDelegationRequest");
117+
impl_stub_serde!(wit::MintEntryRequest, "MintEntryRequest");
118+
119+
// Other response types
120+
impl_stub_serde!(wit::CreateNoteResponse, "CreateNoteResponse");
121+
impl_stub_serde!(wit::ExecuteViaTbaResponse, "ExecuteViaTbaResponse");
122+
impl_stub_serde!(wit::CheckTbaOwnershipResponse, "CheckTbaOwnershipResponse");
123+
124+
// Other types that may need serde
125+
impl_stub_serde!(wit::Balance, "Balance");
126+
impl_stub_serde!(wit::Wallet, "Wallet");
127+
impl_stub_serde!(wit::WalletSpendingLimits, "WalletSpendingLimits");

src/hyperwallet_client/serde_response_impls.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,36 @@ use serde::ser::SerializeStruct;
66
use serde::{Deserialize, Serialize};
77

88
// ============== REQUEST TYPES ==============
9+
// SetWalletLimitsRequest
10+
impl Serialize for wit::SetWalletLimitsRequest {
11+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12+
where
13+
S: serde::Serializer,
14+
{
15+
let mut state = serializer.serialize_struct("SetWalletLimitsRequest", 2)?;
16+
state.serialize_field("wallet_id", &self.wallet_id)?;
17+
state.serialize_field("limits", &self.limits)?;
18+
state.end()
19+
}
20+
}
21+
22+
impl<'de> Deserialize<'de> for wit::SetWalletLimitsRequest {
23+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
24+
where
25+
D: serde::Deserializer<'de>,
26+
{
27+
#[derive(Deserialize)]
28+
struct Helper {
29+
wallet_id: String,
30+
limits: wit::WalletSpendingLimits,
31+
}
32+
let h = Helper::deserialize(deserializer)?;
33+
Ok(wit::SetWalletLimitsRequest {
34+
wallet_id: h.wallet_id,
35+
limits: h.limits,
36+
})
37+
}
38+
}
939

1040
// ImportWalletRequest
1141
impl Serialize for wit::ImportWalletRequest {
@@ -405,6 +435,39 @@ impl<'de> Deserialize<'de> for wit::GetUserOperationReceiptRequest {
405435
}
406436

407437
// ============== RESPONSE TYPES ==============
438+
// SetWalletLimitsResponse
439+
impl Serialize for wit::SetWalletLimitsResponse {
440+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
441+
where
442+
S: serde::Serializer,
443+
{
444+
let mut state = serializer.serialize_struct("SetWalletLimitsResponse", 3)?;
445+
state.serialize_field("success", &self.success)?;
446+
state.serialize_field("wallet_id", &self.wallet_id)?;
447+
state.serialize_field("message", &self.message)?;
448+
state.end()
449+
}
450+
}
451+
452+
impl<'de> Deserialize<'de> for wit::SetWalletLimitsResponse {
453+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
454+
where
455+
D: serde::Deserializer<'de>,
456+
{
457+
#[derive(Deserialize)]
458+
struct Helper {
459+
success: bool,
460+
wallet_id: String,
461+
message: String,
462+
}
463+
let h = Helper::deserialize(deserializer)?;
464+
Ok(wit::SetWalletLimitsResponse {
465+
success: h.success,
466+
wallet_id: h.wallet_id,
467+
message: h.message,
468+
})
469+
}
470+
}
408471

409472
// CreateWalletResponse
410473
impl Serialize for wit::CreateWalletResponse {

src/hyperwallet_client/serde_variant_impls.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ impl Serialize for wit::HyperwalletRequest {
173173
state.serialize_field("type", "MintEntry")?;
174174
state.serialize_field("data", data)?;
175175
}
176+
SetWalletLimits(data) => {
177+
state.serialize_field("type", "SetWalletLimits")?;
178+
state.serialize_field("data", data)?;
179+
}
176180
}
177181

178182
state.end()
@@ -443,6 +447,16 @@ impl<'a> Deserialize<'a> for wit::HyperwalletRequest {
443447
})?;
444448
Ok(GetUserOperationReceipt(req))
445449
}
450+
"SetWalletLimits" => {
451+
let data = data.ok_or_else(|| de::Error::missing_field("data"))?;
452+
let req = serde_json::from_value(data).map_err(|e| {
453+
de::Error::custom(format!(
454+
"Failed to deserialize SetWalletLimitsRequest: {}",
455+
e
456+
))
457+
})?;
458+
Ok(SetWalletLimits(req))
459+
}
446460
"BuildUserOperation" => {
447461
let data = data.ok_or_else(|| de::Error::missing_field("data"))?;
448462
let req = serde_json::from_value(data).map_err(|e| {
@@ -724,6 +738,10 @@ impl Serialize for wit::HyperwalletResponseData {
724738
state.serialize_field("type", "CheckTbaOwnership")?;
725739
state.serialize_field("data", data)?;
726740
}
741+
SetWalletLimits(data) => {
742+
state.serialize_field("type", "SetWalletLimits")?;
743+
state.serialize_field("data", data)?;
744+
}
727745
}
728746

729747
state.end()
@@ -922,6 +940,16 @@ impl<'a> Deserialize<'a> for wit::HyperwalletResponseData {
922940
})?;
923941
Ok(GetTokenBalance(response))
924942
}
943+
"SetWalletLimits" => {
944+
let data = data.ok_or_else(|| de::Error::missing_field("data"))?;
945+
let response = serde_json::from_value(data).map_err(|e| {
946+
de::Error::custom(format!(
947+
"Failed to deserialize SetWalletLimitsResponse: {}",
948+
e
949+
))
950+
})?;
951+
Ok(SetWalletLimits(response))
952+
}
925953
"CreateNote" => {
926954
let data = data.ok_or_else(|| de::Error::missing_field("data"))?;
927955
let response = serde_json::from_value(data).map_err(|e| {

src/hyperwallet_client/types.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,19 @@ pub use wit::{
4444
CheckTbaOwnershipRequest, ConfigurePaymasterRequest, CreateNoteRequest, EstimateGasRequest,
4545
EstimateUserOperationGasRequest, ExecuteViaTbaRequest, GetTransactionHistoryRequest,
4646
GetTransactionReceiptRequest, GetUserOperationReceiptRequest, MintEntryRequest,
47-
ReadNoteRequest, ResolveIdentityRequest, SetupDelegationRequest, SetupTbaDelegationRequest,
48-
SignMessageRequest, SignTransactionRequest, SignUserOperationRequest,
49-
SubmitUserOperationRequest, UpdateSpendingLimitsRequest, VerifyDelegationRequest,
47+
ReadNoteRequest, ResolveIdentityRequest, SetWalletLimitsRequest, SetupDelegationRequest,
48+
SetupTbaDelegationRequest, SignMessageRequest, SignTransactionRequest,
49+
SignUserOperationRequest, SubmitUserOperationRequest, UpdateSpendingLimitsRequest,
50+
VerifyDelegationRequest,
5051
};
5152

53+
// SetWalletLimits request/response types (wallet-level limits)
54+
// Not available in current WIT; requires WIT update to add request/response and variants.
55+
5256
// Re-export response types
5357
pub use wit::{
54-
BuildAndSignUserOperationResponse, CheckTbaOwnershipResponse, SubmitUserOperationResponse,
58+
BuildAndSignUserOperationResponse, CheckTbaOwnershipResponse, SetWalletLimitsResponse,
59+
SubmitUserOperationResponse,
5560
};
5661

5762
// Type aliases for compatibility
@@ -305,6 +310,7 @@ pub fn operation_type(request: &HyperwalletRequest) -> Operation {
305310
HyperwalletRequest::BuildAndSignUserOperation(_) => Operation::BuildAndSignUserOperation,
306311
HyperwalletRequest::EstimateUserOperationGas(_) => Operation::EstimateUserOperationGas,
307312
HyperwalletRequest::ConfigurePaymaster(_) => Operation::ConfigurePaymaster,
313+
HyperwalletRequest::SetWalletLimits(_) => Operation::SetWalletLimits,
308314

309315
// Hypermap Operations
310316
HyperwalletRequest::ResolveIdentity(_) => Operation::ResolveIdentity,

0 commit comments

Comments
 (0)