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
package/src/agent.js
ADDED
|
@@ -0,0 +1,1037 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { PNPClient } from 'pnp-sdk';
|
|
3
|
+
import { getConfig, validateConfig } from './config.js';
|
|
4
|
+
import { generatePrivacyMarket, generateMultipleMarkets } from './privacy-markets.js';
|
|
5
|
+
|
|
6
|
+
export class PrivacyOracleAgent {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.config = options.config || getConfig();
|
|
9
|
+
this.client = null;
|
|
10
|
+
this.initialized = false;
|
|
11
|
+
this.verbose = options.verbose || false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
log(message, level = 'info') {
|
|
15
|
+
if (this.verbose || level === 'error') {
|
|
16
|
+
const prefix = level === 'error' ? '[ERROR]' : '[INFO]';
|
|
17
|
+
console.log(`${prefix} ${message}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async initialize() {
|
|
22
|
+
if (this.initialized) return;
|
|
23
|
+
|
|
24
|
+
const validation = validateConfig(this.config);
|
|
25
|
+
|
|
26
|
+
if (validation.warnings.length > 0) {
|
|
27
|
+
validation.warnings.forEach(w => this.log(w, 'warn'));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!validation.valid && this.config.walletKey) {
|
|
31
|
+
throw new Error(`Configuration errors: ${validation.errors.join(', ')}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.log(`Connecting to ${this.config.network} via Helius RPC...`);
|
|
35
|
+
|
|
36
|
+
if (this.config.walletKey) {
|
|
37
|
+
let privateKey = this.config.walletKey;
|
|
38
|
+
|
|
39
|
+
if (typeof privateKey === 'string') {
|
|
40
|
+
if (privateKey.startsWith('[')) {
|
|
41
|
+
privateKey = Uint8Array.from(JSON.parse(privateKey));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.client = new PNPClient(this.config.rpcUrl, privateKey);
|
|
46
|
+
this.log('Client initialized with signer');
|
|
47
|
+
} else {
|
|
48
|
+
this.client = new PNPClient(this.config.rpcUrl);
|
|
49
|
+
this.log('Client initialized in read-only mode');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.initialized = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async createMarket(options) {
|
|
56
|
+
await this.initialize();
|
|
57
|
+
|
|
58
|
+
if (!this.client.market) {
|
|
59
|
+
throw new Error('Market module not available. Ensure wallet is configured.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const question = options.question;
|
|
63
|
+
const durationDays = options.durationDays || this.config.defaultDurationDays;
|
|
64
|
+
const liquidity = options.liquidity || this.config.defaultLiquidity;
|
|
65
|
+
|
|
66
|
+
const endTime = BigInt(Math.floor(Date.now() / 1000) + (durationDays * 24 * 60 * 60));
|
|
67
|
+
|
|
68
|
+
this.log(`Creating market: "${question}"`);
|
|
69
|
+
this.log(`Duration: ${durationDays} days, Liquidity: ${liquidity}`);
|
|
70
|
+
|
|
71
|
+
const result = await this.client.market.createMarket({
|
|
72
|
+
question,
|
|
73
|
+
initialLiquidity: liquidity,
|
|
74
|
+
endTime,
|
|
75
|
+
baseMint: this.config.collateralMint
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
success: true,
|
|
80
|
+
signature: result.signature,
|
|
81
|
+
market: result.market?.toBase58?.() || result.market?.toString?.() || result.market,
|
|
82
|
+
question,
|
|
83
|
+
durationDays,
|
|
84
|
+
liquidity: liquidity.toString()
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async createP2PMarket(options) {
|
|
89
|
+
await this.initialize();
|
|
90
|
+
|
|
91
|
+
const question = options.question;
|
|
92
|
+
const side = options.side || 'yes';
|
|
93
|
+
const amount = options.amount || this.config.defaultLiquidity;
|
|
94
|
+
const cap = options.cap || amount * 5n;
|
|
95
|
+
const durationDays = options.durationDays || this.config.defaultDurationDays;
|
|
96
|
+
|
|
97
|
+
const endTime = BigInt(Math.floor(Date.now() / 1000) + (durationDays * 24 * 60 * 60));
|
|
98
|
+
|
|
99
|
+
this.log(`Creating P2P market: "${question}"`);
|
|
100
|
+
this.log(`Side: ${side}, Amount: ${amount}, Cap: ${cap}`);
|
|
101
|
+
|
|
102
|
+
const result = await this.client.createP2PMarketGeneral({
|
|
103
|
+
question,
|
|
104
|
+
initialAmount: amount,
|
|
105
|
+
side,
|
|
106
|
+
creatorSideCap: cap,
|
|
107
|
+
endTime,
|
|
108
|
+
collateralTokenMint: this.config.collateralMint
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
success: true,
|
|
113
|
+
signature: result.signature,
|
|
114
|
+
market: result.market,
|
|
115
|
+
yesTokenMint: result.yesTokenMint,
|
|
116
|
+
noTokenMint: result.noTokenMint,
|
|
117
|
+
question,
|
|
118
|
+
side,
|
|
119
|
+
durationDays
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async createPrivacyMarket(options = {}) {
|
|
124
|
+
const marketIdea = generatePrivacyMarket();
|
|
125
|
+
|
|
126
|
+
this.log(`Generated market idea: ${marketIdea.category}`);
|
|
127
|
+
|
|
128
|
+
return this.createMarket({
|
|
129
|
+
question: options.question || marketIdea.question,
|
|
130
|
+
durationDays: options.durationDays || marketIdea.durationDays,
|
|
131
|
+
liquidity: options.liquidity || marketIdea.suggestedLiquidity
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async createBatchMarkets(count = 3) {
|
|
136
|
+
await this.initialize();
|
|
137
|
+
|
|
138
|
+
const ideas = generateMultipleMarkets(count);
|
|
139
|
+
const results = [];
|
|
140
|
+
|
|
141
|
+
for (const idea of ideas) {
|
|
142
|
+
try {
|
|
143
|
+
this.log(`Creating: "${idea.question}"`);
|
|
144
|
+
|
|
145
|
+
const result = await this.createMarket({
|
|
146
|
+
question: idea.question,
|
|
147
|
+
durationDays: idea.durationDays,
|
|
148
|
+
liquidity: idea.suggestedLiquidity
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
results.push({ ...result, category: idea.category });
|
|
152
|
+
|
|
153
|
+
await this.sleep(2000);
|
|
154
|
+
|
|
155
|
+
} catch (error) {
|
|
156
|
+
results.push({
|
|
157
|
+
success: false,
|
|
158
|
+
question: idea.question,
|
|
159
|
+
error: error.message
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return results;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async fetchMarkets() {
|
|
168
|
+
await this.initialize();
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const response = await this.client.fetchMarkets();
|
|
172
|
+
return response;
|
|
173
|
+
} catch (error) {
|
|
174
|
+
this.log(`Error fetching markets: ${error.message}`, 'error');
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async fetchMarketInfo(marketAddress) {
|
|
180
|
+
await this.initialize();
|
|
181
|
+
|
|
182
|
+
const market = new PublicKey(marketAddress);
|
|
183
|
+
const info = await this.client.fetchMarket(market);
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
address: marketAddress,
|
|
187
|
+
question: info.account.question,
|
|
188
|
+
creator: new PublicKey(info.account.creator).toBase58(),
|
|
189
|
+
resolved: info.account.resolved,
|
|
190
|
+
resolvable: info.account.resolvable,
|
|
191
|
+
endTime: new Date(Number(info.account.end_time) * 1000),
|
|
192
|
+
winningToken: info.account.winning_token_id || null
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async getMarketAddresses() {
|
|
197
|
+
await this.initialize();
|
|
198
|
+
return this.client.fetchMarketAddresses();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ========== TRADING METHODS ==========
|
|
202
|
+
|
|
203
|
+
async buyTokens(options) {
|
|
204
|
+
await this.initialize();
|
|
205
|
+
|
|
206
|
+
const { marketAddress, side, amountUsdc } = options;
|
|
207
|
+
const market = new PublicKey(marketAddress);
|
|
208
|
+
|
|
209
|
+
this.log(`Buying ${side.toUpperCase()} tokens for ${amountUsdc} USDC on ${marketAddress}`);
|
|
210
|
+
|
|
211
|
+
if (!this.client.trading) {
|
|
212
|
+
throw new Error('Trading module not available. Ensure wallet is configured.');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const result = await this.client.trading.buyTokensUsdc({
|
|
216
|
+
market,
|
|
217
|
+
usdcAmount: BigInt(Math.floor(amountUsdc * 1_000_000)),
|
|
218
|
+
tokenId: side === 'yes' ? 0 : 1
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
success: true,
|
|
223
|
+
signature: result.signature,
|
|
224
|
+
market: marketAddress,
|
|
225
|
+
side,
|
|
226
|
+
amountUsdc,
|
|
227
|
+
tokensReceived: result.tokensReceived?.toString() || 'unknown'
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async sellTokens(options) {
|
|
232
|
+
await this.initialize();
|
|
233
|
+
|
|
234
|
+
const { marketAddress, side, amount } = options;
|
|
235
|
+
const market = new PublicKey(marketAddress);
|
|
236
|
+
|
|
237
|
+
this.log(`Selling ${amount} ${side.toUpperCase()} tokens on ${marketAddress}`);
|
|
238
|
+
|
|
239
|
+
if (!this.client.trading) {
|
|
240
|
+
throw new Error('Trading module not available. Ensure wallet is configured.');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const result = await this.client.trading.sellTokensBase({
|
|
244
|
+
market,
|
|
245
|
+
tokenAmount: BigInt(Math.floor(amount * 1_000_000)),
|
|
246
|
+
tokenId: side === 'yes' ? 0 : 1
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
success: true,
|
|
251
|
+
signature: result.signature,
|
|
252
|
+
market: marketAddress,
|
|
253
|
+
side,
|
|
254
|
+
amount,
|
|
255
|
+
usdcReceived: result.usdcReceived?.toString() || 'unknown'
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async getMarketPrices(marketAddress) {
|
|
260
|
+
await this.initialize();
|
|
261
|
+
|
|
262
|
+
const market = new PublicKey(marketAddress);
|
|
263
|
+
|
|
264
|
+
if (this.client.trading?.getPrices) {
|
|
265
|
+
const prices = await this.client.trading.getPrices(market);
|
|
266
|
+
return {
|
|
267
|
+
market: marketAddress,
|
|
268
|
+
yesPrice: prices.yesPrice || prices[0],
|
|
269
|
+
noPrice: prices.noPrice || prices[1],
|
|
270
|
+
timestamp: new Date().toISOString()
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Fallback: fetch market info and calculate from pool
|
|
275
|
+
const info = await this.client.fetchMarket(market);
|
|
276
|
+
return {
|
|
277
|
+
market: marketAddress,
|
|
278
|
+
yesPrice: 'N/A - use fetchMarket for pool data',
|
|
279
|
+
noPrice: 'N/A - use fetchMarket for pool data',
|
|
280
|
+
raw: info
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async getBalances(marketAddress) {
|
|
285
|
+
await this.initialize();
|
|
286
|
+
|
|
287
|
+
const market = new PublicKey(marketAddress);
|
|
288
|
+
|
|
289
|
+
if (this.client.trading?.getBalances) {
|
|
290
|
+
const balances = await this.client.trading.getBalances(market);
|
|
291
|
+
return {
|
|
292
|
+
market: marketAddress,
|
|
293
|
+
yesBalance: balances.yesBalance?.toString() || '0',
|
|
294
|
+
noBalance: balances.noBalance?.toString() || '0'
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
market: marketAddress,
|
|
300
|
+
yesBalance: '0',
|
|
301
|
+
noBalance: '0',
|
|
302
|
+
note: 'Balance check requires wallet connection'
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ========== REDEMPTION METHODS ==========
|
|
307
|
+
|
|
308
|
+
async redeemPosition(marketAddress) {
|
|
309
|
+
await this.initialize();
|
|
310
|
+
|
|
311
|
+
const market = new PublicKey(marketAddress);
|
|
312
|
+
|
|
313
|
+
this.log(`Redeeming position on ${marketAddress}`);
|
|
314
|
+
|
|
315
|
+
const result = await this.client.redeemPosition(market);
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
success: true,
|
|
319
|
+
signature: result.signature,
|
|
320
|
+
market: marketAddress,
|
|
321
|
+
amountRedeemed: result.amount?.toString() || 'unknown'
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
async claimRefund(marketAddress) {
|
|
326
|
+
await this.initialize();
|
|
327
|
+
|
|
328
|
+
const market = new PublicKey(marketAddress);
|
|
329
|
+
|
|
330
|
+
this.log(`Claiming refund on ${marketAddress}`);
|
|
331
|
+
|
|
332
|
+
const result = await this.client.claimMarketRefund(market);
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
success: true,
|
|
336
|
+
signature: result.signature,
|
|
337
|
+
market: marketAddress,
|
|
338
|
+
amountRefunded: result.amount?.toString() || 'unknown'
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ========== URL-AWARE MARKET CREATION ==========
|
|
343
|
+
|
|
344
|
+
async createMarketFromSource(options) {
|
|
345
|
+
await this.initialize();
|
|
346
|
+
|
|
347
|
+
const { question, sourceUrl, sourceType, durationDays, liquidity } = options;
|
|
348
|
+
const endTime = BigInt(Math.floor(Date.now() / 1000) + ((durationDays || 30) * 24 * 60 * 60));
|
|
349
|
+
const amount = liquidity || this.config.defaultLiquidity;
|
|
350
|
+
|
|
351
|
+
this.log(`Creating ${sourceType || 'standard'} market: "${question}"`);
|
|
352
|
+
|
|
353
|
+
let result;
|
|
354
|
+
|
|
355
|
+
if (sourceType === 'twitter' && this.client.createMarketTwitter) {
|
|
356
|
+
result = await this.client.createMarketTwitter({
|
|
357
|
+
question,
|
|
358
|
+
tweetUrl: sourceUrl,
|
|
359
|
+
initialLiquidity: amount,
|
|
360
|
+
endTime,
|
|
361
|
+
baseMint: this.config.collateralMint
|
|
362
|
+
});
|
|
363
|
+
} else if (sourceType === 'youtube' && this.client.createMarketYoutube) {
|
|
364
|
+
result = await this.client.createMarketYoutube({
|
|
365
|
+
question,
|
|
366
|
+
youtubeUrl: sourceUrl,
|
|
367
|
+
initialLiquidity: amount,
|
|
368
|
+
endTime,
|
|
369
|
+
baseMint: this.config.collateralMint
|
|
370
|
+
});
|
|
371
|
+
} else if (sourceType === 'defi' && this.client.createMarketDefiLlama) {
|
|
372
|
+
result = await this.client.createMarketDefiLlama({
|
|
373
|
+
question,
|
|
374
|
+
metric: sourceUrl,
|
|
375
|
+
initialLiquidity: amount,
|
|
376
|
+
endTime,
|
|
377
|
+
baseMint: this.config.collateralMint
|
|
378
|
+
});
|
|
379
|
+
} else {
|
|
380
|
+
// Fallback to standard market creation
|
|
381
|
+
result = await this.client.market.createMarket({
|
|
382
|
+
question,
|
|
383
|
+
initialLiquidity: amount,
|
|
384
|
+
endTime,
|
|
385
|
+
baseMint: this.config.collateralMint
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
success: true,
|
|
391
|
+
signature: result.signature,
|
|
392
|
+
market: result.market?.toBase58?.() || result.market?.toString?.() || result.market,
|
|
393
|
+
question,
|
|
394
|
+
sourceType: sourceType || 'standard',
|
|
395
|
+
sourceUrl
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
sleep(ms) {
|
|
400
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ========== PNP ORACLE/SETTLEMENT METHODS ==========
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Fetch settlement criteria from PNP's LLM oracle
|
|
407
|
+
* This returns the AI-generated criteria for how the market should be resolved
|
|
408
|
+
*/
|
|
409
|
+
async fetchSettlementCriteria(marketAddress, options = {}) {
|
|
410
|
+
await this.initialize();
|
|
411
|
+
|
|
412
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
413
|
+
|
|
414
|
+
this.log(`Fetching settlement criteria for ${market}`);
|
|
415
|
+
|
|
416
|
+
try {
|
|
417
|
+
const criteria = await this.client.fetchSettlementCriteria(market, options.baseUrl);
|
|
418
|
+
return {
|
|
419
|
+
success: true,
|
|
420
|
+
market,
|
|
421
|
+
criteria
|
|
422
|
+
};
|
|
423
|
+
} catch (error) {
|
|
424
|
+
this.log(`Error fetching settlement criteria: ${error.message}`, 'error');
|
|
425
|
+
throw error;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Get settlement data (resolution result) from PNP's LLM oracle
|
|
431
|
+
*/
|
|
432
|
+
async getSettlementData(marketAddress, options = {}) {
|
|
433
|
+
await this.initialize();
|
|
434
|
+
|
|
435
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
436
|
+
|
|
437
|
+
this.log(`Fetching settlement data for ${market}`);
|
|
438
|
+
|
|
439
|
+
try {
|
|
440
|
+
const data = await this.client.getSettlementData(market, options.baseUrl);
|
|
441
|
+
return {
|
|
442
|
+
success: true,
|
|
443
|
+
market,
|
|
444
|
+
data
|
|
445
|
+
};
|
|
446
|
+
} catch (error) {
|
|
447
|
+
this.log(`Error fetching settlement data: ${error.message}`, 'error');
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Wait for settlement criteria to become available (with retries)
|
|
454
|
+
*/
|
|
455
|
+
async waitForSettlementCriteria(marketAddress, options = {}) {
|
|
456
|
+
await this.initialize();
|
|
457
|
+
|
|
458
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
459
|
+
const { retryDelayMs = 2000, maxRetryTimeMs = 30000, baseUrl } = options;
|
|
460
|
+
|
|
461
|
+
this.log(`Waiting for settlement criteria for ${market}...`);
|
|
462
|
+
|
|
463
|
+
try {
|
|
464
|
+
const result = await this.client.waitForSettlementCriteria(market, baseUrl, {
|
|
465
|
+
retryDelayMs,
|
|
466
|
+
maxRetryTimeMs
|
|
467
|
+
});
|
|
468
|
+
return {
|
|
469
|
+
success: true,
|
|
470
|
+
market,
|
|
471
|
+
resolvable: result.resolvable,
|
|
472
|
+
answer: result.answer,
|
|
473
|
+
criteria: result.criteria
|
|
474
|
+
};
|
|
475
|
+
} catch (error) {
|
|
476
|
+
this.log(`Error waiting for settlement criteria: ${error.message}`, 'error');
|
|
477
|
+
throw error;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Settle a market using the oracle (set the winning outcome)
|
|
483
|
+
* NOTE: This requires oracle authority
|
|
484
|
+
*/
|
|
485
|
+
async settleMarket(marketAddress, yesWinner) {
|
|
486
|
+
await this.initialize();
|
|
487
|
+
|
|
488
|
+
const market = new PublicKey(marketAddress);
|
|
489
|
+
|
|
490
|
+
this.log(`Settling market ${marketAddress} with outcome: ${yesWinner ? 'YES' : 'NO'}`);
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
const result = await this.client.settleMarket({
|
|
494
|
+
market,
|
|
495
|
+
yesWinner
|
|
496
|
+
});
|
|
497
|
+
return {
|
|
498
|
+
success: true,
|
|
499
|
+
signature: result.signature,
|
|
500
|
+
market: marketAddress,
|
|
501
|
+
outcome: yesWinner ? 'yes' : 'no'
|
|
502
|
+
};
|
|
503
|
+
} catch (error) {
|
|
504
|
+
this.log(`Error settling market: ${error.message}`, 'error');
|
|
505
|
+
throw error;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Set market as resolvable (devnet only)
|
|
511
|
+
*/
|
|
512
|
+
async setMarketResolvable(marketAddress, resolvable = true, forceResolve = false) {
|
|
513
|
+
await this.initialize();
|
|
514
|
+
|
|
515
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
516
|
+
|
|
517
|
+
this.log(`Setting market ${market} resolvable: ${resolvable}`);
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
const result = await this.client.setMarketResolvable(market, resolvable, forceResolve);
|
|
521
|
+
return {
|
|
522
|
+
success: true,
|
|
523
|
+
signature: result.signature,
|
|
524
|
+
market,
|
|
525
|
+
resolvable
|
|
526
|
+
};
|
|
527
|
+
} catch (error) {
|
|
528
|
+
this.log(`Error setting resolvable: ${error.message}`, 'error');
|
|
529
|
+
throw error;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// ========== MARKET DISCOVERY METHODS ==========
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Discover all markets on PNP Exchange (not just created by this agent)
|
|
537
|
+
*/
|
|
538
|
+
async discoverMarkets(options = {}) {
|
|
539
|
+
await this.initialize();
|
|
540
|
+
|
|
541
|
+
this.log('Discovering all PNP markets...');
|
|
542
|
+
|
|
543
|
+
try {
|
|
544
|
+
const markets = await this.client.fetchMarkets();
|
|
545
|
+
return {
|
|
546
|
+
success: true,
|
|
547
|
+
markets: markets,
|
|
548
|
+
count: Array.isArray(markets) ? markets.length : Object.keys(markets).length
|
|
549
|
+
};
|
|
550
|
+
} catch (error) {
|
|
551
|
+
this.log(`Error discovering markets: ${error.message}`, 'error');
|
|
552
|
+
throw error;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Fetch all market addresses (V2)
|
|
558
|
+
*/
|
|
559
|
+
async fetchAllMarketAddresses(baseUrl) {
|
|
560
|
+
await this.initialize();
|
|
561
|
+
|
|
562
|
+
try {
|
|
563
|
+
const addresses = await this.client.fetchMarketAddresses(baseUrl);
|
|
564
|
+
return {
|
|
565
|
+
success: true,
|
|
566
|
+
addresses,
|
|
567
|
+
count: addresses.length
|
|
568
|
+
};
|
|
569
|
+
} catch (error) {
|
|
570
|
+
this.log(`Error fetching market addresses: ${error.message}`, 'error');
|
|
571
|
+
throw error;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Fetch all V3 market addresses
|
|
577
|
+
*/
|
|
578
|
+
async fetchV3MarketAddresses(baseUrl) {
|
|
579
|
+
await this.initialize();
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
const addresses = await this.client.fetchV3MarketAddresses(baseUrl);
|
|
583
|
+
return {
|
|
584
|
+
success: true,
|
|
585
|
+
addresses,
|
|
586
|
+
count: addresses.length
|
|
587
|
+
};
|
|
588
|
+
} catch (error) {
|
|
589
|
+
this.log(`Error fetching V3 market addresses: ${error.message}`, 'error');
|
|
590
|
+
throw error;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Get market metadata (volume, image, etc.)
|
|
596
|
+
*/
|
|
597
|
+
async getMarketMetadata(marketAddress, baseUrl) {
|
|
598
|
+
await this.initialize();
|
|
599
|
+
|
|
600
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
601
|
+
|
|
602
|
+
try {
|
|
603
|
+
const meta = await this.client.getMarketMeta(market, baseUrl);
|
|
604
|
+
return {
|
|
605
|
+
success: true,
|
|
606
|
+
market,
|
|
607
|
+
metadata: meta
|
|
608
|
+
};
|
|
609
|
+
} catch (error) {
|
|
610
|
+
this.log(`Error fetching market metadata: ${error.message}`, 'error');
|
|
611
|
+
throw error;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Get metadata for multiple markets at once
|
|
617
|
+
*/
|
|
618
|
+
async getMarketMetadataBatch(marketAddresses, baseUrl) {
|
|
619
|
+
await this.initialize();
|
|
620
|
+
|
|
621
|
+
const markets = marketAddresses.map(m => typeof m === 'string' ? m : m.toString());
|
|
622
|
+
|
|
623
|
+
try {
|
|
624
|
+
const metas = await this.client.getMarketMetaBatch(markets, baseUrl);
|
|
625
|
+
return {
|
|
626
|
+
success: true,
|
|
627
|
+
markets: metas,
|
|
628
|
+
count: metas.length
|
|
629
|
+
};
|
|
630
|
+
} catch (error) {
|
|
631
|
+
this.log(`Error fetching batch metadata: ${error.message}`, 'error');
|
|
632
|
+
throw error;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Get detailed V2 market info
|
|
638
|
+
*/
|
|
639
|
+
async getV2MarketInfo(marketAddress, options = {}) {
|
|
640
|
+
await this.initialize();
|
|
641
|
+
|
|
642
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
643
|
+
|
|
644
|
+
try {
|
|
645
|
+
const info = await this.client.getV2MarketInfo(market, options);
|
|
646
|
+
return {
|
|
647
|
+
success: true,
|
|
648
|
+
market,
|
|
649
|
+
info
|
|
650
|
+
};
|
|
651
|
+
} catch (error) {
|
|
652
|
+
this.log(`Error fetching V2 market info: ${error.message}`, 'error');
|
|
653
|
+
throw error;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Get detailed P2P market info
|
|
659
|
+
*/
|
|
660
|
+
async getP2PMarketInfo(marketAddress, options = {}) {
|
|
661
|
+
await this.initialize();
|
|
662
|
+
|
|
663
|
+
const market = typeof marketAddress === 'string' ? marketAddress : marketAddress.toString();
|
|
664
|
+
|
|
665
|
+
try {
|
|
666
|
+
const info = await this.client.getP2PMarketInfo(market, options);
|
|
667
|
+
return {
|
|
668
|
+
success: true,
|
|
669
|
+
market,
|
|
670
|
+
info
|
|
671
|
+
};
|
|
672
|
+
} catch (error) {
|
|
673
|
+
this.log(`Error fetching P2P market info: ${error.message}`, 'error');
|
|
674
|
+
throw error;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// ========== P2P MARKET WITH CUSTOM ODDS ==========
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Create a simple P2P market (UI-friendly with USDC amounts)
|
|
682
|
+
*/
|
|
683
|
+
async createP2PMarketSimple(options) {
|
|
684
|
+
await this.initialize();
|
|
685
|
+
|
|
686
|
+
const {
|
|
687
|
+
question,
|
|
688
|
+
side = 'yes',
|
|
689
|
+
amountUsdc = 1,
|
|
690
|
+
durationDays = 30,
|
|
691
|
+
capMultiplier = 5,
|
|
692
|
+
maxPotRatio
|
|
693
|
+
} = options;
|
|
694
|
+
|
|
695
|
+
this.log(`Creating simple P2P market: "${question}"`);
|
|
696
|
+
this.log(`Side: ${side}, Amount: ${amountUsdc} USDC, Cap multiplier: ${capMultiplier}x`);
|
|
697
|
+
|
|
698
|
+
try {
|
|
699
|
+
const result = await this.client.createP2PMarketSimple({
|
|
700
|
+
question,
|
|
701
|
+
side,
|
|
702
|
+
amountUsdc,
|
|
703
|
+
daysUntilEnd: durationDays,
|
|
704
|
+
creatorSideCapMultiplier: capMultiplier,
|
|
705
|
+
collateralTokenMint: this.config.collateralMint,
|
|
706
|
+
maxPotRatio
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
return {
|
|
710
|
+
success: true,
|
|
711
|
+
signature: result.signature,
|
|
712
|
+
market: result.market,
|
|
713
|
+
yesTokenMint: result.yesTokenMint,
|
|
714
|
+
noTokenMint: result.noTokenMint,
|
|
715
|
+
question,
|
|
716
|
+
side,
|
|
717
|
+
amountUsdc,
|
|
718
|
+
durationDays
|
|
719
|
+
};
|
|
720
|
+
} catch (error) {
|
|
721
|
+
this.log(`Error creating simple P2P market: ${error.message}`, 'error');
|
|
722
|
+
throw error;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Create a P2P market with custom odds
|
|
728
|
+
*/
|
|
729
|
+
async createP2PMarketWithOdds(options) {
|
|
730
|
+
await this.initialize();
|
|
731
|
+
|
|
732
|
+
const {
|
|
733
|
+
question,
|
|
734
|
+
side = 'yes',
|
|
735
|
+
amount,
|
|
736
|
+
cap,
|
|
737
|
+
durationDays = 30,
|
|
738
|
+
oddsBps, // Odds in basis points (e.g., 7000 = 70%)
|
|
739
|
+
maxPotRatio
|
|
740
|
+
} = options;
|
|
741
|
+
|
|
742
|
+
const endTime = BigInt(Math.floor(Date.now() / 1000) + (durationDays * 24 * 60 * 60));
|
|
743
|
+
const initialAmount = amount || this.config.defaultLiquidity;
|
|
744
|
+
const creatorSideCap = cap || initialAmount * 5n;
|
|
745
|
+
|
|
746
|
+
this.log(`Creating P2P market with odds: "${question}"`);
|
|
747
|
+
this.log(`Side: ${side}, Odds: ${oddsBps / 100}%`);
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
const result = await this.client.createMarketP2PWithCustomOdds({
|
|
751
|
+
question,
|
|
752
|
+
initialAmount,
|
|
753
|
+
side,
|
|
754
|
+
creatorSideCap,
|
|
755
|
+
endTime,
|
|
756
|
+
oddsBps,
|
|
757
|
+
maxPotRatio,
|
|
758
|
+
collateralTokenMint: this.config.collateralMint
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
return {
|
|
762
|
+
success: true,
|
|
763
|
+
signature: result.signature,
|
|
764
|
+
market: result.market,
|
|
765
|
+
yesTokenMint: result.yesTokenMint,
|
|
766
|
+
noTokenMint: result.noTokenMint,
|
|
767
|
+
question,
|
|
768
|
+
side,
|
|
769
|
+
oddsBps,
|
|
770
|
+
durationDays
|
|
771
|
+
};
|
|
772
|
+
} catch (error) {
|
|
773
|
+
this.log(`Error creating P2P market with odds: ${error.message}`, 'error');
|
|
774
|
+
throw error;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Create an AMM market with custom starting odds
|
|
780
|
+
*/
|
|
781
|
+
async createAMMMarketWithOdds(options) {
|
|
782
|
+
await this.initialize();
|
|
783
|
+
|
|
784
|
+
const {
|
|
785
|
+
question,
|
|
786
|
+
liquidity,
|
|
787
|
+
durationDays = 30,
|
|
788
|
+
yesOddsBps // Starting YES odds in basis points (e.g., 5000 = 50%)
|
|
789
|
+
} = options;
|
|
790
|
+
|
|
791
|
+
const endTime = BigInt(Math.floor(Date.now() / 1000) + (durationDays * 24 * 60 * 60));
|
|
792
|
+
const initialLiquidity = liquidity || this.config.defaultLiquidity;
|
|
793
|
+
|
|
794
|
+
this.log(`Creating AMM market with odds: "${question}"`);
|
|
795
|
+
this.log(`YES odds: ${yesOddsBps / 100}%, Liquidity: ${initialLiquidity}`);
|
|
796
|
+
|
|
797
|
+
try {
|
|
798
|
+
const result = await this.client.createMarketV2WithCustomOdds({
|
|
799
|
+
question,
|
|
800
|
+
initialLiquidity,
|
|
801
|
+
endTime,
|
|
802
|
+
collateralTokenMint: this.config.collateralMint,
|
|
803
|
+
yesOddsBps
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
return {
|
|
807
|
+
success: true,
|
|
808
|
+
signature: result.signature,
|
|
809
|
+
market: result.market,
|
|
810
|
+
question,
|
|
811
|
+
yesOddsBps,
|
|
812
|
+
durationDays
|
|
813
|
+
};
|
|
814
|
+
} catch (error) {
|
|
815
|
+
this.log(`Error creating AMM market with odds: ${error.message}`, 'error');
|
|
816
|
+
throw error;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// ========== CUSTOM ORACLE SUPPORT ==========
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Create a market with a custom oracle/settler address
|
|
824
|
+
*/
|
|
825
|
+
async createMarketWithCustomOracle(options) {
|
|
826
|
+
await this.initialize();
|
|
827
|
+
|
|
828
|
+
const {
|
|
829
|
+
question,
|
|
830
|
+
liquidity,
|
|
831
|
+
durationDays = 30,
|
|
832
|
+
settlerAddress, // The address that will resolve this market
|
|
833
|
+
yesOddsBps = 5000 // Default 50/50
|
|
834
|
+
} = options;
|
|
835
|
+
|
|
836
|
+
const endTime = BigInt(Math.floor(Date.now() / 1000) + (durationDays * 24 * 60 * 60));
|
|
837
|
+
const initialLiquidity = liquidity || this.config.defaultLiquidity;
|
|
838
|
+
const settler = new PublicKey(settlerAddress);
|
|
839
|
+
|
|
840
|
+
this.log(`Creating market with custom oracle: "${question}"`);
|
|
841
|
+
this.log(`Oracle: ${settlerAddress}`);
|
|
842
|
+
|
|
843
|
+
try {
|
|
844
|
+
const result = await this.client.createMarketWithCustomOracle({
|
|
845
|
+
question,
|
|
846
|
+
initialLiquidity,
|
|
847
|
+
endTime,
|
|
848
|
+
collateralMint: this.config.collateralMint,
|
|
849
|
+
settlerAddress: settler,
|
|
850
|
+
yesOddsBps
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
return {
|
|
854
|
+
success: true,
|
|
855
|
+
signature: result.signature,
|
|
856
|
+
market: result.market?.toBase58?.() || result.market?.toString?.() || result.market,
|
|
857
|
+
question,
|
|
858
|
+
settlerAddress,
|
|
859
|
+
durationDays
|
|
860
|
+
};
|
|
861
|
+
} catch (error) {
|
|
862
|
+
this.log(`Error creating market with custom oracle: ${error.message}`, 'error');
|
|
863
|
+
throw error;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// ========== V3 MARKET SUPPORT ==========
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Buy tokens on a V3 market
|
|
871
|
+
*/
|
|
872
|
+
async buyV3Tokens(options) {
|
|
873
|
+
await this.initialize();
|
|
874
|
+
|
|
875
|
+
const { marketAddress, side, amountUsdc } = options;
|
|
876
|
+
const market = new PublicKey(marketAddress);
|
|
877
|
+
|
|
878
|
+
this.log(`Buying V3 ${side.toUpperCase()} tokens for ${amountUsdc} USDC on ${marketAddress}`);
|
|
879
|
+
|
|
880
|
+
try {
|
|
881
|
+
const result = await this.client.buyV3TokensUsdc({
|
|
882
|
+
market,
|
|
883
|
+
buyYesToken: side === 'yes',
|
|
884
|
+
amountUsdc
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
return {
|
|
888
|
+
success: true,
|
|
889
|
+
signature: result.signature,
|
|
890
|
+
market: marketAddress,
|
|
891
|
+
side,
|
|
892
|
+
amountUsdc
|
|
893
|
+
};
|
|
894
|
+
} catch (error) {
|
|
895
|
+
this.log(`Error buying V3 tokens: ${error.message}`, 'error');
|
|
896
|
+
throw error;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Redeem position on a V3 market
|
|
902
|
+
*/
|
|
903
|
+
async redeemV3Position(marketAddress) {
|
|
904
|
+
await this.initialize();
|
|
905
|
+
|
|
906
|
+
const market = new PublicKey(marketAddress);
|
|
907
|
+
|
|
908
|
+
this.log(`Redeeming V3 position on ${marketAddress}`);
|
|
909
|
+
|
|
910
|
+
try {
|
|
911
|
+
const result = await this.client.redeemV3Position(market);
|
|
912
|
+
return {
|
|
913
|
+
success: true,
|
|
914
|
+
signature: result.signature,
|
|
915
|
+
market: marketAddress
|
|
916
|
+
};
|
|
917
|
+
} catch (error) {
|
|
918
|
+
this.log(`Error redeeming V3 position: ${error.message}`, 'error');
|
|
919
|
+
throw error;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Redeem P2P market position
|
|
925
|
+
*/
|
|
926
|
+
async redeemP2PPosition(marketAddress) {
|
|
927
|
+
await this.initialize();
|
|
928
|
+
|
|
929
|
+
this.log(`Redeeming P2P position on ${marketAddress}`);
|
|
930
|
+
|
|
931
|
+
try {
|
|
932
|
+
const result = await this.client.redeemP2PPosition(marketAddress);
|
|
933
|
+
return {
|
|
934
|
+
success: true,
|
|
935
|
+
signature: result.signature,
|
|
936
|
+
market: marketAddress
|
|
937
|
+
};
|
|
938
|
+
} catch (error) {
|
|
939
|
+
this.log(`Error redeeming P2P position: ${error.message}`, 'error');
|
|
940
|
+
throw error;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* Claim P2P market refund
|
|
946
|
+
*/
|
|
947
|
+
async claimP2PRefund(marketAddress) {
|
|
948
|
+
await this.initialize();
|
|
949
|
+
|
|
950
|
+
this.log(`Claiming P2P refund on ${marketAddress}`);
|
|
951
|
+
|
|
952
|
+
try {
|
|
953
|
+
const result = await this.client.claimP2PMarketRefund(marketAddress);
|
|
954
|
+
return {
|
|
955
|
+
success: true,
|
|
956
|
+
signature: result.signature,
|
|
957
|
+
market: marketAddress
|
|
958
|
+
};
|
|
959
|
+
} catch (error) {
|
|
960
|
+
this.log(`Error claiming P2P refund: ${error.message}`, 'error');
|
|
961
|
+
throw error;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// ========== URL DETECTION HELPERS ==========
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Detect Twitter URL in question text
|
|
969
|
+
*/
|
|
970
|
+
detectTwitterUrl(questionText) {
|
|
971
|
+
if (this.client.detectTwitterUrl) {
|
|
972
|
+
return this.client.detectTwitterUrl(questionText);
|
|
973
|
+
}
|
|
974
|
+
// Fallback regex
|
|
975
|
+
const twitterRegex = /https?:\/\/(twitter\.com|x\.com)\/\w+\/status\/\d+/i;
|
|
976
|
+
const match = questionText.match(twitterRegex);
|
|
977
|
+
return {
|
|
978
|
+
question: questionText,
|
|
979
|
+
twitterUrl: match ? match[0] : undefined
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* Detect YouTube URL in question text
|
|
985
|
+
*/
|
|
986
|
+
detectYoutubeUrl(questionText) {
|
|
987
|
+
if (this.client.detectYoutubeUrl) {
|
|
988
|
+
return this.client.detectYoutubeUrl(questionText);
|
|
989
|
+
}
|
|
990
|
+
// Fallback regex
|
|
991
|
+
const youtubeRegex = /https?:\/\/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)[^\s]+/i;
|
|
992
|
+
const match = questionText.match(youtubeRegex);
|
|
993
|
+
return {
|
|
994
|
+
question: questionText,
|
|
995
|
+
youtubeUrl: match ? match[0] : undefined
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
/**
|
|
1000
|
+
* Detect DeFi Llama metric in question text
|
|
1001
|
+
*/
|
|
1002
|
+
detectDefiLlamaUrl(questionText) {
|
|
1003
|
+
if (this.client.detectDefiLlamaUrl) {
|
|
1004
|
+
return this.client.detectDefiLlamaUrl(questionText);
|
|
1005
|
+
}
|
|
1006
|
+
return { question: questionText };
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// ========== GLOBAL CONFIG ==========
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Fetch PNP global configuration
|
|
1013
|
+
*/
|
|
1014
|
+
async fetchGlobalConfig() {
|
|
1015
|
+
await this.initialize();
|
|
1016
|
+
|
|
1017
|
+
try {
|
|
1018
|
+
const config = await this.client.fetchGlobalConfig();
|
|
1019
|
+
return {
|
|
1020
|
+
success: true,
|
|
1021
|
+
config: {
|
|
1022
|
+
publicKey: config.publicKey?.toBase58?.() || config.publicKey,
|
|
1023
|
+
account: config.account
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
this.log(`Error fetching global config: ${error.message}`, 'error');
|
|
1028
|
+
throw error;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
export async function createAgent(options = {}) {
|
|
1034
|
+
const agent = new PrivacyOracleAgent(options);
|
|
1035
|
+
await agent.initialize();
|
|
1036
|
+
return agent;
|
|
1037
|
+
}
|