@exagent/agent 0.3.5 → 0.3.6
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/{chunk-WTECTX2Z.js → chunk-ZRAOPQQW.js} +208 -147
- package/dist/cli.js +39 -97
- package/dist/index.js +1 -1
- package/package.json +18 -18
- package/src/cli.ts +18 -12
- package/src/config.ts +6 -3
- package/src/llm/anthropic.ts +3 -3
- package/src/llm/deepseek.ts +3 -3
- package/src/llm/google.ts +3 -3
- package/src/llm/groq.ts +3 -3
- package/src/llm/mistral.ts +3 -3
- package/src/llm/ollama.ts +3 -3
- package/src/llm/openai.ts +46 -3
- package/src/llm/together.ts +3 -3
- package/src/llm-providers.ts +8 -100
- package/src/prediction/client.ts +11 -4
- package/src/runtime.ts +3 -3
- package/src/setup.ts +18 -10
- package/src/strategy/loader.ts +136 -62
- package/src/strategy/templates.ts +0 -51
- package/test/strategy-loader.test.ts +150 -0
- package/.turbo/turbo-build.log +0 -17
- package/test-bridge-arb-to-base.mjs +0 -223
- package/test-funded-check.mjs +0 -79
- package/test-funded-phase19.mjs +0 -933
- package/test-hl-deposit-recover.mjs +0 -281
- package/test-hl-withdraw.mjs +0 -372
- package/test-live-signing.mjs +0 -374
- package/test-phase7.mjs +0 -416
- package/test-recover-arb.mjs +0 -206
- package/test-spot-bridge.mjs +0 -248
- package/test-wallet-setup.mjs +0 -126
package/test-live-signing.mjs
DELETED
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Live Signing Validation Test
|
|
3
|
-
*
|
|
4
|
-
* Tests our signing/auth code against REAL mainnet APIs.
|
|
5
|
-
* No funds needed — we validate that signatures are accepted
|
|
6
|
-
* (errors should be "insufficient margin", NOT "invalid signature").
|
|
7
|
-
*
|
|
8
|
-
* Tests:
|
|
9
|
-
* 1. Hyperliquid: EIP-712 sign → submit order → expect margin error (not signature error)
|
|
10
|
-
* 2. Polymarket: L2 API key derivation → expect success (proves auth works)
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { createWalletClient, http } from 'viem';
|
|
14
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
15
|
-
import { arbitrum } from 'viem/chains';
|
|
16
|
-
|
|
17
|
-
// Test wallet (no funds — that's fine for signing validation)
|
|
18
|
-
const TEST_PKEY = '0xf1a60fbdb6a77340ce20756f95496b477ea86ab73e01f6c27a503771a80850ad';
|
|
19
|
-
|
|
20
|
-
const account = privateKeyToAccount(TEST_PKEY);
|
|
21
|
-
console.log(`Test wallet: ${account.address}`);
|
|
22
|
-
console.log('═══════════════════════════════════════════════\n');
|
|
23
|
-
|
|
24
|
-
let passed = 0;
|
|
25
|
-
let failed = 0;
|
|
26
|
-
|
|
27
|
-
// ═══════════════════════════════════════════════════════════
|
|
28
|
-
// TEST 1: Hyperliquid EIP-712 Signing
|
|
29
|
-
// ═══════════════════════════════════════════════════════════
|
|
30
|
-
|
|
31
|
-
console.log('TEST 1: Hyperliquid EIP-712 Signing + Order Submission');
|
|
32
|
-
console.log('─────────────────────────────────────────────');
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
// Import our modules from dist
|
|
36
|
-
const { HyperliquidClient, HyperliquidSigner, getNextNonce, HYPERLIQUID_DOMAIN } = await import('./dist/index.js');
|
|
37
|
-
|
|
38
|
-
const config = {
|
|
39
|
-
enabled: true,
|
|
40
|
-
apiUrl: 'https://api.hyperliquid.xyz',
|
|
41
|
-
wsUrl: 'wss://api.hyperliquid.xyz/ws',
|
|
42
|
-
maxLeverage: 10,
|
|
43
|
-
maxNotionalUSD: 50000,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const client = new HyperliquidClient(config);
|
|
47
|
-
|
|
48
|
-
// Create a viem WalletClient for signing
|
|
49
|
-
const walletClient = createWalletClient({
|
|
50
|
-
account,
|
|
51
|
-
chain: arbitrum,
|
|
52
|
-
transport: http('https://arb1.arbitrum.io/rpc'),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const signer = new HyperliquidSigner(walletClient);
|
|
56
|
-
|
|
57
|
-
// Verify signer address
|
|
58
|
-
const signerAddr = signer.getAddress();
|
|
59
|
-
console.log(` Signer address: ${signerAddr}`);
|
|
60
|
-
if (signerAddr.toLowerCase() !== account.address.toLowerCase()) {
|
|
61
|
-
throw new Error('Signer address mismatch!');
|
|
62
|
-
}
|
|
63
|
-
console.log(' ✓ Signer address matches\n');
|
|
64
|
-
|
|
65
|
-
// Get ETH asset index
|
|
66
|
-
const ethIndex = await client.getAssetIndex('ETH');
|
|
67
|
-
console.log(` ETH asset index: ${ethIndex}`);
|
|
68
|
-
|
|
69
|
-
// Simulate the exact same flow as OrderManager.placeOrder
|
|
70
|
-
// (price.toString() on a round number produces "2000", not "2000.0")
|
|
71
|
-
const signal = { price: 2000, size: 0.001, reduceOnly: false };
|
|
72
|
-
const orderWire = {
|
|
73
|
-
a: ethIndex,
|
|
74
|
-
b: true, // buy (long)
|
|
75
|
-
p: signal.price.toString(), // "2000" — correct format
|
|
76
|
-
s: signal.size.toString(), // "0.001"
|
|
77
|
-
r: signal.reduceOnly,
|
|
78
|
-
t: { limit: { tif: 'Gtc' } },
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const action = {
|
|
82
|
-
type: 'order',
|
|
83
|
-
orders: [orderWire],
|
|
84
|
-
grouping: 'na',
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// Sign the action
|
|
88
|
-
const nonce = getNextNonce();
|
|
89
|
-
const { signature } = await signer.signAction(action, nonce);
|
|
90
|
-
console.log(` Signature: ${signature.slice(0, 20)}...${signature.slice(-8)}`);
|
|
91
|
-
console.log(` Nonce: ${nonce}\n`);
|
|
92
|
-
|
|
93
|
-
// Parse signature into r, s, v
|
|
94
|
-
const sigR = signature.slice(0, 66);
|
|
95
|
-
const sigS = `0x${signature.slice(66, 130)}`;
|
|
96
|
-
const sigV = parseInt(signature.slice(130, 132), 16);
|
|
97
|
-
|
|
98
|
-
console.log(' Submitting to Hyperliquid Exchange API...');
|
|
99
|
-
|
|
100
|
-
// Submit to the Exchange API
|
|
101
|
-
const resp = await fetch('https://api.hyperliquid.xyz/exchange', {
|
|
102
|
-
method: 'POST',
|
|
103
|
-
headers: { 'Content-Type': 'application/json' },
|
|
104
|
-
body: JSON.stringify({
|
|
105
|
-
action,
|
|
106
|
-
nonce: Number(nonce),
|
|
107
|
-
signature: { r: sigR, s: sigS, v: sigV },
|
|
108
|
-
vaultAddress: null,
|
|
109
|
-
}),
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const respText = await resp.text();
|
|
113
|
-
let respJson;
|
|
114
|
-
try { respJson = JSON.parse(respText); } catch { respJson = respText; }
|
|
115
|
-
|
|
116
|
-
console.log(` HTTP Status: ${resp.status}`);
|
|
117
|
-
console.log(` Response: ${JSON.stringify(respJson)}\n`);
|
|
118
|
-
|
|
119
|
-
// Analyze the response
|
|
120
|
-
const respStr = typeof respJson === 'string' ? respJson : JSON.stringify(respJson);
|
|
121
|
-
|
|
122
|
-
if (respStr.toLowerCase().includes('invalid signature') ||
|
|
123
|
-
respStr.toLowerCase().includes('signature verification') ||
|
|
124
|
-
respStr.toLowerCase().includes('bad signature')) {
|
|
125
|
-
console.log(' ✗ SIGNATURE REJECTED — our EIP-712 signing is broken!\n');
|
|
126
|
-
failed++;
|
|
127
|
-
} else if (resp.status === 200 || resp.status === 400 || resp.status === 403) {
|
|
128
|
-
// Any response that ISN'T a signature error means our signing works
|
|
129
|
-
// Common expected errors: "Not enough margin", "User does not exist", etc.
|
|
130
|
-
console.log(' ✓ Signature ACCEPTED by Hyperliquid API');
|
|
131
|
-
console.log(' (Order rejected for business reason, not signing — this is expected)\n');
|
|
132
|
-
passed++;
|
|
133
|
-
} else {
|
|
134
|
-
console.log(` ⚠ Unexpected response — needs manual review\n`);
|
|
135
|
-
// Still count as pass if not a signature error
|
|
136
|
-
if (!respStr.toLowerCase().includes('signature')) {
|
|
137
|
-
passed++;
|
|
138
|
-
} else {
|
|
139
|
-
failed++;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
} catch (error) {
|
|
144
|
-
console.log(` ✗ Error: ${error.message}\n`);
|
|
145
|
-
// Check if the error is about signing or about something else
|
|
146
|
-
if (error.message.toLowerCase().includes('signature')) {
|
|
147
|
-
failed++;
|
|
148
|
-
} else {
|
|
149
|
-
console.log(' (Error is not signature-related — may be a network or other issue)');
|
|
150
|
-
failed++;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// ═══════════════════════════════════════════════════════════
|
|
155
|
-
// TEST 2: Hyperliquid Update Leverage (different action type)
|
|
156
|
-
// ═══════════════════════════════════════════════════════════
|
|
157
|
-
|
|
158
|
-
console.log('TEST 2: Hyperliquid Update Leverage Signing');
|
|
159
|
-
console.log('─────────────────────────────────────────────');
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const { HyperliquidClient, HyperliquidSigner, getNextNonce } = await import('./dist/index.js');
|
|
163
|
-
|
|
164
|
-
const config = {
|
|
165
|
-
enabled: true,
|
|
166
|
-
apiUrl: 'https://api.hyperliquid.xyz',
|
|
167
|
-
wsUrl: 'wss://api.hyperliquid.xyz/ws',
|
|
168
|
-
maxLeverage: 10,
|
|
169
|
-
maxNotionalUSD: 50000,
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
const client = new HyperliquidClient(config);
|
|
173
|
-
const walletClient = createWalletClient({
|
|
174
|
-
account,
|
|
175
|
-
chain: arbitrum,
|
|
176
|
-
transport: http('https://arb1.arbitrum.io/rpc'),
|
|
177
|
-
});
|
|
178
|
-
const signer = new HyperliquidSigner(walletClient);
|
|
179
|
-
|
|
180
|
-
const ethIndex = await client.getAssetIndex('ETH');
|
|
181
|
-
|
|
182
|
-
const action = {
|
|
183
|
-
type: 'updateLeverage',
|
|
184
|
-
asset: ethIndex,
|
|
185
|
-
isCross: true,
|
|
186
|
-
leverage: 5,
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const nonce = getNextNonce();
|
|
190
|
-
const { signature } = await signer.signAction(action, nonce);
|
|
191
|
-
|
|
192
|
-
const sigR = signature.slice(0, 66);
|
|
193
|
-
const sigS = `0x${signature.slice(66, 130)}`;
|
|
194
|
-
const sigV = parseInt(signature.slice(130, 132), 16);
|
|
195
|
-
|
|
196
|
-
console.log(' Submitting updateLeverage to Exchange API...');
|
|
197
|
-
|
|
198
|
-
const resp = await fetch('https://api.hyperliquid.xyz/exchange', {
|
|
199
|
-
method: 'POST',
|
|
200
|
-
headers: { 'Content-Type': 'application/json' },
|
|
201
|
-
body: JSON.stringify({
|
|
202
|
-
action,
|
|
203
|
-
nonce: Number(nonce),
|
|
204
|
-
signature: { r: sigR, s: sigS, v: sigV },
|
|
205
|
-
vaultAddress: null,
|
|
206
|
-
}),
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const respText = await resp.text();
|
|
210
|
-
let respJson;
|
|
211
|
-
try { respJson = JSON.parse(respText); } catch { respJson = respText; }
|
|
212
|
-
|
|
213
|
-
console.log(` HTTP Status: ${resp.status}`);
|
|
214
|
-
console.log(` Response: ${JSON.stringify(respJson)}\n`);
|
|
215
|
-
|
|
216
|
-
const respStr = typeof respJson === 'string' ? respJson : JSON.stringify(respJson);
|
|
217
|
-
|
|
218
|
-
if (respStr.toLowerCase().includes('invalid signature') ||
|
|
219
|
-
respStr.toLowerCase().includes('bad signature')) {
|
|
220
|
-
console.log(' ✗ SIGNATURE REJECTED\n');
|
|
221
|
-
failed++;
|
|
222
|
-
} else {
|
|
223
|
-
console.log(' ✓ Leverage update accepted (or rejected for non-signature reason)\n');
|
|
224
|
-
passed++;
|
|
225
|
-
}
|
|
226
|
-
} catch (error) {
|
|
227
|
-
console.log(` ✗ Error: ${error.message}\n`);
|
|
228
|
-
failed++;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// ═══════════════════════════════════════════════════════════
|
|
232
|
-
// TEST 3: Polymarket L2 API Key Derivation
|
|
233
|
-
// ═══════════════════════════════════════════════════════════
|
|
234
|
-
|
|
235
|
-
console.log('TEST 3: Polymarket CLOB API Key Derivation');
|
|
236
|
-
console.log('─────────────────────────────────────────────');
|
|
237
|
-
|
|
238
|
-
try {
|
|
239
|
-
const { PolymarketClient } = await import('./dist/index.js');
|
|
240
|
-
|
|
241
|
-
console.log(' Initializing PolymarketClient...');
|
|
242
|
-
console.log(' (This derives L2 API keys via wallet signature — proves auth works)\n');
|
|
243
|
-
|
|
244
|
-
const pmClient = new PolymarketClient(TEST_PKEY, {
|
|
245
|
-
enabled: true,
|
|
246
|
-
clobApiUrl: 'https://clob.polymarket.com',
|
|
247
|
-
gammaApiUrl: 'https://gamma-api.polymarket.com',
|
|
248
|
-
maxNotionalUSD: 100,
|
|
249
|
-
maxTotalExposureUSD: 200,
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
await pmClient.initialize();
|
|
253
|
-
|
|
254
|
-
if (pmClient.isInitialized) {
|
|
255
|
-
console.log(` ✓ CLOB client initialized successfully`);
|
|
256
|
-
console.log(` ✓ L2 API keys derived — authentication pipeline WORKS`);
|
|
257
|
-
console.log(` Wallet: ${pmClient.getWalletAddress()}\n`);
|
|
258
|
-
passed++;
|
|
259
|
-
|
|
260
|
-
// Test 3b: Try to fetch open orders (validates L2 auth headers)
|
|
261
|
-
console.log(' Fetching open orders (validates L2 auth headers)...');
|
|
262
|
-
const orders = await pmClient.getOpenOrders();
|
|
263
|
-
console.log(` ✓ Open orders response: ${orders.length} orders (expected: 0)\n`);
|
|
264
|
-
|
|
265
|
-
// Test 3c: Try to fetch trade history
|
|
266
|
-
console.log(' Fetching trade history...');
|
|
267
|
-
const trades = await pmClient.getTradeHistory();
|
|
268
|
-
console.log(` ✓ Trade history response: ${trades.length} trades (expected: 0)\n`);
|
|
269
|
-
|
|
270
|
-
passed++; // Auth headers work
|
|
271
|
-
|
|
272
|
-
} else {
|
|
273
|
-
console.log(' ✗ CLOB client failed to initialize\n');
|
|
274
|
-
failed++;
|
|
275
|
-
}
|
|
276
|
-
} catch (error) {
|
|
277
|
-
console.log(` ✗ Error: ${error.message}`);
|
|
278
|
-
if (error.message.includes('401') || error.message.includes('403')) {
|
|
279
|
-
console.log(' (Auth rejected — signing may be incompatible)\n');
|
|
280
|
-
} else {
|
|
281
|
-
console.log(' (May be a network or API issue)\n');
|
|
282
|
-
}
|
|
283
|
-
failed++;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// ═══════════════════════════════════════════════════════════
|
|
287
|
-
// TEST 4: Polymarket Order Signing (expect insufficient balance)
|
|
288
|
-
// ═══════════════════════════════════════════════════════════
|
|
289
|
-
|
|
290
|
-
console.log('TEST 4: Polymarket Order Signing');
|
|
291
|
-
console.log('─────────────────────────────────────────────');
|
|
292
|
-
|
|
293
|
-
try {
|
|
294
|
-
const { PolymarketClient } = await import('./dist/index.js');
|
|
295
|
-
|
|
296
|
-
const pmClient = new PolymarketClient(TEST_PKEY, {
|
|
297
|
-
enabled: true,
|
|
298
|
-
clobApiUrl: 'https://clob.polymarket.com',
|
|
299
|
-
gammaApiUrl: 'https://gamma-api.polymarket.com',
|
|
300
|
-
maxNotionalUSD: 100,
|
|
301
|
-
maxTotalExposureUSD: 200,
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
await pmClient.initialize();
|
|
305
|
-
|
|
306
|
-
// Find a real active market to test against
|
|
307
|
-
console.log(' Finding an active market (trending)...');
|
|
308
|
-
const trending = await pmClient.getTrendingMarkets(1);
|
|
309
|
-
|
|
310
|
-
if (trending.length === 0) {
|
|
311
|
-
console.log(' ⚠ No active markets found — skipping order test\n');
|
|
312
|
-
// Not a failure, just can't test this part
|
|
313
|
-
} else {
|
|
314
|
-
const market = trending[0];
|
|
315
|
-
console.log(` Found: "${market.question}"`);
|
|
316
|
-
console.log(` Token IDs: ${market.outcomeTokenIds.join(', ')}`);
|
|
317
|
-
|
|
318
|
-
const tokenId = market.outcomeTokenIds[0];
|
|
319
|
-
if (tokenId) {
|
|
320
|
-
console.log(`\n Attempting to place a tiny limit order (will fail with balance error)...`);
|
|
321
|
-
try {
|
|
322
|
-
const result = await pmClient.placeLimitOrder({
|
|
323
|
-
tokenId,
|
|
324
|
-
price: 0.01, // Minimum price
|
|
325
|
-
size: 5, // Minimum size
|
|
326
|
-
side: 'BUY',
|
|
327
|
-
});
|
|
328
|
-
console.log(` Order result: ${JSON.stringify(result)}`);
|
|
329
|
-
if (result.success) {
|
|
330
|
-
console.log(' ✓ Order placed successfully (unexpected with no balance, but signing works!)');
|
|
331
|
-
// Cancel it immediately
|
|
332
|
-
if (result.orderId) {
|
|
333
|
-
await pmClient.cancelOrder(result.orderId);
|
|
334
|
-
console.log(' Cancelled test order\n');
|
|
335
|
-
}
|
|
336
|
-
passed++;
|
|
337
|
-
} else {
|
|
338
|
-
console.log(' Order rejected (expected — no balance)\n');
|
|
339
|
-
// This is still a pass for signing if the error isn't about signatures
|
|
340
|
-
passed++;
|
|
341
|
-
}
|
|
342
|
-
} catch (orderError) {
|
|
343
|
-
const msg = orderError.message || String(orderError);
|
|
344
|
-
console.log(` Order error: ${msg}`);
|
|
345
|
-
if (msg.toLowerCase().includes('signature') || msg.toLowerCase().includes('auth')) {
|
|
346
|
-
console.log(' ✗ Order SIGNING failed\n');
|
|
347
|
-
failed++;
|
|
348
|
-
} else {
|
|
349
|
-
console.log(' ✓ Order rejected for non-signing reason (balance, size, etc.)\n');
|
|
350
|
-
passed++;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
} catch (error) {
|
|
356
|
-
console.log(` ✗ Error: ${error.message}\n`);
|
|
357
|
-
failed++;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// ═══════════════════════════════════════════════════════════
|
|
361
|
-
// SUMMARY
|
|
362
|
-
// ═══════════════════════════════════════════════════════════
|
|
363
|
-
|
|
364
|
-
console.log('═══════════════════════════════════════════════');
|
|
365
|
-
console.log(` RESULTS: ${passed} passed, ${failed} failed`);
|
|
366
|
-
console.log('═══════════════════════════════════════════════');
|
|
367
|
-
|
|
368
|
-
if (failed > 0) {
|
|
369
|
-
console.log('\n⚠ Some tests failed. The signing/auth pipeline needs fixes before live trading.');
|
|
370
|
-
process.exit(1);
|
|
371
|
-
} else {
|
|
372
|
-
console.log('\n✓ All signing/auth tests passed. The code is ready for funded live testing.');
|
|
373
|
-
process.exit(0);
|
|
374
|
-
}
|