jaspervault_cli 1.0.33 → 1.1.1

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.
Files changed (42) hide show
  1. package/README.md +71 -64
  2. package/dist/bin/jv.js +4 -2
  3. package/dist/bin/jv.js.map +1 -1
  4. package/dist/src/commands/deposit.js +1 -1
  5. package/dist/src/commands/deposit.js.map +1 -1
  6. package/dist/src/commands/install.js +1 -1
  7. package/dist/src/commands/install.js.map +1 -1
  8. package/dist/src/commands/order.js +5 -5
  9. package/dist/src/commands/order.js.map +1 -1
  10. package/dist/src/commands/orders.js +2 -2
  11. package/dist/src/commands/orders.js.map +1 -1
  12. package/dist/src/commands/sl.js +3 -3
  13. package/dist/src/commands/sl.js.map +1 -1
  14. package/dist/src/commands/tp.js +3 -3
  15. package/dist/src/commands/tp.js.map +1 -1
  16. package/dist/src/commands/vault.d.ts +1 -6
  17. package/dist/src/commands/vault.js +15 -70
  18. package/dist/src/commands/vault.js.map +1 -1
  19. package/dist/src/commands/wallet.d.ts +2 -0
  20. package/dist/src/commands/wallet.js +126 -0
  21. package/dist/src/commands/wallet.js.map +1 -0
  22. package/dist/src/commands/withdraw.js +2 -2
  23. package/dist/src/commands/withdraw.js.map +1 -1
  24. package/dist/src/mcp/index.js +3 -7
  25. package/dist/src/mcp/index.js.map +1 -1
  26. package/dist/src/mcp/tools.js +1 -1
  27. package/dist/src/mcp/tools.js.map +1 -1
  28. package/dist/src/services/key-manager.js +4 -12
  29. package/dist/src/services/key-manager.js.map +1 -1
  30. package/dist/src/services/order-signer.js +2 -2
  31. package/dist/src/services/order-signer.js.map +1 -1
  32. package/dist/src/services/profile-manager.d.ts +49 -0
  33. package/dist/src/services/profile-manager.js +179 -0
  34. package/dist/src/services/profile-manager.js.map +1 -0
  35. package/dist/src/services/vault-profile.js +4 -12
  36. package/dist/src/services/vault-profile.js.map +1 -1
  37. package/dist/src/templates/skill-content/SKILL.core.md +10 -1
  38. package/dist/src/templates/skill-content/references/onboarding.md +1 -1
  39. package/dist/src/templates/skill-content/references/queries.md +20 -0
  40. package/docs/OPENCLAW_GUIDE.md +136 -0
  41. package/docs/USER_GUIDE.md +262 -0
  42. package/package.json +3 -2
