@vesper85/strategy-sdk 0.1.5 → 0.1.7

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @osiris-ai/strategy-sdk
1
+ # @vesper85/strategy-sdk
2
2
 
3
3
  SDK for writing and running trading strategies with Polymarket and Hyperliquid integrations.
4
4
 
@@ -15,11 +15,11 @@ SDK for writing and running trading strategies with Polymarket and Hyperliquid i
15
15
  ## Installation
16
16
 
17
17
  ```bash
18
- npm install @osiris-ai/strategy-sdk
18
+ npm install @vesper85/strategy-sdk
19
19
  # or
20
- pnpm add @osiris-ai/strategy-sdk
20
+ pnpm add @vesper85/strategy-sdk
21
21
  # or
22
- yarn add @osiris-ai/strategy-sdk
22
+ yarn add @vesper85/strategy-sdk
23
23
  ```
24
24
 
25
25
  ## Quick Start
@@ -27,7 +27,7 @@ yarn add @osiris-ai/strategy-sdk
27
27
  ### 1. Create a Tick-Based Strategy
28
28
 
29
29
  ```typescript
30
- import type { OsirisContext, CodeStrategy } from '@osiris-ai/strategy-sdk';
30
+ import type { OsirisContext, CodeStrategy } from '@vesper85/strategy-sdk';
31
31
 
32
32
  export default class MyStrategy implements CodeStrategy {
33
33
  async shouldTrigger(osiris: OsirisContext): Promise<boolean> {
@@ -53,7 +53,7 @@ import type {
53
53
  EventSubscription,
54
54
  StrategyEvent,
55
55
  OsirisContext
56
- } from '@osiris-ai/strategy-sdk';
56
+ } from '@vesper85/strategy-sdk';
57
57
 
58
58
  export class PriceAlertStrategy implements CodeStrategy {
59
59
  // Define what events to subscribe to
@@ -98,10 +98,10 @@ async function main() {
98
98
  });
99
99
 
100
100
  // For tick-based strategies
101
- const engine = createStrategyEngine(strategy, {
101
+ const engine = createStrategyEngine(strategy, context, {
102
102
  logger,
103
103
  tickIntervalMs: 60000,
104
- }, context);
104
+ });
105
105
  engine.start();
106
106
 
107
107
  // For event-based strategies
@@ -129,13 +129,13 @@ interface CodeStrategy {
129
129
  ```
130
130
 
131
131
  ```typescript
132
- import { createStrategyEngine } from '@osiris-ai/strategy-sdk';
132
+ import { createStrategyEngine } from '@vesper85/strategy-sdk';
133
133
 
134
- const engine = createStrategyEngine(strategy, {
134
+ const engine = createStrategyEngine(strategy, context, {
135
135
  logger,
136
136
  strategyId: 'my-strategy',
137
137
  tickIntervalMs: 60000, // Run every 60 seconds
138
- }, context);
138
+ });
139
139
 
140
140
  engine.start();
141
141
  // engine.stop();
@@ -247,7 +247,7 @@ import type {
247
247
  ActivitySubscription,
248
248
  ClobMarketSubscription,
249
249
  CommentsSubscription
250
- } from '@osiris-ai/strategy-sdk';
250
+ } from '@vesper85/strategy-sdk';
251
251
 
252
252
  class MyPolymarketStrategy implements CodeStrategy {
253
253
  subscriptions: EventSubscription[] = [
@@ -370,6 +370,7 @@ const runner = createEventRunner(strategy, {
370
370
  messageType: '*',
371
371
  eventSource: 'polymarket'
372
372
  }
373
+ ```
373
374
 
374
375
  ## Type Guards
375
376
 
@@ -394,7 +395,7 @@ import {
394
395
  // Source routing helpers
395
396
  isPolymarketSubscription,
396
397
  isOsirisSubscription
397
- } from '@osiris-ai/strategy-sdk';
398
+ } from '@vesper85/strategy-sdk';
398
399
 
399
400
  // Check if subscription is for Polymarket
