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,291 @@
|
|
|
1
|
+
// PNPFUCIUS - The PNP Exchange CLI
|
|
2
|
+
// No external LLM required - uses PNP's built-in oracle
|
|
3
|
+
|
|
4
|
+
import * as readline from 'readline';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { executeTool } from './tools/index.js';
|
|
7
|
+
import { printWelcome, printError, printHelp, printGoodbye } from './ui/welcome.js';
|
|
8
|
+
import { handleSlashCommand } from './slash-commands.js';
|
|
9
|
+
import { getConfig } from '../config.js';
|
|
10
|
+
|
|
11
|
+
// Purple color definitions
|
|
12
|
+
const purple = chalk.hex('#A855F7');
|
|
13
|
+
const purpleBright = chalk.hex('#C084FC');
|
|
14
|
+
const purpleDim = chalk.hex('#7C3AED');
|
|
15
|
+
const violet = chalk.hex('#8B5CF6');
|
|
16
|
+
|
|
17
|
+
export class PnpfuciusAgent {
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.config = getConfig();
|
|
20
|
+
this.verbose = options.verbose ?? false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Main entry point - run the interactive CLI
|
|
25
|
+
*/
|
|
26
|
+
async run() {
|
|
27
|
+
printWelcome();
|
|
28
|
+
|
|
29
|
+
console.log(chalk.dim(' Type ') + purple('/help') + chalk.dim(' for commands or enter a command directly.'));
|
|
30
|
+
console.log();
|
|
31
|
+
|
|
32
|
+
const rl = readline.createInterface({
|
|
33
|
+
input: process.stdin,
|
|
34
|
+
output: process.stdout
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Handle Ctrl+C gracefully
|
|
38
|
+
rl.on('SIGINT', () => {
|
|
39
|
+
printGoodbye();
|
|
40
|
+
process.exit(0);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
while (true) {
|
|
44
|
+
try {
|
|
45
|
+
const userInput = await this.prompt(rl);
|
|
46
|
+
|
|
47
|
+
if (!userInput.trim()) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Handle slash commands
|
|
52
|
+
const result = await handleSlashCommand(userInput, {
|
|
53
|
+
agent: this,
|
|
54
|
+
executeTool: this.executeTool.bind(this)
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (result === true) {
|
|
58
|
+
// Command was handled
|
|
59
|
+
continue;
|
|
60
|
+
} else if (result === false) {
|
|
61
|
+
// Not a slash command - show help
|
|
62
|
+
console.log(purpleDim('\n ◆ Unknown command. Type /help for available commands.\n'));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error.code === 'ERR_USE_AFTER_CLOSE') {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
printError(error.message);
|
|
70
|
+
if (this.verbose) {
|
|
71
|
+
console.error(error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Prompt user for input
|
|
79
|
+
*/
|
|
80
|
+
async prompt(rl) {
|
|
81
|
+
return new Promise((resolve) => {
|
|
82
|
+
rl.question(purple('\n❯ '), (answer) => {
|
|
83
|
+
resolve(answer);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Execute a tool and display results
|
|
90
|
+
*/
|
|
91
|
+
async executeTool(toolName, input) {
|
|
92
|
+
console.log(purpleDim(`\n ◆ ${toolName}`));
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const result = await executeTool(toolName, input);
|
|
96
|
+
|
|
97
|
+
if (result.error) {
|
|
98
|
+
console.log(chalk.red(` ✗ ${result.error}`));
|
|
99
|
+
} else {
|
|
100
|
+
console.log(purple(` ✓ Done`));
|
|
101
|
+
this.displayResult(toolName, result);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return result;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.log(chalk.red(` ✗ ${error.message}`));
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Display tool result in a nice format
|
|
113
|
+
*/
|
|
114
|
+
displayResult(toolName, result) {
|
|
115
|
+
console.log();
|
|
116
|
+
|
|
117
|
+
switch (toolName) {
|
|
118
|
+
case 'discover_all_markets':
|
|
119
|
+
this.displayMarketDiscovery(result);
|
|
120
|
+
break;
|
|
121
|
+
case 'get_market_info':
|
|
122
|
+
case 'get_v2_market_info':
|
|
123
|
+
case 'get_p2p_market_info':
|
|
124
|
+
this.displayMarketInfo(result);
|
|
125
|
+
break;
|
|
126
|
+
case 'get_market_prices':
|
|
127
|
+
this.displayPrices(result);
|
|
128
|
+
break;
|
|
129
|
+
case 'get_balances':
|
|
130
|
+
this.displayBalances(result);
|
|
131
|
+
break;
|
|
132
|
+
case 'create_market':
|
|
133
|
+
case 'create_p2p_market_simple':
|
|
134
|
+
case 'create_amm_market_with_odds':
|
|
135
|
+
this.displayMarketCreation(result);
|
|
136
|
+
break;
|
|
137
|
+
case 'buy_tokens':
|
|
138
|
+
case 'sell_tokens':
|
|
139
|
+
case 'buy_v3_tokens':
|
|
140
|
+
this.displayTrade(result);
|
|
141
|
+
break;
|
|
142
|
+
case 'get_settlement_criteria':
|
|
143
|
+
this.displaySettlementCriteria(result);
|
|
144
|
+
break;
|
|
145
|
+
case 'get_settlement_data':
|
|
146
|
+
this.displaySettlementData(result);
|
|
147
|
+
break;
|
|
148
|
+
case 'redeem_position':
|
|
149
|
+
case 'redeem_v3_position':
|
|
150
|
+
case 'redeem_p2p_position':
|
|
151
|
+
this.displayRedemption(result);
|
|
152
|
+
break;
|
|
153
|
+
case 'get_pnp_config':
|
|
154
|
+
this.displayPnpConfig(result);
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
// Generic JSON display
|
|
158
|
+
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
displayMarketDiscovery(result) {
|
|
163
|
+
const v2Count = result.v2_markets?.length || 0;
|
|
164
|
+
const v3Count = result.v3_markets?.length || 0;
|
|
165
|
+
|
|
166
|
+
console.log(purpleBright(` Found ${result.total || v2Count + v3Count} markets on PNP Exchange\n`));
|
|
167
|
+
|
|
168
|
+
if (v2Count > 0) {
|
|
169
|
+
console.log(violet(' V2 Markets (AMM)'));
|
|
170
|
+
for (const addr of result.v2_markets.slice(0, 5)) {
|
|
171
|
+
console.log(` ${purple('◆')} ${chalk.dim(addr)}`);
|
|
172
|
+
}
|
|
173
|
+
if (v2Count > 5) console.log(chalk.dim(` ... and ${v2Count - 5} more`));
|
|
174
|
+
console.log();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (v3Count > 0) {
|
|
178
|
+
console.log(violet(' V3 Markets (P2P)'));
|
|
179
|
+
for (const addr of result.v3_markets.slice(0, 5)) {
|
|
180
|
+
console.log(` ${purple('◆')} ${chalk.dim(addr)}`);
|
|
181
|
+
}
|
|
182
|
+
if (v3Count > 5) console.log(chalk.dim(` ... and ${v3Count - 5} more`));
|
|
183
|
+
console.log();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
console.log(chalk.dim(' Use /info <address> for market details'));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
displayMarketInfo(result) {
|
|
190
|
+
const info = result.info || result;
|
|
191
|
+
console.log(purpleBright(' Market Info\n'));
|
|
192
|
+
|
|
193
|
+
if (info.question) console.log(` ${chalk.dim('Question:')} ${info.question}`);
|
|
194
|
+
if (info.market || result.market) console.log(` ${chalk.dim('Address:')} ${violet(info.market || result.market)}`);
|
|
195
|
+
if (info.endTime) console.log(` ${chalk.dim('End Time:')} ${new Date(Number(info.endTime) * 1000).toLocaleString()}`);
|
|
196
|
+
if (info.yesTokenMint) console.log(` ${chalk.dim('YES Mint:')} ${chalk.dim(info.yesTokenMint)}`);
|
|
197
|
+
if (info.noTokenMint) console.log(` ${chalk.dim('NO Mint:')} ${chalk.dim(info.noTokenMint)}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
displayPrices(result) {
|
|
201
|
+
console.log(purpleBright(' Market Prices\n'));
|
|
202
|
+
console.log(` ${chalk.green('YES:')} ${result.yesPrice || 'N/A'}`);
|
|
203
|
+
console.log(` ${chalk.red('NO:')} ${result.noPrice || 'N/A'}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
displayBalances(result) {
|
|
207
|
+
console.log(purpleBright(' Your Balances\n'));
|
|
208
|
+
console.log(` ${chalk.green('YES tokens:')} ${result.yesBalance || 0}`);
|
|
209
|
+
console.log(` ${chalk.red('NO tokens:')} ${result.noBalance || 0}`);
|
|
210
|
+
if (result.usdcBalance) console.log(` ${chalk.dim('USDC:')} ${result.usdcBalance}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
displayMarketCreation(result) {
|
|
214
|
+
console.log(purpleBright(' Market Created!\n'));
|
|
215
|
+
console.log(` ${chalk.dim('Address:')} ${violet(result.market)}`);
|
|
216
|
+
console.log(` ${chalk.dim('Signature:')} ${chalk.dim(result.signature?.slice(0, 30) + '...')}`);
|
|
217
|
+
console.log(` ${chalk.dim('Network:')} ${result.network}`);
|
|
218
|
+
console.log();
|
|
219
|
+
console.log(chalk.dim(` View on Solscan: https://solscan.io/tx/${result.signature}`));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
displayTrade(result) {
|
|
223
|
+
console.log(purpleBright(' Trade Executed!\n'));
|
|
224
|
+
console.log(` ${chalk.dim('Market:')} ${result.market}`);
|
|
225
|
+
console.log(` ${chalk.dim('Side:')} ${result.side?.toUpperCase()}`);
|
|
226
|
+
console.log(` ${chalk.dim('Amount:')} ${result.amount || result.amountUsdc} USDC`);
|
|
227
|
+
console.log(` ${chalk.dim('Signature:')} ${chalk.dim(result.signature?.slice(0, 30) + '...')}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
displaySettlementCriteria(result) {
|
|
231
|
+
console.log(purpleBright(' PNP Oracle - Settlement Criteria\n'));
|
|
232
|
+
|
|
233
|
+
if (result.criteria) {
|
|
234
|
+
if (typeof result.criteria === 'string') {
|
|
235
|
+
console.log(` ${result.criteria}`);
|
|
236
|
+
} else {
|
|
237
|
+
console.log(chalk.dim(JSON.stringify(result.criteria, null, 2)));
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
console.log(chalk.dim(' No criteria available yet'));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
displaySettlementData(result) {
|
|
245
|
+
console.log(purpleBright(' PNP Oracle - Settlement Data\n'));
|
|
246
|
+
|
|
247
|
+
if (result.data) {
|
|
248
|
+
if (result.data.answer) {
|
|
249
|
+
console.log(` ${chalk.dim('Answer:')} ${result.data.answer === 'yes' ? chalk.green('YES') : chalk.red('NO')}`);
|
|
250
|
+
}
|
|
251
|
+
if (result.data.resolvable !== undefined) {
|
|
252
|
+
console.log(` ${chalk.dim('Resolvable:')} ${result.data.resolvable ? chalk.green('Yes') : chalk.yellow('Not yet')}`);
|
|
253
|
+
}
|
|
254
|
+
if (result.data.reasoning) {
|
|
255
|
+
console.log(` ${chalk.dim('Reasoning:')} ${result.data.reasoning}`);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
console.log(chalk.dim(' No settlement data available yet'));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
displayRedemption(result) {
|
|
263
|
+
console.log(purpleBright(' Position Redeemed!\n'));
|
|
264
|
+
console.log(` ${chalk.dim('Market:')} ${result.market}`);
|
|
265
|
+
console.log(` ${chalk.dim('Signature:')} ${chalk.dim(result.signature?.slice(0, 30) + '...')}`);
|
|
266
|
+
console.log();
|
|
267
|
+
console.log(chalk.green(' Winnings have been sent to your wallet!'));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
displayPnpConfig(result) {
|
|
271
|
+
console.log(purpleBright(' PNP Exchange Configuration\n'));
|
|
272
|
+
|
|
273
|
+
if (result.config) {
|
|
274
|
+
if (result.config.publicKey) {
|
|
275
|
+
console.log(` ${chalk.dim('Config Address:')} ${result.config.publicKey}`);
|
|
276
|
+
}
|
|
277
|
+
if (result.config.account) {
|
|
278
|
+
console.log(chalk.dim(JSON.stringify(result.config.account, null, 2)));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Export factory function
|
|
285
|
+
export function createPnpfuciusAgent(options = {}) {
|
|
286
|
+
return new PnpfuciusAgent(options);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Backwards compatibility
|
|
290
|
+
export const ClaudePredictAgent = PnpfuciusAgent;
|
|
291
|
+
export const createPredictAgent = createPnpfuciusAgent;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// System prompts for Claude Predict
|
|
2
|
+
|
|
3
|
+
export const SYSTEM_PROMPT = `You are Claude Predict, an advanced AI agent for prediction markets on Solana's PNP Exchange.
|
|
4
|
+
|
|
5
|
+
## Core Capabilities
|
|
6
|
+
|
|
7
|
+
You have FULL integration with PNP Exchange protocol, including:
|
|
8
|
+
|
|
9
|
+
### Market Creation
|
|
10
|
+
- **AMM Markets**: Standard liquidity pool markets (create_market)
|
|
11
|
+
- **P2P Markets**: Direct peer-to-peer betting (create_p2p_market_simple)
|
|
12
|
+
- **Custom Odds**: Create markets with specific starting odds (create_amm_market_with_odds, create_p2p_market_with_odds)
|
|
13
|
+
- **Custom Oracle**: Create markets with your own settlement authority (create_market_with_oracle)
|
|
14
|
+
- **Source-Linked**: Markets tied to Twitter, YouTube, or DeFi metrics (create_market_from_source)
|
|
15
|
+
|
|
16
|
+
### Market Discovery
|
|
17
|
+
- **Discover All Markets**: Browse ALL PNP markets, not just yours (discover_all_markets)
|
|
18
|
+
- **Market Metadata**: Volume, images, analytics (get_market_metadata)
|
|
19
|
+
- **V2 Market Info**: AMM market details with multipliers (get_v2_market_info)
|
|
20
|
+
- **P2P Market Info**: P2P reserves and settlement data (get_p2p_market_info)
|
|
21
|
+
|
|
22
|
+
### Trading
|
|
23
|
+
- **Buy Tokens**: Purchase YES/NO tokens with USDC (buy_tokens, buy_v3_tokens)
|
|
24
|
+
- **Sell Tokens**: Sell positions back for USDC (sell_tokens)
|
|
25
|
+
- **Get Prices**: Current market prices and shares (get_market_prices)
|
|
26
|
+
- **Get Balances**: Your token holdings (get_balances)
|
|
27
|
+
|
|
28
|
+
### PNP Oracle & Settlement (LLM-Powered)
|
|
29
|
+
- **Settlement Criteria**: Get AI-generated criteria for how markets resolve (get_settlement_criteria)
|
|
30
|
+
- **Settlement Data**: Get resolution results from PNP's LLM oracle (get_settlement_data)
|
|
31
|
+
- **Wait for Settlement**: Poll until criteria is available (wait_for_settlement)
|
|
32
|
+
- **Settle Market**: Execute settlement with outcome (settle_market) - requires authority
|
|
33
|
+
|
|
34
|
+
### Redemption
|
|
35
|
+
- **Redeem Position**: Claim winnings from resolved markets (redeem_position, redeem_v3_position, redeem_p2p_position)
|
|
36
|
+
- **Claim Refund**: Get refunds from cancelled markets (claim_refund, claim_p2p_refund)
|
|
37
|
+
|
|
38
|
+
### News & AI Scoring
|
|
39
|
+
- **Score News**: AI relevance scoring 0-100 (score_news)
|
|
40
|
+
- **Fetch News**: Get latest privacy news from RSS feeds (fetch_news)
|
|
41
|
+
- **Generate from News**: Create markets from news items (generate_from_news)
|
|
42
|
+
|
|
43
|
+
### Protocol Info
|
|
44
|
+
- **PNP Config**: Get global protocol settings (get_pnp_config)
|
|
45
|
+
|
|
46
|
+
## Privacy Market Categories
|
|
47
|
+
1. **Regulation** - GDPR fines, federal privacy laws, encryption bans, sanctions
|
|
48
|
+
2. **Technology** - ZK adoption, Tornado Cash, confidential transfers, Aztec, RAILGUN
|
|
49
|
+
3. **Adoption** - Signal/Brave users, privacy coin delistings, enterprise ZK
|
|
50
|
+
4. **Events** - Data breaches, surveillance scandals, hackathons, whistleblowers
|
|
51
|
+
|
|
52
|
+
## Guidelines
|
|
53
|
+
|
|
54
|
+
- Be proactive: When users mention news/events, offer to score and create markets
|
|
55
|
+
- When creating markets, suggest appropriate durations (7-365 days) and liquidity based on topic
|
|
56
|
+
- For P2P markets, explain how custom odds work and ask about risk tolerance
|
|
57
|
+
- Use the discover_all_markets tool to show users trading opportunities
|
|
58
|
+
- When checking resolution, first get settlement criteria then settlement data
|
|
59
|
+
- Format responses in markdown with code blocks for addresses/signatures
|
|
60
|
+
- Keep responses concise but informative
|
|
61
|
+
- After tool results, summarize outcomes clearly`;
|
|
62
|
+
|
|
63
|
+
export const WELCOME_MESSAGE = `Type a message to get started, or try:
|
|
64
|
+
- "Generate 3 market ideas about GDPR"
|
|
65
|
+
- "Create a market about Tornado Cash sanctions"
|
|
66
|
+
- "Discover all markets on PNP Exchange"
|
|
67
|
+
- "Create a P2P bet on the next privacy regulation"
|
|
68
|
+
- "Score this news: EU proposes encryption backdoors"
|
|
69
|
+
- /help for all commands`;
|