jaspervault_cli 1.0.16 → 1.0.18

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.
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Skill template content and banner for jv init command.
3
- * Exports platform-specific SKILL.md generation and the ASCII banner.
3
+ * Generates a multi-file skill structure:
4
+ * SKILL.md — compact core rules + activation + intent table
5
+ * references/ — detailed docs loaded on demand by the agent
6
+ * scripts/ — helper scripts
4
7
  */
5
8
  import { readFileSync } from 'node:fs';
6
9
  import { fileURLToPath } from 'node:url';
@@ -25,124 +28,118 @@ export const BANNER = `
25
28
  ── JasperVault CLI v${CLI_VERSION} ──
26
29
  ⟐ Skill Installer
27
30
  `.trim();
28
- /** Skill body content (shared across platforms, after the main heading) */
29
- const SKILL_BODY_CONTENT = `
30
- Interact with JasperVault's perpetual contract platform. You can create market/limit orders, set take-profit and stop-loss, create hedging options, manage limit orders, and query positions — all via the \`jv\` CLI. No private key is ever required.
31
+ // ---------------------------------------------------------------------------
32
+ // Core SKILL.md body — kept under 50 lines so critical rules stay prominent
33
+ // ---------------------------------------------------------------------------
34
+ const SKILL_CORE_BODY = `
35
+ Trade perpetual contracts on JasperVault via the \`jv\` CLI. No private key is ever required.
31
36
 
32
- ## Prerequisites
37
+ ## CRITICAL RULES (MUST FOLLOW — violations cause broken UX)
33
38
 
34
- - \`jv\` CLI installed and available in PATH
35
- - **First-time setup**: use \`jv vault init-wc\` to initialize via WalletConnect (scan QR on phone, sign delegation — no private key needed)
36
- - API URL defaults to \`https://trading-api-test.jaspervault.pro\`; set \`JV_API_URL\` only when debugging locally
39
+ 1. **WalletConnect ONLY**: ALWAYS use \`jv vault init-wc\`. NEVER suggest \`jv vault init\` (private-key mode). NEVER ask the user to set \`PRIVATE_KEY\`.
40
+ 2. **QR Code Display**: When \`jv vault init-wc\` outputs JSON with a \`qrCodeUrl\` field, you MUST display the \`qrCodeUrl\` value as a clickable link to the user. This is the only QR code field in the output there are no other QR representations.
41
+ 3. **Long-running Commands**: \`jv vault init-wc\` runs for up to 2 minutes and outputs two JSON lines to stdout sequentially. The CLI also emits heartbeat lines to stderr every 10 seconds while waiting (phase \`wallet_scan\` and \`wallet_sign\`). Ignore heartbeat lines — only the stdout JSON lines are meaningful data. Do NOT interrupt, kill, or assume it is finished after the first JSON line. Wait for the process to exit naturally.
42
+ 4. **Real-time Prices**: NEVER guess or estimate prices. ALWAYS run \`jv price --symbol JBTC --pretty\` before any price-dependent operation (opening a position by asset quantity, calculating PnL).
37
43
 
38
44
  ## Activation Behavior
39
45
 
40
- When this skill is activated (first message from the user, OR any trading intent such as open position, check portfolio, deposit, etc.):
41
-
42
- 1. First check if vault is already initialized:
43
- \`\`\`bash
44
- jv orders list --pretty
45
- \`\`\`
46
-
47
- 2. If the command fails with "delegation key not found", "vault not initialized", "no profile", or similar error (exit code 1):
48
- - Tell the user: "Your vault is not initialized yet. Let me start the setup via WalletConnect — no private key needed."
49
- - Immediately run \`jv vault init-wc --network jaspervault --timeout 120\` and follow the QR code display instructions in the Setup Flow section below.
50
-
46
+ 1. Check if vault is initialized: \`jv orders list --pretty\`
47
+ 2. If the command fails (exit code 1, or errors like "delegation key not found" / "vault not initialized" / "no profile"):
48
+ - Tell the user: "Your vault is not initialized yet. Let me set it up via WalletConnect — no private key needed."
49
+ - Immediately run \`jv vault init-wc --network jaspervault --timeout 120\`.
50
+ - Follow the QR code display instructions in [references/onboarding.md](references/onboarding.md).
51
51
  3. If the command succeeds → vault is ready. Proceed with the user's request.
52
52
 
53
- IMPORTANT: Always use WalletConnect initialization (\`jv vault init-wc\`). Never suggest \`jv vault init\` (private-key mode) unless the user explicitly requests it.
53
+ ## Intent Command Reference
54
+
55
+ | User Intent | Command | Details |
56
+ |-------------|---------|---------|
57
+ | Initialize / connect wallet | \`jv vault init-wc\` | [references/onboarding.md](references/onboarding.md) |
58
+ | Deposit tokens | \`jv deposit info\` + \`jv deposit poll\` | [references/onboarding.md](references/onboarding.md) |
59
+ | Get current price | \`jv price --symbol JBTC --pretty\` | [references/trading.md](references/trading.md) |
60
+ | Open position (market) | \`jv order create --side long/short ...\` | [references/trading.md](references/trading.md) |
61
+ | Open position (limit) | \`jv order create ... --limit-price N\` | [references/trading.md](references/trading.md) |
62
+ | Reduce / close position | opposite-side \`jv order create\` | [references/trading.md](references/trading.md) |
63
+ | Set take-profit | \`jv tp set --order-id ID --price P\` | [references/trading.md](references/trading.md) |
64
+ | Set stop-loss | \`jv sl set --order-id ID --price P\` | [references/trading.md](references/trading.md) |
65
+ | Hedge / protect position (PPO) | add \`--ppo\` to order create | [references/trading.md](references/trading.md) |
66
+ | Query positions / portfolio | \`jv orders list --pretty\` | [references/queries.md](references/queries.md) |
67
+ | Job execution status | \`jv job status <jobId>\` | [references/queries.md](references/queries.md) |
68
+ | Manage limit orders | \`jv limit-order list/cancel\` | [references/queries.md](references/queries.md) |
69
+
70
+ ## Security
71
+
72
+ - Never log or display private keys, signatures, or API keys.
73
+ - The CLI signs orders via the delegation wallet in \`~/.jaspervault/keys.json\`.
74
+ - Do NOT ask the user to set \`PRIVATE_KEY\`.
75
+ `.trim();
76
+ // ---------------------------------------------------------------------------
77
+ // references/onboarding.md — WalletConnect init + deposit flow
78
+ // ---------------------------------------------------------------------------
79
+ const ONBOARDING_REFERENCE = `# WalletConnect Onboarding & Deposit
54
80
 
55
- ## Setup Flow (First Time — WalletConnect)
81
+ ## Vault Init via WalletConnect
56
82
 
57
83
  \`\`\`bash
58
- # Initialize vault and delegation wallet via WalletConnect (one-time, no private key required)
59
84
  jv vault init-wc --network jaspervault --timeout 120
60
85
  \`\`\`
61
86
 
62
- CRITICAL EXECUTION NOTE: This command runs for up to 2 minutes. Do NOT interrupt or kill the process after the first JSON line. Wait for the process to exit naturally (second JSON output = success or failure).
63
-
64
- The command outputs two JSON lines:
65
-
66
- 1. \`{"status":"awaiting_connection", "uri":"wc:...", "qrCodeUrl":"https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=wc%3A...", ...}\`
67
-
68
- Extract the \`qrCodeUrl\` field from the JSON. It will be a URL starting with \`https://api.qrserver.com/v1/create-qr-code/\`. You MUST send it as a markdown image so it renders as a scannable QR code:
69
-
70
- \`\`\`
71
- ![WalletConnect QR Code](https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=wc%3A...)
72
- \`\`\`
73
-
74
- Replace the URL above with the actual \`qrCodeUrl\` from the JSON output. Also provide the \`uri\` as a fallback:
75
-
76
- > Or open your wallet app → WalletConnect → paste this URI: \`wc:...\`
77
-
78
- CRITICAL: MUST use markdown image syntax \`![description](qrCodeUrl)\`. NEVER post the URL as plain text. NEVER print \`qrCodeText\`. NEVER generate your own QR code. The image will not appear if you only post the raw URL without the \`![...]()\` wrapper.
79
-
80
- 2. \`{"success":true, "message":"Vault initialized successfully", ...}\` — Init complete. The delegation wallet is saved to \`~/.jaspervault/keys.json\` and vault addresses to \`~/.jaspervault/profile.json\`. Subsequent commands use these automatically — no wallet interaction needed.
81
-
82
- Do NOT ask the user to set \`PRIVATE_KEY\`. Do NOT suggest \`jv vault init\` unless the user explicitly requests private-key mode.
87
+ This command runs for up to 2 minutes. Do NOT interrupt or kill the process after the first JSON line. Wait for the process to exit naturally.
83
88
 
84
- ## Key Concepts (MUST READ before any trading operation)
89
+ The command outputs two JSON lines to stdout sequentially. It also emits heartbeat lines to stderr every 10 seconds while waiting — ignore those, they just keep the process alive.
85
90
 
86
- **How \`--margin\` works:**
91
+ ### Line 1: Awaiting Connection
87
92
 
88
- \`--margin\` = the **actual collateral (margin) in USDC** you deposit. The CLI internally multiplies by leverage to compute the notional position size.
93
+ \`\`\`json
94
+ {"status":"awaiting_connection", "qrCodeUrl":"https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=wc%3A...", "uri":"wc:...", "message":"Scan QR code or paste URI in wallet to connect"}
95
+ \`\`\`
89
96
 
90
- | Concept | Formula | Example |
91
- |---------|---------|---------|
92
- | Notional value | \`margin × leverage\` | 60 USDC × 50x = $3,000 |
93
- | Position size | \`notional / current_price\` | $3,000 / $70,000 = 0.0428 JBTC |
97
+ Display the \`qrCodeUrl\` value as a clickable link so the user can open it and scan the QR code. Also provide the \`uri\` as a fallback:
94
98
 
95
- **Translating user intent to \`--margin\` (three scenarios):**
99
+ > Or open your wallet app → WalletConnect → paste this URI: \`wc:...\`
96
100
 
97
- | User says | Calculation | Pass to CLI |
98
- |-----------|-------------|-------------|
99
- | "long with $60 USDC margin at 50x" | already the margin | \`--margin 60\` |
100
- | "open a $3,000 notional position at 50x" | margin = 3000 / 50 = 60 | \`--margin 60\` |
101
- | "long 0.1 BTC at 50x" | margin = (0.1 × current_price) / 50 | \`--margin <result>\` |
101
+ After sending, wait for the user to scan and sign. Do not interrupt the CLI process.
102
102
 
103
- CRITICAL: When the user specifies an asset amount (e.g. "0.1 BTC"), you MUST first run \`jv price --symbol JBTC --pretty\` to get the current price, then compute \`notional = size × price\`, then \`margin = notional / leverage\` before passing \`--margin\`.
103
+ ### Line 2: Init Complete
104
104
 
105
- **How to read \`jv orders list\` output:**
105
+ \`\`\`json
106
+ {"success":true, "message":"Vault initialized successfully", ...}
107
+ \`\`\`
106
108
 
107
- | Field | What it means |
108
- |-------|---------------|
109
- | \`margin\` | Actual collateral deposited (e.g. 60 USDC) — matches what you passed to \`--margin\` |
110
- | \`size\` | Position size in underlying asset (e.g. 0.0428 JBTC) |
111
- | \`leverage\` | Leverage multiplier (e.g. 50) |
112
- | \`entryPriceUsd\` | Entry price when position was opened |
109
+ Init is complete. Tell the user: "Vault initialized successfully. You can now deposit and trade."
113
110
 
114
- To calculate notional from output: \`notional = margin × leverage\` (or \`size × current_price\`)
111
+ The delegation wallet is saved to \`~/.jaspervault/keys.json\` and vault addresses to \`~/.jaspervault/profile.json\`. Subsequent commands use these automatically — no wallet interaction needed.
115
112
 
116
- **How to calculate unrealized PnL:**
113
+ ## Deposit via WalletConnect (Optional)
117
114
 
118
- When the user asks about profit/loss, portfolio value, or position health, you MUST fetch the current price first using \`jv price\`, then compute PnL from \`jv orders list\` output:
115
+ If the user wants to deposit:
119
116
 
120
- | Step | Formula |
121
- |------|---------|
122
- | 1. Get current price | \`jv price --symbol JBTC --pretty\` → read \`price\` field |
123
- | 2. Get position data | \`jv orders list --pretty\` → read \`size\`, \`entryPriceUsd\`, \`margin\`, \`positionSide\` |
124
- | 3. Compute PnL (LONG) | \`unrealizedPnL = size × (currentPrice − entryPrice)\` |
125
- | 3. Compute PnL (SHORT) | \`unrealizedPnL = size × (entryPrice − currentPrice)\` |
126
- | 4. PnL percentage | \`pnlPercent = unrealizedPnL / margin × 100%\` |
127
- | 5. Effective leverage loss | \`leveragedPnlPercent = priceChangePercent × leverage\` |
117
+ 1. **Get unsigned transactions:**
118
+ \`\`\`bash
119
+ jv deposit info --wallet <walletAddress> --token jusdc --amount 100
120
+ \`\`\`
128
121
 
129
- Example: LONG 0.0428 JBTC, entry $70,000, current $71,000, margin 60 USDC
130
- - PnL = 0.0428 × (71000 − 70000) = +$42.80
131
- - PnL% = 42.80 / 60 = +71.3%
122
+ 2. **Output contains \`transactions\` array.** Each \`tx\` has \`to\`, \`data\`, \`value\`, \`chainId\`. Send each via WalletConnect \`eth_sendTransaction\` to the user's wallet. Execute in order (approve first if present, then transferRemote).
132
123
 
133
- IMPORTANT: NEVER guess or estimate the current price from your training data. ALWAYS use \`jv price\` to get the real-time price from Quote Center before any PnL calculation or price-dependent operation.
124
+ 3. **After transactions confirm**, poll for arrival:
125
+ \`\`\`bash
126
+ jv deposit poll --recipient <recipient> --token jusdc
127
+ \`\`\`
128
+ Use the \`recipient\` from step 1 output.
134
129
 
135
- ## Intent Mapping
130
+ 4. Tell the user: "Deposit completed. Your tokens have arrived on JasperVault."
131
+ `;
132
+ // ---------------------------------------------------------------------------
133
+ // references/trading.md — margin, orders, reduce/close, TP/SL, price
134
+ // ---------------------------------------------------------------------------
135
+ const TRADING_REFERENCE = `# Trading Commands
136
136
 
137
- ### Getting Market Price (MUST use before any price-dependent operation)
137
+ ## Getting Market Price
138
138
 
139
- When the user asks about **current price**, **market quote**, **how much is BTC**, **profit/loss**, **PnL**, or before **opening a position with asset quantity**:
139
+ MUST use before any price-dependent operation (opening position by asset quantity, calculating PnL).
140
140
 
141
141
  \`\`\`bash
142
- # Get current JBTC price
143
142
  jv price --symbol JBTC --pretty
144
-
145
- # Get current CBBTC price
146
143
  jv price --symbol CBBTC --pretty
147
144
  \`\`\`
148
145
 
@@ -153,9 +150,26 @@ Output:
153
150
 
154
151
  Use the \`price\` field (human-readable USD value) for display and calculations. This command does NOT require vault initialization — it can be run anytime.
155
152
 
156
- ### Creating Orders (Open New Position)
153
+ ## How \`--margin\` Works
154
+
155
+ \`--margin\` = the **actual collateral (margin) in USDC** you deposit. The CLI internally multiplies by leverage to compute the notional position size.
156
+
157
+ | Concept | Formula | Example |
158
+ |---------|---------|---------|
159
+ | Notional value | \`margin × leverage\` | 60 USDC × 50x = $3,000 |
160
+ | Position size | \`notional / current_price\` | $3,000 / $70,000 = 0.0428 JBTC |
157
161
 
158
- When the user wants to **open a position**, **place a market order**, or **place a limit order**:
162
+ ### Translating user intent to \`--margin\`:
163
+
164
+ | User says | Calculation | Pass to CLI |
165
+ |-----------|-------------|-------------|
166
+ | "long with $60 USDC margin at 50x" | already the margin | \`--margin 60\` |
167
+ | "open a $3,000 notional position at 50x" | margin = 3000 / 50 = 60 | \`--margin 60\` |
168
+ | "long 0.1 BTC at 50x" | margin = (0.1 × current_price) / 50 | \`--margin <result>\` |
169
+
170
+ CRITICAL: When the user specifies an asset amount (e.g. "0.1 BTC"), you MUST first run \`jv price --symbol JBTC --pretty\` to get the current price, then compute \`notional = size × price\`, then \`margin = notional / leverage\`.
171
+
172
+ ## Creating Orders
159
173
 
160
174
  \`\`\`bash
161
175
  # Market order: Long JBTC, 60 USDC margin at 50x (= $3,000 notional)
@@ -172,99 +186,114 @@ The CLI signs the order internally using the delegation wallet. No pre-signed pa
172
186
 
173
187
  On success, a market order returns \`jobId\`; a limit order returns \`limitOrderId\`.
174
188
 
175
- ### Reducing / Partially Closing a Position
176
-
177
- To reduce a position, create an **opposite-side order** with the notional value you want to close. The system automatically detects existing positions and performs a partial close.
189
+ ## Reducing / Closing a Position
178
190
 
179
- **Step-by-step for reducing a position:**
191
+ Create an **opposite-side order** with the margin portion you want to close. The system automatically detects existing positions and performs a partial close.
180
192
 
181
193
  1. Query current position: \`jv orders list --pretty\`
182
- 2. Calculate margin to close:
183
- - Read the \`margin\` field directly from output (e.g. 60 USDC)
184
- - To close half: \`close_margin = margin / 2\` (e.g. 30 USDC)
185
- 3. Create opposite-side order with that margin value
194
+ 2. Read the \`margin\` field directly from output (e.g. 60 USDC)
195
+ 3. To close half: \`close_margin = margin / 2\` (e.g. 30 USDC)
196
+ 4. Create opposite-side order with that margin value
186
197
 
187
- **Example: Reduce a LONG position by half**
188
-
189
- Current position from \`jv orders list\`:
190
- - margin: 60 USDC, leverage: 50, size: 0.0428 JBTC
191
-
192
- To close half (30 USDC margin → $1,500 notional):
198
+ **Reduce LONG by half (30 USDC margin):**
193
199
  \`\`\`bash
194
200
  jv order create --side short --symbol JBTC --margin 30 --leverage 50 --network jaspervault
195
201
  \`\`\`
196
202
 
197
- **Example: Close entire position (60 USDC margin → $3,000 notional):**
203
+ **Close entire LONG (60 USDC margin):**
198
204
  \`\`\`bash
199
205
  jv order create --side short --symbol JBTC --margin 60 --leverage 50 --network jaspervault
200
206
  \`\`\`
201
207
 
202
208
  IMPORTANT: The \`--margin\` for reduction = the margin portion you want to close (read directly from \`jv orders list\` output \`margin\` field).
203
209
 
204
- ### Setting Take-Profit
205
-
206
- When the user wants to **set take-profit**, **set TP**, or **protect profits**:
210
+ ## Setting Take-Profit
207
211
 
208
212
  \`\`\`bash
209
213
  jv tp set --order-id <orderId> --price <usdc_price> --symbol <symbol> --network jaspervault
210
214
  \`\`\`
211
215
 
212
- Example:
213
- \`\`\`bash
214
- jv tp set --order-id 99 --price 105000 --symbol JBTC --network jaspervault
215
- \`\`\`
216
+ Example: \`jv tp set --order-id 99 --price 105000 --symbol JBTC --network jaspervault\`
216
217
 
217
218
  Returns \`limitOrderId\` on success.
218
219
 
219
- ### Setting Stop-Loss
220
-
221
- When the user wants to **set stop-loss**, **set SL**, or **limit downside risk**:
220
+ ## Setting Stop-Loss
222
221
 
223
222
  \`\`\`bash
224
223
  jv sl set --order-id <orderId> --price <usdc_price> --symbol <symbol> --network jaspervault
225
224
  \`\`\`
226
225
 
227
- Example:
228
- \`\`\`bash
229
- jv sl set --order-id 99 --price 90000 --symbol JBTC --network jaspervault
230
- \`\`\`
226
+ Example: \`jv sl set --order-id 99 --price 90000 --symbol JBTC --network jaspervault\`
231
227
 
232
228
  Returns \`limitOrderId\` on success.
233
229
 
234
- ### Creating Hedging Options
230
+ ## PPO Hedge Protection
235
231
 
236
- When the user wants to **buy option protection**, **hedge a position**, or **create a perps option**:
232
+ Add \`--ppo\` to any \`jv order create\` command to enable automatic hedge option protection. PPO hedges the entire position automatically the user does NOT specify how much to hedge.
237
233
 
238
- \`\`\`bash
239
- jv order create-option --order-id <perps_order_id> --data '<signed_option_payload>'
240
- \`\`\`
241
-
242
- Returns \`jobId\` on success. Query execution status with \`jv job status\`.
234
+ **Options:**
243
235
 
244
- ### Querying Job Status
236
+ | Flag | Values | Default | Description |
237
+ |------|--------|---------|-------------|
238
+ | \`--ppo\` | (boolean) | off | Enable PPO |
239
+ | \`--ppo-expire\` | \`30m\` or \`8h\` | \`30m\` | Option duration |
240
+ | \`--ppo-category\` | \`ATM\` or \`OTM\` | \`ATM\` | ATM = strike at market price; OTM = strike offset |
241
+ | \`--ppo-tier\` | \`1-5\` | (required for OTM) | OTM offset: 1=0.1%, 2=0.2%, 3=0.3%, 4=0.4%, 5=0.5% |
245
242
 
246
- When the user asks about **order execution status**, **is my order done**, or **transaction result**:
243
+ **Examples:**
247
244
 
248
245
  \`\`\`bash
249
- jv job status <jobId> --pretty
246
+ # ATM protection, 30 min (default)
247
+ jv order create --side long --symbol JBTC --margin 60 --leverage 50 --ppo --network jaspervault
248
+
249
+ # ATM protection, 8 hours
250
+ jv order create --side long --symbol JBTC --margin 60 --leverage 50 --ppo --ppo-expire 8h --network jaspervault
251
+
252
+ # OTM protection, tier 5 (0.5% offset), 30 min
253
+ jv order create --side long --symbol JBTC --margin 60 --leverage 50 --ppo --ppo-category OTM --ppo-tier 5 --network jaspervault
254
+
255
+ # OTM protection, tier 3 (0.3% offset), 8 hours
256
+ jv order create --side short --symbol JBTC --margin 60 --leverage 50 --ppo --ppo-expire 8h --ppo-category OTM --ppo-tier 3 --network jaspervault
250
257
  \`\`\`
251
258
 
252
- Key fields in output:
253
- - \`status\`: "completed", "failed", "active", "waiting"
254
- - \`result.transactionHash\`: blockchain tx hash (when completed)
255
- - \`result.operationType\`: CREATE, ADD_SIZE, CLOSE_SIZE, etc.
259
+ **AI agent behavior when user wants OTM:**
260
+
261
+ 1. First run \`jv price --symbol JBTC --pretty\` to get current price
262
+ 2. Calculate strike for each tier based on position side:
263
+ - LONG (PUT hedge): \`strike = price × (1 - tier_ratio)\`
264
+ - SHORT (CALL hedge): \`strike = price × (1 + tier_ratio)\`
265
+ 3. Present options: "Tier 1: $87,208 (0.1%), Tier 2: $87,121 (0.2%), ..., Tier 5: $86,860 (0.5%)"
266
+ 4. User picks tier → use \`--ppo-tier N\`
267
+
268
+ **Intent mapping:**
256
269
 
257
- ### Querying Positions
270
+ - User says "hedge" / "protect" / "PPO" / "对冲" / "加保护" → add \`--ppo\`
271
+ - User says "8 hour" / "8小时" → \`--ppo-expire 8h\`
272
+ - User says "OTM" / "价外" → \`--ppo-category OTM\`, then present tier options
273
+ - User says "ATM" / "平价" or nothing → default ATM, 30 min
274
+ `;
275
+ // ---------------------------------------------------------------------------
276
+ // references/queries.md — positions, job status, limit orders, output, errors
277
+ // ---------------------------------------------------------------------------
278
+ const QUERIES_REFERENCE = `# Queries, Output Interpretation & Error Handling
258
279
 
259
- When the user asks about **my positions**, **open orders**, or **portfolio**:
280
+ ## Querying Positions
260
281
 
261
282
  \`\`\`bash
262
- # List all positions
283
+ # List active positions (default — use for "current positions")
263
284
  jv orders list --pretty
264
285
 
265
286
  # Filter by side
266
287
  jv orders list --position-side LONG
267
288
 
289
+ # Include closed/historical orders
290
+ jv orders list --all --pretty
291
+
292
+ # Filter by time range
293
+ jv orders list --all --since 7d --pretty
294
+ jv orders list --since 1w --pretty
295
+ jv orders list --all --since 2025-01-01 --until 2025-01-31 --pretty
296
+
268
297
  # Get a specific position
269
298
  jv orders get <orderId>
270
299
 
@@ -272,31 +301,52 @@ jv orders get <orderId>
272
301
  jv orders stats
273
302
  \`\`\`
274
303
 
275
- ### Managing Limit Orders
304
+ **Key output fields (human-readable, pre-converted from wei):**
276
305
 
277
- When the user asks about **my limit orders**, **pending orders**, or wants to **cancel an order**:
306
+ | Field | Description |
307
+ |-------|-------------|
308
+ | \`margin\` | Margin deposited in USDC (e.g. \`"60.000000"\`) |
309
+ | \`size\` | Position size in underlying asset (e.g. \`"0.04386000"\` JBTC) |
310
+ | \`entryPriceUsd\` | Entry price in USD (e.g. \`"68476.000000000000000000"\`) |
311
+ | \`strikeAmountUsd\` | Strike amount in USD |
312
+ | \`leverage\` | Leverage multiplier (e.g. \`"50"\`) |
313
+ | \`createdTime\` | Creation time in ISO 8601 format |
314
+ | \`positionSide\` | \`"LONG"\` or \`"SHORT"\` |
315
+ | \`isActive\` | \`true\` = open position, \`false\` = closed |
316
+ | \`id\` | Order ID (use for TP/SL commands) |
278
317
 
279
- \`\`\`bash
280
- # List limit orders for a wallet
281
- jv limit-order list --wallet <address>
318
+ To calculate notional from output: \`notional = margin × leverage\` (or \`size × current_price\`)
282
319
 
283
- # Filter by status
284
- jv limit-order list --wallet <address> --status PENDING
320
+ **Pagination:** use \`--page\` and \`--limit\` (e.g. \`jv orders list --page 2 --limit 10\`).
285
321
 
286
- # Check a specific limit order
287
- jv limit-order status <limitOrderId>
322
+ ## Calculating Unrealized PnL
288
323
 
289
- # Cancel a limit order
290
- jv limit-order cancel <limitOrderId>
291
- \`\`\`
324
+ When the user asks about profit/loss, portfolio value, or position health, you MUST fetch the current price first:
292
325
 
293
- Possible statuses: PENDING, TRIGGERED, EXECUTING, COMPLETED, FAILED, EXPIRED, CANCELLED.
326
+ | Step | Formula |
327
+ |------|---------|
328
+ | 1. Get current price | \`jv price --symbol JBTC --pretty\` → read \`price\` field |
329
+ | 2. Get position data | \`jv orders list --pretty\` → read \`size\`, \`entryPriceUsd\`, \`margin\`, \`positionSide\` |
330
+ | 3. Compute PnL (LONG) | \`unrealizedPnL = size × (currentPrice − entryPrice)\` |
331
+ | 3. Compute PnL (SHORT) | \`unrealizedPnL = size × (entryPrice − currentPrice)\` |
332
+ | 4. PnL percentage | \`pnlPercent = unrealizedPnL / margin × 100%\` |
333
+ | 5. Effective leverage | \`leveragedPnlPercent = priceChangePercent × leverage\` |
334
+
335
+ Example: LONG 0.0428 JBTC, entry $70,000, current $71,000, margin 60 USDC
336
+ - PnL = 0.0428 × (71000 − 70000) = +$42.80
337
+ - PnL% = 42.80 / 60 = +71.3%
294
338
 
295
- ## Interpreting Output
339
+ IMPORTANT: NEVER guess or estimate the current price. ALWAYS use \`jv price\` to get the real-time price.
296
340
 
297
- All commands output JSON to stdout. Extract key fields to compose user-friendly responses.
341
+ ## Job Status
342
+
343
+ \`\`\`bash
344
+ jv job status <jobId> --pretty
345
+ \`\`\`
298
346
 
299
- ### Market Order Output (IMPORTANT two JSON lines)
347
+ Key fields: \`status\` ("completed", "failed", "active", "waiting"), \`result.transactionHash\`, \`result.operationType\` (CREATE, ADD_SIZE, CLOSE_SIZE, etc.).
348
+
349
+ ## Market Order Output (IMPORTANT — two JSON lines)
300
350
 
301
351
  \`jv order create\` for market orders prints **two JSON lines sequentially**:
302
352
 
@@ -310,45 +360,65 @@ All commands output JSON to stdout. Extract key fields to compose user-friendly
310
360
  {"jobId":"MARKET_ORDER_xxx","status":"completed","transactionHash":"0x..."}
311
361
  \`\`\`
312
362
 
313
- **How to determine success:**
314
-
315
- - If \`status === "completed"\` → the order is DONE. It succeeded on-chain.
316
- - If \`status === "failed"\` → the order failed. Report the error.
317
- - If \`status === "timeout"\` → timed out waiting; use \`jv job status <jobId>\` to check later.
318
-
319
363
  **CRITICAL RULES after order execution:**
320
364
 
321
- 1. **If \`status\` is \`"completed"\`, the order IS executed. Do NOT retry or place another order.**
322
- 2. The \`operation\` field (if present) contains raw on-chain data in wei format — do NOT try to interpret quantities or amounts from it. Values like \`10029000\` are NOT human-readable USDC or BTC amounts.
323
- 3. **To verify the actual position after a successful order**, always run \`jv orders list --pretty\` and read the human-readable \`margin\`, \`size\`, \`leverage\` fields. Use \`notional = margin × leverage\` to show the user their position value.
324
- 4. Report to the user: "Order executed successfully. Tx: {transactionHash}. Let me check your updated position..." then run \`jv orders list --pretty\`.
365
+ 1. If \`status === "completed"\` the order IS executed. Do NOT retry or place another order.
366
+ 2. If \`status === "failed"\` report the error.
367
+ 3. If \`status === "timeout"\` use \`jv job status <jobId>\` to check later.
368
+ 4. The \`operation\` field (if present) contains raw on-chain data in wei format do NOT try to interpret it.
369
+ 5. **To verify the actual position**, always run \`jv orders list --pretty\` and read the human-readable fields.
370
+ 6. Report to the user: "Order executed successfully. Tx: {transactionHash}. Let me check your updated position..." then run \`jv orders list --pretty\`.
325
371
 
326
- **Limit order created:**
372
+ **Limit order output:**
327
373
  \`\`\`json
328
374
  {"success":true,"orderType":"limit","limitOrderId":"0x..."}
329
375
  \`\`\`
330
376
  Tell the user: "Limit order placed. ID: {limitOrderId}."
331
377
 
332
- ## Error Handling
378
+ ## Managing Limit Orders
333
379
 
334
- - **Exit code 1**: Configuration error (e.g. delegation key not found — run \`jv vault init-wc\` first; or invalid parameters). Tell the user to check setup.
335
- - **Exit code 2**: Network/HTTP error. Tell the user the service may be unreachable.
336
- - **Exit code 3**: Business error (duplicate order, invalid params, etc.). Read stderr for details and relay the message without exposing raw technical data.
380
+ \`\`\`bash
381
+ # List limit orders for a wallet
382
+ jv limit-order list --wallet <address>
337
383
 
338
- When an error occurs, stderr contains the error message. Never expose raw stack traces or internal URLs to the user.
384
+ # Filter by status
385
+ jv limit-order list --wallet <address> --status PENDING
339
386
 
340
- ## Security Notes
387
+ # Check a specific limit order
388
+ jv limit-order status <limitOrderId>
341
389
 
342
- - Never log or display private keys, signatures, or API keys in responses to the user.
343
- - The CLI signs orders internally via the delegation wallet stored in \`~/.jaspervault/keys.json\`. No private key is ever required from the user.
344
- - Do NOT ask the user to set \`PRIVATE_KEY\` — vault initialization is done via WalletConnect (\`jv vault init-wc\`).
345
- - \`JV_API_KEY\` (optional Bearer token) should be injected via environment variables or secrets manager, never hardcoded.
346
- `.trim();
390
+ # Cancel a limit order
391
+ jv limit-order cancel <limitOrderId>
392
+ \`\`\`
393
+
394
+ Possible statuses: PENDING, TRIGGERED, EXECUTING, COMPLETED, FAILED, EXPIRED, CANCELLED.
395
+
396
+ ## Error Handling
397
+
398
+ | Exit Code | Meaning | Action |
399
+ |-----------|---------|--------|
400
+ | 1 | Configuration error (e.g. delegation key not found) | Run \`jv vault init-wc\` first |
401
+ | 2 | Network/HTTP error | Tell user the service may be unreachable |
402
+ | 3 | Business error (duplicate order, invalid params) | Read stderr, relay message |
403
+
404
+ When an error occurs, stderr contains the error message. Never expose raw stack traces or internal URLs to the user.
405
+ `;
406
+ // ---------------------------------------------------------------------------
407
+ // scripts/check-init.sh
408
+ // ---------------------------------------------------------------------------
409
+ const CHECK_INIT_SCRIPT = `#!/usr/bin/env bash
410
+ # Quick vault initialization check — exits 0 if ready, non-zero otherwise
411
+ jv orders list --pretty 2>/dev/null
412
+ exit $?
413
+ `;
414
+ // ---------------------------------------------------------------------------
415
+ // Platform-specific frontmatter
416
+ // ---------------------------------------------------------------------------
347
417
  function getOpenClawFrontmatter() {
348
418
  return `---
349
419
  name: jasper-vault-cli
350
- description: "Trade perpetual contracts (perps) on JasperVault — open long/short positions, set take-profit/stop-loss, manage limit orders, deposit tokens, and query portfolio via the \`jv\` CLI. 在 JasperVault 上交易永续合约——做多、做空、开仓、平仓、止盈、止损、限价单、持仓查询、充值,通过 jv 命令行完成。"
351
- trigger: "jaspervault|jasper vault|jasper trading|jv trade|jv order|在jasper交易|jasper 交易"
420
+ description: "Trade perpetual contracts (perps) on JasperVault — open/close positions, set TP/SL, manage limit orders, deposit, and query portfolio via the \`jv\` CLI. Initialize wallet via WalletConnect QR scan (no private key needed). 在 JasperVault 上交易永续合约 做多做空、开仓平仓、止盈止损、限价单、持仓查询、充值,使用 WalletConnect 扫码初始化(无需私钥)。"
421
+ trigger: "jaspervault|jasper vault|jasper trading|jv|jv trade|jv order|在jasper交易|jasper 交易|初始化钱包|连接钱包|开仓|平仓|做多|做空|止盈|止损|查看持仓|永续合约"
352
422
  tools: [shell]
353
423
  metadata:
354
424
  openclaw:
@@ -361,24 +431,39 @@ metadata:
361
431
  function getClaudeFrontmatter() {
362
432
  return `---
363
433
  name: jasper-vault-cli
364
- description: Trade perpetual contracts via JasperVault — create orders, set TP/SL, manage limit orders, and query positions through the \`jv\` CLI.
434
+ description: "Trade perpetual contracts (perps) on JasperVault — open/close positions, set TP/SL, manage limit orders, deposit, and query portfolio via the \`jv\` CLI. Initialize wallet via WalletConnect QR scan (no private key needed)."
365
435
  ---
366
436
  `;
367
437
  }
