Skip to content

Commit 6b0f5ba

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 6b0f5ba

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

client/src/lib.rs

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,61 @@ 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<Activity, TurnkeyClientError> {
270+
// validate post_body matches the expected request type
271+
serde_json::from_str::<Request>(&post_body)?;
272+
self.process_activity_internal(post_body, path, Some(stamp))
273+
.await
274+
}
275+
276+
async fn process_activity_internal(
277+
&self,
278+
post_body: String,
279+
path: String,
280+
stamp: Option<StampHeader>,
237281
) -> Result<Activity, TurnkeyClientError> {
238282
let mut retry_count = 0;
239283

284+
let stamp = match &stamp {
285+
Some(stamp) => stamp.clone(),
286+
None => self.api_key.stamp(post_body.as_bytes())?,
287+
};
240288
loop {
241-
let response: ActivityResponse = self.process_request(&request, path.clone()).await?;
289+
let response: ActivityResponse = self
290+
.process_request_internal(post_body.clone(), path.clone(), stamp.clone())
291+
.await?;
242292
let activity = response
243293
.activity
244294
.ok_or_else(|| TurnkeyClientError::MissingActivity)?;
@@ -296,9 +346,42 @@ impl<S: Stamp> TurnkeyClient<S> {
296346
Request: Serialize,
297347
Response: DeserializeOwned,
298348
{
299-
let url = format!("{}{}", self.base_url, path);
300349
let post_body = serde_json::to_string(&request)?;
301-
let StampHeader { name, value } = self.api_key.stamp(post_body.as_bytes())?;
350+
let stamp = self.api_key.stamp(post_body.as_bytes())?;
351+
self.process_request_internal(post_body, path, stamp).await
352+
}
353+
354+
/// Processes a `Request` (at `path`) by:
355+
/// * Serializing the request to JSON
356+
/// * POSTing the POST body with the provided stamp to the Turnkey API
357+
///
358+
/// This function is generic and can handle POSTing queries or activities.
359+
pub async fn process_request_with_stamp<Request, Response>(
360+
&self,
361+
post_body: String,
362+
path: String,
363+
stamp: StampHeader,
364+
) -> Result<Response, TurnkeyClientError>
365+
where
366+
Request: DeserializeOwned,
367+
Response: DeserializeOwned,
368+
{
369+
// validate post_body matches the expected request type
370+
serde_json::from_str::<Request>(&post_body)?;
371+
self.process_request_internal(post_body, path, stamp).await
372+
}
373+
374+
async fn process_request_internal<Response>(
375+
&self,
376+
post_body: String,
377+
path: String,
378+
stamp: StampHeader,
379+
) -> Result<Response, TurnkeyClientError>
380+
where
381+
Response: DeserializeOwned,
382+
{
383+
let StampHeader { name, value } = stamp;
384+
let url = format!("{}{}", self.base_url, path);
302385
let res = self
303386
.http
304387
.post(url)

0 commit comments

Comments
 (0)