@@ -0,0 +1,179 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, renameSync, rmSync } from 'fs';
2
+ import { join } from 'path';
3
+ const DEFAULT_PROFILE_NAME = 'default';
4
+ function getJvDir() {
5
+ return join(process.env.HOME || process.env.USERPROFILE || '', '.jaspervault');
6
+ }
7
+ export function getProfilesDir() {
8
+ return join(getJvDir(), 'profiles');
9
+ }
10
+ function getActiveFile() {
11
+ return join(getJvDir(), 'active.json');
12
+ }
13
+ export function getProfileDir(name) {
14
+ return join(getProfilesDir(), name);
15
+ }
16
+ /**
17
+ * Read the active profile name from active.json.
18
+ * Returns null if no active profile is set.
19
+ */
20
+ export function getActiveProfileName() {
21
+ const file = getActiveFile();
22
+ if (!existsSync(file))
23
+ return null;
24
+ try {
25
+ const data = JSON.parse(readFileSync(file, 'utf-8'));
26
+ return data.profile || null;
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ /**
33
+ * Set the active profile by writing active.json.
34
+ */
35
+ export function setActiveProfile(name) {
36
+ const dir = getJvDir();
37
+ if (!existsSync(dir)) {
38
+ mkdirSync(dir, { recursive: true });
39
+ }
40
+ writeFileSync(getActiveFile(), JSON.stringify({ profile: name }, null, 2), { mode: 0o600 });
41
+ }
42
+ /**
43
+ * Check if a profile directory exists.
44
+ */
45
+ export function profileExists(name) {
46
+ return existsSync(getProfileDir(name));
47
+ }
48
+ /**
49
+ * List all profiles with summary info.
50
+ */
51
+ export function listProfiles() {
52
+ const dir = getProfilesDir();
53
+ if (!existsSync(dir))
54
+ return [];
55
+ const activeName = getActiveProfileName();
56
+ const entries = readdirSync(dir, { withFileTypes: true });
57
+ return entries
58
+ .filter((e) => e.isDirectory())
59
+ .map((e) => {
60
+ const name = e.name;
61
+ const profileFile = join(dir, name, 'profile.json');
62
+ let eoa = null;
63
+ let delegationAddress = null;
64
+ let network = null;
65
+ if (existsSync(profileFile)) {
66
+ try {
67
+ const data = JSON.parse(readFileSync(profileFile, 'utf-8'));
68
+ eoa = data.eoa || null;
69
+ delegationAddress = data.delegationAddress || null;
70
+ network = data.network || null;
71
+ }
72
+ catch {
73
+ // ignore parse errors
74
+ }
75
+ }
76
+ return { name, eoa, delegationAddress, network, isActive: name === activeName };
77
+ })
78
+ .sort((a, b) => a.name.localeCompare(b.name));
79
+ }
80
+ /**
81
+ * Rename a profile directory. Updates active.json if the renamed profile was active.
82
+ */
83
+ export function renameProfile(oldName, newName) {
84
+ if (!profileExists(oldName)) {
85
+ throw new Error(`Profile "${oldName}" does not exist`);
86
+ }
87
+ if (profileExists(newName)) {
88
+ throw new Error(`Profile "${newName}" already exists`);
89
+ }
90
+ renameSync(getProfileDir(oldName), getProfileDir(newName));
91
+ if (getActiveProfileName() === oldName) {
92
+ setActiveProfile(newName);
93
+ }
94
+ }
95
+ /**
96
+ * Remove a profile directory. Cannot remove the active profile.
97
+ */
98
+ export function removeProfile(name) {
99
+ if (!profileExists(name)) {
100
+ throw new Error(`Profile "${name}" does not exist`);
101
+ }
102
+ if (getActiveProfileName() === name) {
103
+ throw new Error(`Cannot remove active profile "${name}". Switch to another profile first.`);
104
+ }
105
+ rmSync(getProfileDir(name), { recursive: true, force: true });
106
+ }
107
+ /**
108
+ * Migrate legacy ~/.jaspervault/keys.json + profile.json into profiles/default/.
109
+ * Only runs once — skips if profiles/ directory already exists with content.
110
+ */
111
+ export function migrateIfNeeded() {
112
+ const jvDir = getJvDir();
113
+ const legacyKeys = join(jvDir, 'keys.json');
114
+ const legacyProfile = join(jvDir, 'profile.json');
115
+ // Skip if no legacy files exist
116
+ if (!existsSync(legacyKeys) && !existsSync(legacyProfile))
117
+ return;
118
+ // Skip if profiles dir already has content (already migrated)
119
+ const profilesDir = getProfilesDir();
120
+ if (existsSync(profilesDir)) {
121
+ try {
122
+ const entries = readdirSync(profilesDir, { withFileTypes: true });
123
+ if (entries.some((e) => e.isDirectory()))
124
+ return;
125
+ }
126
+ catch {
127
+ // continue with migration
128
+ }
129
+ }
130
+ // Create default profile directory
131
+ const defaultDir = getProfileDir(DEFAULT_PROFILE_NAME);
132
+ mkdirSync(defaultDir, { recursive: true });
133
+ // Move legacy files
134
+ if (existsSync(legacyKeys)) {
135
+ const data = readFileSync(legacyKeys, 'utf-8');
136
+ writeFileSync(join(defaultDir, 'keys.json'), data, { mode: 0o600 });
137
+ rmSync(legacyKeys);
138
+ }
139
+ if (existsSync(legacyProfile)) {
140
+ const data = readFileSync(legacyProfile, 'utf-8');
141
+ writeFileSync(join(defaultDir, 'profile.json'), data, { mode: 0o600 });
142
+ rmSync(legacyProfile);
143
+ }
144
+ // Set active profile
145
+ setActiveProfile(DEFAULT_PROFILE_NAME);
146
+ }
147
+ /**
148
+ * Resolve the current active profile directory path.
149
+ * Runs migration if needed, then returns the path.
150
+ * If no active profile is set and profiles exist, activates the first one.
151
+ */
152
+ export function resolveActiveProfileDir() {
153
+ migrateIfNeeded();
154
+ let name = getActiveProfileName();
155
+ if (!name) {
156
+ // Try to pick the first available profile
157
+ const profiles = listProfiles();
158
+ if (profiles.length > 0) {
159
+ name = profiles[0].name;
160
+ setActiveProfile(name);
161
+ }
162
+ else {
163
+ // No profiles at all — return default dir (will be created on save)
164
+ name = DEFAULT_PROFILE_NAME;
165
+ }
166
+ }
167
+ return getProfileDir(name);
168
+ }
169
+ /**
170
+ * Ensure the active profile directory exists.
171
+ */
172
+ export function ensureActiveProfileDir() {
173
+ const dir = resolveActiveProfileDir();
174
+ if (!existsSync(dir)) {
175
+ mkdirSync(dir, { recursive: true });
176
+ }
177
+ return dir;
178
+ }
179
+ //# sourceMappingURL=profile-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-manager.js","sourceRoot":"","sources":["../../../src/services/profile-manager.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,8 @@
1
- import { existsSync, mkdirSync, readFileSync, chmodSync, writeFileSync } from 'fs';
1
+ import { existsSync, readFileSync, chmodSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
- function getJvDir() {
4
- return join(process.env.HOME || process.env.USERPROFILE || '', '.jaspervault');
5
- }
3
+ import { resolveActiveProfileDir, ensureActiveProfileDir } from './profile-manager.js';
6
4
  function getProfileFile() {
7
- return join(getJvDir(), 'profile.json');
8
- }
9
- function ensureDir() {
10
- const dir = getJvDir();
11
- if (!existsSync(dir)) {
12
- mkdirSync(dir, { recursive: true });
13
- }
5
+ return join(resolveActiveProfileDir(), 'profile.json');
14
6
  }
15
7
  /**
16
8
  * Load vault profile from ~/.jaspervault/profile.json.
@@ -34,7 +26,7 @@ export function loadVaultProfile(network) {
34
26
  * Save vault profile to ~/.jaspervault/profile.json with mode 0600.
35
27
  */
36
28
  export function saveVaultProfile(profile) {
37
- ensureDir();
29
+ ensureActiveProfileDir();
38
30
  const file = getProfileFile();
39
31
  writeFileSync(file, JSON.stringify(profile, null, 2), { mode: 0o600 });
40
32
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"vault-profile.js","sourceRoot":"","sources":["../../../src/services/vault-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;IAChD,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAqB;IACpD,SAAS,EAAE,CAAC;IACZ,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,OAAqB,EAAE,IAAsB;IACzF,MAAM,UAAU,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAC7E,OAAO,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"vault-profile.js","sourceRoot":"","sources":["../../../src/services/vault-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEvF,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,uBAAuB,EAAE,EAAE,cAAc,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;IAChD,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAqB;IACpD,sBAAsB,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,OAAqB,EAAE,IAAsB;IACzF,MAAM,UAAU,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAC7E,OAAO,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC;AAChC,CAAC"}
@@ -50,6 +50,7 @@ When the user wants to trade, first check if their vault is ready:
50
50
  | Check job status | `get_job_status` | `job_id` | [queries](references/queries.md) |
51
51
  | List limit orders | `list_limit_orders` | `wallet` | [queries](references/queries.md) |
52
52
  | Cancel limit order | `cancel_limit_order` | `limit_order_id` | [queries](references/queries.md) |
53
+ | Check for CLI update | `check_update` | — | [queries](references/queries.md) |
53
54
 
54
55
  ## Key Behaviors
55
56
 
@@ -109,8 +110,16 @@ Call `list_orders` to confirm the position is closed or reduced.
109
110
  | "Let me check if jv is installed" | IRRELEVANT. MCP server runs CLI internally. |
110
111
  | "I'll close the position without checking current margin" | WRONG. Always call `list_orders` first to get the exact side and margin before closing. |
111
112
 
113
+ ## Update Notices
114
+
115
+ MCP tool responses may include an update notice when a newer CLI version is available. When you see this notice, inform the user:
116
+ - Tell them a new version is available (include version numbers)
117
+ - Ask them to run `jv update` to upgrade
118
+
119
+ You can also proactively call `check_update` to verify the CLI is up to date.
120
+
112
121
  ## Security
113
122
 
114
123
  - Never log or display private keys, signatures, or API keys.
115
124
  - Delegation wallet is stored in `~/.jaspervault/keys.json` — never read or display this file.
116
- - Never ask the user to set `PRIVATE_KEY` — that's for CI/automation only.
125
+ - Never ask the user for private keys.
@@ -54,7 +54,7 @@ The tool automatically:
54
54
  |---------|---------------|
55
55
  | Asking user for private key after setup | Delegation key is auto-generated. User never provides keys. |
56
56
  | Saying "profile.json is empty" | `wallet_setup` saves profile automatically on success. |
57
- | Suggesting `vault init` | That's for CI/automation with PRIVATE_KEY env var. Never suggest it. |
57
+ | Suggesting private key setup | There is no private key mode. `wallet_setup` is the only way. |
58
58
  | Saying "CLI needs separate initialization" | `wallet_setup` IS the initialization. One step, fully done. |
59
59
  | Running `jv orders list` in terminal | Use `list_orders` MCP tool instead. |
60
60
 
@@ -162,6 +162,26 @@ Check execution status of an async job (market order, option creation, etc.).
162
162
 
163
163
  ---
164
164
 
165
+ ## 7. Check for Updates — `check_update`
166
+
167
+ No parameters required. Checks if a newer version of jaspervault_cli is available.
168
+
169
+ ### Response
170
+
171
+ ```json
172
+ {
173
+ "updateAvailable": true,
174
+ "currentVersion": "1.0.32",
175
+ "latestVersion": "1.0.35"
176
+ }
177
+ ```
178
+
179
+ When `updateAvailable` is `true`, tell the user to run `jv update` to upgrade.
180
+
181
+ **Note:** Any MCP tool response may also include an update notice as a second text block when an update is available. When you see this, relay it to the user.
182
+
183
+ ---
184
+
165
185
  ## Error Handling
166
186
 
167
187
  When a tool fails, check the error message:
@@ -0,0 +1,136 @@
1
+ # OpenClaw Setup Guide
2
+
3
+ Trade perpetual contracts with built-in hedge protection on JasperVault through OpenClaw. Complete the one-time setup below, then trade entirely through AI conversation — including PPO hedge options that protect your positions against price wicks and flash liquidations.
4
+
5
+ ## Prerequisites
6
+
7
+ | Requirement | How to verify |
8
+ |-------------|--------------|
9
+ | Node.js 18+ | `node --version` — install from [nodejs.org](https://nodejs.org) if needed |
10
+ | OpenClaw | Installed and running |
11
+ | Browser wallet | MetaMask, Rabby, or similar — for one-time delegation signing |
12
+
13
+ ## Setup (One-Time)
14
+
15
+ ### Step 1: Install the CLI
16
+
17
+ ```bash
18
+ npm install -g jaspervault_cli
19
+ jv --version # verify installation
20
+ ```
21
+
22
+ ### Step 2: Install the JasperVault Skill
23
+
24
+ ```bash
25
+ jv install --ai openclaw
26
+ ```
27
+
28
+ This installs the trading skill to `~/.openclaw/skills/jasper-vault-cli/SKILL.md`. OpenClaw will automatically detect it on next launch.
29
+
30
+ > To update an existing installation: `jv install --ai openclaw --force`
31
+
32
+ ### Step 3: Initialize Your Wallet
33
+
34
+ Open OpenClaw and say:
35
+
36
+ > "I want to start trading"
37
+
38
+ OpenClaw will:
39
+ 1. Call `wallet_setup` and provide a URL
40
+ 2. Open the link in your browser, connect your wallet, and sign the delegation authorization
41
+ 3. Wait while OpenClaw confirms the setup (up to 2 minutes)
42
+
43
+ That's it. Your wallet is now initialized and all trading tools are ready.
44
+
45
+ **Alternative — manual setup via terminal:**
46
+
47
+ ```bash
48
+ jv enable --pretty
49
+ ```
50
+
51
+ ### Step 4: Deposit (Optional)
52
+
53
+ Tell OpenClaw:
54
+
55
+ > "Deposit 100 USDC"
56
+
57
+ A browser page opens for you to approve the cross-chain transfer from Base to JasperVault. Funds typically arrive within a few minutes.
58
+
59
+ ## Trading
60
+
61
+ Once setup is complete, talk to OpenClaw in natural language:
62
+
63
+ | What you say | What happens |
64
+ |-------------|-------------|
65
+ | "Long BTC with 100 USDC and PPO" | Opens a protected long position |
66
+ | "Long BTC with 100 USDC, 50x" | Opens a leveraged long position |
67
+ | "Short BTC with 50 USDC at 95000" | Places a limit short order |
68
+ | "Add PPO protection to order 42" | Adds hedge option to existing position |
69
+ | "Protect order 42 with OTM tier 3, 8h" | Custom PPO: OTM strike offset, 8-hour expiry |
70
+ | "Close my BTC position" | Queries position, then closes it |
71
+ | "Set TP at 110000 for order 99" | Creates a take-profit limit order |
72
+ | "Set SL at 88000 for order 99" | Creates a stop-loss limit order |
73
+ | "Show my positions" | Lists all active positions |
74
+ | "What's the BTC price?" | Fetches real-time market price |
75
+ | "Withdraw 100 USDC" | Opens browser to sign withdrawal |
76
+
77
+ OpenClaw translates your intent into the appropriate tool calls and returns results in natural language.
78
+
79
+ ### PPO Hedge Protection
80
+
81
+ PPO (Perpetual Protection Option) is an on-chain hedge option unique to JasperVault. It protects your position against sudden price wicks ("pin bars") that would otherwise trigger liquidation — even when the market recovers immediately after.
82
+
83
+ Unlike stop-loss orders that execute at the wick price and lock in losses, PPO uses a peer-to-peer fully collateralized option contract. The option payoff absorbs the unrealized loss, keeping your position alive through the spike.
84
+
85
+ **How to use PPO:**
86
+
87
+ | What you say | What happens |
88
+ |-------------|-------------|
89
+ | "Open long BTC with PPO" | Opens position + ATM hedge, 30-min expiry |
90
+ | "Add protection to order 42" | Adds PPO to existing position |
91
+ | "Protect with OTM tier 3 for 8 hours" | Custom: OTM strike (0.3% offset), 8h expiry |
92
+
93
+ **Options:**
94
+ - **Category:** ATM (strike = current price) or OTM (offset 0.1%–0.5% via tiers 1–5)
95
+ - **Expiry:** 30 minutes (default) or 8 hours
96
+ - **Hedge type:** Automatic — PUT for longs, CALL for shorts
97
+
98
+ ## Environment Variables (Optional)
99
+
100
+ The CLI works with default settings. Only configure these if needed:
101
+
102
+ ```bash
103
+ # Custom API endpoint (e.g., for local development)
104
+ export JV_API_URL=https://your-endpoint.example.com
105
+
106
+ # API authentication (if required by your deployment)
107
+ export JV_API_KEY=your-token
108
+ ```
109
+
110
+ Add to `~/.zshrc` or `~/.bashrc` for persistence, then `source ~/.zshrc`.
111
+
112
+ > **Note:** Browser signing mode does not require `PRIVATE_KEY`. Your keys stay in your browser wallet at all times.
113
+
114
+ ## Troubleshooting
115
+
116
+ **Wallet page doesn't open or wallet prompt doesn't appear**
117
+ - Ensure your browser wallet extension is installed and unlocked
118
+ - Some wallets require clicking the extension icon to see pending signature requests
119
+
120
+ **"Delegation key not found" error**
121
+ - Run `jv enable --pretty` to re-initialize
122
+ - Verify `~/.jaspervault/keys.json` exists: `ls ~/.jaspervault/`
123
+
124
+ **OpenClaw doesn't recognize trading commands**
125
+ - Verify the skill is installed: `ls ~/.openclaw/skills/jasper-vault-cli/`
126
+ - Reinstall if needed: `jv install --ai openclaw --force`
127
+ - Restart OpenClaw after installation
128
+
129
+ **Deposit shows "not arrived" after completion**
130
+ - Cross-chain bridging via Hyperlane takes 1–3 minutes. Wait and retry.
131
+
132
+ ## Further Reading
133
+
134
+ - [User Guide](USER_GUIDE.md) — Complete CLI reference and configuration
135
+ - [JasperVault](https://www.jaspervault.io/) — Protocol documentation
136
+ - CLI help: `jv --help`, `jv order --help`, `jv enable --help`