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.
- package/dist/src/commands/connect.d.ts +3 -2
- package/dist/src/commands/connect.js +16 -9
- package/dist/src/commands/connect.js.map +1 -1
- package/dist/src/commands/init.js +30 -13
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/order.js +11 -2
- package/dist/src/commands/order.js.map +1 -1
- package/dist/src/commands/sl.js +7 -1
- package/dist/src/commands/sl.js.map +1 -1
- package/dist/src/commands/tp.js +7 -1
- package/dist/src/commands/tp.js.map +1 -1
- package/dist/src/commands/vault.js +6 -5
- package/dist/src/commands/vault.js.map +1 -1
- package/dist/src/services/order-signer.js +2 -1
- package/dist/src/services/order-signer.js.map +1 -1
- package/dist/src/templates/skill-body.d.ts +8 -3
- package/dist/src/templates/skill-body.js +263 -178
- package/dist/src/templates/skill-body.js.map +1 -1
- package/dist/src/types.d.ts +2 -0
- package/dist/src/utils/ppo.d.ts +12 -0
- package/dist/src/utils/ppo.js +45 -0
- package/dist/src/utils/ppo.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skill template content and banner for jv init command.
|
|
3
|
-
*
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
##
|
|
37
|
+
## CRITICAL RULES (MUST FOLLOW — violations cause broken UX)
|
|
33
38
|
|
|
34
|
-
- \`jv\`
|
|
35
|
-
|
|
36
|
-
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-

|
|
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 \`\`. 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
|
-
|
|
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
|
-
|
|
91
|
+
### Line 1: Awaiting Connection
|
|
87
92
|
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
99
|
+
> Or open your wallet app → WalletConnect → paste this URI: \`wc:...\`
|
|
96
100
|
|
|
97
|
-
|
|
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
|
-
|
|
103
|
+
### Line 2: Init Complete
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
\`\`\`json
|
|
106
|
+
{"success":true, "message":"Vault initialized successfully", ...}
|
|
107
|
+
\`\`\`
|
|
106
108
|
|
|
107
|
-
|
|
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
|
-
|
|
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
|
-
|
|
113
|
+
## Deposit via WalletConnect (Optional)
|
|
117
114
|
|
|
118
|
-
|
|
115
|
+
If the user wants to deposit:
|
|
119
116
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
+
## Getting Market Price
|
|
138
138
|
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
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.
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
**
|
|
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
|
-
**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
+
## PPO Hedge Protection
|
|
235
231
|
|
|
236
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
243
|
+
**Examples:**
|
|
247
244
|
|
|
248
245
|
\`\`\`bash
|
|
249
|
-
|
|
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
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
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
|
-
|
|
280
|
+
## Querying Positions
|
|
260
281
|
|
|
261
282
|
\`\`\`bash
|
|
262
|
-
# List
|
|
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
|
-
|
|
304
|
+
**Key output fields (human-readable, pre-converted from wei):**
|
|
276
305
|
|
|
277
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
287
|
-
jv limit-order status <limitOrderId>
|
|
322
|
+
## Calculating Unrealized PnL
|
|
288
323
|
|
|
289
|
-
|
|
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
|
-
|
|
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
|
-
|
|
339
|
+
IMPORTANT: NEVER guess or estimate the current price. ALWAYS use \`jv price\` to get the real-time price.
|
|
296
340
|
|
|
297
|
-
|
|
341
|
+
## Job Status
|
|
342
|
+
|
|
343
|
+
\`\`\`bash
|
|
344
|
+
jv job status <jobId> --pretty
|
|
345
|
+
\`\`\`
|
|
298
346
|
|
|
299
|
-
|
|
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.
|
|
322
|
-
2.
|
|
323
|
-
3.
|
|
324
|
-
4.
|
|
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
|
|
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
|
-
##
|
|
378
|
+
## Managing Limit Orders
|
|
333
379
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
-
|
|
380
|
+
\`\`\`bash
|
|
381
|
+
# List limit orders for a wallet
|
|
382
|
+
jv limit-order list --wallet <address>
|
|
337
383
|
|
|
338
|
-
|
|
384
|
+
# Filter by status
|
|
385
|
+
jv limit-order list --wallet <address> --status PENDING
|
|
339
386
|
|
|
340
|
-
|
|
387
|
+
# Check a specific limit order
|
|
388
|
+
jv limit-order status <limitOrderId>
|
|
341
389
|
|
|
342
|
-
|
|
343
|
-
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
450
|
+
skillMd = getOpenClawFrontmatter() + '\n# JasperVault Trading Skill\n\n' + SKILL_CORE_BODY;
|
|
451
|
+
break;
|
|
376
452
|
case 'claude':
|
|
377
|
-
|
|
453
|
+
skillMd = getClaudeFrontmatter() + '\n# JasperVault Trading Skill\n\n' + SKILL_CORE_BODY;
|
|
454
|
+
break;
|
|
378
455
|
case 'cursor':
|
|
379
|
-
|
|
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
|
|
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"}
|
package/dist/src/types.d.ts
CHANGED