mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-02 07:17:45 +00:00
fix(auth): only fallback derive on API errors
Match upstream behavior: only retry derive-api-key when create-api-key fails with an HTTP status error.
This commit is contained in:
+69
-1
@@ -541,7 +541,10 @@ impl ClobClient {
|
||||
pub async fn create_or_derive_api_key(&self, nonce: Option<U256>) -> Result<ApiCreds> {
|
||||
match self.create_api_key(nonce).await {
|
||||
Ok(creds) => Ok(creds),
|
||||
Err(_) => self.derive_api_key(nonce).await,
|
||||
// Only fall back to derive on API status errors (server responded).
|
||||
// Propagate network/parse/internal errors so callers can handle them appropriately.
|
||||
Err(PolyfillError::Api { .. }) => self.derive_api_key(nonce).await,
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2271,6 +2274,71 @@ mod tests {
|
||||
let api_creds = result.unwrap();
|
||||
assert_eq!(api_creds.api_key, "test-api-key-123");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_create_or_derive_api_key_falls_back_on_api_error() {
|
||||
let mut server = Server::new_async().await;
|
||||
|
||||
// Create fails with a status error -> should fall back to derive.
|
||||
let create_mock = server
|
||||
.mock("POST", "/auth/api-key")
|
||||
.with_status(400)
|
||||
.with_header("content-type", "application/json")
|
||||
.with_body(r#"{"error":"key exists"}"#)
|
||||
.create_async()
|
||||
.await;
|
||||
|
||||
let derive_mock = server
|
||||
.mock("GET", "/auth/derive-api-key")
|
||||
.with_status(200)
|
||||
.with_header("content-type", "application/json")
|
||||
.with_body(
|
||||
r#"{"apiKey":"derived-api-key","secret":"derived-secret","passphrase":"derived-pass"}"#,
|
||||
)
|
||||
.create_async()
|
||||
.await;
|
||||
|
||||
let client = create_test_client_with_auth(&server.url());
|
||||
let result = client.create_or_derive_api_key(None).await;
|
||||
|
||||
create_mock.assert_async().await;
|
||||
derive_mock.assert_async().await;
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap().api_key, "derived-api-key");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_create_or_derive_api_key_does_not_fallback_on_non_api_error() {
|
||||
let mut server = Server::new_async().await;
|
||||
|
||||
// Create returns 200 but with invalid JSON -> not an API status error.
|
||||
let create_mock = server
|
||||
.mock("POST", "/auth/api-key")
|
||||
.with_status(200)
|
||||
.with_header("content-type", "application/json")
|
||||
.with_body("not-json")
|
||||
.create_async()
|
||||
.await;
|
||||
|
||||
// If we incorrectly fall back, this would be called.
|
||||
let derive_mock = server
|
||||
.mock("GET", "/auth/derive-api-key")
|
||||
.with_status(200)
|
||||
.with_header("content-type", "application/json")
|
||||
.with_body(
|
||||
r#"{"apiKey":"derived-api-key","secret":"derived-secret","passphrase":"derived-pass"}"#,
|
||||
)
|
||||
.expect(0)
|
||||
.create_async()
|
||||
.await;
|
||||
|
||||
let client = create_test_client_with_auth(&server.url());
|
||||
let result = client.create_or_derive_api_key(None).await;
|
||||
|
||||
create_mock.assert_async().await;
|
||||
derive_mock.assert_async().await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_get_order_books_batch() {
|
||||
let mut server = Server::new_async().await;
|
||||
|
||||
Reference in New Issue
Block a user