Skip to content

Commit 325b79c

Browse files
committed
Implement support for submitting presigned requests
Adds process_activity_with_stamp & process_request_with_stamp to TurnkeyClient that submit requests using a provided stamp
1 parent 440787f commit 325b79c

File tree

1 file changed

+89
-3
lines changed

1 file changed

+89
-3
lines changed

client/src/lib.rs

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,63 @@ impl<S: Stamp> TurnkeyClient<S> {
234234
&self,
235235
request: Request,
236236
path: String,
237+
) -> Result<Activity, TurnkeyClientError> {
238+
let post_body = serde_json::to_string(&request)?;
239+
self.process_activity_internal(post_body, path, None).await
240+
}
241+
242+
/// POSTs an activity with a provided `stamp` and polls until the status is "COMPLETE"
243+
///
244+
/// `process_activity` accepts a arbitrary `Request` and `path` to POST to the Turnkey API.
245+
/// It encapsulates the polling logic and is generally meant to be called by other
246+
/// activity-specific client functions (e.g. `create_sub_organization`).
247+
///
248+
/// Given the Turnkey API is backwards-compatible, this function can be used to submit old versions of activities.
249+
/// For example, if the latest version for create_sub_organization is "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7",
250+
/// you may want to use `process_activity` to process `ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V6`. Note that this
251+
/// requires manually setting the correct URL and activity request type.
252+
/// The response is an generic Activity. If you're invoking this function manually you'll have to manually look at
253+
/// the correct `.activity.result` enum.
254+
///
255+
/// # Returns
256+
///
257+
/// This function returns an `Activity` object which contains the deserialized version of the response.
258+
///
259+
/// # Errors
260+
///
261+
/// If the server errors with a validation error, a server error, a deserialization error, the proper variant of `TurnkeyClientError` is returned.
262+
/// If the activity is pending and exceeds the maximum amount of retries allowed, `TurnkeyClientError::ExceededRetries` is returned.
263+
/// If the activity requires consensus, `TurnkeyClientError::ActivityRequiresApproval` is returned.
264+
pub async fn process_activity_with_stamp<Request: DeserializeOwned>(
265+
&self,
266+
post_body: String,
267+
path: String,
268+
stamp: StampHeader,
269+
) -> Result<(Request, Activity), TurnkeyClientError> {
270+
// validate post_body matches the expected request type
271+
let request = serde_json::from_str::<Request>(&post_body)?;
272+
let response = self
273+
.process_activity_internal(post_body, path, Some(stamp))
274+
.await;
275+
Ok((request, response?))
276+
}
277+
278+
async fn process_activity_internal(
279+
&self,
280+
post_body: String,
281+
path: String,
282+
stamp: Option<StampHeader>,
237283
) -> Result<Activity, TurnkeyClientError> {
238284
let mut retry_count = 0;
239285

286+
let stamp = match stamp {
287+
Some(stamp) => stamp,
288+
None => self.api_key.stamp(post_body.as_bytes())?,
289+
};
240290
loop {
241-
let response: ActivityResponse = self.process_request(&request, path.clone()).await?;
291+
let response: ActivityResponse = self
292+
.process_request_internal(post_body.clone(), path.clone(), stamp.clone())
293+
.await?;
242294
let activity = response
243295
.activity
244296
.ok_or_else(|| TurnkeyClientError::MissingActivity)?;
@@ -296,9 +348,43 @@ impl<S: Stamp> TurnkeyClient<S> {
296348
Request: Serialize,
297349
Response: DeserializeOwned,
298350
{
299-
let url = format!("{}{}", self.base_url, path);
300351
let post_body = serde_json::to_string(&request)?;
301-
let StampHeader { name, value } = self.api_key.stamp(post_body.as_bytes())?;
352+
let stamp = self.api_key.stamp(post_body.as_bytes())?;
353+
self.process_request_internal(post_body, path, stamp).await
354+
}
355+
356+
/// Processes a `Request` (at `path`) by:
357+
/// * Serializing the request to JSON
358+
/// * POSTing the POST body with the provided stamp to the Turnkey API
359+
///
360+
/// This function is generic and can handle POSTing queries or activities.
361+
pub async fn process_request_with_stamp<Request, Response>(
362+
&self,
363+
post_body: String,
364+
path: String,
365+
stamp: StampHeader,
366+
) -> Result<(Request, Response), TurnkeyClientError>
367+
where
368+
Request: DeserializeOwned,
369+
Response: DeserializeOwned,
370+
{
371+
// validate post_body matches the expected request type
372+
let request = serde_json::from_str::<Request>(&post_body)?;
373+
let response = self.process_request_internal(post_body, path, stamp).await;
374+
Ok((request, response?))
375+
}
376+
377+
async fn process_request_internal<Response>(
378+
&self,
379+
post_body: String,
380+
path: String,
381+
stamp: StampHeader,
382+
) -> Result<Response, TurnkeyClientError>
383+
where
384+
Response: DeserializeOwned,
385+
{
386+
let StampHeader { name, value } = stamp;
387+
let url = format!("{}{}", self.base_url, path);
302388
let res = self
303389
.http
304390
.post(url)

0 commit comments

Comments
 (0)