400
401
  if (isPolymarketSubscription(subscription)) {
@@ -465,7 +466,7 @@ interface OsirisContext {
465
466
  #### In-Memory State (for testing)
466
467
 
467
468
  ```typescript
468
- import { MemoryStateManager } from '@osiris-ai/strategy-sdk';
469
+ import { MemoryStateManager } from '@vesper85/strategy-sdk';
469
470
 
470
471
  const stateManager = new MemoryStateManager();
471
472
  ```
@@ -473,7 +474,7 @@ const stateManager = new MemoryStateManager();
473
474
  #### Redis State (for production)
474
475
 
475
476
  ```typescript
476
- import { RedisStateManager } from '@osiris-ai/strategy-sdk';
477
+ import { RedisStateManager } from '@vesper85/strategy-sdk';
477
478
 
478
479
  const stateManager = new RedisStateManager(
479
480
  'redis://localhost:6379',
@@ -535,7 +536,7 @@ const macd = osiris.ta.calculate('macd_12_26_9', ohlcvData, {
535
536
  ### Signing Transactions
536
537
 
537
538
  ```typescript
538
- import { PrivateKeySigner, OsirisSigner } from '@osiris-ai/strategy-sdk';
539
+ import { PrivateKeySigner, OsirisSigner } from '@vesper85/strategy-sdk';
539
540
 
540
541
  // Private key signer
541
542
  const signer = new PrivateKeySigner({
@@ -21,11 +21,7 @@ export declare class PolymarketClient implements PolymarketAPI {
21
21
  /**
22
22
  * Call an MCP tool with retry logic
23
23
  */
24
- private callMCPTool;
25
- /**
26
- * Execute a tool on an MCP client instance
27
- */
28
- private executeMCPTool;
24
+ private invokeMCPTool;
29
25
  /**
30
26
  * Extract content from MCP tool response (ported from sozu-tg-bot)
31
27
  */
package/dist/index.js CHANGED
@@ -3,11 +3,10 @@ import { ClobClient, Side } from '@polymarket/clob-client';
3
3
  import { ethers } from 'ethers';
4
4
  import axios from 'axios';
5
5
  import { serializeSignature, createWalletClient, http } from 'viem';
6
- import { connectMCPServer, removeConnection } from '@osiris-ai/agent-sdk';
7
6
  import { Hyperliquid } from 'hyperliquid';
8
7
  import { createClient } from 'redis';
9
8
  import superjson from 'superjson';
10
- import { TechnicalAnalysisService } from '@osiris-ai/technical-indicators';
9
+ import { TechnicalAnalysisService } from '@vesper85/technical-indicators';
11
10
  import WebSocket from 'ws';
12
11
  import { RealTimeDataClient, ConnectionStatus } from '@polymarket/real-time-data-client';
13
12
  import { privateKeyToAccount } from 'viem/accounts';
@@ -186,6 +185,117 @@ var OsirisSigner = class {
186
185
  return void 0;
187
186
  }
188
187
  };
188
+ var activeClients = /* @__PURE__ */ new Map();
189
+ var getCacheKey = (mcpUrl, accessToken) => {
190
+ if (accessToken) {
191
+ return `${mcpUrl}:${accessToken.slice(0, 10)}`;
192
+ }
193
+ return `${mcpUrl}:no-auth`;
194
+ };
195
+ var isConnectionStale = (connectedAt) => {
196
+ const tenMinutesAgo = Date.now() - 10 * 60 * 1e3;
197
+ return connectedAt.getTime() < tenMinutesAgo;
198
+ };
199
+ var createHttpClient = (mcpUrl, accessToken) => {
200
+ const headers = {
201
+ "Content-Type": "application/json"
202
+ };
203
+ if (accessToken) {
204
+ headers["Authorization"] = `Bearer ${accessToken}`;
205
+ }
206
+ return axios.create({
207
+ baseURL: mcpUrl,
208
+ headers,
209
+ timeout: 3e4
210
+ });
211
+ };
212
+ var mcpRequest = async (client, method, params) => {
213
+ const requestId = Math.random().toString(36).substring(7);
214
+ const response = await client.post("", {
215
+ jsonrpc: "2.0",
216
+ id: requestId,
217
+ method,
218
+ params: params || {}
219
+ });
220
+ if (response.data.error) {
221
+ throw new Error(response.data.error.message || "MCP request failed");
222
+ }
223
+ return response.data.result;
224
+ };
225
+ var removeConnection = (mcpUrl, accessToken) => {
226
+ const cacheKey = getCacheKey(mcpUrl, accessToken);
227
+ activeClients.delete(cacheKey);
228
+ };
229
+ var connectMCPServer = async (mcpUrl, accessToken) => {
230
+ const cacheKey = getCacheKey(mcpUrl, accessToken);
231
+ const existing = activeClients.get(cacheKey);
232
+ if (existing) {
233
+ if (isConnectionStale(existing.connectedAt)) {
234
+ console.log(`[MCP] Connection to ${mcpUrl} is stale, reconnecting...`);
235
+ removeConnection(mcpUrl, accessToken);
236
+ } else {
237
+ return existing;
238
+ }
239
+ }
240
+ const httpClient = createHttpClient(mcpUrl, accessToken);
241
+ try {
242
+ await mcpRequest(httpClient, "initialize", {
243
+ protocolVersion: "2024-11-05",
244
+ capabilities: {},
245
+ clientInfo: {
246
+ name: "strategy-sdk",
247
+ version: "0.1.0"
248
+ }
249
+ });
250
+ const toolsResponse = await mcpRequest(httpClient, "tools/list", {});
251
+ const tools = toolsResponse.tools || [];
252
+ const instance = {
253
+ url: mcpUrl,
254
+ accessToken,
255
+ connectedAt: /* @__PURE__ */ new Date(),
256
+ tools
257
+ };
258
+ activeClients.set(cacheKey, instance);
259
+ console.log(`[MCP] Connected to ${mcpUrl} (${tools.length} tools available)`);
260
+ return instance;
261
+ } catch (error) {
262
+ console.warn(`[MCP] Failed to connect to ${mcpUrl}, retrying...`);
263
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
264
+ try {
265
+ const httpClient2 = createHttpClient(mcpUrl, accessToken);
266
+ await mcpRequest(httpClient2, "initialize", {
267
+ protocolVersion: "2024-11-05",
268
+ capabilities: {},
269
+ clientInfo: {
270
+ name: "strategy-sdk",
271
+ version: "0.1.0"
272
+ }
273
+ });
274
+ const toolsResponse = await mcpRequest(httpClient2, "tools/list", {});
275
+ const tools = toolsResponse.tools || [];
276
+ const instance = {
277
+ url: mcpUrl,
278
+ accessToken,
279
+ connectedAt: /* @__PURE__ */ new Date(),
280
+ tools
281
+ };
282
+ activeClients.set(cacheKey, instance);
283
+ console.log(`[MCP] Connected to ${mcpUrl} (${tools.length} tools available)`);
284
+ return instance;
285
+ } catch (retryError) {
286
+ console.error(`[MCP] Failed to connect to ${mcpUrl} after retry`);
287
+ throw retryError;
288
+ }
289
+ }
290
+ };
291
+ var callMCPTool = async (mcpUrl, accessToken, toolName, args) => {
292
+ const httpClient = createHttpClient(mcpUrl, accessToken);
293
+ const result = await mcpRequest(httpClient, "tools/call", {
294
+ name: toolName,
295
+ arguments: args || {}
296
+ });
297
+ return result;
298
+ };
189
299
 
190
300
  // src/utils/index.ts
191
301
  function mapToGammaMarket(raw) {
@@ -331,6 +441,9 @@ var PolymarketClient = class {
331
441
  this.logger.info("Initializing MCP connection for Osiris signer...");
332
442
  const mcpUrl = this.options.mcpUrl;
333
443
  const mcpAccessToken = this.options.mcpAccessToken;
444
+ if (!mcpUrl) {
445
+ throw new Error("MCP URL is required for MCP mode. Please provide mcpUrl in options.");
446
+ }
334
447
  if (!mcpAccessToken) {
335
448
  throw new Error("MCP access token is required for MCP mode. Please provide mcpAccessToken in options.");
336
449
  }
@@ -391,45 +504,18 @@ var PolymarketClient = class {
391
504
  /**
392
505
  * Call an MCP tool with retry logic
393
506
  */
394
- async callMCPTool(toolName, args) {
507
+ async invokeMCPTool(toolName, args) {
395
508
  const instance = this.ensureMcpInstance();
396
509
  const mcpUrl = instance.url;
397
510
  const accessToken = instance.accessToken;
398
511
  try {
399
- return await this.executeMCPTool(instance, toolName, args);
512
+ return await callMCPTool(mcpUrl, accessToken, toolName, args);
400
513
  } catch (error) {
401
514
  this.logger.warning(`Tool execution failed for ${toolName}, reconnecting...`, error instanceof Error ? error.message : error);
402
515
  removeConnection(mcpUrl, accessToken);
403
516
  this.mcpInstance = await connectMCPServer(mcpUrl, accessToken);
404
- return await this.executeMCPTool(this.mcpInstance, toolName, args);
405
- }
406
- }
407
- /**
408
- * Execute a tool on an MCP client instance
409
- */
410
- async executeMCPTool(instance, toolName, args) {
411
- const client = instance.client;
412
- if (client._transport && client._transport._client) {
413
- const mcpClient = client._transport._client;
414
- const result = await mcpClient.callTool({
415
- name: toolName,
416
- arguments: args || {}
417
- });
418
- return result;
419
- }
420
- const tools = await client.tools();
421
- const tool = tools[toolName];
422
- if (!tool) {
423
- throw new Error(`Tool ${toolName} not found on MCP server ${instance.url}`);
424
- }
425
- if (typeof tool.execute === "function") {
426
- const result = await tool.execute(args || {});
427
- return result;
428
- }
429
- if (typeof tool === "function") {
430
- return await tool(args || {});
517
+ return await callMCPTool(mcpUrl, accessToken, toolName, args);
431
518
  }
432
- throw new Error(`Tool ${toolName} is not callable`);
433
519
  }
434
520
  /**
435
521
  * Extract content from MCP tool response (ported from sozu-tg-bot)
@@ -675,7 +761,7 @@ var PolymarketClient = class {
675
761
  */
676
762
  async checkAllowanceViaMCP(tokenType) {
677
763
  try {
678
- const allowanceResult = await this.callMCPTool("check_allowance", {
764
+ const allowanceResult = await this.invokeMCPTool("check_allowance", {
679
765
  token: tokenType
680
766
  });
681
767
  console.log("allowanceResult", allowanceResult);
@@ -708,7 +794,7 @@ var PolymarketClient = class {
708
794
  async approveTokensViaMCP(tokenType) {
709
795
  try {
710
796
  this.logger.info(`[MCP] Approving ${tokenType}...`);
711
- const approveResult = await this.callMCPTool("approve_polymarket_tokens", {
797
+ const approveResult = await this.invokeMCPTool("approve_polymarket_tokens", {
712
798
  token_type: tokenType === "USDC" ? "USDC" : "CONDITIONAL_TOKENS",
713
799
  amount: "100",
714
800
  // Amount doesn't matter for max_approval=true
@@ -852,7 +938,7 @@ var PolymarketClient = class {
852
938
  throw new Error("userAddress is required for MCP order placement");
853
939
  }
854
940
  this.logger.info(`Creating limit order via MCP: ${params.side} ${params.size} @ ${params.price}`);
855
- const chooseWalletResult = await this.callMCPTool("choose_wallet", {
941
+ const chooseWalletResult = await this.invokeMCPTool("choose_wallet", {
856
942
  address
857
943
  });
858
944
  const walletError = this.detectMCPError(chooseWalletResult);
@@ -870,7 +956,7 @@ var PolymarketClient = class {
870
956
  errorMsg: `Failed to approve ${params.side === "BUY" ? "USDC" : "Conditional Token"}. Please try again.`
871
957
  };
872
958
  }
873
- const orderResult = await this.callMCPTool("create_and_post_order", {
959
+ const orderResult = await this.invokeMCPTool("create_and_post_order", {
874
960
  userOrder: {
875
961
  tokenID: params.tokenId,
876
962
  side: params.side,
@@ -958,7 +1044,7 @@ var PolymarketClient = class {
958
1044
  throw new Error("userAddress is required for MCP order placement");
959
1045
  }
960
1046
  this.logger.info(`Creating market order via MCP: ${params.side} ${params.amount}`);
961
- const chooseWalletResult = await this.callMCPTool("choose_wallet", {
1047
+ const chooseWalletResult = await this.invokeMCPTool("choose_wallet", {
962
1048
  address
963
1049
  });
964
1050
  const walletError = this.detectMCPError(chooseWalletResult);
@@ -976,7 +1062,7 @@ var PolymarketClient = class {
976
1062
  errorMsg: `Failed to approve ${params.side === "BUY" ? "USDC" : "Conditional Token"}. Please try again.`
977
1063
  };
978
1064
  }
979
- const orderResult = await this.callMCPTool("create_and_post_market_order", {
1065
+ const orderResult = await this.invokeMCPTool("create_and_post_market_order", {
980
1066
  userMarketOrder: {
981
1067
  tokenID: params.tokenId,
982
1068
  side: params.side,
@@ -0,0 +1,2 @@
1
+ export { connectMCPServer, removeConnection, disconnectMCPServer, callMCPTool, getConnectedServers, type MCPClientInstance, type MCPTool, } from './mcp-client';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Lightweight MCP (Model Context Protocol) Client
3
+ *
4
+ * A simplified implementation of MCP for tool calling over HTTP.
5
+ * This replaces the @ai-sdk/mcp dependency with a minimal implementation.
6
+ */
7
+ /**
8
+ * MCP Tool Definition
9
+ */
10
+ export interface MCPTool {
11
+ name: string;
12
+ description?: string;
13
+ inputSchema?: Record<string, any>;
14
+ }
15
+ /**
16
+ * MCP Client Instance
17
+ */
18
+ export interface MCPClientInstance {
19
+ url: string;
20
+ accessToken?: string;
21
+ connectedAt: Date;
22
+ tools: MCPTool[];
23
+ }
24
+ /**
25
+ * MCP Response Content
26
+ */
27
+ interface MCPContent {
28
+ type: string;
29
+ text?: string;
30
+ }
31
+ /**
32
+ * MCP Tool Call Response
33
+ */
34
+ interface MCPToolResponse {
35
+ content?: MCPContent[];
36
+ text?: string;
37
+ result?: any;
38
+ error?: {
39
+ message: string;
40
+ };
41
+ }
42
+ /**
43
+ * Remove a connection from the cache
44
+ */
45
+ export declare const removeConnection: (mcpUrl: string, accessToken?: string) => void;
46
+ /**
47
+ * Connect to an MCP server
48
+ * Connections are cached for reuse
49
+ *
50
+ * @param mcpUrl - MCP server URL
51
+ * @param accessToken - Optional Bearer token for authenticated MCP calls
52
+ */
53
+ export declare const connectMCPServer: (mcpUrl: string, accessToken?: string) => Promise<MCPClientInstance>;
54
+ /**
55
+ * Call an MCP tool
56
+ *
57
+ * @param mcpUrl - MCP server URL
58
+ * @param accessToken - Optional Bearer token
59
+ * @param toolName - Name of the tool to call
60
+ * @param args - Tool arguments
61
+ */
62
+ export declare const callMCPTool: (mcpUrl: string, accessToken: string | undefined, toolName: string, args?: Record<string, any>) => Promise<MCPToolResponse>;
63
+ /**
64
+ * Disconnect from an MCP server
65
+ */
66
+ export declare const disconnectMCPServer: (mcpUrl: string, accessToken?: string) => void;
67
+ /**
68
+ * Get all connected MCP servers
69
+ */
70
+ export declare const getConnectedServers: () => string[];
71
+ export {};
72
+ //# sourceMappingURL=mcp-client.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { OHLCV, TAParams } from "@osiris-ai/technical-indicators";
1
+ import type { OHLCV, TAParams } from "@vesper85/technical-indicators";
2
2
  import type { Event as GammaEvent, Tag, Team, Sport, Series, Comment as GammaComment, SearchResults, PaginatedResponse, MarketFilters, EventFilters, EventPaginationFilters, PaginationParams, SearchParams, GammaMarket } from "polymarket-gamma";
3
3
  import type { ClearinghouseState, SpotMeta, SpotClearinghouseState, SpotMetaAndAssetCtxs, Meta, MetaAndAssetCtxs, UserFunding, UserNonFundingLedgerUpdates, FundingHistory, PredictedFundings, PerpsAtOpenInterestCap, PerpDexLimits, AllMids, UserOpenOrders, FrontendOpenOrders, UserFills, UserRateLimit, OrderStatus, L2Book, CandleSnapshot, HistoricalOrder, TwapSliceFill, SubAccount, VaultDetails, VaultEquity, UserRole, Delegation, DelegatorSummary, DelegatorHistoryEntry, DelegatorReward, ValidatorSummary, VaultSummary, UserFees, PortfolioPeriods, PreTransferCheck, Referral, ExtraAgent, LegalCheck, TwapHistory, MultiSigSigners, BuilderFeeApproval, UserOrderHistory } from "hyperliquid";
4
4
  export interface OsirisState {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesper85/strategy-sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "description": "SDK for writing and running trading strategies with Polymarket and Hyperliquid integrations",
6
6
  "keywords": [
@@ -75,4 +75,4 @@
75
75
  "url": "https://github.com/FetcchX/legion-sdk/issues"
76
76
  },
77
77
  "homepage": "https://github.com/FetcchX/legion-sdk#readme"
78
- }
78
+ }