@vesper85/strategy-sdk 0.1.0 → 0.1.2
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 +202 -213
- package/dist/clients/polymarket-client.d.ts +0 -16
- package/dist/engine/event-runner.d.ts +33 -3
- package/dist/engine/polymarket-event-runner.d.ts +202 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +661 -176
- package/dist/types/event-types.d.ts +111 -11
- package/dist/types/osiris.d.ts +2 -39
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ yarn add @osiris-ai/strategy-sdk
|
|
|
24
24
|
|
|
25
25
|
## Quick Start
|
|
26
26
|
|
|
27
|
-
### 1. Create a
|
|
27
|
+
### 1. Create a Tick-Based Strategy
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
30
|
import type { OsirisContext, CodeStrategy } from '@osiris-ai/strategy-sdk';
|
|
@@ -45,41 +45,72 @@ export default class MyStrategy implements CodeStrategy {
|
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
### 2.
|
|
48
|
+
### 2. Create an Event-Based Strategy
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import type {
|
|
52
|
+
CodeStrategy,
|
|
53
|
+
EventSubscription,
|
|
54
|
+
StrategyEvent,
|
|
55
|
+
OsirisContext
|
|
56
|
+
} from '@osiris-ai/strategy-sdk';
|
|
57
|
+
|
|
58
|
+
export class PriceAlertStrategy implements CodeStrategy {
|
|
59
|
+
// Define what events to subscribe to
|
|
60
|
+
subscriptions: EventSubscription[] = [
|
|
61
|
+
{
|
|
62
|
+
type: 'price',
|
|
63
|
+
market: 'BTC-USD',
|
|
64
|
+
conditions: { priceChangePercent: 5 }
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
// Called when subscribed events occur
|
|
69
|
+
async onEvent(event: StrategyEvent, osiris: OsirisContext): Promise<void> {
|
|
70
|
+
osiris.log(`Price event for ${event.market}: ${event.data.price}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3. Run the Strategy
|
|
49
76
|
|
|
50
77
|
```typescript
|
|
51
78
|
import {
|
|
52
79
|
createOsirisContext,
|
|
53
80
|
createConsoleLogger,
|
|
54
|
-
|
|
81
|
+
createStrategyEngine,
|
|
82
|
+
createEventRunner,
|
|
55
83
|
PrivateKeySigner,
|
|
56
84
|
} from '@osiris-ai/strategy-sdk';
|
|
57
|
-
import MyStrategy from './my-strategy';
|
|
58
85
|
|
|
59
86
|
async function main() {
|
|
60
87
|
const logger = createConsoleLogger();
|
|
61
88
|
|
|
62
|
-
// Create signer
|
|
63
89
|
const signer = new PrivateKeySigner({
|
|
64
90
|
privateKey: process.env.PRIVATE_KEY!,
|
|
65
91
|
});
|
|
66
92
|
|
|
67
|
-
// Create context
|
|
68
93
|
const context = createOsirisContext({
|
|
69
94
|
strategyId: 'my-strategy',
|
|
70
|
-
market: 'hyperliquid',
|
|
95
|
+
market: 'hyperliquid',
|
|
71
96
|
userAddress: signer.getAddress()!,
|
|
72
97
|
signer,
|
|
73
98
|
});
|
|
74
99
|
|
|
75
|
-
//
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
// For tick-based strategies
|
|
101
|
+
const engine = createStrategyEngine(strategy, {
|
|
102
|
+
logger,
|
|
103
|
+
tickIntervalMs: 60000,
|
|
104
|
+
}, context);
|
|
105
|
+
engine.start();
|
|
106
|
+
|
|
107
|
+
// For event-based strategies
|
|
108
|
+
const runner = createEventRunner(strategy, {
|
|
109
|
+
logger,
|
|
110
|
+
eventSourceUrl: 'wss://events.example.com/ws',
|
|
111
|
+
}, context);
|
|
112
|
+
runner.start();
|
|
80
113
|
}
|
|
81
|
-
|
|
82
|
-
main();
|
|
83
114
|
```
|
|
84
115
|
|
|
85
116
|
## Execution Modes
|
|
@@ -102,7 +133,7 @@ import { createStrategyEngine } from '@osiris-ai/strategy-sdk';
|
|
|
102
133
|
|
|
103
134
|
const engine = createStrategyEngine(strategy, {
|
|
104
135
|
logger,
|
|
105
|
-
strategyId: 'my-strategy',
|
|
136
|
+
strategyId: 'my-strategy',
|
|
106
137
|
tickIntervalMs: 60000, // Run every 60 seconds
|
|
107
138
|
}, context);
|
|
108
139
|
|
|
@@ -112,7 +143,7 @@ engine.start();
|
|
|
112
143
|
|
|
113
144
|
### Event-Based Execution (Real-time WebSocket)
|
|
114
145
|
|
|
115
|
-
Reacts to real-time events from
|
|
146
|
+
Reacts to real-time events from WebSocket streams. Best for strategies that need immediate response to market changes.
|
|
116
147
|
|
|
117
148
|
```typescript
|
|
118
149
|
interface CodeStrategy {
|
|
@@ -121,55 +152,121 @@ interface CodeStrategy {
|
|
|
121
152
|
}
|
|
122
153
|
```
|
|
123
154
|
|
|
155
|
+
## Event Subscription Types
|
|
156
|
+
|
|
157
|
+
The SDK uses a discriminated union for type-safe event subscriptions:
|
|
158
|
+
|
|
159
|
+
### MarketSubscription
|
|
160
|
+
|
|
161
|
+
Subscribe to market events (price, orderbook, trade, fill):
|
|
162
|
+
|
|
124
163
|
```typescript
|
|
125
|
-
|
|
164
|
+
{
|
|
165
|
+
type: 'price', // or 'orderbook', 'trade', 'fill'
|
|
166
|
+
market: 'BTC-USD',
|
|
167
|
+
eventSource: 'polymarket', // optional
|
|
168
|
+
conditions: {
|
|
169
|
+
priceChangePercent: 5,
|
|
170
|
+
volumeAbove: 10000,
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
126
174
|
|
|
127
|
-
|
|
128
|
-
subscriptions: EventSubscription[] = [
|
|
129
|
-
{
|
|
130
|
-
type: 'price',
|
|
131
|
-
market: 'BTC-USD',
|
|
132
|
-
conditions: { priceChangePercent: 5 }
|
|
133
|
-
}
|
|
134
|
-
];
|
|
175
|
+
### WalletSubscription
|
|
135
176
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
177
|
+
Subscribe to wallet analysis events (Osiris Pub/Sub only):
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
{
|
|
181
|
+
type: 'wallet',
|
|
182
|
+
wallet: '0x1234567890abcdef...',
|
|
183
|
+
conditions: {
|
|
184
|
+
minWinRate: 60,
|
|
185
|
+
minTradeCount: 10,
|
|
139
186
|
}
|
|
140
187
|
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### OpportunitySubscription
|
|
191
|
+
|
|
192
|
+
Subscribe to trading opportunities (Osiris Pub/Sub only):
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
{
|
|
196
|
+
type: 'opportunity',
|
|
197
|
+
filter: 'wide_spread_markets', // optional, defaults to 'all'
|
|
198
|
+
conditions: {
|
|
199
|
+
minScore: 70,
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### CustomSubscription
|
|
141
205
|
|
|
206
|
+
Subscribe to custom topics:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
{
|
|
210
|
+
type: 'custom',
|
|
211
|
+
topic: 'custom:my-topic',
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Event Sources
|
|
216
|
+
|
|
217
|
+
### Osiris Pub/Sub
|
|
218
|
+
|
|
219
|
+
Connect to Osiris analytics WebSocket for market analysis, wallet tracking, and opportunities:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
142
222
|
const runner = createEventRunner(strategy, {
|
|
143
223
|
logger,
|
|
144
|
-
eventSourceUrl: 'wss://your-
|
|
145
|
-
strategyId: 'price-alert', // Optional
|
|
224
|
+
eventSourceUrl: 'wss://your-osiris-server.com/ws',
|
|
146
225
|
}, context);
|
|
147
|
-
|
|
148
|
-
runner.start();
|
|
149
|
-
// runner.stop();
|
|
150
226
|
```
|
|
151
227
|
|
|
152
|
-
|
|
228
|
+
**Supported topics:**
|
|
229
|
+
- `market:{slug}` - Market analysis events
|
|
230
|
+
- `wallet:{address}` - Wallet analysis events
|
|
231
|
+
- `opps:{filter}` - Trading opportunities
|
|
232
|
+
|
|
233
|
+
### Polymarket RTDS
|
|
234
|
+
|
|
235
|
+
Connect directly to Polymarket's Real-Time Data Socket:
|
|
153
236
|
|
|
154
237
|
```typescript
|
|
155
|
-
|
|
238
|
+
// Set eventSource: 'polymarket' in subscriptions
|
|
239
|
+
subscriptions: EventSubscription[] = [
|
|
240
|
+
{
|
|
241
|
+
type: 'price',
|
|
242
|
+
eventSource: 'polymarket',
|
|
243
|
+
market: 'ETH',
|
|
244
|
+
}
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
const runner = createEventRunner(strategy, {
|
|
248
|
+
logger,
|
|
249
|
+
polymarket: {
|
|
250
|
+
walletAddress: '0x...',
|
|
251
|
+
// clobAuth: { ... } for private subscriptions
|
|
252
|
+
},
|
|
253
|
+
}, context);
|
|
156
254
|
```
|
|
157
255
|
|
|
158
|
-
|
|
256
|
+
## Type Guards
|
|
257
|
+
|
|
258
|
+
Use type guards for runtime type checking:
|
|
159
259
|
|
|
160
260
|
```typescript
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
cron?: string;
|
|
171
|
-
interval?: number;
|
|
172
|
-
};
|
|
261
|
+
import {
|
|
262
|
+
isMarketSubscription,
|
|
263
|
+
isWalletSubscription,
|
|
264
|
+
isOpportunitySubscription,
|
|
265
|
+
isCustomSubscription
|
|
266
|
+
} from '@osiris-ai/strategy-sdk';
|
|
267
|
+
|
|
268
|
+
if (isWalletSubscription(subscription)) {
|
|
269
|
+
console.log(subscription.wallet); // TypeScript knows this is WalletSubscription
|
|
173
270
|
}
|
|
174
271
|
```
|
|
175
272
|
|
|
@@ -179,20 +276,34 @@ interface EventSubscription {
|
|
|
179
276
|
|
|
180
277
|
#### `CodeStrategy`
|
|
181
278
|
|
|
182
|
-
Interface that all strategies must implement
|
|
279
|
+
Interface that all strategies must implement:
|
|
183
280
|
|
|
184
281
|
```typescript
|
|
185
282
|
interface CodeStrategy {
|
|
186
|
-
// Tick-based
|
|
283
|
+
// Tick-based execution
|
|
187
284
|
shouldTrigger?(osiris: OsirisContext): Promise<boolean>;
|
|
188
285
|
onTrigger?(osiris: OsirisContext): Promise<void>;
|
|
189
|
-
|
|
190
|
-
// Event-based
|
|
286
|
+
|
|
287
|
+
// Event-based execution
|
|
191
288
|
subscriptions?: EventSubscription[];
|
|
192
289
|
onEvent?(event: StrategyEvent, osiris: OsirisContext): Promise<void>;
|
|
193
290
|
}
|
|
194
291
|
```
|
|
195
292
|
|
|
293
|
+
#### `StrategyEvent`
|
|
294
|
+
|
|
295
|
+
Event passed to `onEvent` handler:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
interface StrategyEvent {
|
|
299
|
+
type: EventType;
|
|
300
|
+
timestamp: number;
|
|
301
|
+
market?: string; // For market events
|
|
302
|
+
wallet?: string; // For wallet events
|
|
303
|
+
data: EventData;
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
196
307
|
#### `OsirisContext`
|
|
197
308
|
|
|
198
309
|
The context object passed to your strategy methods:
|
|
@@ -203,21 +314,19 @@ interface OsirisContext {
|
|
|
203
314
|
hyperliquid?: HyperliquidAPI; // Available when market='hyperliquid'
|
|
204
315
|
ta: TechnicalAnalysisAPI; // Technical analysis functions
|
|
205
316
|
state: OsirisState; // State management
|
|
206
|
-
signer
|
|
207
|
-
log: (message: string, meta?: any) => void;
|
|
317
|
+
signer?: SignerAPI; // Transaction signer (if configured)
|
|
318
|
+
log: (message: string, meta?: any) => void;
|
|
208
319
|
}
|
|
209
320
|
```
|
|
210
321
|
|
|
211
322
|
### State Management
|
|
212
323
|
|
|
213
|
-
#### In
|
|
324
|
+
#### In-Memory State (for testing)
|
|
214
325
|
|
|
215
326
|
```typescript
|
|
216
|
-
|
|
217
|
-
const value = await osiris.state.get('myKey');
|
|
327
|
+
import { MemoryStateManager } from '@osiris-ai/strategy-sdk';
|
|
218
328
|
|
|
219
|
-
|
|
220
|
-
await osiris.state.set('myKey', { count: 42 });
|
|
329
|
+
const stateManager = new MemoryStateManager();
|
|
221
330
|
```
|
|
222
331
|
|
|
223
332
|
#### Redis State (for production)
|
|
@@ -232,83 +341,35 @@ const stateManager = new RedisStateManager(
|
|
|
232
341
|
);
|
|
233
342
|
|
|
234
343
|
await stateManager.connect();
|
|
235
|
-
// ... use stateManager
|
|
236
|
-
await stateManager.disconnect();
|
|
237
344
|
```
|
|
238
345
|
|
|
239
346
|
### Market APIs
|
|
240
347
|
|
|
241
|
-
####
|
|
242
|
-
|
|
243
|
-
```typescript
|
|
244
|
-
if (osiris.polymarket) {
|
|
245
|
-
// Initialize trading client (required before trading)
|
|
246
|
-
await osiris.polymarket.initializeTradingClient();
|
|
247
|
-
|
|
248
|
-
// ============================================
|
|
249
|
-
// Convenience Trading Methods (Recommended)
|
|
250
|
-
// ============================================
|
|
251
|
-
|
|
252
|
-
// Limit orders
|
|
253
|
-
await osiris.polymarket.buyLimit(tokenId, 0.65, 100); // Buy 100 shares @ $0.65
|
|
254
|
-
await osiris.polymarket.sellLimit(tokenId, 0.70, 50); // Sell 50 shares @ $0.70
|
|
255
|
-
|
|
256
|
-
// Market orders (execute immediately)
|
|
257
|
-
await osiris.polymarket.buyMarket(tokenId, 100); // Buy $100 worth
|
|
258
|
-
await osiris.polymarket.sellMarket(tokenId, 50); // Sell 50 shares
|
|
259
|
-
|
|
260
|
-
// ============================================
|
|
261
|
-
// Full Order Methods (More control)
|
|
262
|
-
// ============================================
|
|
263
|
-
|
|
264
|
-
await osiris.polymarket.createLimitOrder({
|
|
265
|
-
tokenId: '0x...',
|
|
266
|
-
price: 0.65,
|
|
267
|
-
size: 100,
|
|
268
|
-
side: 'BUY',
|
|
269
|
-
feeRateBps: '0',
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
await osiris.polymarket.createMarketOrder({
|
|
273
|
-
tokenId: '0x...',
|
|
274
|
-
amount: 100,
|
|
275
|
-
side: 'BUY',
|
|
276
|
-
slippageTolerance: 0.05,
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// Order management
|
|
280
|
-
const orders = await osiris.polymarket.getOpenOrders();
|
|
281
|
-
await osiris.polymarket.cancelOrder(orderId);
|
|
282
|
-
await osiris.polymarket.cancelAllOrders();
|
|
283
|
-
|
|
284
|
-
// Market data
|
|
285
|
-
const market = await osiris.polymarket.getMarket('market-slug');
|
|
286
|
-
const markets = await osiris.polymarket.getMarkets({ active: true, limit: 50 });
|
|
287
|
-
const orderBook = await osiris.polymarket.getOrderBook(tokenId);
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
#### Hyperliquid Trading
|
|
348
|
+
#### Hyperliquid API
|
|
292
349
|
|
|
293
350
|
```typescript
|
|
294
351
|
if (osiris.hyperliquid) {
|
|
295
|
-
// Get price
|
|
296
352
|
const price = await osiris.hyperliquid.getPrice('BTC');
|
|
297
|
-
|
|
298
|
-
// Get position
|
|
299
353
|
const position = await osiris.hyperliquid.getPosition('BTC');
|
|
300
|
-
|
|
301
|
-
// Get all positions
|
|
302
354
|
const positions = await osiris.hyperliquid.getPositions();
|
|
355
|
+
}
|
|
356
|
+
```
|
|
303
357
|
|
|
304
|
-
|
|
305
|
-
const candles = await osiris.hyperliquid.getCandleSnapshot(
|
|
306
|
-
'BTC', '1d', startTime, endTime
|
|
307
|
-
);
|
|
358
|
+
#### Polymarket API
|
|
308
359
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
await osiris.
|
|
360
|
+
```typescript
|
|
361
|
+
if (osiris.polymarket) {
|
|
362
|
+
const market = await osiris.polymarket.getMarket('market-slug');
|
|
363
|
+
const markets = await osiris.polymarket.getMarkets({ active: true });
|
|
364
|
+
|
|
365
|
+
// Trading (requires initialization)
|
|
366
|
+
await osiris.polymarket.initializeTradingClient();
|
|
367
|
+
await osiris.polymarket.createLimitOrder({
|
|
368
|
+
tokenId: 'token-id',
|
|
369
|
+
side: 'BUY',
|
|
370
|
+
price: 0.5,
|
|
371
|
+
size: 10,
|
|
372
|
+
});
|
|
312
373
|
}
|
|
313
374
|
```
|
|
314
375
|
|
|
@@ -318,18 +379,13 @@ if (osiris.hyperliquid) {
|
|
|
318
379
|
// Calculate RSI
|
|
319
380
|
const rsi = osiris.ta.calculate('rsi_14', ohlcvData, { period: 14 });
|
|
320
381
|
|
|
321
|
-
// Calculate MACD
|
|
382
|
+
// Calculate MACD
|
|
322
383
|
const macd = osiris.ta.calculate('macd_12_26_9', ohlcvData, {
|
|
323
384
|
fastPeriod: 12,
|
|
324
385
|
slowPeriod: 26,
|
|
325
386
|
signalPeriod: 9
|
|
326
387
|
});
|
|
327
388
|
|
|
328
|
-
// Get specific component from multi-value indicator
|
|
329
|
-
const macdSignal = osiris.ta.calculate('macd_12_26_9', ohlcvData, {
|
|
330
|
-
component: 'signal'
|
|
331
|
-
});
|
|
332
|
-
|
|
333
389
|
// Available indicators:
|
|
334
390
|
// Single-value: rsi, sma, ema, atr, adx, obv, cci, mfi, vwap, williams_r, roc, psar, wma
|
|
335
391
|
// Multi-value: macd, bollinger_bands, stochastic, stochastic_rsi, keltner_channels
|
|
@@ -337,111 +393,44 @@ const macdSignal = osiris.ta.calculate('macd_12_26_9', ohlcvData, {
|
|
|
337
393
|
|
|
338
394
|
### Signing Transactions
|
|
339
395
|
|
|
340
|
-
#### Using Private Key Signer
|
|
341
|
-
|
|
342
396
|
```typescript
|
|
343
|
-
import { PrivateKeySigner,
|
|
397
|
+
import { PrivateKeySigner, OsirisSigner } from '@osiris-ai/strategy-sdk';
|
|
344
398
|
|
|
399
|
+
// Private key signer
|
|
345
400
|
const signer = new PrivateKeySigner({
|
|
346
401
|
privateKey: process.env.PRIVATE_KEY!,
|
|
347
402
|
});
|
|
348
403
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const context = createOsirisContext({
|
|
352
|
-
strategyId: 'my-strategy',
|
|
353
|
-
market: 'polymarket',
|
|
354
|
-
userAddress: address!,
|
|
355
|
-
signer,
|
|
356
|
-
});
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
#### Using Osiris Hub Signer
|
|
360
|
-
|
|
361
|
-
```typescript
|
|
362
|
-
import { OsirisSigner, createOsirisContext } from '@osiris-ai/strategy-sdk';
|
|
363
|
-
|
|
364
|
-
const signer = new OsirisSigner({
|
|
404
|
+
// Osiris Hub signer (for managed wallets)
|
|
405
|
+
const osirisSigner = new OsirisSigner({
|
|
365
406
|
hubBaseUrl: 'https://api.osirislabs.xyz/v1',
|
|
366
|
-
accessToken:
|
|
367
|
-
connectionId:
|
|
407
|
+
accessToken: 'your-oauth-token',
|
|
408
|
+
connectionId: 'wallet-connection-id',
|
|
368
409
|
});
|
|
369
410
|
|
|
411
|
+
// Use in context
|
|
370
412
|
const context = createOsirisContext({
|
|
371
413
|
strategyId: 'my-strategy',
|
|
372
414
|
market: 'polymarket',
|
|
373
|
-
userAddress:
|
|
415
|
+
userAddress: signer.getAddress()!,
|
|
374
416
|
signer,
|
|
375
|
-
polymarketOptions: {
|
|
376
|
-
useMcpForOrders: true,
|
|
377
|
-
mcpUrl: 'https://gateway.backend.osirislabs.xyz/@osiris/polymarket/mcp',
|
|
378
|
-
mcpAccessToken: process.env.MCP_ACCESS_TOKEN!,
|
|
379
|
-
},
|
|
380
417
|
});
|
|
381
418
|
```
|
|
382
419
|
|
|
383
|
-
### Logging
|
|
384
|
-
|
|
385
|
-
```typescript
|
|
386
|
-
import { createConsoleLogger } from '@osiris-ai/strategy-sdk';
|
|
387
|
-
|
|
388
|
-
const logger = createConsoleLogger();
|
|
389
|
-
```
|
|
390
|
-
|
|
391
420
|
## Examples
|
|
392
421
|
|
|
393
|
-
See the `examples/` directory:
|
|
394
|
-
|
|
395
|
-
- `example-rsi.ts` - RSI-based trading strategy (tick-based)
|
|
396
|
-
- `example-polymarket.ts` - Polymarket arbitrage strategy (tick-based)
|
|
397
|
-
- `example-event-strategy.ts` - Price alert strategy (event-based)
|
|
398
|
-
- `example-usage.ts` - Complete usage examples
|
|
399
|
-
- `example-signer.ts` - Signer usage examples
|
|
400
|
-
|
|
401
|
-
## Strategy Patterns
|
|
402
|
-
|
|
403
|
-
### Tick-Based Strategy Pattern
|
|
404
|
-
|
|
405
|
-
```typescript
|
|
406
|
-
class MyTickStrategy implements CodeStrategy {
|
|
407
|
-
async shouldTrigger(osiris: OsirisContext): Promise<boolean> {
|
|
408
|
-
// Called every tick - return true to execute
|
|
409
|
-
return true;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
async onTrigger(osiris: OsirisContext): Promise<void> {
|
|
413
|
-
// Your trading logic
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
### Event-Based Strategy Pattern
|
|
419
|
-
|
|
420
|
-
```typescript
|
|
421
|
-
class MyEventStrategy implements CodeStrategy {
|
|
422
|
-
subscriptions: EventSubscription[] = [
|
|
423
|
-
{ type: 'price', market: 'BTC-USD', conditions: { priceChangePercent: 5 } }
|
|
424
|
-
];
|
|
422
|
+
See the `examples/` directory for complete working examples:
|
|
425
423
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
osiris.log(`Event: ${event.type} - ${JSON.stringify(event.data)}`);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
```
|
|
424
|
+
- `example-event-strategy.ts` - Event-based price alert strategy
|
|
425
|
+
- `example-polymarket-events.ts` - Polymarket RTDS integration
|
|
432
426
|
|
|
433
427
|
## Best Practices
|
|
434
428
|
|
|
435
|
-
1. **
|
|
436
|
-
2. **
|
|
437
|
-
3. **
|
|
438
|
-
4. **
|
|
439
|
-
5. **
|
|
440
|
-
6. **Execution Mode**: Choose tick-based for polling, event-based for real-time reactions
|
|
441
|
-
|
|
442
|
-
## TypeScript Support
|
|
443
|
-
|
|
444
|
-
The SDK is written in TypeScript and provides full type definitions. All types are exported.
|
|
429
|
+
1. **Choose the right execution mode**: Use tick-based for periodic checks, event-based for real-time reactions
|
|
430
|
+
2. **State Management**: Use `osiris.state` for persistent data that should survive restarts
|
|
431
|
+
3. **Error Handling**: Always wrap API calls in try-catch blocks
|
|
432
|
+
4. **Rate Limiting**: Be mindful of API rate limits when making frequent calls
|
|
433
|
+
5. **Testing**: Use `MemoryStateManager` for testing, `RedisStateManager` for production
|
|
445
434
|
|
|
446
435
|
## License
|
|
447
436
|
|
|
@@ -87,22 +87,6 @@ export declare class PolymarketClient implements PolymarketAPI {
|
|
|
87
87
|
private ensureApprovals;
|
|
88
88
|
buy(tokenId: string, size: number): Promise<void>;
|
|
89
89
|
sell(tokenId: string, size: number): Promise<void>;
|
|
90
|
-
/**
|
|
91
|
-
* Place a limit buy order
|
|
92
|
-
*/
|
|
93
|
-
buyLimit(tokenId: string, price: number, size: number): Promise<PolymarketOrderResponse>;
|
|
94
|
-
/**
|
|
95
|
-
* Place a limit sell order
|
|
96
|
-
*/
|
|
97
|
-
sellLimit(tokenId: string, price: number, size: number): Promise<PolymarketOrderResponse>;
|
|
98
|
-
/**
|
|
99
|
-
* Place a market buy order
|
|
100
|
-
*/
|
|
101
|
-
buyMarket(tokenId: string, amount: number, slippage?: number): Promise<PolymarketOrderResponse>;
|
|
102
|
-
/**
|
|
103
|
-
* Place a market sell order
|
|
104
|
-
*/
|
|
105
|
-
sellMarket(tokenId: string, size: number, slippage?: number): Promise<PolymarketOrderResponse>;
|
|
106
90
|
getPrice(ticker: string): Promise<number>;
|
|
107
91
|
getIndicator(ticker: string, indicator: string, params?: any): Promise<number>;
|
|
108
92
|
search(params: SearchParams): Promise<SearchResults>;
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import type { CodeStrategy } from "../types/strategy";
|
|
2
2
|
import type { OsirisContext } from "../types/osiris";
|
|
3
3
|
import type { Logger } from "../utils/logger";
|
|
4
|
+
import { PolymarketEventRunner, type PolymarketClobAuth } from "./polymarket-event-runner";
|
|
5
|
+
export type EventRunner = OsirisEventRunner | PolymarketEventRunner;
|
|
4
6
|
/**
|
|
5
7
|
* Configuration for the EventRunner
|
|
6
8
|
*/
|
|
7
9
|
export interface EventRunnerConfig {
|
|
8
10
|
/** Logger instance for logging */
|
|
9
11
|
logger: Logger;
|
|
10
|
-
/** WebSocket URL for the event source server */
|
|
11
|
-
eventSourceUrl
|
|
12
|
+
/** WebSocket URL for the event source server (Required for 'osiris' source) */
|
|
13
|
+
eventSourceUrl?: string;
|
|
12
14
|
/** Optional strategy ID for logging (defaults to 'unnamed-strategy') */
|
|
13
15
|
strategyId?: string;
|
|
16
|
+
/** Polymarket specific configuration */
|
|
17
|
+
polymarket?: {
|
|
18
|
+
clobAuth?: PolymarketClobAuth;
|
|
19
|
+
walletAddress?: string;
|
|
20
|
+
pingIntervalMs?: number;
|
|
21
|
+
};
|
|
14
22
|
/** Reconnection settings */
|
|
15
23
|
reconnect?: {
|
|
16
24
|
/** Maximum number of reconnection attempts (default: 10) */
|
|
@@ -41,7 +49,12 @@ export interface EventRunnerConfig {
|
|
|
41
49
|
* runner.stop();
|
|
42
50
|
* ```
|
|
43
51
|
*/
|
|
44
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Osiris Event Runner (Generic)
|
|
54
|
+
*
|
|
55
|
+
* Connects to a generic Osiris WebSocket event source.
|
|
56
|
+
*/
|
|
57
|
+
export declare class OsirisEventRunner {
|
|
45
58
|
private strategy;
|
|
46
59
|
private config;
|
|
47
60
|
private context;
|
|
@@ -87,7 +100,19 @@ export declare class EventRunner {
|
|
|
87
100
|
/**
|
|
88
101
|
* Subscribe to events based on strategy's subscriptions
|
|
89
102
|
*/
|
|
103
|
+
/**
|
|
104
|
+
* Subscribe to events based on strategy's subscriptions
|
|
105
|
+
* Maps SDK subscriptions to Osiris Pub/Sub protocol
|
|
106
|
+
*/
|
|
90
107
|
private subscribeToEvents;
|
|
108
|
+
/**
|
|
109
|
+
* Map EventSubscription to Osiris Pub/Sub topic string
|
|
110
|
+
* Uses discriminated union to properly handle each subscription type
|
|
111
|
+
*/
|
|
112
|
+
private mapSubscriptionToTopic;
|
|
113
|
+
/**
|
|
114
|
+
* Unsubscribe from events before disconnecting
|
|
115
|
+
*/
|
|
91
116
|
/**
|
|
92
117
|
* Unsubscribe from events before disconnecting
|
|
93
118
|
*/
|
|
@@ -96,6 +121,11 @@ export declare class EventRunner {
|
|
|
96
121
|
* Handle incoming WebSocket messages
|
|
97
122
|
*/
|
|
98
123
|
private handleMessage;
|
|
124
|
+
/**
|
|
125
|
+
* Map incoming Osiris message to StrategyEvent
|
|
126
|
+
* Uses proper fields for each event type (market vs wallet)
|
|
127
|
+
*/
|
|
128
|
+
private mapMessageToStrategyEvent;
|
|
99
129
|
/**
|
|
100
130
|
* Validate that a message is a valid StrategyEvent
|
|
101
131
|
*/
|