首页/区块链与 Web3/okx-growth-competition
O

okx-growth-competition

by @okxv
4.5(120)

此技能专为OKX Agentic Wallet用户设计,提供独家交易竞赛的全生命周期管理。用户可以轻松发现、查看规则、加入竞赛、进行交易、查询排名并领取奖励。它简化了Web3交易竞赛的参与流程,确保用户不错过任何赢取奖励的机会,提升交易体验和效率。

web3tradingcompetitiondefiwalletGitHub
安装方式
npx skills add https://github.com/okx/onchainos-skills --skill okx-growth-competition
compare_arrows

Before / After 效果对比

1 组
使用前

在没有智能体辅助的情况下,用户需要手动浏览多个页面,核对竞赛规则、交易资格、实时排名,并手动执行奖励领取操作,整个过程耗时且容易遗漏重要信息,平均每次竞赛需花费约60分钟。

使用后

通过智能体,用户只需简单指令即可完成竞赛发现、规则查看、参与、排名查询及奖励领取。智能体自动跟踪进度并提供提醒,将每次竞赛的管理时间大幅缩短至约5分钟,显著提升参与效率和体验。

SKILL.md

OKX Growth Competition — Trading Competition

Agentic Wallet exclusive trading competitions. Full lifecycle: list → detail → join → trade → rank → claim.

CLI reference: references/cli-reference.md

Facts about every Agentic Wallet competition (always true unless backend confirms otherwise)

  • chainId — single id. A trading chain AND the claim/reward chain (rewards are paid on this chain; its contract address is here).
  • participateChainIds — array of ids returned by both list and detail endpoints (may be empty on activities created before the field was added). Additional trading chains (no claim role).

