pandora-cli-skills 1.1.18 → 1.1.20
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.
|
@@ -30,6 +30,14 @@ function buildIdempotencyKey(options, quote, nowMs) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function evaluateTrigger(options, quote) {
|
|
33
|
+
if (quote && quote.quoteAvailable === false) {
|
|
34
|
+
return {
|
|
35
|
+
triggered: false,
|
|
36
|
+
reason: 'quote unavailable; skipping trigger evaluation.',
|
|
37
|
+
yesPct: null,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
const yesPct = toNumber(quote && quote.odds && quote.odds.yesPct);
|
|
34
42
|
if (yesPct === null) {
|
|
35
43
|
return {
|
|
@@ -148,26 +156,40 @@ async function runAutopilot(options, deps) {
|
|
|
148
156
|
snapshot.action = {
|
|
149
157
|
mode: options.executeLive ? 'live' : 'paper',
|
|
150
158
|
status: 'blocked',
|
|
151
|
-
reason: `
|
|
159
|
+
reason: `Daily spend cap exceeded: ${(state.dailySpendUsdc + options.amountUsdc).toFixed(2)} > ${options.maxOpenExposureUsdc}.`,
|
|
152
160
|
};
|
|
153
161
|
} else {
|
|
162
|
+
let executionSucceeded = true;
|
|
154
163
|
if (options.executeLive) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
try {
|
|
165
|
+
const execution = await deps.executeFn({
|
|
166
|
+
marketAddress: options.marketAddress,
|
|
167
|
+
side: options.side,
|
|
168
|
+
amountUsdc: options.amountUsdc,
|
|
169
|
+
yesPct: trigger.yesPct,
|
|
170
|
+
maxAmountUsdc: options.maxAmountUsdc,
|
|
171
|
+
minProbabilityPct: options.minProbabilityPct,
|
|
172
|
+
maxProbabilityPct: options.maxProbabilityPct,
|
|
173
|
+
});
|
|
164
174
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
175
|
+
snapshot.action = {
|
|
176
|
+
mode: 'live',
|
|
177
|
+
status: 'executed',
|
|
178
|
+
idempotencyKey: key,
|
|
179
|
+
execution,
|
|
180
|
+
};
|
|
181
|
+
} catch (err) {
|
|
182
|
+
executionSucceeded = false;
|
|
183
|
+
snapshot.action = {
|
|
184
|
+
mode: 'live',
|
|
185
|
+
status: 'failed',
|
|
186
|
+
idempotencyKey: key,
|
|
187
|
+
error: {
|
|
188
|
+
code: err && err.code ? String(err.code) : null,
|
|
189
|
+
message: err && err.message ? String(err.message) : String(err),
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
171
193
|
} else {
|
|
172
194
|
snapshot.action = {
|
|
173
195
|
mode: 'paper',
|
|
@@ -178,10 +200,12 @@ async function runAutopilot(options, deps) {
|
|
|
178
200
|
};
|
|
179
201
|
}
|
|
180
202
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
203
|
+
if (executionSucceeded) {
|
|
204
|
+
state.idempotencyKeys.push(key);
|
|
205
|
+
pruneIdempotencyKeys(state);
|
|
206
|
+
state.dailySpendUsdc = Number((state.dailySpendUsdc + options.amountUsdc).toFixed(6));
|
|
207
|
+
state.tradesToday += 1;
|
|
208
|
+
}
|
|
185
209
|
state.lastExecution = snapshot.action;
|
|
186
210
|
actions.push(snapshot.action);
|
|
187
211
|
|
|
@@ -239,6 +263,7 @@ async function runAutopilot(options, deps) {
|
|
|
239
263
|
cooldownMs: options.cooldownMs,
|
|
240
264
|
maxAmountUsdc: options.maxAmountUsdc,
|
|
241
265
|
maxOpenExposureUsdc: options.maxOpenExposureUsdc,
|
|
266
|
+
dailySpendCapUsdc: options.maxOpenExposureUsdc,
|
|
242
267
|
maxTradesPerDay: options.maxTradesPerDay,
|
|
243
268
|
},
|
|
244
269
|
state,
|
|
@@ -54,6 +54,9 @@ function resolveDistribution(options = {}) {
|
|
|
54
54
|
const explicitYes = toNumber(options.distributionYes);
|
|
55
55
|
const explicitNo = toNumber(options.distributionNo);
|
|
56
56
|
if (explicitYes !== null || explicitNo !== null) {
|
|
57
|
+
if (explicitYes === null || explicitNo === null) {
|
|
58
|
+
throw new Error('distributionYes and distributionNo must both be provided together.');
|
|
59
|
+
}
|
|
57
60
|
if (!Number.isInteger(explicitYes) || !Number.isInteger(explicitNo)) {
|
|
58
61
|
throw new Error('distributionYes and distributionNo must be integers.');
|
|
59
62
|
}
|
|
@@ -73,6 +76,8 @@ function resolveDistribution(options = {}) {
|
|
|
73
76
|
const distribution = computeDistributionHint(sourceYesPct === null ? 0.5 : sourceYesPct / 100);
|
|
74
77
|
if (sourceYesPct === null) {
|
|
75
78
|
diagnostics.push('No source YES probability supplied; defaulted to balanced 50/50 distribution hint.');
|
|
79
|
+
} else if (sourceYesPct === 0 || sourceYesPct === 100) {
|
|
80
|
+
diagnostics.push('Degenerate source YES probability (0% or 100%) may create an extreme one-sided seed.');
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
return {
|
|
@@ -186,7 +191,7 @@ function simulateDirectionalSwap(options = {}) {
|
|
|
186
191
|
const denominator = reserveNo + effectiveIn;
|
|
187
192
|
const outputYes = denominator > 0 ? (reserveYes * effectiveIn) / denominator : 0;
|
|
188
193
|
const postReserveYes = Math.max(0, reserveYes - outputYes);
|
|
189
|
-
const postReserveNo = reserveNo +
|
|
194
|
+
const postReserveNo = reserveNo + effectiveIn;
|
|
190
195
|
return {
|
|
191
196
|
side,
|
|
192
197
|
volumeUsdc: round(volumeUsdc, 6),
|
|
@@ -203,7 +208,7 @@ function simulateDirectionalSwap(options = {}) {
|
|
|
203
208
|
const denominator = reserveYes + effectiveIn;
|
|
204
209
|
const outputNo = denominator > 0 ? (reserveNo * effectiveIn) / denominator : 0;
|
|
205
210
|
const postReserveNo = Math.max(0, reserveNo - outputNo);
|
|
206
|
-
const postReserveYes = reserveYes +
|
|
211
|
+
const postReserveYes = reserveYes + effectiveIn;
|
|
207
212
|
return {
|
|
208
213
|
side,
|
|
209
214
|
volumeUsdc: round(volumeUsdc, 6),
|
|
@@ -270,26 +275,32 @@ function solveVolumeForTargetYesPct(options = {}) {
|
|
|
270
275
|
}
|
|
271
276
|
|
|
272
277
|
function normalizeVolumeScenarios(value, liquidityUsdc) {
|
|
278
|
+
const fallback = () => {
|
|
279
|
+
const liq = Math.max(1, toNumber(liquidityUsdc) || 0);
|
|
280
|
+
return [
|
|
281
|
+
round(liq * 0.25, 6),
|
|
282
|
+
round(liq * 0.5, 6),
|
|
283
|
+
round(liq, 6),
|
|
284
|
+
round(liq * 2, 6),
|
|
285
|
+
];
|
|
286
|
+
};
|
|
287
|
+
|
|
273
288
|
if (Array.isArray(value)) {
|
|
274
|
-
|
|
289
|
+
const parsed = value.map((item) => toNumber(item)).filter((item) => Number.isFinite(item) && item >= 0).map((item) => round(item, 6));
|
|
290
|
+
return parsed.length ? parsed : fallback();
|
|
275
291
|
}
|
|
276
292
|
|
|
277
293
|
const raw = String(value || '').trim();
|
|
278
294
|
if (raw) {
|
|
279
|
-
|
|
295
|
+
const parsed = raw
|
|
280
296
|
.split(',')
|
|
281
297
|
.map((entry) => toNumber(entry.trim()))
|
|
282
298
|
.filter((entry) => Number.isFinite(entry) && entry >= 0)
|
|
283
299
|
.map((entry) => round(entry, 6));
|
|
300
|
+
return parsed.length ? parsed : fallback();
|
|
284
301
|
}
|
|
285
302
|
|
|
286
|
-
|
|
287
|
-
return [
|
|
288
|
-
round(liq * 0.25, 6),
|
|
289
|
-
round(liq * 0.5, 6),
|
|
290
|
-
round(liq, 6),
|
|
291
|
-
round(liq * 2, 6),
|
|
292
|
-
];
|
|
303
|
+
return fallback();
|
|
293
304
|
}
|
|
294
305
|
|
|
295
306
|
function computeHedgeMetrics(options = {}) {
|
|
@@ -534,7 +545,7 @@ function buildMirrorSimulate(options = {}) {
|
|
|
534
545
|
scenarios: scenarioResults,
|
|
535
546
|
diagnostics: [
|
|
536
547
|
'Complete-set mint/split step is exact (raw integer math).',
|
|
537
|
-
'Trade path models
|
|
548
|
+
'Trade path models CPMM directional flow using net-of-fee input in reserve updates; fees are tracked as a separate accrual line.',
|
|
538
549
|
'Use mirror sync + live orderbooks for execution-grade sizing; this command is planning-grade simulation.',
|
|
539
550
|
].concat(distribution.diagnostics || []),
|
|
540
551
|
};
|
|
@@ -170,7 +170,7 @@ function resolveSpenders(options = {}, env = process.env) {
|
|
|
170
170
|
function resolveRuntime(options = {}) {
|
|
171
171
|
const env = options.env || process.env;
|
|
172
172
|
const rpcUrl = options.rpcUrl || env.POLYMARKET_RPC_URL || env.RPC_URL || null;
|
|
173
|
-
const privateKey = options.privateKey || env.POLYMARKET_PRIVATE_KEY ||
|
|
173
|
+
const privateKey = options.privateKey || env.POLYMARKET_PRIVATE_KEY || null;
|
|
174
174
|
const funderAddress = normalizeAddress(options.funder || env.POLYMARKET_FUNDER, 'funder');
|
|
175
175
|
const usdcAddress = normalizeAddress(options.usdcAddress || env.POLYMARKET_USDC_E_ADDRESS, 'usdcAddress')
|
|
176
176
|
|| POLYMARKET_POLYGON_DEFAULTS.usdc;
|
|
@@ -488,6 +488,25 @@ async function fetchJson(url, timeoutMs) {
|
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
+
async function callWithTimeout(work, timeoutMs, label) {
|
|
492
|
+
const limitMs = Number.isInteger(timeoutMs) && timeoutMs > 0 ? timeoutMs : null;
|
|
493
|
+
if (!limitMs) {
|
|
494
|
+
return work();
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
let timer = null;
|
|
498
|
+
try {
|
|
499
|
+
return await Promise.race([
|
|
500
|
+
work(),
|
|
501
|
+
new Promise((_, reject) => {
|
|
502
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${limitMs}ms`)), limitMs);
|
|
503
|
+
}),
|
|
504
|
+
]);
|
|
505
|
+
} finally {
|
|
506
|
+
if (timer) clearTimeout(timer);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
491
510
|
function buildGammaUrl(baseUrl, params) {
|
|
492
511
|
const url = new URL(`${baseUrl}/markets`);
|
|
493
512
|
for (const [key, value] of Object.entries(params || {})) {
|
|
@@ -523,7 +542,7 @@ function extractConditionId(row) {
|
|
|
523
542
|
return value;
|
|
524
543
|
}
|
|
525
544
|
|
|
526
|
-
async function resolveByClobDirect(conditionId, hosts, options, diagnostics) {
|
|
545
|
+
async function resolveByClobDirect(conditionId, hosts, options, diagnostics, timeoutMs) {
|
|
527
546
|
const hostErrors = [];
|
|
528
547
|
for (const candidateHost of hosts) {
|
|
529
548
|
try {
|
|
@@ -534,7 +553,11 @@ async function resolveByClobDirect(conditionId, hosts, options, diagnostics) {
|
|
|
534
553
|
if (!client || typeof client.getMarket !== 'function') {
|
|
535
554
|
throw new Error('CLOB client does not expose getMarket.');
|
|
536
555
|
}
|
|
537
|
-
const market = await
|
|
556
|
+
const market = await callWithTimeout(
|
|
557
|
+
() => client.getMarket(conditionId),
|
|
558
|
+
timeoutMs,
|
|
559
|
+
`Polymarket getMarket(${conditionId})`,
|
|
560
|
+
);
|
|
538
561
|
if (!market) continue;
|
|
539
562
|
return {
|
|
540
563
|
row: market,
|
|
@@ -604,7 +627,7 @@ async function resolvePolymarketMarket(options = {}) {
|
|
|
604
627
|
}
|
|
605
628
|
|
|
606
629
|
if (directConditionId && isConditionId(directConditionId)) {
|
|
607
|
-
const direct = await resolveByClobDirect(directConditionId, hosts, options, diagnostics);
|
|
630
|
+
const direct = await resolveByClobDirect(directConditionId, hosts, options, diagnostics, timeoutMs);
|
|
608
631
|
if (direct && direct.row) {
|
|
609
632
|
rows = [direct.row];
|
|
610
633
|
hostUsed = direct.host;
|
|
@@ -632,7 +655,11 @@ async function resolvePolymarketMarket(options = {}) {
|
|
|
632
655
|
|
|
633
656
|
while (loops < maxPages) {
|
|
634
657
|
loops += 1;
|
|
635
|
-
const page =
|
|
658
|
+
const page = await callWithTimeout(
|
|
659
|
+
() => (cursor ? client.getMarkets(cursor) : client.getMarkets()),
|
|
660
|
+
timeoutMs,
|
|
661
|
+
`Polymarket getMarkets(${candidateHost})`,
|
|
662
|
+
);
|
|
636
663
|
const chunk = Array.isArray(page && page.data) ? page.data : [];
|
|
637
664
|
|
|
638
665
|
if (selectorMode) {
|
|
@@ -790,7 +817,7 @@ function calculateExecutableDepthUsd(orderbook, side, slippageBps) {
|
|
|
790
817
|
};
|
|
791
818
|
}
|
|
792
819
|
|
|
793
|
-
async function getOrderbook(clientOrOptions, tokenId, fallbackOrderbooks = null) {
|
|
820
|
+
async function getOrderbook(clientOrOptions, tokenId, fallbackOrderbooks = null, timeoutMs = null) {
|
|
794
821
|
if (!tokenId) return null;
|
|
795
822
|
|
|
796
823
|
if (fallbackOrderbooks && typeof fallbackOrderbooks === 'object' && fallbackOrderbooks[tokenId]) {
|
|
@@ -801,11 +828,16 @@ async function getOrderbook(clientOrOptions, tokenId, fallbackOrderbooks = null)
|
|
|
801
828
|
return null;
|
|
802
829
|
}
|
|
803
830
|
|
|
804
|
-
return
|
|
831
|
+
return callWithTimeout(
|
|
832
|
+
() => clientOrOptions.getOrderBook(tokenId),
|
|
833
|
+
timeoutMs,
|
|
834
|
+
`Polymarket getOrderBook(${tokenId})`,
|
|
835
|
+
);
|
|
805
836
|
}
|
|
806
837
|
|
|
807
838
|
async function fetchDepthForMarket(market, options = {}) {
|
|
808
839
|
const slippageBps = Number.isFinite(Number(options.slippageBps)) ? Number(options.slippageBps) : 100;
|
|
840
|
+
const timeoutMs = Number.isInteger(options.timeoutMs) && options.timeoutMs > 0 ? options.timeoutMs : 12_000;
|
|
809
841
|
const diagnostics = [];
|
|
810
842
|
const hosts = normalizeHostList(options.host || options.hosts || process.env.POLYMARKET_HOSTS || DEFAULT_POLYMARKET_HOST);
|
|
811
843
|
const cacheFile =
|
|
@@ -825,8 +857,8 @@ async function fetchDepthForMarket(market, options = {}) {
|
|
|
825
857
|
for (const candidateHost of hosts) {
|
|
826
858
|
try {
|
|
827
859
|
const client = new ClobClient(candidateHost, DEFAULT_POLYMARKET_CHAIN);
|
|
828
|
-
const yesFromHost = await getOrderbook(client, market.yesTokenId, null);
|
|
829
|
-
const noFromHost = await getOrderbook(client, market.noTokenId, null);
|
|
860
|
+
const yesFromHost = await getOrderbook(client, market.yesTokenId, null, timeoutMs);
|
|
861
|
+
const noFromHost = await getOrderbook(client, market.noTokenId, null, timeoutMs);
|
|
830
862
|
yesBook = yesFromHost || yesBook;
|
|
831
863
|
noBook = noFromHost || noBook;
|
|
832
864
|
if (yesFromHost || noFromHost) {
|
|
@@ -1289,10 +1321,15 @@ async function fetchPolymarketPositionSummary(options = {}) {
|
|
|
1289
1321
|
const fetchBalance = async (tokenId, sideLabel) => {
|
|
1290
1322
|
if (!tokenId) return;
|
|
1291
1323
|
try {
|
|
1292
|
-
const response = await
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1324
|
+
const response = await callWithTimeout(
|
|
1325
|
+
() =>
|
|
1326
|
+
client.getBalanceAllowance({
|
|
1327
|
+
asset_type: AssetType.CONDITIONAL,
|
|
1328
|
+
token_id: tokenId,
|
|
1329
|
+
}),
|
|
1330
|
+
timeoutMs,
|
|
1331
|
+
`Polymarket getBalanceAllowance(${tokenId})`,
|
|
1332
|
+
);
|
|
1296
1333
|
if (responseContainsError(response)) {
|
|
1297
1334
|
diagnostics.push(
|
|
1298
1335
|
`${sideLabel} balance lookup failed: ${response && response.error ? response.error : `HTTP ${response && response.status ? response.status : 'error'}`}.`,
|
|
@@ -1317,14 +1354,30 @@ async function fetchPolymarketPositionSummary(options = {}) {
|
|
|
1317
1354
|
let openOrders = null;
|
|
1318
1355
|
try {
|
|
1319
1356
|
if (baseSummary.marketId) {
|
|
1320
|
-
openOrders = await
|
|
1357
|
+
openOrders = await callWithTimeout(
|
|
1358
|
+
() => client.getOpenOrders({ market: baseSummary.marketId }),
|
|
1359
|
+
timeoutMs,
|
|
1360
|
+
`Polymarket getOpenOrders(market:${baseSummary.marketId})`,
|
|
1361
|
+
);
|
|
1321
1362
|
} else {
|
|
1322
1363
|
const grouped = [];
|
|
1323
1364
|
if (baseSummary.yesTokenId) {
|
|
1324
|
-
grouped.push(
|
|
1365
|
+
grouped.push(
|
|
1366
|
+
await callWithTimeout(
|
|
1367
|
+
() => client.getOpenOrders({ asset_id: baseSummary.yesTokenId }),
|
|
1368
|
+
timeoutMs,
|
|
1369
|
+
`Polymarket getOpenOrders(asset:${baseSummary.yesTokenId})`,
|
|
1370
|
+
),
|
|
1371
|
+
);
|
|
1325
1372
|
}
|
|
1326
1373
|
if (baseSummary.noTokenId && baseSummary.noTokenId !== baseSummary.yesTokenId) {
|
|
1327
|
-
grouped.push(
|
|
1374
|
+
grouped.push(
|
|
1375
|
+
await callWithTimeout(
|
|
1376
|
+
() => client.getOpenOrders({ asset_id: baseSummary.noTokenId }),
|
|
1377
|
+
timeoutMs,
|
|
1378
|
+
`Polymarket getOpenOrders(asset:${baseSummary.noTokenId})`,
|
|
1379
|
+
),
|
|
1380
|
+
);
|
|
1328
1381
|
}
|
|
1329
1382
|
const dedup = new Map();
|
|
1330
1383
|
for (const group of grouped) {
|
package/cli/pandora.cjs
CHANGED
|
@@ -2954,7 +2954,7 @@ function parseMirrorDeployFlags(args) {
|
|
|
2954
2954
|
continue;
|
|
2955
2955
|
}
|
|
2956
2956
|
if (token === '--private-key') {
|
|
2957
|
-
options.privateKey = requireFlagValue(args, i, '--private-key');
|
|
2957
|
+
options.privateKey = parsePrivateKeyFlag(requireFlagValue(args, i, '--private-key'), '--private-key');
|
|
2958
2958
|
i += 1;
|
|
2959
2959
|
continue;
|
|
2960
2960
|
}
|
|
@@ -4434,6 +4434,7 @@ function parsePolymarketTradeFlags(args) {
|
|
|
4434
4434
|
dryRun: false,
|
|
4435
4435
|
execute: false,
|
|
4436
4436
|
host: null,
|
|
4437
|
+
timeoutMs: DEFAULT_INDEXER_TIMEOUT_MS,
|
|
4437
4438
|
rpcUrl: null,
|
|
4438
4439
|
privateKey: null,
|
|
4439
4440
|
funder: null,
|
|
@@ -4485,6 +4486,11 @@ function parsePolymarketTradeFlags(args) {
|
|
|
4485
4486
|
i += 1;
|
|
4486
4487
|
continue;
|
|
4487
4488
|
}
|
|
4489
|
+
if (token === '--timeout-ms') {
|
|
4490
|
+
options.timeoutMs = parsePositiveInteger(requireFlagValue(args, i, '--timeout-ms'), '--timeout-ms');
|
|
4491
|
+
i += 1;
|
|
4492
|
+
continue;
|
|
4493
|
+
}
|
|
4488
4494
|
if (token === '--dry-run') {
|
|
4489
4495
|
options.dryRun = true;
|
|
4490
4496
|
continue;
|
|
@@ -9768,7 +9774,7 @@ async function runPolymarketCommand(args, context) {
|
|
|
9768
9774
|
console.log(' approve --dry-run|--execute [--rpc-url <url>] [--private-key <hex>] [--funder <address>]');
|
|
9769
9775
|
console.log(' preflight [--rpc-url <url>] [--private-key <hex>] [--funder <address>]');
|
|
9770
9776
|
console.log(
|
|
9771
|
-
' trade --condition-id <id>|--slug <slug>|--token-id <id> --token yes|no --amount-usdc <n> --dry-run|--execute [--side buy|sell] [--polymarket-host <url>] [--rpc-url <url>] [--private-key <hex>] [--funder <address>]',
|
|
9777
|
+
' trade --condition-id <id>|--slug <slug>|--token-id <id> --token yes|no --amount-usdc <n> --dry-run|--execute [--side buy|sell] [--polymarket-host <url>] [--timeout-ms <ms>] [--rpc-url <url>] [--private-key <hex>] [--funder <address>]',
|
|
9772
9778
|
);
|
|
9773
9779
|
}
|
|
9774
9780
|
return;
|
|
@@ -9847,7 +9853,7 @@ async function runPolymarketCommand(args, context) {
|
|
|
9847
9853
|
if (action === 'trade') {
|
|
9848
9854
|
if (includesHelpFlag(actionArgs)) {
|
|
9849
9855
|
const usage =
|
|
9850
|
-
'pandora [--output table|json] polymarket trade --condition-id <id>|--slug <slug>|--token-id <id> --token yes|no --amount-usdc <n> --dry-run|--execute [--side buy|sell] [--polymarket-host <url>] [--rpc-url <url>] [--private-key <hex>] [--funder <address>]';
|
|
9856
|
+
'pandora [--output table|json] polymarket trade --condition-id <id>|--slug <slug>|--token-id <id> --token yes|no --amount-usdc <n> --dry-run|--execute [--side buy|sell] [--polymarket-host <url>] [--timeout-ms <ms>] [--rpc-url <url>] [--private-key <hex>] [--funder <address>]';
|
|
9851
9857
|
if (context.outputMode === 'json') {
|
|
9852
9858
|
emitSuccess(context.outputMode, 'polymarket.trade.help', commandHelpPayload(usage));
|
|
9853
9859
|
} else {
|
|
@@ -9862,7 +9868,7 @@ async function runPolymarketCommand(args, context) {
|
|
|
9862
9868
|
if (!tokenId) {
|
|
9863
9869
|
market = await resolvePolymarketMarket({
|
|
9864
9870
|
host: options.host || process.env.POLYMARKET_HOST || null,
|
|
9865
|
-
timeoutMs:
|
|
9871
|
+
timeoutMs: options.timeoutMs,
|
|
9866
9872
|
marketId: options.conditionId,
|
|
9867
9873
|
slug: options.slug,
|
|
9868
9874
|
});
|
|
@@ -10126,38 +10132,47 @@ async function runSuggestCommand(args, context) {
|
|
|
10126
10132
|
maybeLoadIndexerEnv(shared);
|
|
10127
10133
|
const indexerUrl = resolveIndexerUrl(shared.indexerUrl);
|
|
10128
10134
|
const options = parseSuggestFlags(shared.rest);
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10135
|
+
let history;
|
|
10136
|
+
let arbitrage;
|
|
10137
|
+
try {
|
|
10138
|
+
history = await fetchHistory({
|
|
10139
|
+
wallet: options.wallet,
|
|
10140
|
+
chainId: null,
|
|
10141
|
+
marketAddress: null,
|
|
10142
|
+
side: 'both',
|
|
10143
|
+
status: 'all',
|
|
10144
|
+
limit: 250,
|
|
10145
|
+
after: null,
|
|
10146
|
+
before: null,
|
|
10147
|
+
orderBy: 'timestamp',
|
|
10148
|
+
orderDirection: 'desc',
|
|
10149
|
+
includeSeed: false,
|
|
10150
|
+
indexerUrl,
|
|
10151
|
+
timeoutMs: shared.timeoutMs,
|
|
10152
|
+
});
|
|
10153
|
+
arbitrage = await scanArbitrage({
|
|
10154
|
+
indexerUrl,
|
|
10155
|
+
timeoutMs: shared.timeoutMs,
|
|
10156
|
+
chainId: null,
|
|
10157
|
+
venues: options.includeVenues,
|
|
10158
|
+
limit: Math.max(options.count * 3, 10),
|
|
10159
|
+
minSpreadPct: 3,
|
|
10160
|
+
minLiquidityUsd: 1000,
|
|
10161
|
+
maxCloseDiffHours: 24,
|
|
10162
|
+
similarityThreshold: 0.86,
|
|
10163
|
+
crossVenueOnly: true,
|
|
10164
|
+
withRules: false,
|
|
10165
|
+
includeSimilarity: false,
|
|
10166
|
+
questionContains: null,
|
|
10167
|
+
polymarketHost: null,
|
|
10168
|
+
polymarketMockUrl: null,
|
|
10169
|
+
});
|
|
10170
|
+
} catch (err) {
|
|
10171
|
+
if (err && err.code) {
|
|
10172
|
+
throw new CliError(err.code, err.message || 'suggest failed.', err.details);
|
|
10173
|
+
}
|
|
10174
|
+
throw err;
|
|
10175
|
+
}
|
|
10161
10176
|
|
|
10162
10177
|
const suggestions = buildSuggestions({
|
|
10163
10178
|
wallet: options.wallet,
|