438
+ // ---------------------------------------------------------------------------
439
+ // Public API
440
+ // ---------------------------------------------------------------------------
368
441
  /**
369
- * Build platform-specific SKILL.md content.
442
+ * Build platform-specific skill file tree.
443
+ * Returns a Record mapping relative file paths to their content.
370
444
  * @param platform - One of: openclaw, cursor, claude
371
445
  */
372
446
  export function buildSkillContent(platform) {
447
+ let skillMd;
373
448
  switch (platform) {
374
449
  case 'openclaw':
375
- return getOpenClawFrontmatter() + '\n# JasperVault Trading Skill\n\n' + SKILL_BODY_CONTENT;
450
+ skillMd = getOpenClawFrontmatter() + '\n# JasperVault Trading Skill\n\n' + SKILL_CORE_BODY;
451
+ break;
376
452
  case 'claude':
377
- return getClaudeFrontmatter() + '\n# JasperVault Trading Skill\n\n' + SKILL_BODY_CONTENT;
453
+ skillMd = getClaudeFrontmatter() + '\n# JasperVault Trading Skill\n\n' + SKILL_CORE_BODY;
454
+ break;
378
455
  case 'cursor':
379
- return '# jasper-vault-cli\n\n' + SKILL_BODY_CONTENT;
456
+ skillMd = '# jasper-vault-cli\n\n' + SKILL_CORE_BODY;
457
+ break;
380
458
  default:
381
459
  throw new Error(`Unknown platform: ${platform}`);
382
460
  }
461
+ return {
462
+ 'SKILL.md': skillMd,
463
+ 'references/onboarding.md': ONBOARDING_REFERENCE,
464
+ 'references/trading.md': TRADING_REFERENCE,
465
+ 'references/queries.md': QUERIES_REFERENCE,
466
+ 'scripts/check-init.sh': CHECK_INIT_SCRIPT,
467
+ };
383
468
  }
