请帮我在当前 Claude Code 环境中安装 "wakeup-alert-api-client" Skill,让你以后可以替我调用 Wakeup 加密风险电话告警 API。 步骤: 1. 创建目录 `~/.claude/skills/wakeup-alert-api-client/references/`。 2. 把下面三段内容分别保存为: - `~/.claude/skills/wakeup-alert-api-client/SKILL.md` - `~/.claude/skills/wakeup-alert-api-client/references/api-reference.md` - `~/.claude/skills/wakeup-alert-api-client/references/x402-payment.md` 3. 安装完成后告诉我,并简要说明这个 skill 能做什么。 ===== FILE: SKILL.md ===== --- name: wakeup-alert-api-client description: "Use when an agent needs to integrate with the Wakeup crypto risk alert service: pay x402 to create alert rules, manage rules with the returned accessToken, recover a lost token via /login, test rules, or inspect alert events. Wakeup uses a payer-bound token model on X Layer." --- # Wakeup Alert API Client ## Overview Wakeup is a crypto risk monitoring service. A wallet pays once via x402 to create a rule; the same payment binds the wallet as the rule owner and returns a 365-day `accessToken` that is then used to manage every subsequent operation. The wallet itself is the identity — there is no signup. Key behaviors to know before calling: - `POST /api/v1/rules` is the only paid create path; it returns `{ rule, accessToken, expiresAt }`. - `POST /api/v1/login` lets a wallet that lost its token pay a tiny fee to rotate it and pull all historical rules. - `POST /api/v1/rules/:id/test` is **both** x402-paid **and** Bearer-auth gated (test still consumes a real delivery slot). - All other rule and event endpoints are Bearer-auth only and free. - A rule that fires for real is auto-archived (`status = "consumed"`), which prevents repeat charges. - `PATCH /api/v1/rules/:id` only accepts safe fields (`name`, `status`, `actions`, `pollIntervalSeconds`). Changing `type` / `target` / `condition` requires a brand-new paid rule. Load references only as needed: - `references/api-reference.md`: endpoint table, auth model, rule schema, payload examples per monitor type. - `references/x402-payment.md`: 402 flow, payment header decoding, X Layer / USDt0 amounts. ## Workflow 1. Establish the base URL. - Production: `https://wakemeup.cc`. - Use the deployed URL the user provides instead. 2. Health check. - `GET /api/v1/health` — surface connectivity issues before paid calls. 3. Decide the operation: create new vs. manage existing vs. recover token. 4. Create a rule (paid). - `POST /api/v1/rules` with the JSON payload from `references/api-reference.md`. - Pass the payer wallet via the `x-payer-address` header (current placeholder until the facilitator-derived payer is wired in). - Pay via x402; see `references/x402-payment.md`. Without a payment-capable client, decode and report the 402 challenge instead of pretending success. - **Persist the returned `accessToken` to disk before returning to the user** — see "Token persistence" below. The agent loses memory across sessions; without persistence the user has to pay the `/login` fee to recover. 5. Manage existing rules (Bearer auth, free). - `Authorization: Bearer wkp_...` - `GET /api/v1/rules` lists every rule (active / paused / consumed) for the bound wallet. - `GET /api/v1/rules/:id`, `PATCH /api/v1/rules/:id`, `DELETE /api/v1/rules/:id` for single-rule lifecycle. - PATCH only accepts `name` / `status` / `actions` / `pollIntervalSeconds`. 6. Test a rule. - `POST /api/v1/rules/:id/test` requires **both** the Bearer token and an x402 payment. - Body `{ "send": false }` evaluates only; `{ "send": true }` evaluates and fires the phone delivery if triggered, which also archives the rule (`consumed`). 7. Inspect evidence (Bearer auth, free). - First call `GET /api/v1/rules` or `GET /api/v1/rules/:id` and inspect each rule's `executionLogs`. These logs show recent scheduler/manual-test checks, including non-triggered checks, cooldown skips, and failures. - Use `GET /api/v1/events?limit=50` only for real trigger evidence; events are created when a rule actually fires and are scoped to the bound wallet's rules. - `GET /api/v1/events/:id` — single triggered event with delivery history. 8. Recover a lost token. - `POST /api/v1/login` with `x-payer-address: 0xYourWallet` (intended paid; tiny x402 fee proves wallet ownership). - Returns a fresh `accessToken` and the wallet's full rule history; the previous token is invalidated immediately. - After recovery, **rewrite the persisted token file** with the new value. ## Token Persistence The agent does not retain `accessToken` between sessions. Always store it locally on the user's machine immediately after `POST /api/v1/rules` or `POST /api/v1/login`. Default location and shape: ```text ~/.wakeup/tokens.json (chmod 600) ``` ```json { "": { "": { "accessToken": "wkp_...", "expiresAt": "2027-05-14T..." } } } ``` Rules: - **Always read this file at the start of a manage / test / events workflow** before asking the user for a token. Match by base URL + lowercased payer address. - Write atomically (write to `tokens.json.tmp` then rename). Set permissions to `600` so other local users cannot read it. - Overwrite the entry on every successful create/login response — `/login` rotation invalidates the old value immediately. - If the file is missing or the entry has expired (`expiresAt` in the past), do **not** silently fail. Tell the user the token can't be found locally and offer the recovery path: run `POST /api/v1/login` for this payer (step 8). After recovery, write the new token to `~/.wakeup/tokens.json` before continuing the original workflow. If the user declines, ask them to paste the token directly or skip the operation — never invent or reuse another wallet's token. - Never paste the token into logs, URLs, error messages shown to the user, or any third-party service. - If the user explicitly asks for a different storage location (env var, password manager, secrets file), honor that and skip writing to `~/.wakeup/tokens.json`. ## Guardrails - Treat the `accessToken` as a bearer secret. Do not log it, do not embed it in URLs, do not share between wallets. - Do not request or store seller-side secrets (OKX facilitator API keys, wallet private keys). Those live on the Wakeup server. - Read-only exchange API keys submitted for `cex_position_risk` must never include trade or withdrawal permissions. - `dex_price` uses OKX DEX Market Price. Use `source: "okx_dex"` with `chainIndex` and lowercase EVM `tokenContractAddress`; do not send old CoinGecko `coinId` payloads. - Wakeup's only x402-protected resources are `POST /api/v1/rules`, `POST /api/v1/rules/:id/test`, and `POST /api/v1/login`. Do not assume `/weather` (the OKX docs example) exists here. - USDt0 on X Layer uses 6 decimals: `amount: "100000"` means `0.1 USDT`. - If a paid call returns anything other than 402 before payment was attempted, surface the server error verbatim — do not fabricate a payment success or a synthetic accessToken. - When a rule is `consumed`, do not re-test it; create a fresh rule (and pay again) if continued monitoring is needed. ===== END FILE ===== ===== FILE: references/api-reference.md ===== # Wakeup API Reference ## Base URL Use the user-provided service URL. Production URL: ```text https://wakemeup.cc ``` ## Auth Model Wakeup binds rules to a wallet ("payer") and issues a 365-day bearer token at first paid create. - `POST /api/v1/rules` — pay via x402; identifies payer via the `x-payer-address` header (placeholder until facilitator-derived payer is wired). Returns `{ rule, accessToken, expiresAt }`. - `POST /api/v1/login` — pay a tiny x402 fee to rotate the token and pull the full rule history. Use when the token is lost or leaked. - All other rule/event endpoints require `Authorization: Bearer wkp_...`. - `GET /api/v1/health` is the only fully public endpoint. ## Endpoint Table ```text GET /api/v1/health free POST /api/v1/rules paid (x402) → returns accessToken POST /api/v1/login paid (x402, tiny) → rotates accessToken GET /api/v1/rules auth (Bearer) GET /api/v1/rules/:id auth PATCH /api/v1/rules/:id auth (safe fields only) DELETE /api/v1/rules/:id auth POST /api/v1/rules/:id/test auth + paid (x402) GET /api/v1/events?limit=50 auth GET /api/v1/events/:id auth ``` PATCH safe fields: `name`, `status`, `actions`, `pollIntervalSeconds`. To change `type` / `target` / `condition`, create a new paid rule. ## Token Persistence (agent-side) The agent has no memory across sessions. After a successful `POST /api/v1/rules` or `POST /api/v1/login`, write the token to disk so the next session can manage existing rules without paying again. Default path: `~/.wakeup/tokens.json` (mode `600`), keyed by base URL → lowercased payer address: ```json { "https://wakemeup.cc": { "0xabc...": { "accessToken": "wkp_...", "expiresAt": "2027-05-14T..." } } } ``` At the start of any manage / test / events flow, read this file first. If the entry is missing or expired, ask the user to supply the token or run `/login`. Always overwrite on `/login` because the previous token is invalidated immediately. ## Lifecycle Flow ```text 1. POST /api/v1/rules + x402 + x-payer-address → 201 { rule, accessToken: "wkp_...", expiresAt } 2. Manage with Bearer: GET /api/v1/rules GET /api/v1/rules/:id PATCH /api/v1/rules/:id { name?, status?, actions?, pollIntervalSeconds? } DELETE /api/v1/rules/:id POST /api/v1/rules/:id/test { "send": false | true } ← also requires x402 payment 3. When the rule fires for real, the server marks it consumed and stops polling. 4. Lost the token? POST /api/v1/login with x-payer-address (+ x402) → 200 { accessToken, expiresAt, rules: [...] } ``` ## Rule Object Required create fields: ```json { "name": "Human readable rule name", "type": "cex_price", "target": {}, "condition": { "metric": "price", "operator": "below", "value": 999999 }, "actions": [ { "type": "phone_call", "phone": "+10000000000", "cooldownSeconds": 60 } ], "pollIntervalSeconds": 30 } ``` Actions may use either `phone` or `configId`, not both. If both are omitted, the server reuses the payer wallet's most recent phone-call config; the first rule for a wallet must provide `phone` or `configId`. `GET /api/v1/rules`, `GET /api/v1/rules/:id`, and `/login` rule history include `executionLogs`, the three newest evaluation logs for each rule. These logs are written for scheduler checks and manual tests, including non-triggered checks and failures, so clients can show that monitoring is actively running. Execution log shape: ```json { "id": "...", "ruleId": "...", "source": "scheduler", "status": "success", "triggered": false, "metric": "price", "observedValue": 100.12, "threshold": 90, "message": "【BTC low price】BTCUSDT 价格当前值:100.12;条件:价格低于90;结果:未触发", "error": null, "eventId": null, "createdAt": "2026-05-14T00:00:00.000Z" } ``` Supported operators: ```text above | below | gte | lte | outside_range | inside_range ``` Range operators require `upperValue`, and `upperValue` must be greater than `value`. ## Create Example (full request) ```bash curl -i -X POST "$BASE_URL/api/v1/rules" \ -H "Content-Type: application/json" \ -H "x-payer-address: 0xYourWallet" \ -H "PAYMENT-SIGNATURE: " \ -d '{ "name": "USDC wallet balance below 1000", "type": "wallet_balance", "target": { "chain": "ethereum", "walletAddress": "0x...", "tokenSymbol": "USDC" }, "condition": { "metric": "balance", "operator": "below", "value": 1000 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] }' ``` Successful response (201): ```json { "rule": { "id": "...", "status": "active", "...": "..." }, "accessToken": "wkp_...", "expiresAt": "2027-05-14T..." } ``` ## Manage Example (Bearer) ```bash curl "$BASE_URL/api/v1/rules" \ -H "Authorization: Bearer $WAKEUP_TOKEN" curl -X PATCH "$BASE_URL/api/v1/rules/$RULE_ID" \ -H "Authorization: Bearer $WAKEUP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "status": "paused" }' curl -X DELETE "$BASE_URL/api/v1/rules/$RULE_ID" \ -H "Authorization: Bearer $WAKEUP_TOKEN" ``` ## Token Recovery (/login) ```bash curl -X POST "$BASE_URL/api/v1/login" \ -H "x-payer-address: 0xYourWallet" \ -H "PAYMENT-SIGNATURE: " ``` Always rotates the token; the previous token is immediately invalid. ## Test a Rule (auth + paid) ```bash # evaluate only curl -X POST "$BASE_URL/api/v1/rules/$RULE_ID/test" \ -H "Authorization: Bearer $WAKEUP_TOKEN" \ -H "PAYMENT-SIGNATURE: " \ -H "Content-Type: application/json" \ -d '{}' # evaluate and trigger phone delivery (also marks rule consumed) curl -X POST "$BASE_URL/api/v1/rules/$RULE_ID/test" \ -H "Authorization: Bearer $WAKEUP_TOKEN" \ -H "PAYMENT-SIGNATURE: " \ -H "Content-Type: application/json" \ -d '{"send": true}' ``` ## Event Evidence (auth) ```bash curl "$BASE_URL/api/v1/events?limit=50" \ -H "Authorization: Bearer $WAKEUP_TOKEN" curl "$BASE_URL/api/v1/events/$EVENT_ID" \ -H "Authorization: Bearer $WAKEUP_TOKEN" ``` Events are scoped to the bound wallet's rules. Each entry includes rule id, observed metric, threshold, trigger message, and per-channel delivery status. ## Supported Rule Types ### CEX Price Type: `cex_price` Metrics: ```text price | changePct | absDiff | ratio ``` `target.source` is optional and defaults to `"binance"`. The Binance fetcher tries USDT-margined futures (`fapi.binance.com`) first and falls back to spot (`api.binance.com`) — use the standard `BTCUSDT` / `ETHUSDT` symbol form for both. Example: ```json { "name": "BTC price below threshold", "type": "cex_price", "target": { "symbol": "BTCUSDT" }, "condition": { "metric": "price", "operator": "below", "value": 999999 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }], "pollIntervalSeconds": 30 } ``` Ratio example: ```json { "name": "BTC/ETH ratio below 10", "type": "cex_price", "target": { "symbol": "BTCUSDT", "symbolB": "ETHUSDT" }, "condition": { "metric": "ratio", "operator": "below", "value": 10 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] } ``` ### DEX / Aggregated Price Type: `dex_price` Metrics: ```text price | changePct | absDiff | ratio ``` DEX prices are fetched from OKX DEX Market Price (`/api/v6/dex/market/price`). Required target fields: `source: "okx_dex"`, `symbol`, `chainIndex`, and `tokenContractAddress`. For EVM tokens, pass the contract address in lowercase. For ratio rules, also provide `tokenContractAddressB`; `chainIndexB` is optional and defaults to `chainIndex`. ```json { "name": "WETH DEX quote below threshold", "type": "dex_price", "target": { "source": "okx_dex", "symbol": "WETH", "chainIndex": "1", "tokenContractAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" }, "condition": { "metric": "price", "operator": "below", "value": 999999 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] } ``` ### Wallet Balance Type: `wallet_balance` Metric: `balance` Required target fields: `chain`, `walletAddress`. Supported chains: `ethereum`, `arbitrum`, `base`. Supply `tokenContract` (and optional `tokenSymbol`) for ERC20; omit for native balance. ```json { "name": "USDC wallet balance below 1000", "type": "wallet_balance", "target": { "chain": "ethereum", "walletAddress": "0x...", "tokenContract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "tokenSymbol": "USDC" }, "condition": { "metric": "balance", "operator": "below", "value": 1000 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] } ``` ### AAVE Account Risk Type: `aave_account_risk` Common metrics: `healthFactor`, `ltv`, `totalDebtUsd`, `availableBorrowsUsd`, plus collateral / liquidation values exposed by the evaluator. Required target fields: `chain`, `walletAddress`. ```json { "name": "AAVE health factor below 1.25", "type": "aave_account_risk", "target": { "chain": "ethereum", "walletAddress": "0x..." }, "condition": { "metric": "healthFactor", "operator": "below", "value": 1.25 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] } ``` ### CEX Position Risk Type: `cex_position_risk` Supported exchanges: `hyperliquid`, `binance`, `okx`. - Hyperliquid: requires `walletAddress`. - Binance / OKX: require either `credentialId` (a previously stored read-only key) or inline read-only credentials. OKX inline credentials also require `apiPassphrase`. Hyperliquid example: ```json { "name": "Hyperliquid distance to liquidation below 8%", "type": "cex_position_risk", "target": { "exchange": "hyperliquid", "walletAddress": "0x...", "symbol": "BTC" }, "condition": { "metric": "distanceToLiqPct", "operator": "below", "value": 8 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] } ``` Binance account margin example: ```json { "name": "Binance account margin ratio above 60%", "type": "cex_position_risk", "target": { "exchange": "binance", "credentialId": "cred_binance" }, "condition": { "metric": "accountMarginRatio", "operator": "above", "value": 60 }, "actions": [{ "type": "phone_call", "phone": "+10000000000" }] } ``` ===== END FILE ===== ===== FILE: references/x402-payment.md ===== # x402 Payment Reference ## Protected Wakeup Resources ```text POST /api/v1/rules create a rule (issues accessToken) POST /api/v1/rules/:id/test evaluate or fire a rule (also requires Bearer auth) POST /api/v1/login rotate accessToken + pull rule history ``` These endpoints are gated when the Wakeup server has `X402_PAYMENT_ENABLED=true`. Every other endpoint is either Bearer-auth or free. ## Payment Terms ```text scheme: exact network: eip155:196 # X Layer token: USDt0 asset: 0x779ded0c9e1022225f8e0630b35a9b54be713736 amount: 100000 # atomic units, 6 decimals human amount: 0.1 USDT # for /rules and /rules/:id/test payTo: 0x69421fd0099582730233083da0ff79f33c865476 ``` Amount is in token atomic units. USDt0 uses 6 decimals, so `100000` means `0.1`. The `/login` route is intended to charge a much smaller proof-of-ownership amount (e.g. `$0.00001`); read its 402 challenge to confirm the live price. ## Validate the Server-Side Payment Gate Run an unpaid request: ```bash curl -i -X POST "$BASE_URL/api/v1/rules" \ -H "Content-Type: application/json" \ -H "x-payer-address: 0xYourWallet" \ -d '{}' ``` Expected shape: ```http HTTP/1.1 402 Payment Required content-type: application/json payment-required: eyJ4NDAyVmVyc2lvbiI6... ``` The response body may be: ```json { "error": "Payment required", "payment": { "protocol": "x402", "network": "eip155:196", "scheme": "exact", "description": "Create a crypto alert rule" } } ``` Decode the header for inspection: ```bash HEADER=$(curl -i -sS -X POST "$BASE_URL/api/v1/rules" \ -H "Content-Type: application/json" \ -H "x-payer-address: 0xYourWallet" \ -d '{}' | awk 'BEGIN{IGNORECASE=1} /^payment-required:/{print $2}' | tr -d '\r') node -e 'console.log(JSON.stringify(JSON.parse(Buffer.from(process.argv[1], "base64").toString("utf8")), null, 2))' "$HEADER" ``` Expected decoded fields: ```json { "x402Version": 2, "accepts": [ { "scheme": "exact", "network": "eip155:196", "asset": "0x779ded0c9e1022225f8e0630b35a9b54be713736", "amount": "100000", "payTo": "0x69421fd0099582730233083da0ff79f33c865476", "extra": { "name": "USD₮0", "version": "1" } } ] } ``` ## Identifying the Payer Until the facilitator-derived payer wiring lands, the server reads the wallet from the `x-payer-address` request header. Always send it on every paid call. Once the facilitator settlement result is wired in, this header becomes a fallback only. ## Paying Client Notes The Wakeup server is the x402 seller. A consuming agent needs its own x402 buyer/client capability and X Layer wallet funding to retry the request with a valid payment header. If the current agent environment does not include a wallet or x402 buyer SDK: 1. Make the unpaid request with `x-payer-address` set. 2. Decode and report the `payment-required` header. 3. Ask the caller to provide a payment-capable client or handle payment outside the agent. 4. Do not pretend the call succeeded and never fabricate an `accessToken`. After successful payment: - `POST /api/v1/rules` → `201 { rule, accessToken, expiresAt }` plus an x402 receipt header. Persist `accessToken` for all subsequent management calls. - `POST /api/v1/rules/:id/test` → normal evaluation/delivery JSON; the rule will be marked `consumed` if `send: true` triggered a real delivery. - `POST /api/v1/login` → `200 { accessToken, expiresAt, rules }`; the previous token is invalidated. ===== END FILE =====