@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
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CTFManager - Unified CTF Operations and Event Monitoring
|
|
3
|
+
*
|
|
4
|
+
* Core Design Philosophy:
|
|
5
|
+
* - Unifies CTF operations (split/merge/redeem) + real-time event monitoring
|
|
6
|
+
* - Monitors on-chain ERC1155 Transfer events (not polling!)
|
|
7
|
+
* - Provides complete operation lifecycle tracking
|
|
8
|
+
* - Auto-validates operations before submission
|
|
9
|
+
*
|
|
10
|
+
* Architecture (similar to OrderManager):
|
|
11
|
+
* ```
|
|
12
|
+
* CTFManager
|
|
13
|
+
* ├── CTFClient (execute operations)
|
|
14
|
+
* ├── ethers.Contract (listen to ERC1155 events)
|
|
15
|
+
* └── Event Emitter (operation_detected, transaction_confirmed)
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const ctfMgr = new CTFManager({
|
|
21
|
+
* privateKey: '0x...',
|
|
22
|
+
* conditionId: '0x...',
|
|
23
|
+
* primaryTokenId: '123...',
|
|
24
|
+
* secondaryTokenId: '456...',
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* await ctfMgr.start();
|
|
28
|
+
*
|
|
29
|
+
* // Listen to real-time CTF events
|
|
30
|
+
* ctfMgr.on('split_detected', (event) => {
|
|
31
|
+
* console.log(`Split: ${event.amount} USDC → tokens`);
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* ctfMgr.on('merge_detected', (event) => {
|
|
35
|
+
* console.log(`Merge: ${event.amount} tokens → USDC`);
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* ctfMgr.on('redeem_detected', (event) => {
|
|
39
|
+
* console.log(`Redeem: ${event.amount} winning tokens`);
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Execute operations (automatically tracked)
|
|
43
|
+
* await ctfMgr.split('100');
|
|
44
|
+
* await ctfMgr.merge('50');
|
|
45
|
+
* await ctfMgr.redeem();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
import { EventEmitter } from 'events';
|
|
49
|
+
import { ethers, Contract } from 'ethers';
|
|
50
|
+
import { CTFClient, CTF_CONTRACT } from '../clients/ctf-client.js';
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// CTFManager Implementation
|
|
53
|
+
// ============================================================================
|
|
54
|
+
export class CTFManager extends EventEmitter {
|
|
55
|
+
// ========== Dependencies ==========
|
|
56
|
+
ctfClient;
|
|
57
|
+
provider;
|
|
58
|
+
ctfContract;
|
|
59
|
+
// ========== Configuration ==========
|
|
60
|
+
config;
|
|
61
|
+
initialized = false;
|
|
62
|
+
userAddress;
|
|
63
|
+
// ========== Event Tracking ==========
|
|
64
|
+
processedEvents = new Set();
|
|
65
|
+
constructor(config) {
|
|
66
|
+
super();
|
|
67
|
+
this.config = {
|
|
68
|
+
rpcUrl: config.rpcUrl ?? 'https://polygon-rpc.com',
|
|
69
|
+
chainId: config.chainId ?? 137,
|
|
70
|
+
debug: config.debug ?? false,
|
|
71
|
+
...config,
|
|
72
|
+
};
|
|
73
|
+
// Initialize CTFClient for operations
|
|
74
|
+
this.ctfClient = new CTFClient({
|
|
75
|
+
privateKey: config.privateKey,
|
|
76
|
+
rpcUrl: this.config.rpcUrl,
|
|
77
|
+
chainId: this.config.chainId,
|
|
78
|
+
});
|
|
79
|
+
// Initialize provider for event listening
|
|
80
|
+
this.provider = new ethers.providers.JsonRpcProvider(this.config.rpcUrl);
|
|
81
|
+
// Get user address from private key
|
|
82
|
+
const wallet = new ethers.Wallet(config.privateKey);
|
|
83
|
+
this.userAddress = wallet.address;
|
|
84
|
+
// Initialize CTF contract for event listening
|
|
85
|
+
const CTF_ABI = [
|
|
86
|
+
// ERC-1155 standard events
|
|
87
|
+
'event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value)',
|
|
88
|
+
'event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values)',
|
|
89
|
+
// CTF-specific events (faster and more reliable detection)
|
|
90
|
+
'event PositionSplit(address indexed stakeholder, address indexed collateralToken, bytes32 indexed parentCollectionId, bytes32 conditionId, uint256[] partition, uint256 amount)',
|
|
91
|
+
'event PositionsMerge(address indexed stakeholder, address indexed collateralToken, bytes32 indexed parentCollectionId, bytes32 conditionId, uint256[] partition, uint256 amount)',
|
|
92
|
+
'event PayoutRedemption(address indexed redeemer, address indexed collateralToken, bytes32 indexed parentCollectionId, bytes32 conditionId, uint256[] indexSets, uint256 payout)',
|
|
93
|
+
];
|
|
94
|
+
this.ctfContract = new Contract(CTF_CONTRACT, CTF_ABI, this.provider);
|
|
95
|
+
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Lifecycle Management
|
|
98
|
+
// ============================================================================
|
|
99
|
+
/**
|
|
100
|
+
* Start CTFManager
|
|
101
|
+
* - Starts listening to CTF-specific events (primary detection)
|
|
102
|
+
* - Also listens to ERC1155 Transfer events (fallback)
|
|
103
|
+
*/
|
|
104
|
+
async start() {
|
|
105
|
+
if (this.initialized)
|
|
106
|
+
return;
|
|
107
|
+
// ========== Primary Detection: CTF-specific events ==========
|
|
108
|
+
// These provide direct, fast detection without parsing Transfer events
|
|
109
|
+
// Listen to PositionSplit events
|
|
110
|
+
this.ctfContract.on('PositionSplit', async (stakeholder, collateralToken, parentCollectionId, conditionId, partition, amount, event) => {
|
|
111
|
+
await this.handlePositionSplit(stakeholder, conditionId, amount, event);
|
|
112
|
+
});
|
|
113
|
+
// Listen to PositionsMerge events
|
|
114
|
+
this.ctfContract.on('PositionsMerge', async (stakeholder, collateralToken, parentCollectionId, conditionId, partition, amount, event) => {
|
|
115
|
+
await this.handlePositionsMerge(stakeholder, conditionId, amount, event);
|
|
116
|
+
});
|
|
117
|
+
// Listen to PayoutRedemption events
|
|
118
|
+
this.ctfContract.on('PayoutRedemption', async (redeemer, collateralToken, parentCollectionId, conditionId, indexSets, payout, event) => {
|
|
119
|
+
await this.handlePayoutRedemption(redeemer, conditionId, indexSets, payout, event);
|
|
120
|
+
});
|
|
121
|
+
// ========== Fallback Detection: ERC1155 Transfer events ==========
|
|
122
|
+
// Keep these as fallback in case CTF events are not emitted for some reason
|
|
123
|
+
// Listen to TransferSingle events (covers split/merge/redeem)
|
|
124
|
+
this.ctfContract.on('TransferSingle', async (operator, from, to, id, value, event) => {
|
|
125
|
+
await this.handleTransferSingle(operator, from, to, id, value, event);
|
|
126
|
+
});
|
|
127
|
+
// Listen to TransferBatch events (less common, but possible)
|
|
128
|
+
this.ctfContract.on('TransferBatch', async (operator, from, to, ids, values, event) => {
|
|
129
|
+
await this.handleTransferBatch(operator, from, to, ids, values, event);
|
|
130
|
+
});
|
|
131
|
+
this.initialized = true;
|
|
132
|
+
this.log('CTFManager started, listening to on-chain events (CTF-specific + Transfer fallback)');
|
|
133
|
+
this.emit('initialized');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Stop CTFManager
|
|
137
|
+
* - Removes all event listeners
|
|
138
|
+
*/
|
|
139
|
+
stop() {
|
|
140
|
+
// Remove CTF-specific event listeners
|
|
141
|
+
this.ctfContract.removeAllListeners('PositionSplit');
|
|
142
|
+
this.ctfContract.removeAllListeners('PositionsMerge');
|
|
143
|
+
this.ctfContract.removeAllListeners('PayoutRedemption');
|
|
144
|
+
// Remove Transfer event listeners
|
|
145
|
+
this.ctfContract.removeAllListeners('TransferSingle');
|
|
146
|
+
this.ctfContract.removeAllListeners('TransferBatch');
|
|
147
|
+
this.initialized = false;
|
|
148
|
+
this.log('CTFManager stopped');
|
|
149
|
+
this.emit('stopped');
|
|
150
|
+
}
|
|
151
|
+
// ============================================================================
|
|
152
|
+
// CTF Operations (Execute + Auto-Track)
|
|
153
|
+
// ============================================================================
|
|
154
|
+
/**
|
|
155
|
+
* Split USDC into YES + NO tokens
|
|
156
|
+
* Transaction is automatically tracked via on-chain events
|
|
157
|
+
*/
|
|
158
|
+
async split(amount) {
|
|
159
|
+
if (!this.initialized) {
|
|
160
|
+
throw new Error('CTFManager not initialized. Call start() first.');
|
|
161
|
+
}
|
|
162
|
+
this.log(`Splitting ${amount} USDC...`);
|
|
163
|
+
const result = await this.ctfClient.split(this.config.conditionId, amount);
|
|
164
|
+
if (result.success) {
|
|
165
|
+
this.log(`Split successful: ${result.txHash}`);
|
|
166
|
+
// Event will be automatically detected via TransferSingle listener
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Merge YES + NO tokens into USDC
|
|
172
|
+
* Transaction is automatically tracked via on-chain events
|
|
173
|
+
*/
|
|
174
|
+
async merge(amount) {
|
|
175
|
+
if (!this.initialized) {
|
|
176
|
+
throw new Error('CTFManager not initialized. Call start() first.');
|
|
177
|
+
}
|
|
178
|
+
this.log(`Merging ${amount} tokens...`);
|
|
179
|
+
const tokenIds = {
|
|
180
|
+
yesTokenId: this.config.primaryTokenId,
|
|
181
|
+
noTokenId: this.config.secondaryTokenId,
|
|
182
|
+
};
|
|
183
|
+
const result = await this.ctfClient.mergeByTokenIds(this.config.conditionId, tokenIds, amount);
|
|
184
|
+
if (result.success) {
|
|
185
|
+
this.log(`Merge successful: ${result.txHash}`);
|
|
186
|
+
// Event will be automatically detected via TransferSingle listener
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Redeem winning tokens for USDC (after market resolution)
|
|
192
|
+
* Transaction is automatically tracked via on-chain events
|
|
193
|
+
*/
|
|
194
|
+
async redeem(outcome) {
|
|
195
|
+
if (!this.initialized) {
|
|
196
|
+
throw new Error('CTFManager not initialized. Call start() first.');
|
|
197
|
+
}
|
|
198
|
+
this.log(`Redeeming tokens...`);
|
|
199
|
+
const tokenIds = {
|
|
200
|
+
yesTokenId: this.config.primaryTokenId,
|
|
201
|
+
noTokenId: this.config.secondaryTokenId,
|
|
202
|
+
};
|
|
203
|
+
const result = await this.ctfClient.redeemByTokenIds(this.config.conditionId, tokenIds, outcome);
|
|
204
|
+
if (result.success) {
|
|
205
|
+
this.log(`Redeem successful: ${result.txHash}`);
|
|
206
|
+
// Event will be automatically detected via TransferSingle listener
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// Event Handlers
|
|
212
|
+
// ============================================================================
|
|
213
|
+
/**
|
|
214
|
+
* Handle TransferSingle event
|
|
215
|
+
*
|
|
216
|
+
* ERC1155 TransferSingle patterns:
|
|
217
|
+
* - Split: from=0x0, to=user, id=YES/NO (two events)
|
|
218
|
+
* - Merge: from=user, to=0x0, id=YES/NO (two events)
|
|
219
|
+
* - Redeem: from=user, to=0x0, id=winningToken (one event)
|
|
220
|
+
*/
|
|
221
|
+
async handleTransferSingle(operator, from, to, id, value, event) {
|
|
222
|
+
try {
|
|
223
|
+
// Only track events for this user
|
|
224
|
+
const fromLower = from.toLowerCase();
|
|
225
|
+
const toLower = to.toLowerCase();
|
|
226
|
+
const userLower = this.userAddress.toLowerCase();
|
|
227
|
+
if (fromLower !== userLower && toLower !== userLower) {
|
|
228
|
+
return; // Not this user's event
|
|
229
|
+
}
|
|
230
|
+
const tokenId = id.toString();
|
|
231
|
+
const amount = value.toString();
|
|
232
|
+
// Check if this token belongs to our market
|
|
233
|
+
if (tokenId !== this.config.primaryTokenId && tokenId !== this.config.secondaryTokenId) {
|
|
234
|
+
return; // Different market
|
|
235
|
+
}
|
|
236
|
+
// Deduplication
|
|
237
|
+
const eventKey = `${event.transactionHash}-${event.logIndex}`;
|
|
238
|
+
if (this.processedEvents.has(eventKey)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
this.processedEvents.add(eventKey);
|
|
242
|
+
// Cleanup old processed events (keep last 1000)
|
|
243
|
+
if (this.processedEvents.size > 2000) {
|
|
244
|
+
const toKeep = Array.from(this.processedEvents).slice(-1000);
|
|
245
|
+
this.processedEvents = new Set(toKeep);
|
|
246
|
+
}
|
|
247
|
+
// Get block timestamp
|
|
248
|
+
const block = await event.getBlock();
|
|
249
|
+
const timestamp = block.timestamp * 1000; // Convert to ms
|
|
250
|
+
// Detect operation type
|
|
251
|
+
if (fromLower === ethers.constants.AddressZero.toLowerCase() && toLower === userLower) {
|
|
252
|
+
// Split: 0x0 → user
|
|
253
|
+
await this.detectSplit(tokenId, amount, event.transactionHash, event.blockNumber, timestamp);
|
|
254
|
+
}
|
|
255
|
+
else if (fromLower === userLower && toLower === ethers.constants.AddressZero.toLowerCase()) {
|
|
256
|
+
// Merge or Redeem: user → 0x0
|
|
257
|
+
await this.detectMergeOrRedeem(tokenId, amount, event.transactionHash, event.blockNumber, timestamp);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
console.error('[CTFManager] Error handling TransferSingle:', error);
|
|
262
|
+
this.emit('error', error);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Handle TransferBatch event (less common)
|
|
267
|
+
*/
|
|
268
|
+
async handleTransferBatch(operator, from, to, ids, values, event) {
|
|
269
|
+
// TransferBatch is less common for CTF operations
|
|
270
|
+
// But we should handle it for completeness
|
|
271
|
+
for (let i = 0; i < ids.length; i++) {
|
|
272
|
+
await this.handleTransferSingle(operator, from, to, ids[i], values[i], event);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// ============================================================================
|
|
276
|
+
// CTF-Specific Event Handlers (Primary Detection)
|
|
277
|
+
// ============================================================================
|
|
278
|
+
/**
|
|
279
|
+
* Handle PositionSplit event
|
|
280
|
+
* Direct detection of Split operation - faster than parsing Transfer events
|
|
281
|
+
*/
|
|
282
|
+
async handlePositionSplit(stakeholder, conditionId, amount, event) {
|
|
283
|
+
try {
|
|
284
|
+
// Only track events for this user
|
|
285
|
+
if (stakeholder.toLowerCase() !== this.userAddress.toLowerCase()) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// Only track events for this market
|
|
289
|
+
const conditionIdHex = ethers.utils.hexlify(conditionId);
|
|
290
|
+
if (conditionIdHex.toLowerCase() !== this.config.conditionId.toLowerCase()) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
// Deduplication
|
|
294
|
+
const eventKey = `split-${event.transactionHash}-${event.logIndex}`;
|
|
295
|
+
if (this.processedEvents.has(eventKey)) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
this.processedEvents.add(eventKey);
|
|
299
|
+
// Cleanup old processed events (keep last 1000)
|
|
300
|
+
if (this.processedEvents.size > 2000) {
|
|
301
|
+
const toKeep = Array.from(this.processedEvents).slice(-1000);
|
|
302
|
+
this.processedEvents = new Set(toKeep);
|
|
303
|
+
}
|
|
304
|
+
// Get block timestamp
|
|
305
|
+
const block = await event.getBlock();
|
|
306
|
+
const timestamp = block.timestamp * 1000; // Convert to ms
|
|
307
|
+
// Convert amount from wei to USDC (6 decimals)
|
|
308
|
+
const amountStr = ethers.utils.formatUnits(amount, 6);
|
|
309
|
+
const splitEvent = {
|
|
310
|
+
type: 'split',
|
|
311
|
+
userAddress: this.userAddress,
|
|
312
|
+
conditionId: this.config.conditionId,
|
|
313
|
+
primaryTokenId: this.config.primaryTokenId,
|
|
314
|
+
secondaryTokenId: this.config.secondaryTokenId,
|
|
315
|
+
amount: amountStr,
|
|
316
|
+
txHash: event.transactionHash,
|
|
317
|
+
blockNumber: event.blockNumber,
|
|
318
|
+
timestamp,
|
|
319
|
+
};
|
|
320
|
+
this.log(`[CTF Event] Split detected: ${amountStr} USDC`);
|
|
321
|
+
this.emit('split_detected', splitEvent);
|
|
322
|
+
this.emit('operation_detected', splitEvent);
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
console.error('[CTFManager] Error handling PositionSplit:', error);
|
|
326
|
+
this.emit('error', error);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Handle PositionsMerge event
|
|
331
|
+
* Direct detection of Merge operation - faster than parsing Transfer events
|
|
332
|
+
*/
|
|
333
|
+
async handlePositionsMerge(stakeholder, conditionId, amount, event) {
|
|
334
|
+
try {
|
|
335
|
+
// Only track events for this user
|
|
336
|
+
if (stakeholder.toLowerCase() !== this.userAddress.toLowerCase()) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
// Only track events for this market
|
|
340
|
+
const conditionIdHex = ethers.utils.hexlify(conditionId);
|
|
341
|
+
if (conditionIdHex.toLowerCase() !== this.config.conditionId.toLowerCase()) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
// Deduplication
|
|
345
|
+
const eventKey = `merge-${event.transactionHash}-${event.logIndex}`;
|
|
346
|
+
if (this.processedEvents.has(eventKey)) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this.processedEvents.add(eventKey);
|
|
350
|
+
// Cleanup old processed events (keep last 1000)
|
|
351
|
+
if (this.processedEvents.size > 2000) {
|
|
352
|
+
const toKeep = Array.from(this.processedEvents).slice(-1000);
|
|
353
|
+
this.processedEvents = new Set(toKeep);
|
|
354
|
+
}
|
|
355
|
+
// Get block timestamp
|
|
356
|
+
const block = await event.getBlock();
|
|
357
|
+
const timestamp = block.timestamp * 1000; // Convert to ms
|
|
358
|
+
// Convert amount from wei to USDC (6 decimals)
|
|
359
|
+
const amountStr = ethers.utils.formatUnits(amount, 6);
|
|
360
|
+
const mergeEvent = {
|
|
361
|
+
type: 'merge',
|
|
362
|
+
userAddress: this.userAddress,
|
|
363
|
+
conditionId: this.config.conditionId,
|
|
364
|
+
primaryTokenId: this.config.primaryTokenId,
|
|
365
|
+
secondaryTokenId: this.config.secondaryTokenId,
|
|
366
|
+
amount: amountStr,
|
|
367
|
+
txHash: event.transactionHash,
|
|
368
|
+
blockNumber: event.blockNumber,
|
|
369
|
+
timestamp,
|
|
370
|
+
};
|
|
371
|
+
this.log(`[CTF Event] Merge detected: ${amountStr} USDC`);
|
|
372
|
+
this.emit('merge_detected', mergeEvent);
|
|
373
|
+
this.emit('operation_detected', mergeEvent);
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
console.error('[CTFManager] Error handling PositionsMerge:', error);
|
|
377
|
+
this.emit('error', error);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Handle PayoutRedemption event
|
|
382
|
+
* Direct detection of Redeem operation - faster than parsing Transfer events
|
|
383
|
+
*/
|
|
384
|
+
async handlePayoutRedemption(redeemer, conditionId, indexSets, payout, event) {
|
|
385
|
+
try {
|
|
386
|
+
// Only track events for this user
|
|
387
|
+
if (redeemer.toLowerCase() !== this.userAddress.toLowerCase()) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
// Only track events for this market
|
|
391
|
+
const conditionIdHex = ethers.utils.hexlify(conditionId);
|
|
392
|
+
if (conditionIdHex.toLowerCase() !== this.config.conditionId.toLowerCase()) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
// Deduplication
|
|
396
|
+
const eventKey = `redeem-${event.transactionHash}-${event.logIndex}`;
|
|
397
|
+
if (this.processedEvents.has(eventKey)) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
this.processedEvents.add(eventKey);
|
|
401
|
+
// Cleanup old processed events (keep last 1000)
|
|
402
|
+
if (this.processedEvents.size > 2000) {
|
|
403
|
+
const toKeep = Array.from(this.processedEvents).slice(-1000);
|
|
404
|
+
this.processedEvents = new Set(toKeep);
|
|
405
|
+
}
|
|
406
|
+
// Get block timestamp
|
|
407
|
+
const block = await event.getBlock();
|
|
408
|
+
const timestamp = block.timestamp * 1000; // Convert to ms
|
|
409
|
+
// Convert payout from wei to USDC (6 decimals)
|
|
410
|
+
const payoutStr = ethers.utils.formatUnits(payout, 6);
|
|
411
|
+
// Determine which token was redeemed based on indexSets
|
|
412
|
+
// indexSets[0] represents the outcome index (0 or 1)
|
|
413
|
+
const outcomeIndex = indexSets[0].toNumber();
|
|
414
|
+
const winningTokenId = outcomeIndex === 0
|
|
415
|
+
? this.config.primaryTokenId
|
|
416
|
+
: this.config.secondaryTokenId;
|
|
417
|
+
const redeemEvent = {
|
|
418
|
+
type: 'redeem',
|
|
419
|
+
userAddress: this.userAddress,
|
|
420
|
+
conditionId: this.config.conditionId,
|
|
421
|
+
winningTokenId,
|
|
422
|
+
amount: payoutStr,
|
|
423
|
+
txHash: event.transactionHash,
|
|
424
|
+
blockNumber: event.blockNumber,
|
|
425
|
+
timestamp,
|
|
426
|
+
};
|
|
427
|
+
this.log(`[CTF Event] Redeem detected: ${payoutStr} USDC (token ${winningTokenId})`);
|
|
428
|
+
this.emit('redeem_detected', redeemEvent);
|
|
429
|
+
this.emit('operation_detected', redeemEvent);
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
console.error('[CTFManager] Error handling PayoutRedemption:', error);
|
|
433
|
+
this.emit('error', error);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Detect split operation
|
|
438
|
+
* Split creates TWO Transfer events (0x0 → user) for both tokens
|
|
439
|
+
* We need to wait for the second event to confirm it's a split
|
|
440
|
+
*/
|
|
441
|
+
async detectSplit(tokenId, amount, txHash, blockNumber, timestamp) {
|
|
442
|
+
// Wait a bit to see if there's a second Transfer event
|
|
443
|
+
// (Split always creates two events in the same transaction)
|
|
444
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
445
|
+
const event = {
|
|
446
|
+
type: 'split',
|
|
447
|
+
userAddress: this.userAddress,
|
|
448
|
+
conditionId: this.config.conditionId,
|
|
449
|
+
primaryTokenId: this.config.primaryTokenId,
|
|
450
|
+
secondaryTokenId: this.config.secondaryTokenId,
|
|
451
|
+
amount,
|
|
452
|
+
txHash,
|
|
453
|
+
blockNumber,
|
|
454
|
+
timestamp,
|
|
455
|
+
};
|
|
456
|
+
this.log(`Split detected: ${amount} tokens`);
|
|
457
|
+
this.emit('split_detected', event);
|
|
458
|
+
this.emit('operation_detected', event);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Detect merge or redeem operation
|
|
462
|
+
* - Merge: TWO Transfer events (user → 0x0) for both tokens
|
|
463
|
+
* - Redeem: ONE Transfer event (user → 0x0) for winning token
|
|
464
|
+
*/
|
|
465
|
+
async detectMergeOrRedeem(tokenId, amount, txHash, blockNumber, timestamp) {
|
|
466
|
+
// Wait a bit to see if there's a second Transfer event
|
|
467
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
468
|
+
// Get all Transfer events in this transaction
|
|
469
|
+
const receipt = await this.provider.getTransactionReceipt(txHash);
|
|
470
|
+
const transfers = receipt.logs
|
|
471
|
+
.filter(log => {
|
|
472
|
+
try {
|
|
473
|
+
const parsed = this.ctfContract.interface.parseLog(log);
|
|
474
|
+
return parsed.name === 'TransferSingle';
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
})
|
|
480
|
+
.map(log => this.ctfContract.interface.parseLog(log));
|
|
481
|
+
const userTransfers = transfers.filter(t => t.args.from.toLowerCase() === this.userAddress.toLowerCase());
|
|
482
|
+
if (userTransfers.length === 2) {
|
|
483
|
+
// Merge: both tokens transferred
|
|
484
|
+
const event = {
|
|
485
|
+
type: 'merge',
|
|
486
|
+
userAddress: this.userAddress,
|
|
487
|
+
conditionId: this.config.conditionId,
|
|
488
|
+
primaryTokenId: this.config.primaryTokenId,
|
|
489
|
+
secondaryTokenId: this.config.secondaryTokenId,
|
|
490
|
+
amount,
|
|
491
|
+
txHash,
|
|
492
|
+
blockNumber,
|
|
493
|
+
timestamp,
|
|
494
|
+
};
|
|
495
|
+
this.log(`Merge detected: ${amount} tokens`);
|
|
496
|
+
this.emit('merge_detected', event);
|
|
497
|
+
this.emit('operation_detected', event);
|
|
498
|
+
}
|
|
499
|
+
else if (userTransfers.length === 1) {
|
|
500
|
+
// Redeem: only winning token transferred
|
|
501
|
+
const event = {
|
|
502
|
+
type: 'redeem',
|
|
503
|
+
userAddress: this.userAddress,
|
|
504
|
+
conditionId: this.config.conditionId,
|
|
505
|
+
winningTokenId: tokenId,
|
|
506
|
+
amount,
|
|
507
|
+
txHash,
|
|
508
|
+
blockNumber,
|
|
509
|
+
timestamp,
|
|
510
|
+
};
|
|
511
|
+
this.log(`Redeem detected: ${amount} tokens (${tokenId})`);
|
|
512
|
+
this.emit('redeem_detected', event);
|
|
513
|
+
this.emit('operation_detected', event);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
// ============================================================================
|
|
517
|
+
// Helpers
|
|
518
|
+
// ============================================================================
|
|
519
|
+
/**
|
|
520
|
+
* Log message (if debug enabled)
|
|
521
|
+
*/
|
|
522
|
+
log(message) {
|
|
523
|
+
if (this.config.debug) {
|
|
524
|
+
console.log(`[CTFManager] ${message}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Get current balances
|
|
529
|
+
*/
|
|
530
|
+
async getBalances() {
|
|
531
|
+
const tokenIds = {
|
|
532
|
+
yesTokenId: this.config.primaryTokenId,
|
|
533
|
+
noTokenId: this.config.secondaryTokenId,
|
|
534
|
+
};
|
|
535
|
+
const balance = await this.ctfClient.getPositionBalanceByTokenIds(this.config.conditionId, tokenIds);
|
|
536
|
+
return {
|
|
537
|
+
primary: balance.yesBalance,
|
|
538
|
+
secondary: balance.noBalance,
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
//# sourceMappingURL=ctf-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ctf-manager.js","sourceRoot":"","sources":["../../../src/services/ctf-manager.ts"],"names":[],"mappings":"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"}
|