The full trading-chain set for an activity is the UNION: {chainId} ∪ participateChainIds. Trades on any chain in that union count toward the same competition standing. The claim chain is chainId only.

  1. The trading-chain set is {chainId} ∪ participateChainIds (dedup). Render each id as a human-readable name via the canonical Chain id → display name table. Currently supported competition chains: 1 → Ethereum, 196 → X Layer, 501 → Solana.
  2. Trades on any chain in the union count toward the same competition standing. Trades on chains NOT in the union do not count. Never tell a user "your chain doesn't count" without first checking the union.
  3. myRankInfo.userTotal = 0 means the user has not yet hit the qualifying threshold or the backend metric pipeline has not picked up their trades yet — it does NOT mean the user's chain is unsupported.
  4. competition_rank takes a single optional wallet. Omit it for self-rank — the tool auto-resolves the chain-appropriate address from the active account based on competition_detail.chainId (the primary chain used for reward claim and rank indexing). Pass an explicit address ONLY when querying someone else's rank; the address chain (EVM 0x... else Solana) must match the activity's primary chain or the tool rejects the call (no silent wrong-chain queries). The chain you query on is just a lens — trades on every other chain in the union still count toward the same ranking.
  5. Claim path uses only chainId (that's where the reward contract / activity address lives). Everything else — trading eligibility, "which chains count", chain-list display in templates — uses the union of both fields.

When the user asks "Does my chain count for this competition?" or "Which chains can I trade on?", answer from the union of chainId and participateChainIds. When rendering the "Chain" column / line in a template, render that same union (deduplicated) — see the {supportedChains} computation rule in each Step's field-mapping section.

Identity resolution invariant (deterministic — always answerable)

Algorithm (always runs internally; AI cannot bypass):

Tool / call shapeIdentity sentWhy
competition_user_status (always)accountId (self)self-only tool; covers every chain in participateChainIds in one call
competition_rank with no walletaccountId (self)default self-rank, no chain picking needed
competition_rank with wallet=<addr>walletAddress (cross-user)the tool validates that addr's chain family (EVM 0x... else Solana) matches the activity's primary chainId; mismatch → call is rejected (no silent wrong-chain query)
competition_claim (pre-check)accountId (self)claim is always self-action; uses accountId for the eligibility check

How to answer "which identity did you use?":

CallWhat to say (translate to user's language)
Self-query (no wallet arg)"I used your accountId — the backend looks up your status across every chain in this competition (participateChainIds) in one call."
Cross-user query (wallet arg passed)"I used the wallet address <addr> you specified — it was validated to match the activity's primary chain before the call."

Forbidden answers (paraphrase patterns observed and are wrong):

  • ❌ "The tool sends both accountId and walletAddress" — Wrong. Exactly one, never both.
  • ❌ "The tool picks EVM or SOL based on chain" — Wrong (post-refactor). That was the old wallet-only model. Self-queries now send accountId, no chain pick.
  • ❌ "I'm not sure which one the tool ended up sending" — Wrong. It is deterministic from the call shape; always answerable from the above table.

For multi-activity queries (e.g. competition_user_status with no activity_name), the same accountId is reused for every activity in the iteration — the backend joins by accountId, not address. The answer is uniformly "I used your accountId for all activities".

⚠️ Mandatory reading order

The template structure is fixed; the language follows the user — see the ## Output Language rule above. When the user writes Chinese, translate the template strings to natural Chinese. When the user writes English, use English as written. Placeholders (including chain display names from {supportedChains}) stay as-is.

Quick router (user intent → template section):

  • "list competitions / show available competitions" → Step 1 (table, optionally split by Active / Ended)
  • "show details / show rules / show prize pool" → Step 2 (Basic info block + 4 reward sections, with {supportedChains} chain line and required participation / Skill copy)
  • "register / join" → Step 3 (registration success fixed template + disclaimer)
  • "trade for me" → Step 4 (delegate to okx-dex-swap)
  • "leaderboard / ranking" → Step 5
  • "claim reward" → Step 6 (use competition_claim MCP, atomic)
  • "show registered wallet" → Additional Flows / Query Registered Wallet
  • "export wallet" → Additional Flows / Wallet Export Guard

If the user's intent does not clearly map to one of the above, ask which they meant before responding — do not invent a freeform format.

Pre-flight

Read ../okx-agentic-wallet/_shared/preflight.md. If missing, read _shared/preflight.md.

Command Index

#CommandAuthDescription
1onchainos competition list [--status 0|1|2] [--page-size N] [--page-num N]NoneList Agentic Wallet exclusive competitions (default status=0, active only)
2onchainos competition detail --activity-id <id>NoneGet rules, prize pool, chain, timeline
3onchainos competition rank --activity-id <id> [--wallet <addr>] --sort-type <type> [--limit N]NoneLeaderboard + user rank. Omit --wallet to auto-resolve from the active account; the command fetches competition_detail.chainId and picks the chain-appropriate address. Pass --wallet ONLY to query someone else's rank — the address chain must match the activity chain or the call is rejected. MCP tool competition_rank mirrors this (single optional wallet). Discover available sort-type values from competition_detail → tabConfigs[].rankFieldConfig[].sortValueMap.descend (do not hardcode).
4onchainos competition user-status [--activity-id <id>]Wallet loginCheck participation & reward status using the active user's accountId (omit --activity-id to check all activities). MCP tool competition_user_status takes no wallet args — accountId is loaded from the local wallet store.
5onchainos competition join --activity-id <id> --evm-wallet <addr> --sol-wallet <addr> --chain-index <chain_id>Wallet loginRegister for the competition. MCP tool competition_join makes both wallet args optional.
6onchainos competition claim --activity-id <id> --evm-wallet <addr> --sol-wallet <addr>Wallet loginCLI returns unsigned calldata. MCP tool competition_claim is atomic — wallets are optional, signing + broadcast happens inside the tool, returns txHash array. Surfaces needContact: true for top-tier winners (see Step 6 contact-collection sub-flow).
7onchainos competition submit-contact --activity-id <id> --contact-type <Telegram|WeChat|Email|Twitter> --contact-value <text>Wallet loginRecord a contact method for top-tier winners (called only after a claim that returned needContact: true). MCP tool competition_submit_contact looks up accountId + joinedAddress internally.

--status (request filter): 0=active, 1=ended, 2=all
activityStatus (response field): 3=active, 4=ended — these are DIFFERENT values from the request filter
sort-type: dynamic — read from competition_detail → tabConfigs[].rankFieldConfig[].sortValueMap.descend. Currently observed values: 1=PnL% (realized ROI), 7=PnL (realized profit). Future activities may add more — always trust tabConfigs over hardcoding.

Output Rules

Internal-only IDs vs user-facing display. Internal numeric IDs (activityId, chainIndex, accountId) are returned in tool responses on purpose — they are needed to chain calls between tools (e.g. after competition_join, you may need to call competition_detail with the activity id to fill the success template). Keep them in the data layer; never render them in user-visible messages.

Forbidden user-visible patterns (do NOT produce output like this):

  • ❌ Agentic Trading Contest (#107)
  • ❌ #106 (agenticwallettest1)
  • ❌ A column titled ID, Activity ID, #, or any equivalent in the user's language
  • ❌ A row labeled Activity ID, ID, #, or any equivalent in the user's language (e.g. a 2-column key/value table where a row maps the id label to the numeric value) — this is the same violation as a column, just rotated
  • ❌ Any reference like competition 107, id 107, the activity id is 107, or the same wording in another language
  • ❌ Numeric id rendered anywhere a user can see it, regardless of label, shape, or language

Correct user-visible pattern:

  • ✅ Agentic Trading Contest
  • ✅ When disambiguating two activities with the same name, append chainName (e.g. Agentic Trading Contest (Solana)), never the ID.

Behind the scenes (allowed and expected):

  • ✅ Reading activityId from a competition_user_status / competition_join response and passing it to competition_detail to fetch the data needed by a fixed template.
  • ✅ Any tool-to-tool chaining via numeric ids — as long as the final user-facing message omits them.

When the user asks to act on a specific activity (e.g. "claim Agentic Trading Contest"), the MCP tools competition_claim / competition_join accept activity_name and resolve the id server-side, so you can also use names directly without doing your own lookup.

Time Formatting (MANDATORY)

Preferred — use backend-formatted strings when available:

For the competition_detail response, the backend now returns pre-formatted UTC+8 strings — use them verbatim, do NOT recompute from the raw epoch:

FieldFormatExample
startTimeFormattedyyyy-MM-dd HH:mm:ss (UTC+8, no suffix)"2026-05-07 18:00:00"
endTimeFormattedyyyy-MM-dd HH:mm:ss (UTC+8, no suffix)"2026-05-21 18:00:00"

When rendering, take the string as-is and append (UTC+8) for the timezone marker (e.g. 2026-05-07 18:00:00 (UTC+8)). This is the only correct path for detail view times — the backend has already done the math; computing from startTime / endTime epoch invites off-by-an-hour errors and AI hallucination.

Raw fields — only use when no *Formatted counterpart is present:

FieldFormatExample rawNotes
startTime, endTime (list response — no formatted variant returned)10-digit Unix seconds1778148000Multiply by 1000 only if the runtime expects ms
joinTime, claimTime (user-status response)10-digit Unix seconds1778148000Same
rankUpdateTime (rank response)13-digit Unix milliseconds1774359000638Divide by 1000 to convert to seconds first

If you see a 13-digit value where a 10-digit is documented (or vice versa), do NOT silently coerce — flag it as a backend anomaly.

Display format — exact, no improvisation:

  • Detail view (with *Formatted available): YYYY-MM-DD HH:mm:ss (UTC+8) — example: 2026-05-07 18:00:00 (UTC+8) (use the formatted string + suffix)
  • List view compact range: YYYY-MM-DD ~ YYYY-MM-DD (UTC+8 day boundary) — example: 2026-05-07 ~ 2026-05-21 (compute from raw startTime / endTime, take the date portion only)
  • joinTime / claimTime in user-facing context: YYYY-MM-DD HH:mm (UTC+8) (compute from raw epoch)
  • rankUpdateTime (last refresh marker): YYYY-MM-DD HH:mm:ss (UTC+8) (compute from raw ms epoch)

Timezone rule: ALL competition times displayed to the user are in UTC+8 (China Standard Time). The competition product is operated in UTC+8; never display raw UTC, never use the user's local timezone.

When you DO need to convert from raw epoch (no formatted field available):

  1. Identify the field's documented unit (seconds or milliseconds — see table above).
  2. Convert to a Date object using the correct unit.
  3. Format as a UTC+8 wall-clock string per the display format above.
  4. Always append the (UTC+8) suffix.

...

用户评价 (0)

发表评价

效果
易用性
文档
兼容性

暂无评价

统计数据

安装量10.9K
评分4.5 / 5.0
版本
更新日期2026年10月7日
对比案例1 组

用户评分

4.5(120)
5
37%
4
43%
3
13%
2
5%
1
2%

为此 Skill 评分

0.0

兼容平台

🤖claude-code

时间线

创建2026年5月28日
最后更新2026年10月7日
🎁 Agent 知识卡片
调研问卷