@blockrun/franklin 3.15.72 → 3.15.74
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/agent/context.js +2 -2
- package/dist/tools/prediction.d.ts +6 -2
- package/dist/tools/prediction.js +186 -25
- package/package.json +1 -1
package/dist/agent/context.js
CHANGED
|
@@ -336,12 +336,12 @@ Your training data is frozen in the past. Live-world questions MUST be answered
|
|
|
336
336
|
|
|
337
337
|
If you find yourself about to emit one of these, stop and call the tool instead. If you don't know which ticker the user means, call ExaSearch or AskUser — never deflect.
|
|
338
338
|
|
|
339
|
-
**Prediction markets (PredictionMarket).** When the user asks about real-world odds — elections, "will X happen by year-end", "Polymarket on Y", "Kalshi market for Z", "what are the odds of recession" — use **PredictionMarket** instead of guessing.
|
|
339
|
+
**Prediction markets (PredictionMarket).** When the user asks about real-world odds — elections, "will X happen by year-end", "Polymarket on Y", "Kalshi market for Z", "what are the odds of recession" — use **PredictionMarket** instead of guessing. Ten actions, route by intent:
|
|
340
340
|
- "is there a market on X anywhere?" / unknown which platform → \`searchAll\` (\$0.005) — single call across Polymarket+Kalshi+Limitless+Opinion+Predict.Fun.
|
|
341
341
|
- "what are the odds on Polymarket / Kalshi specifically" → \`searchPolymarket\` (\$0.001) and \`searchKalshi\` (\$0.001) **in parallel**; comparing implied probability across the two venues is the high-value answer.
|
|
342
342
|
- "where do Polymarket and Kalshi disagree / arbitrage" → \`crossPlatform\` (\$0.005) returns pre-matched pairs.
|
|
343
343
|
- "who's profitable / top traders / who should I follow on Polymarket" → \`leaderboard\` (\$0.001) — global top wallets by P&L.
|
|
344
|
-
- "
|
|
344
|
+
- "analyze this wallet / can I copy this trader / 复制交易 / show me their P&L AND positions" → run \`walletProfile\` + \`walletPnl\` + \`walletPositions\` IN PARALLEL with the same address. Three \$0.005 calls = full picture for \$0.015. Do NOT \`Bash\`-curl \`data-api.polymarket.com\` directly — those are paid Predexon endpoints and going around them defeats the wallet-attached architecture. If just the profile is needed: \`walletProfile\` alone (single address → /wallet/{addr}, comma-list → batch).
|
|
345
345
|
- "what are smart traders betting on right now / smart money flow across markets" → \`smartActivity\` (\$0.005) — markets where high-P&L wallets are positioning.
|
|
346
346
|
- "show smart money on this specific Polymarket market / this condition_id" → \`smartMoney\` (\$0.005) with \`conditionId="<condition_id>"\`.
|
|
347
347
|
|
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
* crossPlatform $0.005 matching market pairs across Polymarket+Kalshi
|
|
18
18
|
* (the arbitrage / consensus signal)
|
|
19
19
|
* leaderboard $0.001 global Polymarket leaderboard — top wallets by P&L
|
|
20
|
-
* walletProfile $0.005
|
|
21
|
-
*
|
|
20
|
+
* walletProfile $0.005 full Polymarket wallet profile (single wallet)
|
|
21
|
+
* or batch profiles (comma-separated wallets)
|
|
22
|
+
* walletPnl $0.005 P&L summary + realized P&L time series for one
|
|
23
|
+
* Polymarket wallet
|
|
24
|
+
* walletPositions $0.005 open + historical positions for one Polymarket
|
|
25
|
+
* wallet
|
|
22
26
|
* smartActivity $0.005 discover markets where high-performing wallets
|
|
23
27
|
* are active right now
|
|
24
28
|
* smartMoney $0.005 smart-money positioning on one Polymarket
|
package/dist/tools/prediction.js
CHANGED
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
* crossPlatform $0.005 matching market pairs across Polymarket+Kalshi
|
|
18
18
|
* (the arbitrage / consensus signal)
|
|
19
19
|
* leaderboard $0.001 global Polymarket leaderboard — top wallets by P&L
|
|
20
|
-
* walletProfile $0.005
|
|
21
|
-
*
|
|
20
|
+
* walletProfile $0.005 full Polymarket wallet profile (single wallet)
|
|
21
|
+
* or batch profiles (comma-separated wallets)
|
|
22
|
+
* walletPnl $0.005 P&L summary + realized P&L time series for one
|
|
23
|
+
* Polymarket wallet
|
|
24
|
+
* walletPositions $0.005 open + historical positions for one Polymarket
|
|
25
|
+
* wallet
|
|
22
26
|
* smartActivity $0.005 discover markets where high-performing wallets
|
|
23
27
|
* are active right now
|
|
24
28
|
* smartMoney $0.005 smart-money positioning on one Polymarket
|
|
@@ -98,7 +102,7 @@ async function getWithPayment(path, query, ctx) {
|
|
|
98
102
|
const errText = await response.text().catch(() => '');
|
|
99
103
|
// Surface failed paid calls in the Markets-tab health summary.
|
|
100
104
|
recordFetch({ provider: 'blockrun', endpoint: path, ok: false, latencyMs: Date.now() - startedAt });
|
|
101
|
-
throw new Error(`PredictionMarket ${path} failed (${response.status}): ${errText.slice(0,
|
|
105
|
+
throw new Error(`PredictionMarket ${path} failed (${response.status}): ${errText.slice(0, 600)}`);
|
|
102
106
|
}
|
|
103
107
|
recordFetch({
|
|
104
108
|
provider: 'blockrun',
|
|
@@ -186,11 +190,18 @@ function formatUsd(value) {
|
|
|
186
190
|
return `$${(n / 1e3).toFixed(1)}K`;
|
|
187
191
|
return `$${n.toFixed(2)}`;
|
|
188
192
|
}
|
|
193
|
+
function formatQuantity(value) {
|
|
194
|
+
const n = asNumber(value);
|
|
195
|
+
if (n == null)
|
|
196
|
+
return String(value ?? 'n/a');
|
|
197
|
+
return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(undefined, { maximumFractionDigits: 4 });
|
|
198
|
+
}
|
|
189
199
|
function formatPct(value, digits = 1) {
|
|
190
200
|
const n = asNumber(value);
|
|
191
201
|
if (n == null)
|
|
192
202
|
return 'n/a';
|
|
193
|
-
|
|
203
|
+
const pct = Math.abs(n) > 1 ? n : n * 100;
|
|
204
|
+
return `${pct.toFixed(digits)}%`;
|
|
194
205
|
}
|
|
195
206
|
// API responses sometimes come wrapped as `{data: [...], pagination: ...}`,
|
|
196
207
|
// other times as a bare array. Normalise to an array.
|
|
@@ -207,15 +218,23 @@ function unwrapList(raw) {
|
|
|
207
218
|
return obj.pairs;
|
|
208
219
|
if (Array.isArray(obj.results))
|
|
209
220
|
return obj.results;
|
|
221
|
+
if (Array.isArray(obj.positions))
|
|
222
|
+
return obj.positions;
|
|
210
223
|
}
|
|
211
224
|
return [];
|
|
212
225
|
}
|
|
226
|
+
function parseWalletsInput(value) {
|
|
227
|
+
return value
|
|
228
|
+
.split(',')
|
|
229
|
+
.map(w => w.trim())
|
|
230
|
+
.filter(Boolean);
|
|
231
|
+
}
|
|
213
232
|
async function execute(input, ctx) {
|
|
214
|
-
const { action, search, status, sort, limit, conditionId, wallets } = input;
|
|
233
|
+
const { action, search, status, sort, limit, conditionId, wallets, granularity } = input;
|
|
215
234
|
const cappedLimit = Math.min(Math.max(1, limit ?? DEFAULT_LIMIT), MAX_LIMIT);
|
|
216
235
|
if (!action) {
|
|
217
236
|
return {
|
|
218
|
-
output: 'Error: action is required (searchAll | searchPolymarket | searchKalshi | crossPlatform | leaderboard | walletProfile | smartActivity | smartMoney)',
|
|
237
|
+
output: 'Error: action is required (searchAll | searchPolymarket | searchKalshi | crossPlatform | leaderboard | walletProfile | walletPnl | walletPositions | smartActivity | smartMoney)',
|
|
219
238
|
isError: true,
|
|
220
239
|
};
|
|
221
240
|
}
|
|
@@ -225,8 +244,12 @@ async function execute(input, ctx) {
|
|
|
225
244
|
// One $0.005 call across 5 platforms — Polymarket, Kalshi, Limitless,
|
|
226
245
|
// Opinion, Predict.Fun. The right entry point for "is there a market
|
|
227
246
|
// on X anywhere?" — beats firing per-platform searches in parallel.
|
|
247
|
+
// Predexon expects `q` for the search term — verified 2026-05-06 from
|
|
248
|
+
// a live 422: {"detail":[{"type":"missing","loc":["query","q"]}]}.
|
|
249
|
+
// Public input field stays `search` for ergonomic consistency with
|
|
250
|
+
// searchPolymarket / searchKalshi; rename on the wire.
|
|
228
251
|
const raw = await getWithPayment('/v1/pm/markets/search', {
|
|
229
|
-
search,
|
|
252
|
+
q: search,
|
|
230
253
|
status,
|
|
231
254
|
sort,
|
|
232
255
|
limit: cappedLimit,
|
|
@@ -332,17 +355,33 @@ async function execute(input, ctx) {
|
|
|
332
355
|
isError: true,
|
|
333
356
|
};
|
|
334
357
|
}
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
// the
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
358
|
+
// Smart dispatch: a single wallet → /wallet/{addr} (full profile,
|
|
359
|
+
// labels, scores, stats); a comma-list → /wallets/profiles (batch).
|
|
360
|
+
// The 3.15.70 ship hit the BATCH endpoint for everything and got 422
|
|
361
|
+
// for the single-wallet case; the gateway team confirmed 2026-05-06
|
|
362
|
+
// the right surface for "analyze this trader" is the path-parameter
|
|
363
|
+
// single-wallet endpoint, not the batch query-param one.
|
|
364
|
+
const parsedWallets = parseWalletsInput(wallets);
|
|
365
|
+
if (parsedWallets.length === 0) {
|
|
366
|
+
return {
|
|
367
|
+
output: 'Error: `wallets` must include at least one Polymarket wallet address',
|
|
368
|
+
isError: true,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const list = parsedWallets.join(',');
|
|
372
|
+
const isBatch = parsedWallets.length > 1;
|
|
373
|
+
const raw = isBatch
|
|
374
|
+
? await getWithPayment('/v1/pm/polymarket/wallets/profiles', {
|
|
375
|
+
addresses: list,
|
|
376
|
+
}, ctx)
|
|
377
|
+
: await getWithPayment(`/v1/pm/polymarket/wallet/${encodeURIComponent(list)}`, {}, ctx);
|
|
378
|
+
// Single-wallet path returns a single profile object; batch returns
|
|
379
|
+
// an array (or {data:[]}). unwrapList handles the batch shape but
|
|
380
|
+
// returns [] for a bare object — wrap explicitly so the formatter
|
|
381
|
+
// below sees the single profile.
|
|
382
|
+
const profiles = isBatch
|
|
383
|
+
? unwrapList(raw)
|
|
384
|
+
: (raw && typeof raw === 'object' ? [raw] : []);
|
|
346
385
|
if (profiles.length === 0) {
|
|
347
386
|
return { output: `No profile data returned for: ${wallets}` };
|
|
348
387
|
}
|
|
@@ -379,11 +418,124 @@ async function execute(input, ctx) {
|
|
|
379
418
|
lines.push('', `_$0.005 paid via x402._`);
|
|
380
419
|
return { output: lines.join('\n') };
|
|
381
420
|
}
|
|
421
|
+
case 'walletPnl': {
|
|
422
|
+
// Single-wallet P&L summary + time series.
|
|
423
|
+
// Predexon path: /v1/pm/polymarket/wallet/pnl/{wallet} — Tier 2 ($0.005).
|
|
424
|
+
if (!wallets || !wallets.trim()) {
|
|
425
|
+
return {
|
|
426
|
+
output: 'Error: `wallets` is required for walletPnl (single Polymarket wallet address)',
|
|
427
|
+
isError: true,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
const parsedWallets = parseWalletsInput(wallets);
|
|
431
|
+
if (parsedWallets.length !== 1) {
|
|
432
|
+
return {
|
|
433
|
+
output: 'Error: walletPnl accepts exactly one wallet address. For multiple wallets, call walletPnl once per address in parallel.',
|
|
434
|
+
isError: true,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
const wallet = parsedWallets[0];
|
|
438
|
+
// Predexon requires `granularity` from the enum {day, week, month,
|
|
439
|
+
// year, all} — verified 2026-05-06 in two live 422 turns. Default
|
|
440
|
+
// `day`; agent can override via input field for longer aggregations.
|
|
441
|
+
const raw = await getWithPayment(`/v1/pm/polymarket/wallet/pnl/${encodeURIComponent(wallet)}`, { granularity: granularity ?? 'day' }, ctx);
|
|
442
|
+
if (!raw || typeof raw !== 'object') {
|
|
443
|
+
return { output: `No P&L data returned for ${wallet}` };
|
|
444
|
+
}
|
|
445
|
+
const data = raw;
|
|
446
|
+
const realized = data.realized_pnl ?? data.realizedPnl ?? data.total_pnl ?? data.pnl;
|
|
447
|
+
const unrealized = data.unrealized_pnl ?? data.unrealizedPnl;
|
|
448
|
+
const total = data.total_value ?? data.totalValue ?? data.equity;
|
|
449
|
+
const volume = data.volume ?? data.total_volume;
|
|
450
|
+
const winRate = data.win_rate ?? data.winRate;
|
|
451
|
+
const w = wallet.length > 12 ? `${wallet.slice(0, 8)}…${wallet.slice(-4)}` : wallet;
|
|
452
|
+
const lines = [`## Polymarket wallet P&L — \`${w}\``, ''];
|
|
453
|
+
const summary = [];
|
|
454
|
+
if (realized != null)
|
|
455
|
+
summary.push(`realized ${formatUsd(realized)}`);
|
|
456
|
+
if (unrealized != null)
|
|
457
|
+
summary.push(`unrealized ${formatUsd(unrealized)}`);
|
|
458
|
+
if (total != null)
|
|
459
|
+
summary.push(`equity ${formatUsd(total)}`);
|
|
460
|
+
if (volume != null)
|
|
461
|
+
summary.push(`vol ${formatUsd(volume)}`);
|
|
462
|
+
if (winRate != null)
|
|
463
|
+
summary.push(`win ${formatPct(winRate, 0)}`);
|
|
464
|
+
if (summary.length > 0)
|
|
465
|
+
lines.push(summary.join(' · '));
|
|
466
|
+
// Optional time series — show recent points compactly if present.
|
|
467
|
+
const series = (data.series ?? data.history ?? data.daily);
|
|
468
|
+
if (Array.isArray(series) && series.length > 0) {
|
|
469
|
+
lines.push('', `**Recent points** (latest ${Math.min(7, series.length)}):`);
|
|
470
|
+
series.slice(-7).forEach(pt => {
|
|
471
|
+
const t = (pt.date ?? pt.ts ?? pt.timestamp);
|
|
472
|
+
const v = (pt.pnl ?? pt.value ?? pt.cumulative_pnl);
|
|
473
|
+
if (t != null && v != null) {
|
|
474
|
+
const tStr = typeof t === 'number' ? new Date(t).toISOString().slice(0, 10) : String(t).slice(0, 10);
|
|
475
|
+
lines.push(`- ${tStr} · ${formatUsd(v)}`);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
lines.push('', `_$0.005 paid via x402._`);
|
|
480
|
+
return { output: lines.join('\n') };
|
|
481
|
+
}
|
|
482
|
+
case 'walletPositions': {
|
|
483
|
+
// Single-wallet positions (open + historical).
|
|
484
|
+
// Predexon path: /v1/pm/polymarket/wallet/positions/{wallet} — Tier 2 ($0.005).
|
|
485
|
+
if (!wallets || !wallets.trim()) {
|
|
486
|
+
return {
|
|
487
|
+
output: 'Error: `wallets` is required for walletPositions (single Polymarket wallet address)',
|
|
488
|
+
isError: true,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
const parsedWallets = parseWalletsInput(wallets);
|
|
492
|
+
if (parsedWallets.length !== 1) {
|
|
493
|
+
return {
|
|
494
|
+
output: 'Error: walletPositions accepts exactly one wallet address. For multiple wallets, call walletPositions once per address in parallel.',
|
|
495
|
+
isError: true,
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
const wallet = parsedWallets[0];
|
|
499
|
+
const raw = await getWithPayment(`/v1/pm/polymarket/wallet/positions/${encodeURIComponent(wallet)}`, { limit: cappedLimit }, ctx);
|
|
500
|
+
const positions = unwrapList(raw);
|
|
501
|
+
if (positions.length === 0) {
|
|
502
|
+
return { output: `No positions returned for ${wallet}` };
|
|
503
|
+
}
|
|
504
|
+
const w = wallet.length > 12 ? `${wallet.slice(0, 8)}…${wallet.slice(-4)}` : wallet;
|
|
505
|
+
const lines = [
|
|
506
|
+
`## Polymarket positions — \`${w}\` — ${positions.length} position${positions.length === 1 ? '' : 's'}`,
|
|
507
|
+
'',
|
|
508
|
+
];
|
|
509
|
+
positions.slice(0, cappedLimit).forEach((p, i) => {
|
|
510
|
+
const title = (p.title || p.market || p.question || p.market_slug || 'untitled');
|
|
511
|
+
const outcome = (p.outcome || p.side);
|
|
512
|
+
const size = p.size ?? p.shares ?? p.quantity;
|
|
513
|
+
const avgPrice = p.avg_price ?? p.avgPrice ?? p.average_price;
|
|
514
|
+
const currentValue = p.current_value ?? p.currentValue ?? p.value;
|
|
515
|
+
const pnl = p.pnl ?? p.unrealized_pnl ?? p.realized_pnl;
|
|
516
|
+
const pnlPct = p.pnl_pct ?? p.pnlPct ?? p.percent_pnl;
|
|
517
|
+
const parts = [];
|
|
518
|
+
if (outcome)
|
|
519
|
+
parts.push(outcome);
|
|
520
|
+
if (size != null)
|
|
521
|
+
parts.push(`size ${formatQuantity(size)}`);
|
|
522
|
+
if (avgPrice != null)
|
|
523
|
+
parts.push(`avg ${formatPct(avgPrice)}`);
|
|
524
|
+
if (currentValue != null)
|
|
525
|
+
parts.push(`now ${formatUsd(currentValue)}`);
|
|
526
|
+
if (pnl != null) {
|
|
527
|
+
const pctStr = pnlPct != null ? ` (${formatPct(pnlPct, 1)})` : '';
|
|
528
|
+
parts.push(`P&L ${formatUsd(pnl)}${pctStr}`);
|
|
529
|
+
}
|
|
530
|
+
lines.push(`${i + 1}. **${title}** — ${parts.join(' · ')}`);
|
|
531
|
+
});
|
|
532
|
+
lines.push('', `_$0.005 paid via x402._`);
|
|
533
|
+
return { output: lines.join('\n') };
|
|
534
|
+
}
|
|
382
535
|
case 'smartActivity': {
|
|
383
536
|
// "Discover markets where high-performing wallets are active right now."
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
// launch). Verified 2026-05-05 against blockrun.ai/openapi.json.
|
|
537
|
+
// Complements `smartMoney`: this discovers interesting markets across
|
|
538
|
+
// the venue; smartMoney drills into one condition_id.
|
|
387
539
|
const raw = await getWithPayment('/v1/pm/polymarket/markets/smart-activity', {
|
|
388
540
|
limit: cappedLimit,
|
|
389
541
|
search,
|
|
@@ -537,7 +689,7 @@ async function execute(input, ctx) {
|
|
|
537
689
|
}
|
|
538
690
|
default:
|
|
539
691
|
return {
|
|
540
|
-
output: `Error: unknown action "${action}". Use: searchAll, searchPolymarket, searchKalshi, crossPlatform, leaderboard, walletProfile, smartActivity, smartMoney`,
|
|
692
|
+
output: `Error: unknown action "${action}". Use: searchAll, searchPolymarket, searchKalshi, crossPlatform, leaderboard, walletProfile, walletPnl, walletPositions, smartActivity, smartMoney`,
|
|
541
693
|
isError: true,
|
|
542
694
|
};
|
|
543
695
|
}
|
|
@@ -556,13 +708,15 @@ export const predictionMarketCapability = {
|
|
|
556
708
|
'`searchKalshi` (Kalshi only, supports sort+status — $0.001), ' +
|
|
557
709
|
'`crossPlatform` (matched market pairs across Polymarket+Kalshi for arbitrage / consensus — $0.005), ' +
|
|
558
710
|
'`leaderboard` (global top wallets by P&L on Polymarket — $0.001), ' +
|
|
559
|
-
'`walletProfile` (
|
|
711
|
+
'`walletProfile` (full Polymarket wallet profile — labels, scores, stats. Single address → /wallet/{addr}; comma-list → batch /wallets/profiles — $0.005), ' +
|
|
712
|
+
'`walletPnl` (single Polymarket wallet P&L summary + time series — $0.005), ' +
|
|
713
|
+
'`walletPositions` (single Polymarket wallet positions — open + historical with P&L per position — $0.005), ' +
|
|
560
714
|
'`smartActivity` (markets where high-P&L wallets are positioning right now — $0.005), ' +
|
|
561
715
|
'`smartMoney` (smart-money positioning on one Polymarket condition_id — $0.005). ' +
|
|
562
716
|
'Default routing: ' +
|
|
563
717
|
'"is there a market on X anywhere" → searchAll. ' +
|
|
564
718
|
'"top wallets / who is profitable / who should I follow on Polymarket" → leaderboard. ' +
|
|
565
|
-
'"
|
|
719
|
+
'"analyze this wallet / can I copy this trader / 复制交易 / show me their P&L AND positions" → run walletProfile + walletPnl + walletPositions IN PARALLEL with the same address — three $0.005 calls give the full picture for $0.015. Do not Bash-curl Polymarket directly; the agent has paid tools for this. ' +
|
|
566
720
|
'"what are smart traders betting on right now" → smartActivity. ' +
|
|
567
721
|
'"show smart money on this specific Polymarket market" → smartMoney with conditionId. ' +
|
|
568
722
|
'"should I bet on X" → run searchPolymarket + searchKalshi in parallel and compare implied probabilities — divergence is the signal.',
|
|
@@ -578,6 +732,8 @@ export const predictionMarketCapability = {
|
|
|
578
732
|
'crossPlatform',
|
|
579
733
|
'leaderboard',
|
|
580
734
|
'walletProfile',
|
|
735
|
+
'walletPnl',
|
|
736
|
+
'walletPositions',
|
|
581
737
|
'smartActivity',
|
|
582
738
|
'smartMoney',
|
|
583
739
|
],
|
|
@@ -585,7 +741,7 @@ export const predictionMarketCapability = {
|
|
|
585
741
|
},
|
|
586
742
|
search: {
|
|
587
743
|
type: 'string',
|
|
588
|
-
description: 'Search query. Used by searchAll / searchPolymarket / searchKalshi / smartActivity. Optional for crossPlatform/leaderboard/walletProfile/smartMoney.',
|
|
744
|
+
description: 'Search query. Used by searchAll / searchPolymarket / searchKalshi / smartActivity. Optional for crossPlatform/leaderboard/walletProfile/walletPnl/walletPositions/smartMoney.',
|
|
589
745
|
},
|
|
590
746
|
status: {
|
|
591
747
|
type: 'string',
|
|
@@ -607,6 +763,11 @@ export const predictionMarketCapability = {
|
|
|
607
763
|
type: 'string',
|
|
608
764
|
description: 'For smartMoney: Polymarket condition_id from searchPolymarket or smartActivity.',
|
|
609
765
|
},
|
|
766
|
+
granularity: {
|
|
767
|
+
type: 'string',
|
|
768
|
+
enum: ['day', 'week', 'month', 'year', 'all'],
|
|
769
|
+
description: 'For walletPnl: time bucket for the P&L series. Default day.',
|
|
770
|
+
},
|
|
610
771
|
},
|
|
611
772
|
required: ['action'],
|
|
612
773
|
},
|
package/package.json
CHANGED