@hypelens/hypelens-agent-rail 0.1.15 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/package.json +1 -1
- package/skill/hypelens-agent-rail/SKILL.md +2 -2
- package/src/exchange.js +66 -3
- package/src/mcp.js +1 -1
package/README.md
CHANGED
|
@@ -2,13 +2,22 @@
|
|
|
2
2
|
**Place, cancel, close Hyperliquid perps.** Agent wallet once · auto-round · **1bp on fills — no sub.**
|
|
3
3
|
## Install → approve → place
|
|
4
4
|
```bash
|
|
5
|
+
# MCP stdio (Claude / Cursor / any MCP host)
|
|
5
6
|
npx -y @hypelens/hypelens-agent-rail
|
|
7
|
+
|
|
8
|
+
# Claude Code one-liner
|
|
9
|
+
claude mcp add hypelens -- npx -y @hypelens/hypelens-agent-rail
|
|
10
|
+
|
|
11
|
+
# OpenClaw / ClawHub skill (skill slug, not npm alone)
|
|
12
|
+
clawhub install hypelens-agent-rail
|
|
13
|
+
# skills.sh (needs public GH; polyparlay anon currently 404)
|
|
14
|
+
npx skills add polyparlay/hypelens -s hypelens-agent-rail -y
|
|
6
15
|
```
|
|
7
16
|
1. `hl_quickstart` (optional) → `hl_new_agent_wallet` → `HYPELENS_AGENT_PK`
|
|
8
17
|
2. `hl_approve_payloads(agentAddress)` — **MASTER** signs approveAgent + ApproveBuilderFee **0.01%** once, then POST both
|
|
9
18
|
3. `hl_place_order` / `hl_cancel_order` / `hl_close_position` / `hl_positions` / `hl_balances`
|
|
10
19
|
|
|
11
|
-
**First place (testnet default):** after approve, `hl_place_order({coin:"BTC", isBuy:true, sizeUsd:12, leverage:2})` — **sizeUsd alone** auto-fetches mark and rounds size; `entryPx` optional. No feed required.
|
|
20
|
+
**First place (testnet default):** after approve, `hl_place_order({coin:"BTC", isBuy:true, sizeUsd:12, leverage:2})` — **sizeUsd alone** auto-fetches mark and rounds size; `entryPx` optional. No feed required. On reject after sizeUsd, response includes `error` + `next` (margin / approve / min notional).
|
|
12
21
|
|
|
13
22
|
Default **testnet**. `HYPELENS_NET=mainnet` for live. Fee: **1bp on fills** — no sub. Missing `HYPELENS_AGENT_PK` errors point at the same path.
|
|
14
23
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypelens/hypelens-agent-rail",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Place, cancel, and close Hyperliquid perps from OpenClaw/MCP. Agent wallet once, auto-round, 1bp on fills (no sub). First place: hl_place_order BTC sizeUsd 12. npx @hypelens/hypelens-agent-rail",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: Hyperliquid Place
|
|
3
3
|
description: >-
|
|
4
4
|
hyperliquid place cancel close — Hyperliquid perps rail for OpenClaw/MCP.
|
|
5
5
|
Agent wallet once, auto-round, 1bp builder on fills (no sub). Keywords:
|
|
@@ -31,7 +31,7 @@ metadata:
|
|
|
31
31
|
npx -y @hypelens/hypelens-agent-rail
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
**ClawHub / OpenClaw:** `clawhub install hypelens-agent-rail` · **skills.sh:** `npx skills add polyparlay/hypelens`
|
|
34
|
+
**ClawHub / OpenClaw:** `clawhub install hypelens-agent-rail` · **skills.sh:** `npx skills add polyparlay/hypelens -s hypelens-agent-rail -y` · **MCP:** `npx -y @hypelens/hypelens-agent-rail`
|
|
35
35
|
|
|
36
36
|
## Quickstart (place-ready)
|
|
37
37
|
|
package/src/exchange.js
CHANGED
|
@@ -132,6 +132,57 @@ async function resolveSizeAndPx({ coin, size, entryPx, sizeUsd }) {
|
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
/** Extract HL place/cancel wire error + actionable next after sizeUsd resolve. */
|
|
136
|
+
function interpretExchangeResult(body) {
|
|
137
|
+
if (!body || typeof body !== 'object') {
|
|
138
|
+
return { ok: false, error: 'empty exchange response', next: 'retry hl_place_order({coin:"BTC", isBuy:true, sizeUsd:12, leverage:2}) on testnet' };
|
|
139
|
+
}
|
|
140
|
+
if (body.status === 'err' || body.status === 'error') {
|
|
141
|
+
const raw = typeof body.response === 'string' ? body.response : JSON.stringify(body.response || body);
|
|
142
|
+
return { ok: false, error: raw, next: hintFromHlError(raw) };
|
|
143
|
+
}
|
|
144
|
+
const statuses = body?.response?.data?.statuses;
|
|
145
|
+
if (Array.isArray(statuses)) {
|
|
146
|
+
for (const s of statuses) {
|
|
147
|
+
if (s && typeof s.error === 'string' && s.error) {
|
|
148
|
+
return { ok: false, error: s.error, next: hintFromHlError(s.error), statuses };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// resting / filled / etc
|
|
152
|
+
const resting = statuses.find((s) => s && (s.resting || s.filled));
|
|
153
|
+
if (resting) return { ok: true, error: null, next: null, statuses };
|
|
154
|
+
if (statuses.length) return { ok: true, error: null, next: null, statuses };
|
|
155
|
+
}
|
|
156
|
+
if (body.status === 'ok') return { ok: true, error: null, next: null };
|
|
157
|
+
return { ok: false, error: JSON.stringify(body), next: hintFromHlError(JSON.stringify(body)) };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function hintFromHlError(msg) {
|
|
161
|
+
const m = String(msg || '').toLowerCase();
|
|
162
|
+
if (m.includes('insufficient') || m.includes('margin') || m.includes('not enough')) {
|
|
163
|
+
return 'Fund agent on this net (default testnet) or lower sizeUsd; check hl_balances.equity then retry sizeUsd place';
|
|
164
|
+
}
|
|
165
|
+
if (m.includes('does not exist') || m.includes('user or api wallet') || m.includes('unknown user')) {
|
|
166
|
+
return 'MASTER must POST approveAgent + ApproveBuilderFee 1bp (hl_approve_payloads) before first place; then sizeUsd:12';
|
|
167
|
+
}
|
|
168
|
+
if (m.includes('builder') && (m.includes('fee') || m.includes('approval') || m.includes('approve'))) {
|
|
169
|
+
return 'MASTER must sign ApproveBuilderFee 0.01% (1bp) via hl_approve_payloads and POST it; then retry sizeUsd place';
|
|
170
|
+
}
|
|
171
|
+
if (m.includes('minimum') || m.includes('min ') || m.includes('$10') || m.includes('too small')) {
|
|
172
|
+
return 'Increase sizeUsd (BTC first place: sizeUsd:12) — HL min notional; auto-round may shrink tiny sizes to zero';
|
|
173
|
+
}
|
|
174
|
+
if (m.includes('oracle') || m.includes('price') && m.includes('far')) {
|
|
175
|
+
return 'Omit entryPx and pass sizeUsd only (uses mark), or set entryPx near mark; retry hl_place_order sizeUsd';
|
|
176
|
+
}
|
|
177
|
+
if (m.includes('leverage') || m.includes('max lev')) {
|
|
178
|
+
return 'Lower leverage (first place: leverage:2) or set coin max leverage on HL, then retry sizeUsd place';
|
|
179
|
+
}
|
|
180
|
+
if (m.includes('permit') || m.includes('agent') && m.includes('not')) {
|
|
181
|
+
return 'Run hl_approve_payloads(agentAddress) — MASTER signs approveAgent once, POST, then sizeUsd place';
|
|
182
|
+
}
|
|
183
|
+
return 'Check hl_exchange_status + hl_balances; ensure MASTER approved agent+1bp builder; retry hl_place_order({coin:"BTC", isBuy:true, sizeUsd:12, leverage:2}) on testnet';
|
|
184
|
+
}
|
|
185
|
+
|
|
135
186
|
async function postL1(action) {
|
|
136
187
|
const { actions, signer } = loadShipped();
|
|
137
188
|
assertPlacementAllowed(actions);
|
|
@@ -142,7 +193,9 @@ async function postL1(action) {
|
|
|
142
193
|
body: JSON.stringify({ action: signed.action, signature: signed.signature, nonce: signed.nonce })
|
|
143
194
|
});
|
|
144
195
|
const body = await res.json().catch(() => ({}));
|
|
145
|
-
|
|
196
|
+
const interpreted = interpretExchangeResult(body);
|
|
197
|
+
const ok = res.ok && interpreted.ok;
|
|
198
|
+
return { ok, net: net(), response: body, error: interpreted.error, next: interpreted.next, statuses: interpreted.statuses || null };
|
|
146
199
|
}
|
|
147
200
|
|
|
148
201
|
async function clearinghouse(user) {
|
|
@@ -240,7 +293,7 @@ export async function placeOrder({ coin, isBuy, size = null, entryPx = null, siz
|
|
|
240
293
|
tpPx
|
|
241
294
|
});
|
|
242
295
|
const posted = await postL1(action);
|
|
243
|
-
|
|
296
|
+
const out = {
|
|
244
297
|
placed: posted.ok,
|
|
245
298
|
net: posted.net,
|
|
246
299
|
response: posted.response,
|
|
@@ -254,6 +307,14 @@ export async function placeOrder({ coin, isBuy, size = null, entryPx = null, siz
|
|
|
254
307
|
sizingWarn,
|
|
255
308
|
feeModel: '1bp on fills only — no subscription'
|
|
256
309
|
};
|
|
310
|
+
if (!posted.ok) {
|
|
311
|
+
out.error = posted.error || 'place rejected by exchange';
|
|
312
|
+
out.next = posted.next || hintFromHlError(posted.error || '');
|
|
313
|
+
if (posted.statuses) out.statuses = posted.statuses;
|
|
314
|
+
} else {
|
|
315
|
+
out.next = 'placed — cancel via hl_cancel_order; close via hl_close_position; fees 1bp on fills only';
|
|
316
|
+
}
|
|
317
|
+
return out;
|
|
257
318
|
}
|
|
258
319
|
|
|
259
320
|
/** Cancel by oid and/or cloid. */
|
|
@@ -266,7 +327,9 @@ export async function cancelOrder({ coin, oid = null, cloid = null }) {
|
|
|
266
327
|
else if (oid != null) action = actions.buildCancelAction([{ assetIndex, oid: Number(oid) }]);
|
|
267
328
|
else throw new Error('oid or cloid required — pass oid or cloid to hl_cancel_order');
|
|
268
329
|
const posted = await postL1(action);
|
|
269
|
-
|
|
330
|
+
const out = { cancelled: posted.ok, net: posted.net, response: posted.response, coin: resolveCoin(coin).toUpperCase(), oid, cloid };
|
|
331
|
+
if (!posted.ok) { out.error = posted.error || 'cancel rejected'; out.next = posted.next || hintFromHlError(posted.error || ''); }
|
|
332
|
+
return out;
|
|
270
333
|
}
|
|
271
334
|
|
|
272
335
|
/** IOC reduce-only close for a coin (uses position size if size omitted). */
|
package/src/mcp.js
CHANGED
|
@@ -13,7 +13,7 @@ const wrap = (fn) => async (args) => {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export async function main() {
|
|
16
|
-
const server = new McpServer({ name: 'hypelens-agent-rail', version: '0.1.
|
|
16
|
+
const server = new McpServer({ name: 'hypelens-agent-rail', version: '0.1.16' });
|
|
17
17
|
|
|
18
18
|
server.tool('hl_quickstart',
|
|
19
19
|
'CALL FIRST: place-ready bootstrap — wallet + MASTER ApproveBuilderFee 1bp once, then hl_place_order sizeUsd:12. Default testnet. 1bp fills, no sub.',
|