@catalyst-team/poly-sdk 0.4.3 → 0.4.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/src/clients/bridge-client.d.ts +131 -1
- package/dist/src/clients/bridge-client.d.ts.map +1 -1
- package/dist/src/clients/bridge-client.js +143 -0
- package/dist/src/clients/bridge-client.js.map +1 -1
- package/dist/src/core/order-status.d.ts +159 -0
- package/dist/src/core/order-status.d.ts.map +1 -0
- package/dist/src/core/order-status.js +254 -0
- package/dist/src/core/order-status.js.map +1 -0
- package/dist/src/core/types.d.ts +124 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js +120 -0
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/services/ctf-detector.d.ts +215 -0
- package/dist/src/services/ctf-detector.d.ts.map +1 -0
- package/dist/src/services/ctf-detector.js +420 -0
- package/dist/src/services/ctf-detector.js.map +1 -0
- package/dist/src/services/ctf-manager.d.ts +202 -0
- package/dist/src/services/ctf-manager.d.ts.map +1 -0
- package/dist/src/services/ctf-manager.js +542 -0
- package/dist/src/services/ctf-manager.js.map +1 -0
- package/dist/src/services/order-manager.d.ts +440 -0
- package/dist/src/services/order-manager.d.ts.map +1 -0
- package/dist/src/services/order-manager.js +853 -0
- package/dist/src/services/order-manager.js.map +1 -0
- package/dist/src/services/order-manager.test.d.ts +10 -0
- package/dist/src/services/order-manager.test.d.ts.map +1 -0
- package/dist/src/services/order-manager.test.js +751 -0
- package/dist/src/services/order-manager.test.js.map +1 -0
- package/dist/src/services/trading-service.d.ts +89 -1
- package/dist/src/services/trading-service.d.ts.map +1 -1
- package/dist/src/services/trading-service.js +227 -1
- package/dist/src/services/trading-service.js.map +1 -1
- package/package.json +1 -1
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,sBAAsB;AACtB,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzE,cAAc,iBAAiB,CAAC;AAIhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc;AACd,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAwBtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAOxD,8DAA8D;AAC9D,qEAAqE;AAErE,8CAA8C;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAsB3E,WAAW;AACX,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAkB7D,OAAO,EAAE,aAAa,EAAE,aAAa,IAAI,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGpG,oEAAoE;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AA0BtE,4EAA4E;AAE5E,+EAA+E;AAC/E,qDAAqD;AACrD,+EAA+E;AAE/E,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAuB7B,+EAA+E;AAC/E,2DAA2D;AAC3D,+EAA+E;AAE/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAgB7D,sDAAsD;AACtD,+EAA+E;AAE/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAoB/D,0CAA0C;AAC1C,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAqClD,2FAA2F;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAsBnE,6DAA6D;AAC7D,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mCAAmC,CAAC;AA0C3C,2DAA2D;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAwB9D,wDAAwD;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAQ/D,mDAAmD;AACnD,OAAO,EACL,cAAc,EACd,eAAe,EACf,YAAY;AACZ,wCAAwC;AACxC,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CTF Detector
|
|
3
|
+
*
|
|
4
|
+
* Monitors Conditional Token Framework (CTF) operations:
|
|
5
|
+
* - Split: USDC → YES + NO tokens
|
|
6
|
+
* - Merge: YES + NO tokens → USDC
|
|
7
|
+
* - Redeem: Winning token → USDC (after market resolution)
|
|
8
|
+
*
|
|
9
|
+
* Detection Methods:
|
|
10
|
+
* - WebSocket: ERC1155 Transfer events (primary, low-latency)
|
|
11
|
+
* - Polling: Balance changes (backup, reliable)
|
|
12
|
+
*
|
|
13
|
+
* ERC1155 Transfer Event Patterns:
|
|
14
|
+
* - Split: Transfer(from=0x0, to=user, tokenId=YES/NO, amount)
|
|
15
|
+
* - Merge: Transfer(from=user, to=0x0, tokenId=YES/NO, amount)
|
|
16
|
+
* - Redeem: Transfer(from=user, to=0x0, tokenId=winningToken, amount)
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* ```ts
|
|
20
|
+
* const detector = new CTFDetector({
|
|
21
|
+
* privateKey: '0x...',
|
|
22
|
+
* market: { conditionId, primaryTokenId, secondaryTokenId },
|
|
23
|
+
* mode: 'hybrid',
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* detector.on('split', (operation) => console.log('Split detected:', operation));
|
|
27
|
+
* detector.on('merge', (operation) => console.log('Merge detected:', operation));
|
|
28
|
+
* detector.on('redeem', (operation) => console.log('Redeem detected:', operation));
|
|
29
|
+
*
|
|
30
|
+
* await detector.start();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
import { EventEmitter } from 'events';
|
|
34
|
+
/**
|
|
35
|
+
* Detection mode
|
|
36
|
+
*/
|
|
37
|
+
export type DetectionMode = 'websocket' | 'polling' | 'hybrid';
|
|
38
|
+
/**
|
|
39
|
+
* CTF operation types
|
|
40
|
+
*/
|
|
41
|
+
export type CTFOperationType = 'split' | 'merge' | 'redeem';
|
|
42
|
+
/**
|
|
43
|
+
* CTF operation event base
|
|
44
|
+
*/
|
|
45
|
+
interface CTFOperationBase {
|
|
46
|
+
/** Operation type */
|
|
47
|
+
type: CTFOperationType;
|
|
48
|
+
/** User address */
|
|
49
|
+
userAddress: string;
|
|
50
|
+
/** Market condition ID */
|
|
51
|
+
conditionId: string;
|
|
52
|
+
/** Amount of tokens involved */
|
|
53
|
+
amount: string;
|
|
54
|
+
/** Timestamp */
|
|
55
|
+
timestamp: number;
|
|
56
|
+
/** Transaction hash (if available) */
|
|
57
|
+
transactionHash?: string;
|
|
58
|
+
/** Block number (if available) */
|
|
59
|
+
blockNumber?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Split operation event
|
|
63
|
+
* USDC → YES + NO tokens
|
|
64
|
+
*/
|
|
65
|
+
export interface SplitOperation extends CTFOperationBase {
|
|
66
|
+
type: 'split';
|
|
67
|
+
/** Primary (YES) token ID */
|
|
68
|
+
primaryTokenId: string;
|
|
69
|
+
/** Secondary (NO) token ID */
|
|
70
|
+
secondaryTokenId: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Merge operation event
|
|
74
|
+
* YES + NO tokens → USDC
|
|
75
|
+
*/
|
|
76
|
+
export interface MergeOperation extends CTFOperationBase {
|
|
77
|
+
type: 'merge';
|
|
78
|
+
/** Primary (YES) token ID */
|
|
79
|
+
primaryTokenId: string;
|
|
80
|
+
/** Secondary (NO) token ID */
|
|
81
|
+
secondaryTokenId: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Redeem operation event
|
|
85
|
+
* Winning token → USDC (after market resolution)
|
|
86
|
+
*/
|
|
87
|
+
export interface RedeemOperation extends CTFOperationBase {
|
|
88
|
+
type: 'redeem';
|
|
89
|
+
/** Winning token ID */
|
|
90
|
+
winningTokenId: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* CTF operation union type
|
|
94
|
+
*/
|
|
95
|
+
export type CTFOperation = SplitOperation | MergeOperation | RedeemOperation;
|
|
96
|
+
/**
|
|
97
|
+
* CTF detector configuration
|
|
98
|
+
*/
|
|
99
|
+
export interface CTFDetectorConfig {
|
|
100
|
+
/** Private key for wallet */
|
|
101
|
+
privateKey: string;
|
|
102
|
+
/** Market info (conditionId, token IDs) */
|
|
103
|
+
market: {
|
|
104
|
+
conditionId: string;
|
|
105
|
+
primaryTokenId: string;
|
|
106
|
+
secondaryTokenId: string;
|
|
107
|
+
};
|
|
108
|
+
/** RPC URL for Polygon network (optional) */
|
|
109
|
+
rpcUrl?: string;
|
|
110
|
+
/** Detection mode (default: 'hybrid') */
|
|
111
|
+
mode?: 'websocket' | 'polling' | 'hybrid';
|
|
112
|
+
/** Polling interval in ms (default: 10000) */
|
|
113
|
+
pollInterval?: number;
|
|
114
|
+
/** Polling fallback delay in ms (default: 60000) */
|
|
115
|
+
pollFallbackDelay?: number;
|
|
116
|
+
/** Chain ID (default: 137 Polygon mainnet) */
|
|
117
|
+
chainId?: number;
|
|
118
|
+
/** Enable debug logging (default: false) */
|
|
119
|
+
debug?: boolean;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* CTF Detector
|
|
123
|
+
*
|
|
124
|
+
* Features:
|
|
125
|
+
* - WebSocket for low-latency detection (ERC1155 Transfer events)
|
|
126
|
+
* - Polling for reliability (balance changes)
|
|
127
|
+
* - Deduplication to prevent duplicate events
|
|
128
|
+
* - Hybrid mode for best reliability
|
|
129
|
+
*/
|
|
130
|
+
export declare class CTFDetector extends EventEmitter {
|
|
131
|
+
private config;
|
|
132
|
+
private tradingService;
|
|
133
|
+
private ctfClient;
|
|
134
|
+
private realtimeService;
|
|
135
|
+
private rateLimiter;
|
|
136
|
+
private subscription;
|
|
137
|
+
private pollTimer;
|
|
138
|
+
private fallbackTimer;
|
|
139
|
+
private running;
|
|
140
|
+
private lastBalanceSnapshot;
|
|
141
|
+
private processedOperations;
|
|
142
|
+
private lastWebSocketUpdate;
|
|
143
|
+
private websocketConnected;
|
|
144
|
+
constructor(config: CTFDetectorConfig);
|
|
145
|
+
/**
|
|
146
|
+
* Start CTF operation detection
|
|
147
|
+
*/
|
|
148
|
+
start(): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Stop CTF operation detection
|
|
151
|
+
*/
|
|
152
|
+
stop(): void;
|
|
153
|
+
/**
|
|
154
|
+
* Start WebSocket subscription
|
|
155
|
+
*
|
|
156
|
+
* Note: Currently poly-sdk RealtimeServiceV2 supports user_order and user_trade events.
|
|
157
|
+
* ERC1155 Transfer events would require additional WebSocket channel support.
|
|
158
|
+
* For now, this is a placeholder for future implementation.
|
|
159
|
+
*/
|
|
160
|
+
private startWebSocket;
|
|
161
|
+
/**
|
|
162
|
+
* Wait for WebSocket connection
|
|
163
|
+
*/
|
|
164
|
+
private waitForConnection;
|
|
165
|
+
/**
|
|
166
|
+
* Start polling
|
|
167
|
+
*/
|
|
168
|
+
private startPolling;
|
|
169
|
+
/**
|
|
170
|
+
* Schedule fallback polling
|
|
171
|
+
*
|
|
172
|
+
* In hybrid mode, start polling after a delay if WebSocket hasn't received updates
|
|
173
|
+
*/
|
|
174
|
+
private scheduleFallbackPolling;
|
|
175
|
+
/**
|
|
176
|
+
* Poll for CTF operations by checking balance changes
|
|
177
|
+
*/
|
|
178
|
+
private pollForCTFOperations;
|
|
179
|
+
/**
|
|
180
|
+
* Update balance snapshot
|
|
181
|
+
*/
|
|
182
|
+
private updateBalanceSnapshot;
|
|
183
|
+
/**
|
|
184
|
+
* Detect split operation
|
|
185
|
+
*/
|
|
186
|
+
private detectSplit;
|
|
187
|
+
/**
|
|
188
|
+
* Detect merge operation
|
|
189
|
+
*/
|
|
190
|
+
private detectMerge;
|
|
191
|
+
/**
|
|
192
|
+
* Detect redeem operation
|
|
193
|
+
*/
|
|
194
|
+
private detectRedeem;
|
|
195
|
+
/**
|
|
196
|
+
* Get statistics
|
|
197
|
+
*/
|
|
198
|
+
getStats(): {
|
|
199
|
+
websocketConnected: boolean;
|
|
200
|
+
lastWebSocketUpdate: number;
|
|
201
|
+
lastBalanceCheck: number | null;
|
|
202
|
+
mode: DetectionMode;
|
|
203
|
+
processedOperations: number;
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Log message (if debug enabled)
|
|
207
|
+
*/
|
|
208
|
+
private log;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Factory function to create CTFDetector
|
|
212
|
+
*/
|
|
213
|
+
export declare function createCTFDetector(config: CTFDetectorConfig): CTFDetector;
|
|
214
|
+
export {};
|
|
215
|
+
//# sourceMappingURL=ctf-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ctf-detector.d.ts","sourceRoot":"","sources":["../../../src/services/ctf-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CTF Detector
|
|
3
|
+
*
|
|
4
|
+
* Monitors Conditional Token Framework (CTF) operations:
|
|
5
|
+
* - Split: USDC → YES + NO tokens
|
|
6
|
+
* - Merge: YES + NO tokens → USDC
|
|
7
|
+
* - Redeem: Winning token → USDC (after market resolution)
|
|
8
|
+
*
|
|
9
|
+
* Detection Methods:
|
|
10
|
+
* - WebSocket: ERC1155 Transfer events (primary, low-latency)
|
|
11
|
+
* - Polling: Balance changes (backup, reliable)
|
|
12
|
+
*
|
|
13
|
+
* ERC1155 Transfer Event Patterns:
|
|
14
|
+
* - Split: Transfer(from=0x0, to=user, tokenId=YES/NO, amount)
|
|
15
|
+
* - Merge: Transfer(from=user, to=0x0, tokenId=YES/NO, amount)
|
|
16
|
+
* - Redeem: Transfer(from=user, to=0x0, tokenId=winningToken, amount)
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* ```ts
|
|
20
|
+
* const detector = new CTFDetector({
|
|
21
|
+
* privateKey: '0x...',
|
|
22
|
+
* market: { conditionId, primaryTokenId, secondaryTokenId },
|
|
23
|
+
* mode: 'hybrid',
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* detector.on('split', (operation) => console.log('Split detected:', operation));
|
|
27
|
+
* detector.on('merge', (operation) => console.log('Merge detected:', operation));
|
|
28
|
+
* detector.on('redeem', (operation) => console.log('Redeem detected:', operation));
|
|
29
|
+
*
|
|
30
|
+
* await detector.start();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
import { EventEmitter } from 'events';
|
|
34
|
+
import { TradingService } from './trading-service.js';
|
|
35
|
+
import { RateLimiter } from '../core/rate-limiter.js';
|
|
36
|
+
import { createUnifiedCache } from '../core/unified-cache.js';
|
|
37
|
+
import { RealtimeServiceV2 } from './realtime-service-v2.js';
|
|
38
|
+
import { CTFClient } from '../clients/ctf-client.js';
|
|
39
|
+
/**
|
|
40
|
+
* CTF Detector
|
|
41
|
+
*
|
|
42
|
+
* Features:
|
|
43
|
+
* - WebSocket for low-latency detection (ERC1155 Transfer events)
|
|
44
|
+
* - Polling for reliability (balance changes)
|
|
45
|
+
* - Deduplication to prevent duplicate events
|
|
46
|
+
* - Hybrid mode for best reliability
|
|
47
|
+
*/
|
|
48
|
+
export class CTFDetector extends EventEmitter {
|
|
49
|
+
config;
|
|
50
|
+
tradingService;
|
|
51
|
+
ctfClient;
|
|
52
|
+
realtimeService;
|
|
53
|
+
rateLimiter;
|
|
54
|
+
subscription = null;
|
|
55
|
+
pollTimer = null;
|
|
56
|
+
fallbackTimer = null;
|
|
57
|
+
running = false;
|
|
58
|
+
// Track last balance snapshot for change detection
|
|
59
|
+
lastBalanceSnapshot = null;
|
|
60
|
+
// Track processed operations to avoid duplicates
|
|
61
|
+
processedOperations = new Set();
|
|
62
|
+
// Track last successful WebSocket update
|
|
63
|
+
lastWebSocketUpdate = Date.now();
|
|
64
|
+
// Track if WebSocket is connected
|
|
65
|
+
websocketConnected = false;
|
|
66
|
+
constructor(config) {
|
|
67
|
+
super();
|
|
68
|
+
this.config = {
|
|
69
|
+
mode: config.mode ?? 'hybrid',
|
|
70
|
+
pollInterval: config.pollInterval ?? 10000,
|
|
71
|
+
pollFallbackDelay: config.pollFallbackDelay ?? 60000,
|
|
72
|
+
chainId: config.chainId ?? 137,
|
|
73
|
+
debug: config.debug ?? false,
|
|
74
|
+
rpcUrl: config.rpcUrl ?? 'https://polygon-rpc.com',
|
|
75
|
+
...config,
|
|
76
|
+
};
|
|
77
|
+
this.rateLimiter = new RateLimiter();
|
|
78
|
+
const cache = createUnifiedCache();
|
|
79
|
+
this.tradingService = new TradingService(this.rateLimiter, cache, {
|
|
80
|
+
privateKey: config.privateKey,
|
|
81
|
+
chainId: this.config.chainId,
|
|
82
|
+
});
|
|
83
|
+
// Initialize CTFClient for balance queries
|
|
84
|
+
this.ctfClient = new CTFClient({
|
|
85
|
+
privateKey: config.privateKey,
|
|
86
|
+
chainId: this.config.chainId,
|
|
87
|
+
rpcUrl: config.rpcUrl,
|
|
88
|
+
});
|
|
89
|
+
this.realtimeService = new RealtimeServiceV2({
|
|
90
|
+
autoReconnect: true,
|
|
91
|
+
pingInterval: 5000,
|
|
92
|
+
debug: this.config.debug,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// ============= Lifecycle =============
|
|
96
|
+
/**
|
|
97
|
+
* Start CTF operation detection
|
|
98
|
+
*/
|
|
99
|
+
async start() {
|
|
100
|
+
if (this.running)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
// Initialize trading client
|
|
104
|
+
await this.tradingService.initialize();
|
|
105
|
+
// Get initial balance snapshot
|
|
106
|
+
await this.updateBalanceSnapshot();
|
|
107
|
+
const mode = this.config.mode;
|
|
108
|
+
// Start WebSocket if enabled
|
|
109
|
+
if (mode === 'websocket' || mode === 'hybrid') {
|
|
110
|
+
await this.startWebSocket();
|
|
111
|
+
}
|
|
112
|
+
// Start polling if enabled or as fallback
|
|
113
|
+
if (mode === 'polling') {
|
|
114
|
+
this.startPolling();
|
|
115
|
+
}
|
|
116
|
+
else if (mode === 'hybrid') {
|
|
117
|
+
// In hybrid mode, start polling as backup after fallback delay
|
|
118
|
+
this.scheduleFallbackPolling();
|
|
119
|
+
}
|
|
120
|
+
this.running = true;
|
|
121
|
+
this.log(`Started in ${mode} mode`);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('[CTFDetector] Failed to start:', error);
|
|
125
|
+
this.emit('error', error);
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Stop CTF operation detection
|
|
131
|
+
*/
|
|
132
|
+
stop() {
|
|
133
|
+
// Stop WebSocket
|
|
134
|
+
if (this.subscription) {
|
|
135
|
+
this.subscription.unsubscribe();
|
|
136
|
+
this.subscription = null;
|
|
137
|
+
}
|
|
138
|
+
this.realtimeService.disconnect();
|
|
139
|
+
this.websocketConnected = false;
|
|
140
|
+
// Stop polling
|
|
141
|
+
if (this.pollTimer) {
|
|
142
|
+
clearInterval(this.pollTimer);
|
|
143
|
+
this.pollTimer = null;
|
|
144
|
+
}
|
|
145
|
+
// Stop fallback timer
|
|
146
|
+
if (this.fallbackTimer) {
|
|
147
|
+
clearTimeout(this.fallbackTimer);
|
|
148
|
+
this.fallbackTimer = null;
|
|
149
|
+
}
|
|
150
|
+
this.running = false;
|
|
151
|
+
this.log('Stopped');
|
|
152
|
+
}
|
|
153
|
+
// ============= WebSocket Detection =============
|
|
154
|
+
/**
|
|
155
|
+
* Start WebSocket subscription
|
|
156
|
+
*
|
|
157
|
+
* Note: Currently poly-sdk RealtimeServiceV2 supports user_order and user_trade events.
|
|
158
|
+
* ERC1155 Transfer events would require additional WebSocket channel support.
|
|
159
|
+
* For now, this is a placeholder for future implementation.
|
|
160
|
+
*/
|
|
161
|
+
async startWebSocket() {
|
|
162
|
+
try {
|
|
163
|
+
const credentials = this.tradingService.getCredentials();
|
|
164
|
+
if (!credentials) {
|
|
165
|
+
throw new Error('Failed to get API credentials from TradingService');
|
|
166
|
+
}
|
|
167
|
+
// Connect to WebSocket
|
|
168
|
+
this.realtimeService.connect();
|
|
169
|
+
// Wait for connection
|
|
170
|
+
await this.waitForConnection(10000);
|
|
171
|
+
// TODO: Subscribe to ERC1155 Transfer events
|
|
172
|
+
// Currently RealtimeServiceV2 doesn't have a channel for ERC1155 events
|
|
173
|
+
// This would need to be added to poly-sdk or use alternative WebSocket provider
|
|
174
|
+
this.websocketConnected = true;
|
|
175
|
+
this.lastWebSocketUpdate = Date.now();
|
|
176
|
+
this.log('WebSocket connected (note: ERC1155 events not yet supported)');
|
|
177
|
+
this.emit('connected');
|
|
178
|
+
// If WebSocket doesn't support ERC1155 events, fall back to polling
|
|
179
|
+
if (this.config.mode === 'hybrid' && !this.pollTimer) {
|
|
180
|
+
this.log('Falling back to polling (ERC1155 WebSocket not available)');
|
|
181
|
+
this.startPolling();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.error('[CTFDetector] WebSocket connection failed:', error);
|
|
186
|
+
this.websocketConnected = false;
|
|
187
|
+
// If hybrid mode, fall back to polling immediately
|
|
188
|
+
if (this.config.mode === 'hybrid' && !this.pollTimer) {
|
|
189
|
+
this.log('Falling back to polling due to WebSocket failure');
|
|
190
|
+
this.startPolling();
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Wait for WebSocket connection
|
|
197
|
+
*/
|
|
198
|
+
async waitForConnection(timeout) {
|
|
199
|
+
return new Promise((resolve, reject) => {
|
|
200
|
+
const timer = setTimeout(() => reject(new Error('WebSocket connection timeout')), timeout);
|
|
201
|
+
const onConnected = () => {
|
|
202
|
+
clearTimeout(timer);
|
|
203
|
+
this.realtimeService.off('connected', onConnected);
|
|
204
|
+
this.realtimeService.off('error', onError);
|
|
205
|
+
resolve();
|
|
206
|
+
};
|
|
207
|
+
const onError = (err) => {
|
|
208
|
+
clearTimeout(timer);
|
|
209
|
+
this.realtimeService.off('connected', onConnected);
|
|
210
|
+
this.realtimeService.off('error', onError);
|
|
211
|
+
reject(err);
|
|
212
|
+
};
|
|
213
|
+
this.realtimeService.once('connected', onConnected);
|
|
214
|
+
this.realtimeService.once('error', onError);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// ============= Polling Detection =============
|
|
218
|
+
/**
|
|
219
|
+
* Start polling
|
|
220
|
+
*/
|
|
221
|
+
startPolling() {
|
|
222
|
+
if (this.pollTimer)
|
|
223
|
+
return; // Already polling
|
|
224
|
+
const interval = this.config.pollInterval;
|
|
225
|
+
this.pollTimer = setInterval(() => {
|
|
226
|
+
this.pollForCTFOperations();
|
|
227
|
+
}, interval);
|
|
228
|
+
this.log(`Polling started with ${interval}ms interval`);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Schedule fallback polling
|
|
232
|
+
*
|
|
233
|
+
* In hybrid mode, start polling after a delay if WebSocket hasn't received updates
|
|
234
|
+
*/
|
|
235
|
+
scheduleFallbackPolling() {
|
|
236
|
+
if (this.fallbackTimer)
|
|
237
|
+
return;
|
|
238
|
+
this.fallbackTimer = setTimeout(() => {
|
|
239
|
+
const timeSinceLastUpdate = Date.now() - this.lastWebSocketUpdate;
|
|
240
|
+
const delay = this.config.pollFallbackDelay;
|
|
241
|
+
if (timeSinceLastUpdate > delay && !this.pollTimer) {
|
|
242
|
+
this.log(`No WebSocket updates for ${timeSinceLastUpdate}ms, starting fallback polling`);
|
|
243
|
+
this.startPolling();
|
|
244
|
+
}
|
|
245
|
+
// Reschedule check
|
|
246
|
+
this.fallbackTimer = null;
|
|
247
|
+
this.scheduleFallbackPolling();
|
|
248
|
+
}, this.config.pollFallbackDelay);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Poll for CTF operations by checking balance changes
|
|
252
|
+
*/
|
|
253
|
+
async pollForCTFOperations() {
|
|
254
|
+
if (!this.running) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
const previousSnapshot = this.lastBalanceSnapshot;
|
|
259
|
+
await this.updateBalanceSnapshot();
|
|
260
|
+
const currentSnapshot = this.lastBalanceSnapshot;
|
|
261
|
+
if (!previousSnapshot) {
|
|
262
|
+
// First snapshot, no comparison
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
// Detect balance changes
|
|
266
|
+
const primaryChange = BigInt(currentSnapshot.primary) - BigInt(previousSnapshot.primary);
|
|
267
|
+
const secondaryChange = BigInt(currentSnapshot.secondary) - BigInt(previousSnapshot.secondary);
|
|
268
|
+
// Split: both balances increase
|
|
269
|
+
if (primaryChange > 0 && secondaryChange > 0) {
|
|
270
|
+
await this.detectSplit(primaryChange, currentSnapshot.timestamp);
|
|
271
|
+
}
|
|
272
|
+
// Merge: both balances decrease
|
|
273
|
+
if (primaryChange < 0 && secondaryChange < 0) {
|
|
274
|
+
await this.detectMerge(-primaryChange, currentSnapshot.timestamp);
|
|
275
|
+
}
|
|
276
|
+
// Redeem: one balance decreases, other stays same
|
|
277
|
+
if (primaryChange < 0 && secondaryChange === BigInt(0)) {
|
|
278
|
+
await this.detectRedeem(this.config.market.primaryTokenId, -primaryChange, currentSnapshot.timestamp);
|
|
279
|
+
}
|
|
280
|
+
if (secondaryChange < 0 && primaryChange === BigInt(0)) {
|
|
281
|
+
await this.detectRedeem(this.config.market.secondaryTokenId, -secondaryChange, currentSnapshot.timestamp);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
console.error('[CTFDetector] Polling error:', error);
|
|
286
|
+
this.emit('error', error);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Update balance snapshot
|
|
291
|
+
*/
|
|
292
|
+
async updateBalanceSnapshot() {
|
|
293
|
+
try {
|
|
294
|
+
// Use CTFClient to query ERC-1155 token balances
|
|
295
|
+
const tokenIds = {
|
|
296
|
+
yesTokenId: this.config.market.primaryTokenId,
|
|
297
|
+
noTokenId: this.config.market.secondaryTokenId,
|
|
298
|
+
};
|
|
299
|
+
const balance = await this.ctfClient.getPositionBalanceByTokenIds(this.config.market.conditionId, tokenIds);
|
|
300
|
+
this.lastBalanceSnapshot = {
|
|
301
|
+
primary: balance.yesBalance,
|
|
302
|
+
secondary: balance.noBalance,
|
|
303
|
+
timestamp: Date.now(),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
console.error('[CTFDetector] Failed to update balance snapshot:', error);
|
|
308
|
+
throw error;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// ============= Operation Detection =============
|
|
312
|
+
/**
|
|
313
|
+
* Detect split operation
|
|
314
|
+
*/
|
|
315
|
+
async detectSplit(amount, timestamp) {
|
|
316
|
+
const operationKey = `split-${amount.toString()}-${timestamp}`;
|
|
317
|
+
if (this.processedOperations.has(operationKey)) {
|
|
318
|
+
return; // Already processed
|
|
319
|
+
}
|
|
320
|
+
this.processedOperations.add(operationKey);
|
|
321
|
+
// Cleanup old processed operations (keep last 500)
|
|
322
|
+
if (this.processedOperations.size > 1000) {
|
|
323
|
+
const toKeep = Array.from(this.processedOperations).slice(-500);
|
|
324
|
+
this.processedOperations = new Set(toKeep);
|
|
325
|
+
}
|
|
326
|
+
const address = this.tradingService.getAddress();
|
|
327
|
+
if (!address)
|
|
328
|
+
return;
|
|
329
|
+
const operation = {
|
|
330
|
+
type: 'split',
|
|
331
|
+
userAddress: address,
|
|
332
|
+
conditionId: this.config.market.conditionId,
|
|
333
|
+
primaryTokenId: this.config.market.primaryTokenId,
|
|
334
|
+
secondaryTokenId: this.config.market.secondaryTokenId,
|
|
335
|
+
amount: amount.toString(),
|
|
336
|
+
timestamp,
|
|
337
|
+
};
|
|
338
|
+
this.log(`Split detected: ${amount.toString()} tokens`);
|
|
339
|
+
this.emit('split', operation);
|
|
340
|
+
this.emit('operation', operation);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Detect merge operation
|
|
344
|
+
*/
|
|
345
|
+
async detectMerge(amount, timestamp) {
|
|
346
|
+
const operationKey = `merge-${amount.toString()}-${timestamp}`;
|
|
347
|
+
if (this.processedOperations.has(operationKey)) {
|
|
348
|
+
return; // Already processed
|
|
349
|
+
}
|
|
350
|
+
this.processedOperations.add(operationKey);
|
|
351
|
+
const address = this.tradingService.getAddress();
|
|
352
|
+
if (!address)
|
|
353
|
+
return;
|
|
354
|
+
const operation = {
|
|
355
|
+
type: 'merge',
|
|
356
|
+
userAddress: address,
|
|
357
|
+
conditionId: this.config.market.conditionId,
|
|
358
|
+
primaryTokenId: this.config.market.primaryTokenId,
|
|
359
|
+
secondaryTokenId: this.config.market.secondaryTokenId,
|
|
360
|
+
amount: amount.toString(),
|
|
361
|
+
timestamp,
|
|
362
|
+
};
|
|
363
|
+
this.log(`Merge detected: ${amount.toString()} tokens`);
|
|
364
|
+
this.emit('merge', operation);
|
|
365
|
+
this.emit('operation', operation);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Detect redeem operation
|
|
369
|
+
*/
|
|
370
|
+
async detectRedeem(winningTokenId, amount, timestamp) {
|
|
371
|
+
const operationKey = `redeem-${winningTokenId}-${amount.toString()}-${timestamp}`;
|
|
372
|
+
if (this.processedOperations.has(operationKey)) {
|
|
373
|
+
return; // Already processed
|
|
374
|
+
}
|
|
375
|
+
this.processedOperations.add(operationKey);
|
|
376
|
+
const address = this.tradingService.getAddress();
|
|
377
|
+
if (!address)
|
|
378
|
+
return;
|
|
379
|
+
const operation = {
|
|
380
|
+
type: 'redeem',
|
|
381
|
+
userAddress: address,
|
|
382
|
+
conditionId: this.config.market.conditionId,
|
|
383
|
+
winningTokenId,
|
|
384
|
+
amount: amount.toString(),
|
|
385
|
+
timestamp,
|
|
386
|
+
};
|
|
387
|
+
this.log(`Redeem detected: ${amount.toString()} tokens (${winningTokenId})`);
|
|
388
|
+
this.emit('redeem', operation);
|
|
389
|
+
this.emit('operation', operation);
|
|
390
|
+
}
|
|
391
|
+
// ============= Statistics =============
|
|
392
|
+
/**
|
|
393
|
+
* Get statistics
|
|
394
|
+
*/
|
|
395
|
+
getStats() {
|
|
396
|
+
return {
|
|
397
|
+
websocketConnected: this.websocketConnected,
|
|
398
|
+
lastWebSocketUpdate: this.lastWebSocketUpdate,
|
|
399
|
+
lastBalanceCheck: this.lastBalanceSnapshot?.timestamp ?? null,
|
|
400
|
+
mode: this.config.mode,
|
|
401
|
+
processedOperations: this.processedOperations.size,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
// ============= Helpers =============
|
|
405
|
+
/**
|
|
406
|
+
* Log message (if debug enabled)
|
|
407
|
+
*/
|
|
408
|
+
log(message) {
|
|
409
|
+
if (this.config.debug) {
|
|
410
|
+
console.log(`[CTFDetector] ${message}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Factory function to create CTFDetector
|
|
416
|
+
*/
|
|
417
|
+
export function createCTFDetector(config) {
|
|
418
|
+
return new CTFDetector(config);
|
|
419
|
+
}
|
|
420
|
+
//# sourceMappingURL=ctf-detector.js.map
|