@invizi/cli 0.1.9 → 0.1.11
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/auth.js +0 -3
- package/dist/commands/trades.js +1 -1
- package/dist/invizi.js +13 -8
- package/dist/track.js +131 -0
- package/package.json +3 -2
package/dist/auth.js
CHANGED
|
@@ -199,9 +199,6 @@ async function status() {
|
|
|
199
199
|
if (email) {
|
|
200
200
|
console.log(`Email: ${email}`);
|
|
201
201
|
}
|
|
202
|
-
if (Array.isArray(me.permissions) && me.permissions.length > 0) {
|
|
203
|
-
console.log(`Permissions: ${me.permissions.join(', ')}`);
|
|
204
|
-
}
|
|
205
202
|
return 0;
|
|
206
203
|
}
|
|
207
204
|
function logout() {
|
package/dist/commands/trades.js
CHANGED
|
@@ -239,7 +239,7 @@ export async function trades(args) {
|
|
|
239
239
|
const config = loadConfig();
|
|
240
240
|
const address = positionals.find(a => /^0x[0-9a-fA-F]{40}$/.test(a)) || config.address;
|
|
241
241
|
if (!address) {
|
|
242
|
-
console.error('No address found. Run: invizi
|
|
242
|
+
console.error('No address found. Run: invizi track <address>');
|
|
243
243
|
console.error('Or pass directly: invizi trades 0x...');
|
|
244
244
|
return 1;
|
|
245
245
|
}
|
package/dist/invizi.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { auth, getAuthorizationHeader } from './auth.js';
|
|
3
|
-
import {
|
|
3
|
+
import { track } from './track.js';
|
|
4
4
|
import { getApiUrl, getConfigPath, loadConfig, redactConfig } from './config.js';
|
|
5
5
|
import { setup } from './setup.js';
|
|
6
6
|
import { trades } from './commands/index.js';
|
|
@@ -9,16 +9,17 @@ function showLocalHelp() {
|
|
|
9
9
|
Invizi CLI
|
|
10
10
|
|
|
11
11
|
Data:
|
|
12
|
-
invizi
|
|
13
|
-
invizi
|
|
12
|
+
invizi market Market overview — prices, macro, yields, funding
|
|
13
|
+
invizi market -c SOL + coin deep dive (RSI, taker flow, whale imb)
|
|
14
|
+
invizi market list All tradeable assets with prices
|
|
14
15
|
invizi scout <COIN> Quick coin scan (price, funding, RSI, OBI)
|
|
15
|
-
invizi market BTC/ETH/SOL prices, fear/greed, funding extremes
|
|
16
16
|
invizi trades Analyze past trades — P&L by coin (local)
|
|
17
17
|
|
|
18
18
|
Account:
|
|
19
|
-
invizi
|
|
19
|
+
invizi login Login
|
|
20
|
+
invizi logout Logout
|
|
20
21
|
invizi auth status Show current identity
|
|
21
|
-
invizi
|
|
22
|
+
invizi track <address> Track a wallet address
|
|
22
23
|
|
|
23
24
|
Setup:
|
|
24
25
|
invizi setup Configure API + install AI skills
|
|
@@ -131,8 +132,12 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
131
132
|
}
|
|
132
133
|
if (command === 'auth')
|
|
133
134
|
return auth(args.slice(1));
|
|
134
|
-
if (command === '
|
|
135
|
-
return
|
|
135
|
+
if (command === 'login')
|
|
136
|
+
return auth(['login']);
|
|
137
|
+
if (command === 'logout')
|
|
138
|
+
return auth(['logout']);
|
|
139
|
+
if (command === 'track')
|
|
140
|
+
return track(args.slice(1));
|
|
136
141
|
if (command === 'trades')
|
|
137
142
|
return trades(args.slice(1));
|
|
138
143
|
if (command === 'setup')
|
package/dist/track.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { getApiUrl, loadConfig, saveConfig } from './config.js';
|
|
2
|
+
import { getAuthorizationHeader } from './auth.js';
|
|
3
|
+
const HLP_API = 'https://api.hyperliquid.xyz/info';
|
|
4
|
+
function detectChain(address) {
|
|
5
|
+
if (/^0x[0-9a-fA-F]{40}$/.test(address))
|
|
6
|
+
return 'evm';
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const EXCHANGE_CHECKERS = {
|
|
10
|
+
evm: [{ name: 'hyperliquid', check: validateHlpAddress }],
|
|
11
|
+
};
|
|
12
|
+
async function validateHlpAddress(address) {
|
|
13
|
+
const [stateRes, fillsRes] = await Promise.all([
|
|
14
|
+
fetch(HLP_API, {
|
|
15
|
+
method: 'POST',
|
|
16
|
+
headers: { 'Content-Type': 'application/json' },
|
|
17
|
+
body: JSON.stringify({ type: 'clearinghouseState', user: address }),
|
|
18
|
+
}),
|
|
19
|
+
fetch(HLP_API, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: { 'Content-Type': 'application/json' },
|
|
22
|
+
body: JSON.stringify({ type: 'userFills', user: address }),
|
|
23
|
+
}),
|
|
24
|
+
]);
|
|
25
|
+
if (!stateRes.ok || !fillsRes.ok) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const state = (await stateRes.json());
|
|
29
|
+
const fills = (await fillsRes.json());
|
|
30
|
+
return {
|
|
31
|
+
positions: state.assetPositions?.length || 0,
|
|
32
|
+
accountValue: Number.parseFloat(state.marginSummary?.accountValue || '0'),
|
|
33
|
+
trades: fills.length || 0,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function registerWithServer(exchange, address, label) {
|
|
37
|
+
const apiUrl = getApiUrl();
|
|
38
|
+
const authHeader = await getAuthorizationHeader();
|
|
39
|
+
if (!authHeader) {
|
|
40
|
+
throw new Error('Not authenticated. Run: invizi auth login');
|
|
41
|
+
}
|
|
42
|
+
const res = await fetch(`${apiUrl}/api/connect`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
Authorization: authHeader,
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify({ exchange, address, label }),
|
|
49
|
+
});
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
const bodyText = await res.text();
|
|
52
|
+
let parsed = null;
|
|
53
|
+
try {
|
|
54
|
+
parsed = JSON.parse(bodyText);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
parsed = null;
|
|
58
|
+
}
|
|
59
|
+
if (res.status === 403 && parsed?.error?.includes('Tracking limit reached')) {
|
|
60
|
+
const tracked = parsed.trackedAddress;
|
|
61
|
+
const details = tracked
|
|
62
|
+
? `existing ${tracked.exchange}:${tracked.address}${tracked.label ? ` (${tracked.label})` : ''}`
|
|
63
|
+
: 'already at limit';
|
|
64
|
+
throw new Error(`Tracking limit reached (${details}).`);
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`Server error: ${res.status} ${parsed?.error || bodyText}`);
|
|
67
|
+
}
|
|
68
|
+
return (await res.json());
|
|
69
|
+
}
|
|
70
|
+
export async function track(args) {
|
|
71
|
+
const address = args[0];
|
|
72
|
+
const labelIdx = args.indexOf('--label');
|
|
73
|
+
const label = labelIdx !== -1 ? args[labelIdx + 1] || null : null;
|
|
74
|
+
if (!address) {
|
|
75
|
+
console.error('Usage: invizi track <wallet-address> [--label name]');
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
const chain = detectChain(address);
|
|
79
|
+
if (!chain) {
|
|
80
|
+
console.error(`Unrecognized address format: ${address}`);
|
|
81
|
+
console.error('Supported: EVM addresses (0x...)');
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
const checkers = EXCHANGE_CHECKERS[chain];
|
|
85
|
+
if (!checkers || checkers.length === 0) {
|
|
86
|
+
console.error(`No supported exchanges for chain: ${chain}`);
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
console.log(`Scanning exchanges for ${address}...`);
|
|
90
|
+
const found = [];
|
|
91
|
+
for (const { name, check } of checkers) {
|
|
92
|
+
const info = await check(address);
|
|
93
|
+
if (info && (info.positions > 0 || info.trades > 0 || info.accountValue > 0)) {
|
|
94
|
+
found.push({ exchange: name, info });
|
|
95
|
+
console.log(` [ok] ${name}: ${info.positions} positions, ${info.trades} trades, $${info.accountValue.toFixed(2)}`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log(` [x] ${name}: no activity`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (found.length === 0) {
|
|
102
|
+
console.error('No activity found on any supported exchange for this address.');
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
const selected = found[0];
|
|
106
|
+
try {
|
|
107
|
+
const result = await registerWithServer(selected.exchange, address, label);
|
|
108
|
+
const config = loadConfig();
|
|
109
|
+
config.userId = result.userId;
|
|
110
|
+
config.trackedAddressId = result.trackedAddressId;
|
|
111
|
+
delete config.accountId;
|
|
112
|
+
config.address = address;
|
|
113
|
+
config.exchange = selected.exchange;
|
|
114
|
+
if (label)
|
|
115
|
+
config.label = label;
|
|
116
|
+
saveConfig(config);
|
|
117
|
+
console.log(`Connected watch-only tracking: ${selected.exchange}`);
|
|
118
|
+
if (result.alreadyTracked) {
|
|
119
|
+
console.log(' Already tracked previously.');
|
|
120
|
+
}
|
|
121
|
+
console.log(` Positions: ${selected.info.positions}`);
|
|
122
|
+
console.log(` Trades: ${selected.info.trades}`);
|
|
123
|
+
console.log(` Account value: $${selected.info.accountValue.toFixed(2)}`);
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
128
|
+
console.error(`Failed to register: ${message}`);
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@invizi/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Invizi CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"build": "tsc -p tsconfig.json",
|
|
15
15
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
16
16
|
"test": "jest",
|
|
17
|
-
"prepack": "npm run build"
|
|
17
|
+
"prepack": "npm run build",
|
|
18
|
+
"postinstall": "node -e \"console.log('\\n\\x1b[1m✨ Invizi CLI installed!\\x1b[0m\\n\\nGet started:\\n invizi login Authenticate\\n invizi connect <address> Connect your wallet\\n invizi setup Install AI skills\\n invizi market Check the markets\\n invizi --help See all commands\\n')\""
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
21
|
"@types/jest": "^30.0.0",
|