TokenDraft幻想加密竞赛完整套件——使用Solana钱包认证、查询/加入/自动加入竞赛,以及管理自动选秀资产
TokenDraft 认证是一项面向实际任务的技能,主要用于两步挑战响应流程;私有密钥永远不会离开本地环境;
该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;
若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
两步挑战-响应流程。私钥永不离开本地环境。
登录成功后,请将 TOKENDRAFT_USER_ID(来自 user.id)和 TOKENDRAFT_JWT(来自 token)作为环境变量存储。所有其他 TokenDraft 接口均需这两个变量。
若任意 TokenDraft 接口返回 401 状态码,请自动重新执行本身份验证流程,并重试失败的请求。
curl -X POST https://tokendraft-production.up.railway.app/api/v2/agents/nonce
-H "Content-Type: application/json"
-d '{"walletPublicKey": ""}'
返回 { nonce, message }。其中 message 是需签名的完整字符串。Nonce 有效期为 5 分钟,且仅可使用一次。
在本地使用 Ed25519 对 message 进行签名,并对签名结果进行 base58 编码:
curl -X POST https://tokendraft-production.up.railway.app/api/v2/agents/login
-H "Content-Type: application/json"
-d '{
"walletPublicKey": "",
"nonce": "",
"signature": ""
}'
返回 { token, user }。首次登录将自动创建账户。
首次登录时(用户 displayName 为类似 "a3F9x" 的短哈希),请询问用户是否希望设置显示名称。若用户同意,请调用下方「更新显示名称」接口。
curl -X POST "https://tokendraft-production.up.railway.app/api/v2/users/displayName"
-H "Authorization: Bearer $TOKENDRAFT_JWT"
-H "Content-Type: application/json"
-d '{"displayName": ""}'
约束条件:显示名称必须全平台唯一;每 24 小时最多修改一次;若触发限流,将返回 HTTP 429 状态码,并在响应体中包含 retryAfterMs 字段。
import nacl from 'tweetnacl';
import bs58 from 'bs58';
const secretKey = bs58.decode(process.env.SOLANA_PRIVATE_KEY);
const keyPair = nacl.sign.keyPair.fromSecretKey(secretKey);
const walletPublicKey = bs58.encode(keyPair.publicKey);
// 步骤 1
const { nonce, message } = await fetch('https://tokendraft-production.up.railway.app/api/v2/agents/nonce', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ walletPublicKey }),
}).then(r => r.json());
// 步骤 2
const messageBytes = new TextEncoder().encode(message);
const signature = nacl.sign.detached(messageBytes, keyPair.secretKey);
const signatureBase58 = bs58.encode(signature);
const { token, user } = await fetch('https://tokendraft-production.up.railway.app/api/v2/agents/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ walletPublicKey, nonce, signature: signatureBase58 }),
}).then(r => r.json());
所有认证请求均需携带以下头信息:
Authorization: Bearer $TOKENDRAFT_JWT
Token 本身永不过期,但可能因服务端密钥轮换而被主动作废。
所有接口均使用基础 URL https://tokendraft-production.up.railway.app,并要求请求头包含 Authorization: Bearer $TOKENDRAFT_JWT。若收到 401 响应,请通过上述身份验证流程重新认证。
curl "https://tokendraft-production.up.railway.app/api/v2/agents/tournaments?" -H "Authorization: Bearer $TOKENDRAFT_JWT"
| 参数 | 类型 | 说明 |
|---|---|---|
isOpen |
boolean | 是否接受报名 |
isInProgress |
boolean | 是否正在进行中 |
isFinished |
boolean | 是否已结束 |
isRegistered |
boolean | 按用户当前报名状态过滤 |
finishedLookbackHours |
number | 查询已结束赛事的时间范围(单位:小时;默认值:24;0 表示不限制) |
多个筛选参数之间为逻辑 AND 关系。若未指定任何状态参数,则默认仅返回 isOpen=true 的锦标赛。
返回 TournamentSummary 对象数组:
{ id: string, name: string, buyInAmountSol: number, registrationStartTime: string,
registrationEndTime: string, state: string, numPlayersRegistered: number,
maxPlayers: number, amIRegistered: boolean,
draftType: "snake" | "boosterPack" | "instantRoster",
rosterSlots: { Chain?: number, Meme?: number, Utility?: number, NFT?: number, Flex?: number } }
若 buyInAmountSol 为 0:
curl -X POST "https://tokendraft-production.up.railway.app/api/v2/tournaments/join/" -H "Authorization: Bearer $TOKENDRAFT_JWT"
HTTP 200 表示报名成功。请将任何错误信息透传给用户。
若该锦标赛为 instantRoster 类型,请同步更新资产优先级排序。
对于 buyInAmountSol > 0 的锦标赛,请先校验用户 SOL 余额是否足以覆盖买入金额及手续费。
1. 初始化交易:
curl -X POST "https://tokendraft-production.up.railway.app/api/v2/buyIn/initiateTransaction"
-H "Authorization: Bearer $TOKENDRAFT_JWT"
-H "Content-Type: application/json"
-d '{"tournamentId": "", "walletPublicKey": ""}'
返回 { transaction (base64), expectedSignature, tournamentInfo }。
2. 签名:将 transaction 反序列化为 VersionedTransaction,使用钱包密钥对签名,再重新序列化为 base64 格式。
3. 发送已签名交易:
curl -X POST "https://tokendraft-production.up.railway.app/api/v2/buyIn/sendSignedTransaction"
-H "Content-Type: application/json"
-d '{
"signedTransactionBase64": "",
"tournamentId": "",
"expectedSignature": "",
"walletPublicKey": ""
}'
HTTP 200 表示报名成功。请向用户透传错误信息(如:锦标赛已满员、用户已报名、链上执行失败等)。
若该锦标赛为 instantRoster 类型,请同步更新资产优先级排序。
当 draftType 为 "instantRoster" 时,系统将依据玩家的资产优先级排序,立即全自动完成整套阵容构建。此过程无实时选秀环节——所有选择均以机器速度完成,回合时间为 0 秒。不同玩家之间允许重复选择同一资产(例如两名玩家均可持有同一枚代币),但单个玩家不可在阵容中重复选择同一资产。
加入 instantRoster 锦标赛后,您必须设置资产优先级排序,以便自动选秀器明确应如何选取资产。
锦标赛的 rosterSlots 字段指明了每类资产所需数量。从 GET /api/v2/assets 获取的每个资产均包含 assetType 字段(例如 "Chain"、"Meme"、"Utility"、"NFT")。其中 "Flex" 槽位可接受任意类型的资产。
操作步骤:
GET /api/v2/assets — 返回 [{ id, name, ticker, assetType, priceUSD, marketcapUSD, dayChangePercent, dayVolumeUSD, ... }]rosterSlots(例如 { "Chain": 2, "Meme": 2, "Utility": 1, "NFT": 1, "Flex": 1 })assetType 下最优资产rosterSlots 中声明,或其值 ≤ 0,则在排序时忽略该类型所有资产PUT /api/v2/assetPriorityRankings 提交排序后的资产列表示例 — 给定 rosterSlots: { "Chain": 2, "Meme": 2, "Utility": 1, "NFT": 1, "Flex": 1 } 和「最高市值」策略:
assets = GET /api/v2/assets
按 marketcapUSD 降序排列各 assetType 下的资产:
chains = assets.filter(a => a.assetType === "Chain").sort(by marketcapUSD desc)
memes = assets.filter(a => a.assetType === "Meme").sort(by marketcapUSD desc)
utils = assets.filter(a => a.assetType === "Utility").sort(by marketcapUSD desc)
nfts = assets.filter(a => a.assetType === "NFT").sort(by marketcapUSD desc)
为每个槽位选取 Top N 资产:
rank 1: chains[0] (Chain 槽位 1)
rank 2: chains[1] (Chain 槽位 2)
rank 3: memes[0] (Meme 槽位 1)
rank 4: memes[1] (Meme 槽位 2)
rank 5: utils[0] (Utility 槽位)
rank 6: nfts[0] (NFT 槽位)
rank 7: 剩余资产中综合最优的一项(Flex 槽位)
rank 1 的资产将被选为「队长」,其得分权重为双倍,因此请将整体最优资产设为 rank 1。
提交至 PUT /api/v2/assetPriorityRankings:
{ "assets": [{"assetId":"","rank":1}, ...], "autoDraftStrategy": "MKT_CAP_DESC" }
draftType === "instantRoster" 的赛事GET /api/v2/assets 获取资产数据rosterSlots 要求的 7 项资产排序列表PUT /api/v2/assetPriorityRankings 提交排序配置定时任务,每 30 分钟自动加入所有开放中的锦标赛:
openclaw cron add --name "tokendraft-auto-join" --cron "*/30 * * * *" --session isolated --message "Auto-join open TokenDraft tournaments. Steps: 1. Authenticate with TokenDraft (see auth section above). 2. GET /agents/tournaments?isOpen=true&isRegistered=false to find open tournaments. 3. For each: if buyInAmountSol is 0, POST /tournaments/join/. If > 0, check SOL balance and follow buy-in flow. 4. If the joined tournament has draftType 'instantRoster', also set asset priority rankings that fulfil the rosterSlots. 5. Report results for each tournament (joined or error reason)."
可通过以下命令管理定时任务:openclaw cron list、openclaw cron remove 、openclaw cron edit 。
所有接口均使用基础 URL https://tokendraft-production.up.railway.app,并要求请求头包含 Authorization: Bearer $TOKENDRAFT_JWT。若收到 401 响应,请通过上述身份验证流程重新认证。
在拉取资产数据前,请先询问用户希望按何种维度排序资产(例如:按市值、按 24 小时交易量、逢低买入、优先 memecoin 等)。
curl "https://tokendraft-production.up.railway.app/api/v2/assets" -H "Authorization: Bearer $TOKENDRAFT_JWT"
返回资产数组,字段包括:id、name、ticker、priceUSD、marketcapUSD、dayChangePercent、dayVolumeUSD、adpRanking、assetType、tags。
为每个资产分配一个排名,1 表示首轮被选中,N 表示最后被选中。请结合用户建议与财务数据综合判断。
内置策略(通过设置 autoDraftStrategy 字段启用,无需手动指定排名):
VOL_24H_DESC、VOL_24H_ASC、MKT_CAP_ASC、MKT_CAP_DESC、ADP、PERCENT_24H_ASC、PERCENT_24H_DESC
curl -X PUT "https://tokendraft-production.up.railway.app/api/v2/assetPriorityRankings"
-H "Authorization: Bearer $TOKENDRAFT_JWT"
-H "Content-Type: application/json"
-d '{
"assets": [{"assetId": "", "rank": 1}, ...],
"autoDraftStrategy": "PERCENT_24H_DESC"
}'
仅需提交前 7 项资产;rank 值须为互不重复的整数;autoDraftStrategy 为必填字段,若用户未指定,则默认使用 "PERCENT_24H_DESC"。该策略亦作为部分资产无法参与排序时的兜底方案。
向用户征询排序建议及更新频率后,创建定时任务:
openclaw cron add --name "tokendraft-auto-rank" --cron "" --session isolated --message "Update TokenDraft rankings. Steps: 1. Authenticate (see auth section above). 2. GET /api/v2/assets for current data. 3. Rank all assets 1-N based on: . 4. PUT /api/v2/assetPriorityRankings with ranked list. 5. Report success or failure."
可通过以下命令管理定时任务:openclaw cron list、openclaw cron remove 、openclaw cron edit 。