mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-11-02 07:46:11 +00:00
Merge pull request #209 from dylanzhong662-max/feat-rate-limit-upgrade-link
feat: show plan upgrade guidance on rate limits
This commit is contained in:
@@ -108,6 +108,8 @@ All cooking routes go through GMGN's leaky-bucket limiter with `rate=20` and `ca
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers — Unix timestamp for when the limit resets.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- `cooking create` is a real transaction: **never loop or auto-resubmit** after a `429`. Wait until the reset time, then ask for confirmation again before retrying.
|
||||
|
||||
@@ -78,6 +78,8 @@ All market routes used by this skill go through GMGN's leaky-bucket limiter with
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
|
||||
@@ -76,6 +76,8 @@ All portfolio routes used by this skill go through GMGN's leaky-bucket limiter w
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
|
||||
@@ -106,6 +106,8 @@ All swap-related routes used by this skill go through GMGN's leaky-bucket limite
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- `swap` is a real transaction: never loop or auto-submit repeated swap attempts after a `429`. Wait until the reset time, then ask for confirmation again before retrying.
|
||||
|
||||
@@ -67,6 +67,8 @@ All token routes used by this skill go through GMGN's leaky-bucket limiter with
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
|
||||
@@ -81,6 +81,8 @@ All tracking routes used by this skill go through GMGN's leaky-bucket limiter wi
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
|
||||
@@ -528,6 +528,8 @@ A single run of this skill's script can burn through several of these in sequenc
|
||||
|
||||
**When a request returns `429`, stop and proactively tell the user exactly when they can retry — never fail silently, never keep retrying without saying anything.**
|
||||
|
||||
- On `RATE_LIMIT_EXCEEDED`, tell the user exactly: `已达到当前套餐的限频上限,点击 https://gmgn.ai/ai?chain=bsc&tab=paid_plans 升级套餐,获得更高速率限制`. Show this upgrade guidance at most once per user task. Do not repeat it for subsequent `RATE_LIMIT_BANNED` responses during the same cooldown.
|
||||
|
||||
- Extract the reset time: read `X-RateLimit-Reset` from the response headers (Unix timestamp), or if the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), use that instead — it's the Unix timestamp when the ban lifts (typically 5 minutes for a ban).
|
||||
- Convert whichever timestamp you got to the user's local time and state it plainly, e.g. *"Rate-limited — you can retry this wallet after 14:32:05 (in ~4 minutes)."* Do this even if the run partially succeeded (see below) — the user needs to know when the rest of the analysis can resume.
|
||||
- **Resume, don't restart**: if the script is mid-run (e.g. the Dev security scan hits `429` after `portfolio stats` and `activity` already succeeded), report what you already have (stats/tags/track-record score can still be shown), state the reset time for the remaining calls, and re-run only those remaining calls after it passes — don't re-fetch data you already have.
|
||||
|
||||
@@ -30,6 +30,8 @@ interface ResponseEnvelope {
|
||||
data?: unknown;
|
||||
message?: string;
|
||||
error?: string;
|
||||
upgrade_url?: string;
|
||||
upgrade_message?: string;
|
||||
}
|
||||
|
||||
interface OpenApiErrorParams {
|
||||
@@ -40,6 +42,8 @@ interface OpenApiErrorParams {
|
||||
apiError?: string;
|
||||
apiMessage?: string;
|
||||
resetAtUnix?: number;
|
||||
upgradeUrl?: string;
|
||||
upgradeMessage?: string;
|
||||
}
|
||||
|
||||
class OpenApiError extends Error {
|
||||
@@ -50,6 +54,8 @@ class OpenApiError extends Error {
|
||||
readonly apiError?: string;
|
||||
readonly apiMessage?: string;
|
||||
readonly resetAtUnix?: number;
|
||||
readonly upgradeUrl?: string;
|
||||
readonly upgradeMessage?: string;
|
||||
|
||||
constructor(params: OpenApiErrorParams) {
|
||||
super(buildOpenApiErrorMessage(params));
|
||||
@@ -61,6 +67,8 @@ class OpenApiError extends Error {
|
||||
this.apiError = params.apiError;
|
||||
this.apiMessage = params.apiMessage;
|
||||
this.resetAtUnix = params.resetAtUnix;
|
||||
this.upgradeUrl = params.upgradeUrl;
|
||||
this.upgradeMessage = params.upgradeMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,6 +723,8 @@ export class OpenApiClient {
|
||||
apiError: json.error,
|
||||
apiMessage: json.message,
|
||||
resetAtUnix,
|
||||
upgradeUrl: json.upgrade_url,
|
||||
upgradeMessage: json.upgrade_message,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -783,7 +793,11 @@ function buildOpenApiErrorMessage(params: OpenApiErrorParams): string {
|
||||
}
|
||||
|
||||
if (params.apiError === "RATE_LIMIT_EXCEEDED" || params.apiError === "RATE_LIMIT_BANNED") {
|
||||
return `${message}. Rate limit resets at ${resetText}. Stop sending requests before then; repeated requests can extend the ban by 5s up to 5 minutes.`;
|
||||
const retryGuidance = `Rate limit resets at ${resetText}. Stop sending requests before then; repeated requests can extend the ban by 5s up to 5 minutes.`;
|
||||
if (params.apiError === "RATE_LIMIT_EXCEEDED" && params.upgradeMessage) {
|
||||
return `${message}. ${retryGuidance} ${params.upgradeMessage}`;
|
||||
}
|
||||
return `${message}. ${retryGuidance}`;
|
||||
}
|
||||
|
||||
return `${message}. Received HTTP 429; retry after ${resetText}.`;
|
||||
|
||||
Reference in New Issue
Block a user