用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/jiayaoqijia/cryptoskill --skill polyhub-copy命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
"Peer-driven onchain reputation layer for AI agents enabling kudos across reliability, speed, accuracy, creativity, and security categories."
"Interaction layer where humans, AI agents, and blockchain converge, powering a trustless reputation economy for ERC-8004 ecosystem."
"Interaction layer powering trustless reputation economy for ERC-8004 ecosystem with rewards for honest contributions."
基于 SOC 职业分类
正在显示 SKILL.md
| name | polyhub_copy |
| description | Manage copy-trading tasks, view signals, positions and trades on Polyhub using an API key. |
Version: v0.3.3
Use this skill when the user asks about:
POLYHUB_API_BASE_URL — Polyhub API server URL (e.g. https://api.polyhub.example.com)POLYHUB_API_KEY — API key (must start with phub_)curl must be available in the runtime environment.jq is strongly recommended for building JSON payloads safely.POLYHUB_API_KEY in the output.POST/PATCH/DELETE), repeat the action summary and wait for explicit user confirmation before calling the API.jq -n instead of interpolating raw shell strings.taskId must be a 24-char hex MongoDB ObjectID: ^[0-9a-fA-F]{24}$ruleId must be non-empty.taskIds in batch operations must all match the taskId format.status for positions should only be passed when the user explicitly requests a filter.Use the bash tool to call the API with curl.
For common intents, map user requests like this:
GET /api/v1/copy-tasksPATCH /api/v1/copy-tasks/{taskId} with statusPATCH /api/v1/copy-tasks/{taskId} with taskConfigGET /positions or GET /tradesPOST /sell or POST /sell-allGET /api/v1/copy-signals or /statsBASE="${POLYHUB_API_BASE_URL%/}"
AUTH=(-H "Authorization: Bearer $POLYHUB_API_KEY" -H "Content-Type: application/json")
if [[ ! "$TASK_ID" =~ ^[0-9a-fA-F]{24}$ ]]; then echo "Invalid taskId"; exit 2; fi
if [[ -z "${RULE_ID:-}" ]]; then echo "Invalid ruleId"; exit 2; fi
for id in "${TASK_IDS[@]}"; do
if [[ ! "$id" =~ ^[0-9a-fA-F]{24}$ ]]; then
echo "Invalid taskId in batch: $id"
exit 2
fi
done
GET /api/v1/copy-tasksincludeDeleted=true|false (default: true)curl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-tasks?includeDeleted=true"
Guidance:
includeDeleted=true when the user wants a full history or is looking for a previously deleted task.includeDeleted=false when the user only wants active/non-deleted tasks.POST /api/v1/copy-taskstargetTrader (Polymarket address of the smart money)domain.CreateCopyTaskPayload: targetUsername, taskConfig, filteredByTag, tpslRulesBefore calling: ask the user for targetTrader at minimum. Summarize and confirm.
Minimum fields to ask:
targetTraderfilteredByTag, targetUsernametaskConfig fields explicitlytpslRulesPAYLOAD="$(jq -n \
--arg targetTrader "0x..." \
'{targetTrader: $targetTrader}')"
curl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks" \
-d "$PAYLOAD"
If the user wants advanced config, build taskConfig and tpslRules explicitly instead of accepting arbitrary JSON.
GET /api/v1/copy-tasks/{taskId}curl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-tasks/$TASK_ID"
PATCH /api/v1/copy-tasks/{taskId}statustaskConfigfilteredByTagtargetUsernametpslRules using create / update / cancelBefore calling: validate taskId, summarize changes, and confirm.
Minimum fields to ask:
taskIdstatustaskConfigtargetUsername, filteredByTagtpslRulesPAYLOAD="$(jq -n \
--arg status "PAUSED" \
'{status: $status}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Example: update taskConfig safely
PAYLOAD="$(jq -n \
--argjson buyOnly true \
--argjson maxBoughtPerMarket 50 \
'{taskConfig: {buyOnly: $buyOnly, maxBoughtPerMarket: $maxBoughtPerMarket}}')"
Example: change copy mode to ONE_TO_ONE
PAYLOAD="$(jq -n \
'{taskConfig: {copyMode: "ONE_TO_ONE"}}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Example: change copy mode to FIXED_SIZE
FIXED_SIZE should include taskConfig.fixedAmount.
PAYLOAD="$(jq -n \
--argjson fixedAmount 5 \
'{taskConfig: {copyMode: "FIXED_SIZE", fixedAmount: $fixedAmount}}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Copy mode guidance:
taskConfig.copyMode is the field that controls the task's copy mode.ONE_TO_ONE, FIXED_SIZE.FIXED_SIZE, also ask for taskConfig.fixedAmount.ONE_TO_ONE, omit fixedAmount unless the user explicitly wants to keep it stored.Use these fields when the user wants to change task-level copy behavior. Prefer changing only the fields the user explicitly asked for.
Common fields:
taskConfig.copyMode
ONE_TO_ONE, FIXED_SIZE.taskConfig.fixedAmount
copyMode=FIXED_SIZE.taskConfig.navMultiplier
1.taskConfig.positionUtilization
0, which means no filter.taskConfig.buyOnly
true, non-BUY signals are skipped.taskConfig.buyLimitPerTradeMin
0 effectively means no lower bound.taskConfig.buyLimitPerTradeMax
0 effectively means no upper bound.taskConfig.maxBoughtPerCopyTask
0 effectively means no cap.taskConfig.maxBoughtPerMarket
0 effectively means no cap.taskConfig.priceRangeMin
0.01.taskConfig.priceRangeMax
0.99.taskConfig.minLiquidity
0 effectively means no filter.taskConfig.minFillSize
Recommended clarification rules before updating:
fixedAmount.navMultiplier or fixedAmount.buyLimitPerTradeMin, buyLimitPerTradeMax, or both.maxBoughtPerCopyTask or maxBoughtPerMarket.priceRangeMin and priceRangeMax.convictionLevel.status or a taskConfig change.Example: update navMultiplier
PAYLOAD="$(jq -n \
--argjson navMultiplier 1.5 \
'{taskConfig: {navMultiplier: $navMultiplier}}')"
Example: enable buy-only mode
PAYLOAD="$(jq -n \
--argjson buyOnly true \
'{taskConfig: {buyOnly: $buyOnly}}')"
Example: limit per-trade buy amount
PAYLOAD="$(jq -n \
--argjson min 2 \
--argjson max 10 \
'{taskConfig: {buyLimitPerTradeMin: $min, buyLimitPerTradeMax: $max}}')"
Example: limit total bought amount
PAYLOAD="$(jq -n \
--argjson maxBoughtPerCopyTask 100 \
--argjson maxBoughtPerMarket 25 \
'{taskConfig: {maxBoughtPerCopyTask: $maxBoughtPerCopyTask, maxBoughtPerMarket: $maxBoughtPerMarket}}')"
Example: restrict execution price range
PAYLOAD="$(jq -n \
--argjson min 0.1 \
--argjson max 0.9 \
'{taskConfig: {priceRangeMin: $min, priceRangeMax: $max}}')"
Example: combine multiple taskConfig changes
PAYLOAD="$(jq -n \
--argjson buyOnly true \
--argjson navMultiplier 1.2 \
--argjson maxBoughtPerMarket 20 \
'{
taskConfig: {
buyOnly: $buyOnly,
navMultiplier: $navMultiplier,
maxBoughtPerMarket: $maxBoughtPerMarket
}
}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Example: update convictionLevel
PAYLOAD="$(jq -n \
--arg convictionLevel "STRICT" \
'{taskConfig: {convictionLevel: $convictionLevel}}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Conviction level guidance:
OFF: disable conviction filter.LOOSE: lower threshold, more signals can pass.STANDARD: default mode.STRICT: higher threshold, fewer signals can pass.Example: update taskConfig and status together
PAYLOAD="$(jq -n \
--arg status "RUNNING" \
--argjson buyOnly true \
'{
status: $status,
taskConfig: {
buyOnly: $buyOnly
}
}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Example: update TPSL rules safely
PAYLOAD="$(jq -n \
--arg ruleId "$RULE_ID" \
--argjson takeProfitPct 20 \
'{tpslRules: {update: [{id: $ruleId, takeProfitPct: $takeProfitPct}]}}')"
Example: update task status
PAYLOAD="$(jq -n \
--arg status "PAUSED" \
'{status: $status}')"
curl -sS --fail-with-body "${AUTH[@]}" -X PATCH "$BASE/api/v1/copy-tasks/$TASK_ID" \
-d "$PAYLOAD"
Status guidance:
status values for update are: RUNNING, PAUSED, STOPPED.PAUSED when the user wants to temporarily stop following new trades.RUNNING when the user wants to resume an active task.STOPPED only when the user explicitly wants the task stopped rather than just paused.DELETED in update payloads; deletion should use DELETE /api/v1/copy-tasks/{taskId}.DELETE /api/v1/copy-tasks/{taskId}Before calling: validate taskId and confirm.
Minimum fields to ask:
taskIdcurl -sS --fail-with-body "${AUTH[@]}" -X DELETE "$BASE/api/v1/copy-tasks/$TASK_ID"
GET /api/v1/copy-tasks/total-pnlcurl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-tasks/total-pnl"
GET /api/v1/copy-tasks/{taskId}/positionsstatus (optional)
active, closedcurl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-tasks/$TASK_ID/positions?status=active"
Guidance:
active returns positions with remaining amount above the close threshold.closed returns positions whose remaining amount is effectively zero.status is omitted or unknown, the backend currently returns all positions.active / closed rather than open / closed.GET /api/v1/copy-tasks/{taskId}/tradescurl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-tasks/$TASK_ID/trades"
POST /api/v1/copy-tasks/{taskId}/sellmarketId (preferred) or conditionIdamount (partial sell; omit to sell full position)Before calling: validate taskId, summarize (which market, amount), and confirm.
Minimum fields to ask:
taskIdmarketId or conditionIdamount only when the user wants a partial sellPAYLOAD="$(jq -n \
--arg marketId "..." \
--argjson amount 10 \
'{marketId: $marketId, amount: $amount}')"
curl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks/$TASK_ID/sell" \
-d "$PAYLOAD"
POST /api/v1/copy-tasks/{taskId}/sell-allBefore calling: validate taskId and confirm — this sells ALL positions for the task.
Minimum fields to ask:
taskIdcurl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks/$TASK_ID/sell-all"
POST /api/v1/copy-tasks/batch-updatetaskIds (array of task IDs)status (string), taskConfig (object)Before calling: summarize which tasks and what changes, and confirm.
Minimum fields to ask:
taskIdsstatus, taskConfigTASK_IDS=("64f0c7e7b8e4f8c1a1b2c3d4" "64f0c7e7b8e4f8c1a1b2c3d5")
PAYLOAD="$(jq -n \
--arg status "PAUSED" \
--argjson taskIds "$(printf '%s\n' "${TASK_IDS[@]}" | jq -R . | jq -s .)" \
'{taskIds: $taskIds, status: $status}')"
curl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks/batch-update" \
-d "$PAYLOAD"
Example: batch update taskConfig.copyMode
TASK_IDS=("64f0c7e7b8e4f8c1a1b2c3d4" "64f0c7e7b8e4f8c1a1b2c3d5")
PAYLOAD="$(jq -n \
--argjson taskIds "$(printf '%s\n' "${TASK_IDS[@]}" | jq -R . | jq -s .)" \
'{
taskIds: $taskIds,
taskConfig: {
copyMode: "ONE_TO_ONE"
}
}')"
curl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks/batch-update" \
-d "$PAYLOAD"
Batch update guidance:
status uses the same allowed values as single-task update: RUNNING, PAUSED, STOPPED.taskConfig replaces the task config object sent in the batch request, so only send fields you intentionally want to set.status nor taskConfig is provided, the backend currently just returns the selected tasks.POST /api/v1/copy-tasks/batch-deletetaskIds (array of task IDs)Before calling: confirm deletion.
Minimum fields to ask:
taskIdsTASK_IDS=("64f0c7e7b8e4f8c1a1b2c3d4" "64f0c7e7b8e4f8c1a1b2c3d5")
PAYLOAD="$(jq -n \
--argjson taskIds "$(printf '%s\n' "${TASK_IDS[@]}" | jq -R . | jq -s .)" \
'{taskIds: $taskIds}')"
curl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks/batch-delete" \
-d "$PAYLOAD"
GET /api/v1/copy-signalslimit (int, default 50)cursor (int, offset for pagination)since (RFC3339 timestamp)sinceCreatedAt (RFC3339 timestamp)action (one of: COPIED, SKIPPED, FAILED, RECEIVED)trader (address filter)curl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-signals?limit=20&action=COPIED"
Prefer composing the query from user intent. Only pass filters the user asked for.
Validation:
limit must be a positive integer.cursor must be a non-negative integer.since and sinceCreatedAt must be RFC3339 or RFC3339Nano timestamps.action values are: COPIED, SKIPPED, FAILED, RECEIVED.Action guidance:
RECEIVED: the signal was ingested.COPIED: the copy order was placed successfully.SKIPPED: the signal was intentionally not copied because checks or limits blocked it.FAILED: the system attempted processing but failed.Example: fetch signals since a specific time
curl -sS --fail-with-body "${AUTH[@]}" \
"$BASE/api/v1/copy-signals?since=2026-03-01T00:00:00Z&limit=50"
Example: fetch next page using cursor
curl -sS --fail-with-body "${AUTH[@]}" \
"$BASE/api/v1/copy-signals?cursor=50&limit=50"
GET /api/v1/copy-signals/streamcurl -sS -N "${AUTH[@]}" "$BASE/api/v1/copy-signals/stream"
Stream guidance:
ready and copy_signal.GET /api/v1/copy-signals/statsReturns signal counts grouped by action and by trader.
curl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-signals/stats"
GET /api/v1/copy-tasks/{taskId}/tpsl-rules/{ruleId}Minimum fields to ask:
taskId, ruleIdcurl -sS --fail-with-body "${AUTH[@]}" "$BASE/api/v1/copy-tasks/$TASK_ID/tpsl-rules/$RULE_ID"
POST /api/v1/copy-tasks/{taskId}/tpsl-rules/{ruleId}/simulateMinimum fields to ask:
taskId, ruleIdcurl -sS --fail-with-body "${AUTH[@]}" -X POST "$BASE/api/v1/copy-tasks/$TASK_ID/tpsl-rules/$RULE_ID/simulate"
When creating a task, tpslRules items may include:
sourceOrderId, sourceTypeconditionId, tokenId, assetId, entryPrice, entrySize, sidetakeProfitPct, takeProfitProb, stopLossPct, limitPriceOffset, orderTimeout, fallbackToMarketWhen updating a task, tpslRules should be wrapped as:
create: array of new inline rulesupdate: array of {id, ...patchFields}cancel: array of ruleIdExample: create a task with one TPSL rule
PAYLOAD="$(jq -n \
--arg targetTrader "0x..." \
--arg sourceOrderId "order_123" \
--arg sourceType "copy_trade" \
--argjson takeProfitPct 20 \
--argjson stopLossPct 10 \
'{
targetTrader: $targetTrader,
tpslRules: [
{
sourceOrderId: $sourceOrderId,
sourceType: $sourceType,
takeProfitPct: $takeProfitPct,
stopLossPct: $stopLossPct
}
]
}')"
401: API key missing/invalid/expired/disabled. Ask user to check or regenerate key.404: Task or resource not found. Ask user to verify taskId.409: Task already exists (duplicate targetTrader).422: Copy task limit exceeded.400: Invalid payload or invalid query param such as includeDeleted.5xx: Server error. Retry once with backoff; if still failing, report response body.0 effectively means no filter.taskConfig.maxPriceDeviation
taskConfig.expiryHours
0.taskConfig.convictionLevel
OFF, LOOSE, STANDARD, STRICT.STANDARD.