pnpfucius 2.0.0
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 +396 -0
- package/bin/claude-predict.js +5 -0
- package/bin/pnpfucius.js +8 -0
- package/package.json +71 -0
- package/src/agent.js +1037 -0
- package/src/ai/index.js +6 -0
- package/src/ai/market-generator.js +186 -0
- package/src/ai/resolver.js +172 -0
- package/src/ai/scorer.js +184 -0
- package/src/analytics/aggregator.js +198 -0
- package/src/cli.js +948 -0
- package/src/collateral/privacy-tokens.js +183 -0
- package/src/config.js +128 -0
- package/src/daemon/index.js +321 -0
- package/src/daemon/lifecycle.js +168 -0
- package/src/daemon/scheduler.js +252 -0
- package/src/events/emitter.js +147 -0
- package/src/helius/client.js +221 -0
- package/src/helius/transaction-tracker.js +192 -0
- package/src/helius/webhooks.js +233 -0
- package/src/index.js +139 -0
- package/src/monitoring/news-monitor.js +262 -0
- package/src/monitoring/news-scorer.js +236 -0
- package/src/predict/agent.js +291 -0
- package/src/predict/prompts.js +69 -0
- package/src/predict/slash-commands.js +361 -0
- package/src/predict/tools/analytics-tools.js +83 -0
- package/src/predict/tools/bash-tool.js +87 -0
- package/src/predict/tools/file-tools.js +140 -0
- package/src/predict/tools/index.js +120 -0
- package/src/predict/tools/market-tools.js +851 -0
- package/src/predict/tools/news-tools.js +130 -0
- package/src/predict/ui/renderer.js +215 -0
- package/src/predict/ui/welcome.js +146 -0
- package/src/privacy-markets.js +194 -0
- package/src/storage/market-store.js +418 -0
- package/src/utils/spinner.js +172 -0
|
@@ -0,0 +1,851 @@
|
|
|
1
|
+
// Market tool definitions and implementations for PNPFUCIUS
|
|
2
|
+
|
|
3
|
+
import { createAgent } from '../../agent.js';
|
|
4
|
+
import { createMarketStore } from '../../storage/market-store.js';
|
|
5
|
+
import { getConfig } from '../../config.js';
|
|
6
|
+
|
|
7
|
+
// Tool definitions for PNPFUCIUS
|
|
8
|
+
export const marketToolDefinitions = [
|
|
9
|
+
{
|
|
10
|
+
name: 'create_market',
|
|
11
|
+
description: 'Create a prediction market on Solana. Returns market address and transaction signature.',
|
|
12
|
+
input_schema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
question: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'The YES/NO market question'
|
|
18
|
+
},
|
|
19
|
+
duration_days: {
|
|
20
|
+
type: 'number',
|
|
21
|
+
description: 'Market duration in days (default: 30)'
|
|
22
|
+
},
|
|
23
|
+
liquidity_usdc: {
|
|
24
|
+
type: 'number',
|
|
25
|
+
description: 'Initial liquidity in USDC (default: 1)'
|
|
26
|
+
},
|
|
27
|
+
type: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
enum: ['amm', 'p2p'],
|
|
30
|
+
description: 'Market type (default: amm)'
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
required: ['question']
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'list_markets',
|
|
38
|
+
description: 'List existing prediction markets with optional filters',
|
|
39
|
+
input_schema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
status: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
enum: ['active', 'resolved', 'all'],
|
|
45
|
+
description: 'Filter by market status'
|
|
46
|
+
},
|
|
47
|
+
category: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
description: 'Filter by category'
|
|
50
|
+
},
|
|
51
|
+
limit: {
|
|
52
|
+
type: 'number',
|
|
53
|
+
description: 'Max markets to return (default: 10)'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'get_market_info',
|
|
60
|
+
description: 'Get detailed information about a specific market',
|
|
61
|
+
input_schema: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {
|
|
64
|
+
address: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'Market address on Solana'
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
required: ['address']
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
// ========== TRADING TOOLS ==========
|
|
73
|
+
{
|
|
74
|
+
name: 'buy_tokens',
|
|
75
|
+
description: 'Buy YES or NO tokens on a prediction market using USDC',
|
|
76
|
+
input_schema: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
market_address: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'The market address on Solana'
|
|
82
|
+
},
|
|
83
|
+
side: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
enum: ['yes', 'no'],
|
|
86
|
+
description: 'Which token to buy (yes or no)'
|
|
87
|
+
},
|
|
88
|
+
amount_usdc: {
|
|
89
|
+
type: 'number',
|
|
90
|
+
description: 'Amount of USDC to spend'
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
required: ['market_address', 'side', 'amount_usdc']
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'sell_tokens',
|
|
98
|
+
description: 'Sell YES or NO tokens from a prediction market for USDC',
|
|
99
|
+
input_schema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
market_address: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
description: 'The market address on Solana'
|
|
105
|
+
},
|
|
106
|
+
side: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
enum: ['yes', 'no'],
|
|
109
|
+
description: 'Which token to sell (yes or no)'
|
|
110
|
+
},
|
|
111
|
+
amount: {
|
|
112
|
+
type: 'number',
|
|
113
|
+
description: 'Amount of tokens to sell'
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
required: ['market_address', 'side', 'amount']
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'get_market_prices',
|
|
121
|
+
description: 'Get current YES and NO token prices for a market',
|
|
122
|
+
input_schema: {
|
|
123
|
+
type: 'object',
|
|
124
|
+
properties: {
|
|
125
|
+
market_address: {
|
|
126
|
+
type: 'string',
|
|
127
|
+
description: 'The market address on Solana'
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
required: ['market_address']
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'get_balances',
|
|
135
|
+
description: 'Get your YES and NO token balances for a market',
|
|
136
|
+
input_schema: {
|
|
137
|
+
type: 'object',
|
|
138
|
+
properties: {
|
|
139
|
+
market_address: {
|
|
140
|
+
type: 'string',
|
|
141
|
+
description: 'The market address on Solana'
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
required: ['market_address']
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
// ========== REDEMPTION TOOLS ==========
|
|
148
|
+
{
|
|
149
|
+
name: 'redeem_position',
|
|
150
|
+
description: 'Redeem winning tokens from a resolved market for USDC',
|
|
151
|
+
input_schema: {
|
|
152
|
+
type: 'object',
|
|
153
|
+
properties: {
|
|
154
|
+
market_address: {
|
|
155
|
+
type: 'string',
|
|
156
|
+
description: 'The resolved market address'
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
required: ['market_address']
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'claim_refund',
|
|
164
|
+
description: 'Claim creator refund from an unresolved/cancelled market',
|
|
165
|
+
input_schema: {
|
|
166
|
+
type: 'object',
|
|
167
|
+
properties: {
|
|
168
|
+
market_address: {
|
|
169
|
+
type: 'string',
|
|
170
|
+
description: 'The market address'
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
required: ['market_address']
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
// ========== URL-AWARE MARKET CREATION ==========
|
|
177
|
+
{
|
|
178
|
+
name: 'create_market_from_source',
|
|
179
|
+
description: 'Create a market linked to a verifiable source (Twitter, YouTube, or DeFi metric)',
|
|
180
|
+
input_schema: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
properties: {
|
|
183
|
+
question: {
|
|
184
|
+
type: 'string',
|
|
185
|
+
description: 'The YES/NO market question'
|
|
186
|
+
},
|
|
187
|
+
source_url: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'URL of the source (tweet, video, or DeFi metric identifier)'
|
|
190
|
+
},
|
|
191
|
+
source_type: {
|
|
192
|
+
type: 'string',
|
|
193
|
+
enum: ['twitter', 'youtube', 'defi'],
|
|
194
|
+
description: 'Type of source for verification'
|
|
195
|
+
},
|
|
196
|
+
duration_days: {
|
|
197
|
+
type: 'number',
|
|
198
|
+
description: 'Market duration in days (default: 30)'
|
|
199
|
+
},
|
|
200
|
+
liquidity_usdc: {
|
|
201
|
+
type: 'number',
|
|
202
|
+
description: 'Initial liquidity in USDC (default: 1)'
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
required: ['question', 'source_url', 'source_type']
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// ========== PNP ORACLE/SETTLEMENT TOOLS ==========
|
|
210
|
+
{
|
|
211
|
+
name: 'get_settlement_criteria',
|
|
212
|
+
description: 'Get AI-generated settlement criteria from PNP\'s LLM oracle. Returns how the market should be evaluated for resolution.',
|
|
213
|
+
input_schema: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
properties: {
|
|
216
|
+
market_address: {
|
|
217
|
+
type: 'string',
|
|
218
|
+
description: 'The market address on Solana'
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
required: ['market_address']
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: 'get_settlement_data',
|
|
226
|
+
description: 'Get the resolution result from PNP\'s LLM oracle. Returns the answer and reasoning for market resolution.',
|
|
227
|
+
input_schema: {
|
|
228
|
+
type: 'object',
|
|
229
|
+
properties: {
|
|
230
|
+
market_address: {
|
|
231
|
+
type: 'string',
|
|
232
|
+
description: 'The market address on Solana'
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
required: ['market_address']
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: 'wait_for_settlement',
|
|
240
|
+
description: 'Wait for settlement criteria to become available (with automatic retries). Useful for newly created markets.',
|
|
241
|
+
input_schema: {
|
|
242
|
+
type: 'object',
|
|
243
|
+
properties: {
|
|
244
|
+
market_address: {
|
|
245
|
+
type: 'string',
|
|
246
|
+
description: 'The market address on Solana'
|
|
247
|
+
},
|
|
248
|
+
timeout_seconds: {
|
|
249
|
+
type: 'number',
|
|
250
|
+
description: 'Maximum time to wait in seconds (default: 30)'
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
required: ['market_address']
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: 'settle_market',
|
|
258
|
+
description: 'Settle a market with a specific outcome (requires oracle authority). Use this to resolve a market.',
|
|
259
|
+
input_schema: {
|
|
260
|
+
type: 'object',
|
|
261
|
+
properties: {
|
|
262
|
+
market_address: {
|
|
263
|
+
type: 'string',
|
|
264
|
+
description: 'The market address on Solana'
|
|
265
|
+
},
|
|
266
|
+
outcome: {
|
|
267
|
+
type: 'string',
|
|
268
|
+
enum: ['yes', 'no'],
|
|
269
|
+
description: 'The winning outcome'
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
required: ['market_address', 'outcome']
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
// ========== MARKET DISCOVERY TOOLS ==========
|
|
277
|
+
{
|
|
278
|
+
name: 'discover_all_markets',
|
|
279
|
+
description: 'Discover ALL prediction markets on PNP Exchange (not just ones you created). Returns a list of all available markets.',
|
|
280
|
+
input_schema: {
|
|
281
|
+
type: 'object',
|
|
282
|
+
properties: {
|
|
283
|
+
version: {
|
|
284
|
+
type: 'string',
|
|
285
|
+
enum: ['v2', 'v3', 'all'],
|
|
286
|
+
description: 'Market version to fetch (default: all)'
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'get_market_metadata',
|
|
293
|
+
description: 'Get metadata for a market including volume, image, and other analytics.',
|
|
294
|
+
input_schema: {
|
|
295
|
+
type: 'object',
|
|
296
|
+
properties: {
|
|
297
|
+
market_address: {
|
|
298
|
+
type: 'string',
|
|
299
|
+
description: 'The market address on Solana'
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
required: ['market_address']
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: 'get_v2_market_info',
|
|
307
|
+
description: 'Get detailed V2 (AMM) market information including token mints, multipliers, and settlement criteria.',
|
|
308
|
+
input_schema: {
|
|
309
|
+
type: 'object',
|
|
310
|
+
properties: {
|
|
311
|
+
market_address: {
|
|
312
|
+
type: 'string',
|
|
313
|
+
description: 'The V2 market address on Solana'
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
required: ['market_address']
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
name: 'get_p2p_market_info',
|
|
321
|
+
description: 'Get detailed P2P market information including reserves, mints, and settlement criteria.',
|
|
322
|
+
input_schema: {
|
|
323
|
+
type: 'object',
|
|
324
|
+
properties: {
|
|
325
|
+
market_address: {
|
|
326
|
+
type: 'string',
|
|
327
|
+
description: 'The P2P market address on Solana'
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
required: ['market_address']
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
// ========== P2P MARKET TOOLS WITH CUSTOM ODDS ==========
|
|
335
|
+
{
|
|
336
|
+
name: 'create_p2p_market_simple',
|
|
337
|
+
description: 'Create a simple P2P prediction market with USDC. Easier to use than the standard P2P creation.',
|
|
338
|
+
input_schema: {
|
|
339
|
+
type: 'object',
|
|
340
|
+
properties: {
|
|
341
|
+
question: {
|
|
342
|
+
type: 'string',
|
|
343
|
+
description: 'The YES/NO market question'
|
|
344
|
+
},
|
|
345
|
+
side: {
|
|
346
|
+
type: 'string',
|
|
347
|
+
enum: ['yes', 'no'],
|
|
348
|
+
description: 'Which side you are betting on (default: yes)'
|
|
349
|
+
},
|
|
350
|
+
amount_usdc: {
|
|
351
|
+
type: 'number',
|
|
352
|
+
description: 'Amount of USDC to put up (default: 1)'
|
|
353
|
+
},
|
|
354
|
+
duration_days: {
|
|
355
|
+
type: 'number',
|
|
356
|
+
description: 'Market duration in days (default: 30)'
|
|
357
|
+
},
|
|
358
|
+
cap_multiplier: {
|
|
359
|
+
type: 'number',
|
|
360
|
+
description: 'How much more the other side can bet (default: 5x)'
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
required: ['question']
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: 'create_p2p_market_with_odds',
|
|
368
|
+
description: 'Create a P2P market with custom starting odds. Specify exact odds in basis points.',
|
|
369
|
+
input_schema: {
|
|
370
|
+
type: 'object',
|
|
371
|
+
properties: {
|
|
372
|
+
question: {
|
|
373
|
+
type: 'string',
|
|
374
|
+
description: 'The YES/NO market question'
|
|
375
|
+
},
|
|
376
|
+
side: {
|
|
377
|
+
type: 'string',
|
|
378
|
+
enum: ['yes', 'no'],
|
|
379
|
+
description: 'Which side you are betting on'
|
|
380
|
+
},
|
|
381
|
+
amount_usdc: {
|
|
382
|
+
type: 'number',
|
|
383
|
+
description: 'Amount of USDC to put up'
|
|
384
|
+
},
|
|
385
|
+
odds_percent: {
|
|
386
|
+
type: 'number',
|
|
387
|
+
description: 'Your side\'s odds as a percentage (e.g., 70 for 70%)'
|
|
388
|
+
},
|
|
389
|
+
duration_days: {
|
|
390
|
+
type: 'number',
|
|
391
|
+
description: 'Market duration in days (default: 30)'
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
required: ['question', 'side', 'odds_percent']
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
name: 'create_amm_market_with_odds',
|
|
399
|
+
description: 'Create an AMM market with custom starting odds. The YES price will start at the specified percentage.',
|
|
400
|
+
input_schema: {
|
|
401
|
+
type: 'object',
|
|
402
|
+
properties: {
|
|
403
|
+
question: {
|
|
404
|
+
type: 'string',
|
|
405
|
+
description: 'The YES/NO market question'
|
|
406
|
+
},
|
|
407
|
+
yes_odds_percent: {
|
|
408
|
+
type: 'number',
|
|
409
|
+
description: 'Starting YES odds as a percentage (e.g., 60 for 60%)'
|
|
410
|
+
},
|
|
411
|
+
liquidity_usdc: {
|
|
412
|
+
type: 'number',
|
|
413
|
+
description: 'Initial liquidity in USDC (default: 1)'
|
|
414
|
+
},
|
|
415
|
+
duration_days: {
|
|
416
|
+
type: 'number',
|
|
417
|
+
description: 'Market duration in days (default: 30)'
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
required: ['question', 'yes_odds_percent']
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
|
|
424
|
+
// ========== CUSTOM ORACLE TOOLS ==========
|
|
425
|
+
{
|
|
426
|
+
name: 'create_market_with_oracle',
|
|
427
|
+
description: 'Create a market with a custom oracle/settler address. You specify who can resolve the market.',
|
|
428
|
+
input_schema: {
|
|
429
|
+
type: 'object',
|
|
430
|
+
properties: {
|
|
431
|
+
question: {
|
|
432
|
+
type: 'string',
|
|
433
|
+
description: 'The YES/NO market question'
|
|
434
|
+
},
|
|
435
|
+
settler_address: {
|
|
436
|
+
type: 'string',
|
|
437
|
+
description: 'Solana address that will have authority to settle this market'
|
|
438
|
+
},
|
|
439
|
+
liquidity_usdc: {
|
|
440
|
+
type: 'number',
|
|
441
|
+
description: 'Initial liquidity in USDC (default: 1)'
|
|
442
|
+
},
|
|
443
|
+
yes_odds_percent: {
|
|
444
|
+
type: 'number',
|
|
445
|
+
description: 'Starting YES odds as a percentage (default: 50)'
|
|
446
|
+
},
|
|
447
|
+
duration_days: {
|
|
448
|
+
type: 'number',
|
|
449
|
+
description: 'Market duration in days (default: 30)'
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
required: ['question', 'settler_address']
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
|
|
456
|
+
// ========== V3/P2P REDEMPTION TOOLS ==========
|
|
457
|
+
{
|
|
458
|
+
name: 'redeem_v3_position',
|
|
459
|
+
description: 'Redeem winning tokens from a resolved V3 market',
|
|
460
|
+
input_schema: {
|
|
461
|
+
type: 'object',
|
|
462
|
+
properties: {
|
|
463
|
+
market_address: {
|
|
464
|
+
type: 'string',
|
|
465
|
+
description: 'The resolved V3 market address'
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
required: ['market_address']
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
name: 'redeem_p2p_position',
|
|
473
|
+
description: 'Redeem winning tokens from a resolved P2P market',
|
|
474
|
+
input_schema: {
|
|
475
|
+
type: 'object',
|
|
476
|
+
properties: {
|
|
477
|
+
market_address: {
|
|
478
|
+
type: 'string',
|
|
479
|
+
description: 'The resolved P2P market address'
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
required: ['market_address']
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: 'claim_p2p_refund',
|
|
487
|
+
description: 'Claim creator refund from an unresolved/cancelled P2P market',
|
|
488
|
+
input_schema: {
|
|
489
|
+
type: 'object',
|
|
490
|
+
properties: {
|
|
491
|
+
market_address: {
|
|
492
|
+
type: 'string',
|
|
493
|
+
description: 'The P2P market address'
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
required: ['market_address']
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
|
|
500
|
+
// ========== BUY V3 TOKENS ==========
|
|
501
|
+
{
|
|
502
|
+
name: 'buy_v3_tokens',
|
|
503
|
+
description: 'Buy YES or NO tokens on a V3 prediction market using USDC',
|
|
504
|
+
input_schema: {
|
|
505
|
+
type: 'object',
|
|
506
|
+
properties: {
|
|
507
|
+
market_address: {
|
|
508
|
+
type: 'string',
|
|
509
|
+
description: 'The V3 market address on Solana'
|
|
510
|
+
},
|
|
511
|
+
side: {
|
|
512
|
+
type: 'string',
|
|
513
|
+
enum: ['yes', 'no'],
|
|
514
|
+
description: 'Which token to buy (yes or no)'
|
|
515
|
+
},
|
|
516
|
+
amount_usdc: {
|
|
517
|
+
type: 'number',
|
|
518
|
+
description: 'Amount of USDC to spend'
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
required: ['market_address', 'side', 'amount_usdc']
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
|
|
525
|
+
// ========== GLOBAL CONFIG ==========
|
|
526
|
+
{
|
|
527
|
+
name: 'get_pnp_config',
|
|
528
|
+
description: 'Get PNP Exchange global configuration including program addresses and settings',
|
|
529
|
+
input_schema: {
|
|
530
|
+
type: 'object',
|
|
531
|
+
properties: {}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
// Tool implementations
|
|
537
|
+
export async function executeMarketTool(name, input) {
|
|
538
|
+
const config = getConfig();
|
|
539
|
+
|
|
540
|
+
switch (name) {
|
|
541
|
+
case 'create_market': {
|
|
542
|
+
const agent = await createAgent({ verbose: false });
|
|
543
|
+
const result = await agent.createMarket({
|
|
544
|
+
question: input.question,
|
|
545
|
+
durationDays: input.duration_days || 30,
|
|
546
|
+
liquidity: BigInt(Math.floor((input.liquidity_usdc || 1) * 1_000_000)),
|
|
547
|
+
marketType: input.type || 'amm'
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
return {
|
|
551
|
+
success: true,
|
|
552
|
+
market: result.market,
|
|
553
|
+
signature: result.signature,
|
|
554
|
+
question: input.question,
|
|
555
|
+
duration_days: input.duration_days || 30,
|
|
556
|
+
liquidity_usdc: input.liquidity_usdc || 1,
|
|
557
|
+
type: input.type || 'amm',
|
|
558
|
+
network: config.network
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
case 'list_markets': {
|
|
563
|
+
const store = createMarketStore();
|
|
564
|
+
let markets = store.getAllMarkets();
|
|
565
|
+
|
|
566
|
+
// Apply filters
|
|
567
|
+
if (input.status && input.status !== 'all') {
|
|
568
|
+
markets = markets.filter(m => m.status === input.status);
|
|
569
|
+
}
|
|
570
|
+
if (input.category) {
|
|
571
|
+
markets = markets.filter(m => m.category === input.category);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Apply limit
|
|
575
|
+
const limit = input.limit || 10;
|
|
576
|
+
markets = markets.slice(0, limit);
|
|
577
|
+
|
|
578
|
+
return {
|
|
579
|
+
markets,
|
|
580
|
+
total: markets.length,
|
|
581
|
+
filters: {
|
|
582
|
+
status: input.status || 'all',
|
|
583
|
+
category: input.category || 'all'
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
case 'get_market_info': {
|
|
589
|
+
const agent = await createAgent({ verbose: false });
|
|
590
|
+
const info = await agent.fetchMarketInfo(input.address);
|
|
591
|
+
return info;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// ========== TRADING TOOLS ==========
|
|
595
|
+
|
|
596
|
+
case 'buy_tokens': {
|
|
597
|
+
const agent = await createAgent({ verbose: false });
|
|
598
|
+
const result = await agent.buyTokens({
|
|
599
|
+
marketAddress: input.market_address,
|
|
600
|
+
side: input.side,
|
|
601
|
+
amountUsdc: input.amount_usdc
|
|
602
|
+
});
|
|
603
|
+
return result;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
case 'sell_tokens': {
|
|
607
|
+
const agent = await createAgent({ verbose: false });
|
|
608
|
+
const result = await agent.sellTokens({
|
|
609
|
+
marketAddress: input.market_address,
|
|
610
|
+
side: input.side,
|
|
611
|
+
amount: input.amount
|
|
612
|
+
});
|
|
613
|
+
return result;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
case 'get_market_prices': {
|
|
617
|
+
const agent = await createAgent({ verbose: false });
|
|
618
|
+
const result = await agent.getMarketPrices(input.market_address);
|
|
619
|
+
return result;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
case 'get_balances': {
|
|
623
|
+
const agent = await createAgent({ verbose: false });
|
|
624
|
+
const result = await agent.getBalances(input.market_address);
|
|
625
|
+
return result;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// ========== REDEMPTION TOOLS ==========
|
|
629
|
+
|
|
630
|
+
case 'redeem_position': {
|
|
631
|
+
const agent = await createAgent({ verbose: false });
|
|
632
|
+
const result = await agent.redeemPosition(input.market_address);
|
|
633
|
+
return result;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
case 'claim_refund': {
|
|
637
|
+
const agent = await createAgent({ verbose: false });
|
|
638
|
+
const result = await agent.claimRefund(input.market_address);
|
|
639
|
+
return result;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// ========== URL-AWARE MARKET CREATION ==========
|
|
643
|
+
|
|
644
|
+
case 'create_market_from_source': {
|
|
645
|
+
const agent = await createAgent({ verbose: false });
|
|
646
|
+
const result = await agent.createMarketFromSource({
|
|
647
|
+
question: input.question,
|
|
648
|
+
sourceUrl: input.source_url,
|
|
649
|
+
sourceType: input.source_type,
|
|
650
|
+
durationDays: input.duration_days || 30,
|
|
651
|
+
liquidity: BigInt(Math.floor((input.liquidity_usdc || 1) * 1_000_000))
|
|
652
|
+
});
|
|
653
|
+
return {
|
|
654
|
+
...result,
|
|
655
|
+
duration_days: input.duration_days || 30,
|
|
656
|
+
liquidity_usdc: input.liquidity_usdc || 1,
|
|
657
|
+
network: config.network
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// ========== PNP ORACLE/SETTLEMENT TOOLS ==========
|
|
662
|
+
|
|
663
|
+
case 'get_settlement_criteria': {
|
|
664
|
+
const agent = await createAgent({ verbose: false });
|
|
665
|
+
const result = await agent.fetchSettlementCriteria(input.market_address);
|
|
666
|
+
return result;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
case 'get_settlement_data': {
|
|
670
|
+
const agent = await createAgent({ verbose: false });
|
|
671
|
+
const result = await agent.getSettlementData(input.market_address);
|
|
672
|
+
return result;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
case 'wait_for_settlement': {
|
|
676
|
+
const agent = await createAgent({ verbose: false });
|
|
677
|
+
const timeoutMs = (input.timeout_seconds || 30) * 1000;
|
|
678
|
+
const result = await agent.waitForSettlementCriteria(input.market_address, {
|
|
679
|
+
maxRetryTimeMs: timeoutMs
|
|
680
|
+
});
|
|
681
|
+
return result;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
case 'settle_market': {
|
|
685
|
+
const agent = await createAgent({ verbose: false });
|
|
686
|
+
const result = await agent.settleMarket(
|
|
687
|
+
input.market_address,
|
|
688
|
+
input.outcome === 'yes'
|
|
689
|
+
);
|
|
690
|
+
return result;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// ========== MARKET DISCOVERY TOOLS ==========
|
|
694
|
+
|
|
695
|
+
case 'discover_all_markets': {
|
|
696
|
+
const agent = await createAgent({ verbose: false });
|
|
697
|
+
const version = input.version || 'all';
|
|
698
|
+
|
|
699
|
+
if (version === 'v2') {
|
|
700
|
+
const result = await agent.fetchAllMarketAddresses();
|
|
701
|
+
return { ...result, version: 'v2' };
|
|
702
|
+
} else if (version === 'v3') {
|
|
703
|
+
const result = await agent.fetchV3MarketAddresses();
|
|
704
|
+
return { ...result, version: 'v3' };
|
|
705
|
+
} else {
|
|
706
|
+
// Fetch both
|
|
707
|
+
const [v2Result, v3Result] = await Promise.all([
|
|
708
|
+
agent.fetchAllMarketAddresses().catch(e => ({ addresses: [], error: e.message })),
|
|
709
|
+
agent.fetchV3MarketAddresses().catch(e => ({ addresses: [], error: e.message }))
|
|
710
|
+
]);
|
|
711
|
+
return {
|
|
712
|
+
success: true,
|
|
713
|
+
v2_markets: v2Result.addresses || [],
|
|
714
|
+
v3_markets: v3Result.addresses || [],
|
|
715
|
+
total: (v2Result.addresses?.length || 0) + (v3Result.addresses?.length || 0)
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
case 'get_market_metadata': {
|
|
721
|
+
const agent = await createAgent({ verbose: false });
|
|
722
|
+
const result = await agent.getMarketMetadata(input.market_address);
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
case 'get_v2_market_info': {
|
|
727
|
+
const agent = await createAgent({ verbose: false });
|
|
728
|
+
const result = await agent.getV2MarketInfo(input.market_address);
|
|
729
|
+
return result;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
case 'get_p2p_market_info': {
|
|
733
|
+
const agent = await createAgent({ verbose: false });
|
|
734
|
+
const result = await agent.getP2PMarketInfo(input.market_address);
|
|
735
|
+
return result;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// ========== P2P MARKET TOOLS WITH CUSTOM ODDS ==========
|
|
739
|
+
|
|
740
|
+
case 'create_p2p_market_simple': {
|
|
741
|
+
const agent = await createAgent({ verbose: false });
|
|
742
|
+
const result = await agent.createP2PMarketSimple({
|
|
743
|
+
question: input.question,
|
|
744
|
+
side: input.side || 'yes',
|
|
745
|
+
amountUsdc: input.amount_usdc || 1,
|
|
746
|
+
durationDays: input.duration_days || 30,
|
|
747
|
+
capMultiplier: input.cap_multiplier || 5
|
|
748
|
+
});
|
|
749
|
+
return {
|
|
750
|
+
...result,
|
|
751
|
+
network: config.network
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
case 'create_p2p_market_with_odds': {
|
|
756
|
+
const agent = await createAgent({ verbose: false });
|
|
757
|
+
const oddsBps = Math.floor((input.odds_percent || 50) * 100);
|
|
758
|
+
const result = await agent.createP2PMarketWithOdds({
|
|
759
|
+
question: input.question,
|
|
760
|
+
side: input.side,
|
|
761
|
+
amount: BigInt(Math.floor((input.amount_usdc || 1) * 1_000_000)),
|
|
762
|
+
durationDays: input.duration_days || 30,
|
|
763
|
+
oddsBps
|
|
764
|
+
});
|
|
765
|
+
return {
|
|
766
|
+
...result,
|
|
767
|
+
odds_percent: input.odds_percent,
|
|
768
|
+
network: config.network
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
case 'create_amm_market_with_odds': {
|
|
773
|
+
const agent = await createAgent({ verbose: false });
|
|
774
|
+
const yesOddsBps = Math.floor((input.yes_odds_percent || 50) * 100);
|
|
775
|
+
const result = await agent.createAMMMarketWithOdds({
|
|
776
|
+
question: input.question,
|
|
777
|
+
liquidity: BigInt(Math.floor((input.liquidity_usdc || 1) * 1_000_000)),
|
|
778
|
+
durationDays: input.duration_days || 30,
|
|
779
|
+
yesOddsBps
|
|
780
|
+
});
|
|
781
|
+
return {
|
|
782
|
+
...result,
|
|
783
|
+
yes_odds_percent: input.yes_odds_percent,
|
|
784
|
+
liquidity_usdc: input.liquidity_usdc || 1,
|
|
785
|
+
network: config.network
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// ========== CUSTOM ORACLE TOOLS ==========
|
|
790
|
+
|
|
791
|
+
case 'create_market_with_oracle': {
|
|
792
|
+
const agent = await createAgent({ verbose: false });
|
|
793
|
+
const yesOddsBps = Math.floor((input.yes_odds_percent || 50) * 100);
|
|
794
|
+
const result = await agent.createMarketWithCustomOracle({
|
|
795
|
+
question: input.question,
|
|
796
|
+
settlerAddress: input.settler_address,
|
|
797
|
+
liquidity: BigInt(Math.floor((input.liquidity_usdc || 1) * 1_000_000)),
|
|
798
|
+
durationDays: input.duration_days || 30,
|
|
799
|
+
yesOddsBps
|
|
800
|
+
});
|
|
801
|
+
return {
|
|
802
|
+
...result,
|
|
803
|
+
liquidity_usdc: input.liquidity_usdc || 1,
|
|
804
|
+
network: config.network
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// ========== V3/P2P REDEMPTION TOOLS ==========
|
|
809
|
+
|
|
810
|
+
case 'redeem_v3_position': {
|
|
811
|
+
const agent = await createAgent({ verbose: false });
|
|
812
|
+
const result = await agent.redeemV3Position(input.market_address);
|
|
813
|
+
return result;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
case 'redeem_p2p_position': {
|
|
817
|
+
const agent = await createAgent({ verbose: false });
|
|
818
|
+
const result = await agent.redeemP2PPosition(input.market_address);
|
|
819
|
+
return result;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
case 'claim_p2p_refund': {
|
|
823
|
+
const agent = await createAgent({ verbose: false });
|
|
824
|
+
const result = await agent.claimP2PRefund(input.market_address);
|
|
825
|
+
return result;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// ========== BUY V3 TOKENS ==========
|
|
829
|
+
|
|
830
|
+
case 'buy_v3_tokens': {
|
|
831
|
+
const agent = await createAgent({ verbose: false });
|
|
832
|
+
const result = await agent.buyV3Tokens({
|
|
833
|
+
marketAddress: input.market_address,
|
|
834
|
+
side: input.side,
|
|
835
|
+
amountUsdc: input.amount_usdc
|
|
836
|
+
});
|
|
837
|
+
return result;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// ========== GLOBAL CONFIG ==========
|
|
841
|
+
|
|
842
|
+
case 'get_pnp_config': {
|
|
843
|
+
const agent = await createAgent({ verbose: false });
|
|
844
|
+
const result = await agent.fetchGlobalConfig();
|
|
845
|
+
return result;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
default:
|
|
849
|
+
return { error: `Unknown market tool: ${name}` };
|
|
850
|
+
}
|
|
851
|
+
}
|