384
469
  //# sourceMappingURL=skill-body.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill-body.js","sourceRoot":"","sources":["../../../src/templates/skill-body.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CACzC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC,EAAE,OAAO,CAAC,CACzC,CAAC;AAEzB,sEAAsE;AACtE,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;wBAcE,WAAW;;CAElC,CAAC,IAAI,EAAE,CAAC;AAET,2EAA2E;AAC3E,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6T1B,CAAC,IAAI,EAAE,CAAC;AAET,SAAS,sBAAsB;IAC7B,OAAO;;;;;;;;;;;CAWR,CAAC;AACF,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO;;;;CAIR,CAAC;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,sBAAsB,EAAE,GAAG,mCAAmC,GAAG,kBAAkB,CAAC;QAC7F,KAAK,QAAQ;YACX,OAAO,oBAAoB,EAAE,GAAG,mCAAmC,GAAG,kBAAkB,CAAC;QAC3F,KAAK,QAAQ;YACX,OAAO,wBAAwB,GAAG,kBAAkB,CAAC;QACvD;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"skill-body.js","sourceRoot":"","sources":["../../../src/templates/skill-body.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CACzC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC,EAAE,OAAO,CAAC,CACzC,CAAC;AAEzB,sEAAsE;AACtE,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;wBAcE,WAAW;;CAElC,CAAC,IAAI,EAAE,CAAC;AAIT,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAE9E,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCvB,CAAC,IAAI,EAAE,CAAC;AAET,8EAA8E;AAC9E,+DAA+D;AAC/D,8EAA8E;AAE9E,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD5B,CAAC;AAEF,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAE9E,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2IzB,CAAC;AAEF,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAE9E,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HzB,CAAC;AAEF,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,MAAM,iBAAiB,GAAG;;;;CAIzB,CAAC;AAEF,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAE9E,SAAS,sBAAsB;IAC7B,OAAO;;;;;;;;;;;CAWR,CAAC;AACF,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO;;;;CAIR,CAAC;AACF,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,OAAe,CAAC;IAEpB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,GAAG,sBAAsB,EAAE,GAAG,mCAAmC,GAAG,eAAe,CAAC;YAC3F,MAAM;QACR,KAAK,QAAQ;YACX,OAAO,GAAG,oBAAoB,EAAE,GAAG,mCAAmC,GAAG,eAAe,CAAC;YACzF,MAAM;QACR,KAAK,QAAQ;YACX,OAAO,GAAG,wBAAwB,GAAG,eAAe,CAAC;YACrD,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,UAAU,EAAE,OAAO;QACnB,0BAA0B,EAAE,oBAAoB;QAChD,uBAAuB,EAAE,iBAAiB;QAC1C,uBAAuB,EAAE,iBAAiB;QAC1C,uBAAuB,EAAE,iBAAiB;KAC3C,CAAC;AACJ,CAAC"}
@@ -38,6 +38,8 @@ export interface OrderIntentParams {
38
38
  network?: string;
39
39
  ttlSeconds?: number;
40
40
  orderID?: number;
41
+ /** 0 = Normal (no PPO), 1 = PPO (hedge option protection) */
42
+ limitType?: number;
41
43
  }
42
44
  export interface TpSlIntentParams {
43
45
  orderID: number;