From 7ef74225b864528dd7a3bee243b387c6dc15fbf3 Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Fri, 17 Jan 2025 10:48:45 +0100 Subject: [PATCH] feat: tvf data in publish payload --- relay_client/src/http.rs | 1 + relay_client/src/lib.rs | 23 ++++++++++++++++++ relay_client/src/websocket.rs | 1 + relay_rpc/src/auth/cacao/signature/eip191.rs | 2 +- relay_rpc/src/jwt.rs | 2 +- relay_rpc/src/rpc.rs | 25 ++++++++++++++++++++ relay_rpc/src/rpc/tests.rs | 13 +++++++++- 7 files changed, 64 insertions(+), 3 deletions(-) diff --git a/relay_client/src/http.rs b/relay_client/src/http.rs index 475292e..a4dbc23 100644 --- a/relay_client/src/http.rs +++ b/relay_client/src/http.rs @@ -125,6 +125,7 @@ impl Client { ttl_secs, tag, prompt, + tvf_data: None, }) .await .map(|_| ()) diff --git a/relay_client/src/lib.rs b/relay_client/src/lib.rs index 7408975..cc906fb 100644 --- a/relay_client/src/lib.rs +++ b/relay_client/src/lib.rs @@ -48,6 +48,13 @@ pub struct ConnectionOptions { /// Optional origin of the request. Subject to allow-list validation. pub origin: Option, + /// Optional package name. Used instead of `origin` for allow-list + /// validation. + pub package_name: Option, + + /// Optional bundle ID. Used instead of `origin` for allow-list validation. + pub bundle_id: Option, + /// Optional user agent parameters. pub user_agent: Option, } @@ -60,6 +67,8 @@ impl ConnectionOptions { auth: Authorization::Query(auth), origin: None, user_agent: None, + package_name: None, + bundle_id: None, } } @@ -68,6 +77,16 @@ impl ConnectionOptions { self } + pub fn with_package_name(mut self, package_name: impl Into) -> Self { + self.package_name = Some(package_name.into()); + self + } + + pub fn with_bundle_id(mut self, bundle_id: impl Into) -> Self { + self.bundle_id = Some(bundle_id.into()); + self + } + pub fn with_origin(mut self, origin: impl Into>) -> Self { self.origin = origin.into(); self @@ -85,6 +104,8 @@ impl ConnectionOptions { project_id: &'a ProjectId, auth: Option<&'a SerializedAuthToken>, ua: Option<&'a UserAgent>, + package_name: Option<&'a str>, + bundle_id: Option<&'a str>, } let query = serde_qs::to_string(&QueryParams { @@ -95,6 +116,8 @@ impl ConnectionOptions { None }, ua: self.user_agent.as_ref(), + package_name: self.package_name.as_deref(), + bundle_id: self.bundle_id.as_deref(), }) .map_err(RequestBuildError::Query)?; diff --git a/relay_client/src/websocket.rs b/relay_client/src/websocket.rs index 29bb2f5..a515695 100644 --- a/relay_client/src/websocket.rs +++ b/relay_client/src/websocket.rs @@ -168,6 +168,7 @@ impl Client { ttl_secs: ttl.as_secs() as u32, tag, prompt, + tvf_data: None, }); self.request(request); diff --git a/relay_rpc/src/auth/cacao/signature/eip191.rs b/relay_rpc/src/auth/cacao/signature/eip191.rs index ba30394..e8b5713 100644 --- a/relay_rpc/src/auth/cacao/signature/eip191.rs +++ b/relay_rpc/src/auth/cacao/signature/eip191.rs @@ -10,7 +10,7 @@ pub const EIP191: &str = "eip191"; pub fn eip191_bytes(message: &str) -> Vec { format!( "\u{0019}Ethereum Signed Message:\n{}{}", - message.as_bytes().len(), + message.len(), message ) .into() diff --git a/relay_rpc/src/jwt.rs b/relay_rpc/src/jwt.rs index 120a99d..d37599f 100644 --- a/relay_rpc/src/jwt.rs +++ b/relay_rpc/src/jwt.rs @@ -67,7 +67,7 @@ impl Default for JwtHeader<'_> { } } -impl<'a> JwtHeader<'a> { +impl JwtHeader<'_> { pub fn is_valid(&self) -> bool { self.typ == JWT_HEADER_TYP && self.alg == JWT_HEADER_ALG } diff --git a/relay_rpc/src/rpc.rs b/relay_rpc/src/rpc.rs index 751eaec..b0eca54 100644 --- a/relay_rpc/src/rpc.rs +++ b/relay_rpc/src/rpc.rs @@ -88,6 +88,12 @@ impl Payload { Self::Response(response) => response.validate(), } } + + pub fn strip_analytics(&mut self) { + if let Self::Request(req) = self { + req.strip_analytics(); + } + } } impl From for Payload @@ -520,6 +526,16 @@ impl ServiceRequest for BatchReceiveMessages { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TvfData { + pub correlation_id: Option>, + pub chain_id: Option>, + pub rpc_methods: Option>>, + pub tx_hashes: Option>>, + pub contract_addresses: Option>>, +} + /// Data structure representing publish request params. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Publish { @@ -545,6 +561,9 @@ pub struct Publish { /// webhook to a client through a push server. #[serde(default, skip_serializing_if = "is_default")] pub prompt: bool, + + #[serde(default, flatten, skip_serializing_if = "is_default")] + pub tvf_data: Option, } impl Publish { @@ -860,4 +879,10 @@ impl Request { Params::Subscription(params) => params.validate(), } } + + pub fn strip_analytics(&mut self) { + if let Params::Publish(params) = &mut self.params { + params.tvf_data = None; + } + } } diff --git a/relay_rpc/src/rpc/tests.rs b/relay_rpc/src/rpc/tests.rs index 80da24d..a50c3f4 100644 --- a/relay_rpc/src/rpc/tests.rs +++ b/relay_rpc/src/rpc/tests.rs @@ -11,6 +11,13 @@ fn request() { ttl_secs: 12, tag: 0, prompt: false, + tvf_data: Some(TvfData { + correlation_id: Some("correlation_id".into()), + chain_id: Some("chain_id".into()), + rpc_methods: Some(vec!["rpc_method".into()]), + tx_hashes: Some(vec!["tx_hash".into()]), + contract_addresses: Some(vec!["contract_address".into()]), + }), }), )); @@ -18,7 +25,7 @@ fn request() { assert_eq!( &serialized, - r#"{"id":1,"jsonrpc":"2.0","method":"irn_publish","params":{"topic":"topic","message":"payload","attestation":"attestation_payload","ttl":12,"tag":0}}"# + r#"{"id":1,"jsonrpc":"2.0","method":"irn_publish","params":{"topic":"topic","message":"payload","attestation":"attestation_payload","ttl":12,"tag":0,"correlationId":"correlation_id","chainId":"chain_id","rpcMethods":["rpc_method"],"txHashes":["tx_hash"],"contractAddresses":["contract_address"]}}"# ); let deserialized: Payload = serde_json::from_str(&serialized).unwrap(); @@ -294,6 +301,7 @@ fn validation() { ttl_secs: 0, tag: 0, prompt: false, + tvf_data: None, }), }; assert_eq!(request.validate(), Err(PayloadError::InvalidRequestId)); @@ -309,6 +317,7 @@ fn validation() { ttl_secs: 0, tag: 0, prompt: false, + tvf_data: None, }), }; assert_eq!(request.validate(), Err(PayloadError::InvalidJsonRpcVersion)); @@ -324,6 +333,7 @@ fn validation() { ttl_secs: 0, tag: 0, prompt: false, + tvf_data: None, }), }; assert_eq!(request.validate(), Ok(())); @@ -339,6 +349,7 @@ fn validation() { ttl_secs: 0, tag: 0, prompt: false, + tvf_data: None, }), }; assert_eq!(request.validate(), Err(PayloadError::InvalidTopic));