@quantish/agent 0.1.0 → 0.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.
- package/dist/index.js +154 -7
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -2566,7 +2566,150 @@ You can work with the local filesystem:
|
|
|
2566
2566
|
- When writing code, follow existing patterns and conventions
|
|
2567
2567
|
- For dangerous operations (rm, sudo), explain what you're doing
|
|
2568
2568
|
|
|
2569
|
-
You help users build trading bots and agents by combining coding skills with trading capabilities
|
|
2569
|
+
You help users build trading bots and agents by combining coding skills with trading capabilities.
|
|
2570
|
+
|
|
2571
|
+
## Building Standalone Trading Bots
|
|
2572
|
+
|
|
2573
|
+
When users ask you to create trading bots or agents that run independently (not through this CLI), here's how to integrate with the Quantish MCP API:
|
|
2574
|
+
|
|
2575
|
+
### MCP API Endpoint
|
|
2576
|
+
\`\`\`
|
|
2577
|
+
POST https://quantish-sdk-production.up.railway.app/mcp/execute
|
|
2578
|
+
\`\`\`
|
|
2579
|
+
|
|
2580
|
+
### Authentication
|
|
2581
|
+
\`\`\`
|
|
2582
|
+
Header: x-api-key: <QUANTISH_API_KEY>
|
|
2583
|
+
\`\`\`
|
|
2584
|
+
The API key is stored in the user's environment as QUANTISH_API_KEY. Always read from env vars, never hardcode.
|
|
2585
|
+
|
|
2586
|
+
### Request Format (JSON-RPC 2.0)
|
|
2587
|
+
\`\`\`javascript
|
|
2588
|
+
const response = await fetch('https://quantish-sdk-production.up.railway.app/mcp/execute', {
|
|
2589
|
+
method: 'POST',
|
|
2590
|
+
headers: {
|
|
2591
|
+
'Content-Type': 'application/json',
|
|
2592
|
+
'x-api-key': process.env.QUANTISH_API_KEY
|
|
2593
|
+
},
|
|
2594
|
+
body: JSON.stringify({
|
|
2595
|
+
jsonrpc: '2.0',
|
|
2596
|
+
method: 'tools/call',
|
|
2597
|
+
params: {
|
|
2598
|
+
name: 'tool_name',
|
|
2599
|
+
arguments: { /* tool args */ }
|
|
2600
|
+
},
|
|
2601
|
+
id: Date.now()
|
|
2602
|
+
})
|
|
2603
|
+
});
|
|
2604
|
+
\`\`\`
|
|
2605
|
+
|
|
2606
|
+
### Response Format
|
|
2607
|
+
\`\`\`javascript
|
|
2608
|
+
// Success response structure:
|
|
2609
|
+
{
|
|
2610
|
+
"jsonrpc": "2.0",
|
|
2611
|
+
"result": {
|
|
2612
|
+
"content": [{
|
|
2613
|
+
"type": "text",
|
|
2614
|
+
"text": "{\\"key\\": \\"value\\"}" // JSON string - parse this!
|
|
2615
|
+
}]
|
|
2616
|
+
},
|
|
2617
|
+
"id": 123
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
// Parse the inner JSON:
|
|
2621
|
+
const data = await response.json();
|
|
2622
|
+
const result = JSON.parse(data.result.content[0].text);
|
|
2623
|
+
\`\`\`
|
|
2624
|
+
|
|
2625
|
+
### Key Trading Tools (require QUANTISH_API_KEY)
|
|
2626
|
+
- \`get_balances\`: Returns { usdc, nativeUsdc, matic } for EOA and Safe wallets
|
|
2627
|
+
- \`get_positions\`: Returns array of current share holdings with market info
|
|
2628
|
+
- \`place_order\`: Place order. Args: { conditionId, tokenId, side: "BUY"|"SELL", price: 0.01-0.99, size: number }
|
|
2629
|
+
- \`cancel_order\`: Cancel order. Args: { orderId }
|
|
2630
|
+
- \`get_orders\`: List orders. Args: { status?: "LIVE"|"FILLED"|"CANCELLED" }
|
|
2631
|
+
- \`get_orderbook\`: Get bids/asks. Args: { tokenId }
|
|
2632
|
+
- \`get_price\`: Get midpoint price. Args: { tokenId }
|
|
2633
|
+
- \`get_deposit_addresses\`: Get addresses to fund wallet
|
|
2634
|
+
- \`transfer_usdc\`: Send USDC. Args: { toAddress, amount }
|
|
2635
|
+
|
|
2636
|
+
### Key Discovery Tools (free, no auth required)
|
|
2637
|
+
Discovery uses a different endpoint with an embedded public key:
|
|
2638
|
+
\`\`\`
|
|
2639
|
+
POST https://quantish.live/mcp/execute
|
|
2640
|
+
Header: X-API-Key: qm_ueQeqrmvZyHtR1zuVbLYkhx0fKyVAuV8
|
|
2641
|
+
\`\`\`
|
|
2642
|
+
|
|
2643
|
+
- \`search_markets\`: Find markets. Args: { query, limit?, platform?: "polymarket"|"kalshi"|"all" }
|
|
2644
|
+
- \`get_market_details\`: Get market info. Args: { platform, marketId }
|
|
2645
|
+
- \`get_trending_markets\`: Popular markets. Args: { limit?, platform? }
|
|
2646
|
+
- \`find_arbitrage\`: Find arb opportunities. Args: { minProfitPercent?, type? }
|
|
2647
|
+
|
|
2648
|
+
### Important: Token IDs and Condition IDs
|
|
2649
|
+
When placing orders, you need:
|
|
2650
|
+
- \`conditionId\`: The market's condition ID (from market details)
|
|
2651
|
+
- \`tokenId\`: The specific outcome's token ID (YES or NO token from market.tokens array)
|
|
2652
|
+
|
|
2653
|
+
Example flow:
|
|
2654
|
+
1. search_markets({ query: "bitcoin" }) \u2192 get market list
|
|
2655
|
+
2. get_market_details({ platform: "polymarket", marketId: "..." }) \u2192 get tokens array
|
|
2656
|
+
3. Extract tokenId for YES/NO outcome you want
|
|
2657
|
+
4. place_order({ conditionId, tokenId, side: "BUY", price: 0.55, size: 100 })
|
|
2658
|
+
|
|
2659
|
+
### Bot Code Template (Node.js)
|
|
2660
|
+
\`\`\`javascript
|
|
2661
|
+
#!/usr/bin/env node
|
|
2662
|
+
require('dotenv').config();
|
|
2663
|
+
|
|
2664
|
+
const MCP_URL = 'https://quantish-sdk-production.up.railway.app/mcp/execute';
|
|
2665
|
+
const API_KEY = process.env.QUANTISH_API_KEY;
|
|
2666
|
+
|
|
2667
|
+
async function callTool(name, args = {}) {
|
|
2668
|
+
const response = await fetch(MCP_URL, {
|
|
2669
|
+
method: 'POST',
|
|
2670
|
+
headers: {
|
|
2671
|
+
'Content-Type': 'application/json',
|
|
2672
|
+
'x-api-key': API_KEY
|
|
2673
|
+
},
|
|
2674
|
+
body: JSON.stringify({
|
|
2675
|
+
jsonrpc: '2.0',
|
|
2676
|
+
method: 'tools/call',
|
|
2677
|
+
params: { name, arguments: args },
|
|
2678
|
+
id: Date.now()
|
|
2679
|
+
})
|
|
2680
|
+
});
|
|
2681
|
+
|
|
2682
|
+
const data = await response.json();
|
|
2683
|
+
if (data.error) throw new Error(data.error.message);
|
|
2684
|
+
|
|
2685
|
+
try {
|
|
2686
|
+
return JSON.parse(data.result.content[0].text);
|
|
2687
|
+
} catch {
|
|
2688
|
+
return data.result.content[0].text;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
// Example: Monitor price and alert
|
|
2693
|
+
async function monitorPrice(tokenId, threshold) {
|
|
2694
|
+
const result = await callTool('get_price', { tokenId });
|
|
2695
|
+
console.log(\`Price: \${result.mid}\`);
|
|
2696
|
+
if (parseFloat(result.mid) > threshold) {
|
|
2697
|
+
console.log('ALERT: Price crossed threshold!');
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
// Run every 60 seconds
|
|
2702
|
+
setInterval(() => monitorPrice(process.env.TOKEN_ID, 0.5), 60000);
|
|
2703
|
+
\`\`\`
|
|
2704
|
+
|
|
2705
|
+
### Bot Best Practices
|
|
2706
|
+
1. **Environment Variables**: Always use process.env for API keys
|
|
2707
|
+
2. **Error Handling**: Wrap all API calls in try/catch
|
|
2708
|
+
3. **Rate Limiting**: Poll at 30-60 second intervals minimum
|
|
2709
|
+
4. **Logging**: Log all trades with timestamps for debugging
|
|
2710
|
+
5. **Testing**: Test with small amounts first
|
|
2711
|
+
6. **Graceful Shutdown**: Handle SIGINT to clean up
|
|
2712
|
+
7. **.env.example**: Always create a template for required env vars`;
|
|
2570
2713
|
var Agent = class {
|
|
2571
2714
|
anthropic;
|
|
2572
2715
|
mcpClient;
|
|
@@ -3092,7 +3235,7 @@ import { useState, useCallback, useRef, useEffect } from "react";
|
|
|
3092
3235
|
import { Box, Text, useApp, useInput } from "ink";
|
|
3093
3236
|
import TextInput from "ink-text-input";
|
|
3094
3237
|
import Spinner from "ink-spinner";
|
|
3095
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3238
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3096
3239
|
function formatTokenCount(count) {
|
|
3097
3240
|
if (count < 1e3) return String(count);
|
|
3098
3241
|
if (count < 1e5) return `${(count / 1e3).toFixed(1)}k`;
|
|
@@ -3569,18 +3712,22 @@ Stopped ${count} background process${count > 1 ? "es" : ""}.`);
|
|
|
3569
3712
|
msg.role === "system" && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: "gray", italic: true, children: msg.content }) })
|
|
3570
3713
|
] }, i)) }),
|
|
3571
3714
|
currentToolCalls.length > 0 && /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: currentToolCalls.map((tc, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3572
|
-
/* @__PURE__ */
|
|
3573
|
-
|
|
3574
|
-
|
|
3715
|
+
/* @__PURE__ */ jsx(Box, { children: tc.pending ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3716
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: /* @__PURE__ */ jsx(Spinner, { type: "dots" }) }),
|
|
3717
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
3575
3718
|
" ",
|
|
3576
3719
|
tc.name
|
|
3577
|
-
] })
|
|
3720
|
+
] }),
|
|
3721
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: formatArgs(tc.args) }),
|
|
3722
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: " Running..." })
|
|
3723
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3724
|
+
/* @__PURE__ */ jsxs(Text, { color: tc.success ? "green" : "red", children: [
|
|
3578
3725
|
tc.success ? "\u2713" : "\u2717",
|
|
3579
3726
|
" ",
|
|
3580
3727
|
tc.name
|
|
3581
3728
|
] }),
|
|
3582
3729
|
/* @__PURE__ */ jsx(Text, { color: "gray", children: formatArgs(tc.args) })
|
|
3583
|
-
] }),
|
|
3730
|
+
] }) }),
|
|
3584
3731
|
!tc.pending && tc.result && /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
|
|
3585
3732
|
"\u2192 ",
|
|
3586
3733
|
formatResult(tc.result, 100)
|
package/package.json
CHANGED