pmxt-core 2.50.16 → 2.51.1

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.
Files changed (50) hide show
  1. package/dist/exchanges/hunch/api.d.ts +736 -0
  2. package/dist/exchanges/hunch/api.js +820 -0
  3. package/dist/exchanges/hunch/auth.d.ts +36 -0
  4. package/dist/exchanges/hunch/auth.js +63 -0
  5. package/dist/exchanges/hunch/errors.d.ts +26 -0
  6. package/dist/exchanges/hunch/errors.js +94 -0
  7. package/dist/exchanges/hunch/fetcher.d.ts +204 -0
  8. package/dist/exchanges/hunch/fetcher.js +130 -0
  9. package/dist/exchanges/hunch/index.d.ts +51 -0
  10. package/dist/exchanges/hunch/index.js +330 -0
  11. package/dist/exchanges/hunch/normalizer.d.ts +56 -0
  12. package/dist/exchanges/hunch/normalizer.js +180 -0
  13. package/dist/exchanges/hunch/price.d.ts +5 -0
  14. package/dist/exchanges/hunch/price.js +12 -0
  15. package/dist/exchanges/hunch/utils.d.ts +79 -0
  16. package/dist/exchanges/hunch/utils.js +182 -0
  17. package/dist/exchanges/hunch/websocket.d.ts +25 -0
  18. package/dist/exchanges/hunch/websocket.js +137 -0
  19. package/dist/exchanges/hyperliquid/auth.js +15 -2
  20. package/dist/exchanges/hyperliquid/fetcher.d.ts +26 -1
  21. package/dist/exchanges/hyperliquid/fetcher.js +66 -4
  22. package/dist/exchanges/hyperliquid/index.d.ts +4 -1
  23. package/dist/exchanges/hyperliquid/index.js +84 -20
  24. package/dist/exchanges/hyperliquid/normalizer.d.ts +4 -3
  25. package/dist/exchanges/hyperliquid/normalizer.js +69 -11
  26. package/dist/exchanges/hyperliquid/utils.d.ts +7 -1
  27. package/dist/exchanges/hyperliquid/utils.js +16 -4
  28. package/dist/exchanges/kalshi/api.d.ts +1 -1
  29. package/dist/exchanges/kalshi/api.js +1 -1
  30. package/dist/exchanges/limitless/api.d.ts +1 -1
  31. package/dist/exchanges/limitless/api.js +1 -1
  32. package/dist/exchanges/myriad/api.d.ts +1 -1
  33. package/dist/exchanges/myriad/api.js +1 -1
  34. package/dist/exchanges/opinion/api.d.ts +1 -1
  35. package/dist/exchanges/opinion/api.js +1 -1
  36. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  37. package/dist/exchanges/polymarket/api-clob.js +1 -1
  38. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  39. package/dist/exchanges/polymarket/api-data.js +1 -1
  40. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  41. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  42. package/dist/exchanges/probable/api.d.ts +1 -1
  43. package/dist/exchanges/probable/api.js +1 -1
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.js +5 -1
  46. package/dist/server/app.js +1 -0
  47. package/dist/server/exchange-factory.js +8 -0
  48. package/dist/server/openapi.yaml +18 -0
  49. package/dist/types.d.ts +4 -0
  50. package/package.json +3 -3
@@ -0,0 +1,36 @@
1
+ import { ExchangeCredentials } from '../../BaseExchange';
2
+ import { type LocalAccount } from 'viem';
3
+ export interface HunchCredentials extends ExchangeCredentials {
4
+ /** EOA private key that pays the x402 USDC authorization (Base). */
5
+ privateKey?: string;
6
+ /** Wallet address for keyless reads (positions/balance). Derived from
7
+ * `privateKey` when present; required on its own for read-only use. */
8
+ walletAddress?: string;
9
+ /** Optional base URL override (defaults to https://www.playhunch.xyz). */
10
+ baseUrl?: string;
11
+ }
12
+ /**
13
+ * Hunch auth holder.
14
+ *
15
+ * Reads are KEYLESS — `getHeaders()` returns only a JSON content type, and the
16
+ * read methods that need a wallet (positions/balance) take the address as a
17
+ * query param, not an auth header.
18
+ *
19
+ * The money path (createOrder) signs an EIP-3009 `transferWithAuthorization`
20
+ * with the wallet's viem `LocalAccount`, obtained lazily from `privateKey`.
21
+ */
22
+ export declare class HunchAuth {
23
+ private readonly credentials;
24
+ private account?;
25
+ constructor(credentials: HunchCredentials);
26
+ /** Reads carry no auth — the wallet IS the account (passed as a param). */
27
+ getHeaders(): Record<string, string>;
28
+ /** The wallet address (explicit, or derived from the private key). */
29
+ get walletAddress(): string | undefined;
30
+ get hasSigner(): boolean;
31
+ /** Lazily build (and cache) the viem account that signs the x402 payment. */
32
+ getAccount(): LocalAccount;
33
+ requireWalletAddress(method: string): string;
34
+ private deriveAddress;
35
+ private normalizePk;
36
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HunchAuth = void 0;
4
+ const errors_1 = require("../../errors");
5
+ const accounts_1 = require("viem/accounts");
6
+ /**
7
+ * Hunch auth holder.
8
+ *
9
+ * Reads are KEYLESS — `getHeaders()` returns only a JSON content type, and the
10
+ * read methods that need a wallet (positions/balance) take the address as a
11
+ * query param, not an auth header.
12
+ *
13
+ * The money path (createOrder) signs an EIP-3009 `transferWithAuthorization`
14
+ * with the wallet's viem `LocalAccount`, obtained lazily from `privateKey`.
15
+ */
16
+ class HunchAuth {
17
+ credentials;
18
+ account;
19
+ constructor(credentials) {
20
+ this.credentials = credentials;
21
+ }
22
+ /** Reads carry no auth — the wallet IS the account (passed as a param). */
23
+ getHeaders() {
24
+ return { 'Content-Type': 'application/json' };
25
+ }
26
+ /** The wallet address (explicit, or derived from the private key). */
27
+ get walletAddress() {
28
+ if (this.credentials.walletAddress)
29
+ return this.credentials.walletAddress;
30
+ const derived = this.deriveAddress();
31
+ return derived;
32
+ }
33
+ get hasSigner() {
34
+ return !!this.credentials.privateKey;
35
+ }
36
+ /** Lazily build (and cache) the viem account that signs the x402 payment. */
37
+ getAccount() {
38
+ if (this.account)
39
+ return this.account;
40
+ if (!this.credentials.privateKey) {
41
+ throw new errors_1.AuthenticationError('Placing a real Hunch bet requires a privateKey to sign the x402 USDC ' +
42
+ 'payment. Initialize HunchExchange with { privateKey }.', 'Hunch');
43
+ }
44
+ this.account = (0, accounts_1.privateKeyToAccount)(this.normalizePk(this.credentials.privateKey));
45
+ return this.account;
46
+ }
47
+ requireWalletAddress(method) {
48
+ const addr = this.walletAddress;
49
+ if (!addr) {
50
+ throw new errors_1.AuthenticationError(`${method} requires a wallet address. Pass { walletAddress } or { privateKey } in credentials.`, 'Hunch');
51
+ }
52
+ return addr;
53
+ }
54
+ deriveAddress() {
55
+ if (!this.credentials.privateKey)
56
+ return undefined;
57
+ return (0, accounts_1.privateKeyToAccount)(this.normalizePk(this.credentials.privateKey)).address;
58
+ }
59
+ normalizePk(pk) {
60
+ return (pk.startsWith('0x') ? pk : `0x${pk}`);
61
+ }
62
+ }
63
+ exports.HunchAuth = HunchAuth;
@@ -0,0 +1,26 @@
1
+ import { ErrorMapper } from '../../utils/error-mapper';
2
+ import { BadRequest } from '../../errors';
3
+ /**
4
+ * Maps Hunch agent-API error bodies to pmxt unified errors.
5
+ *
6
+ * Hunch follows an "errors-as-documentation" convention: every 4xx/5xx carries
7
+ * `{ error, message, hint?, docsUrl?, retriable? }` where `error` is a STABLE
8
+ * machine code (the AGENT_ERROR_CODES catalogue). We branch on that code first
9
+ * (precise), then fall back to the base mapper's status-code routing.
10
+ *
11
+ * Catalogue (src/agent/errors.ts): invalid_wallet, invalid_request,
12
+ * market_not_found, market_closed, market_resolved, invalid_side,
13
+ * size_below_min, size_above_simple_tier, quote_required, quote_expired,
14
+ * quote_mismatch, slippage_exceeded, insufficient_balance, payment_required,
15
+ * payment_invalid, pool_impact_exceeded, trading_paused, rate_limited,
16
+ * internal_error.
17
+ */
18
+ export declare class HunchErrorMapper extends ErrorMapper {
19
+ constructor();
20
+ mapError(error: unknown): ReturnType<ErrorMapper['mapError']>;
21
+ protected extractErrorMessage(error: unknown): string;
22
+ protected mapBadRequestError(message: string, data: unknown): BadRequest;
23
+ /** Pull Hunch's stable machine code out of the response body. */
24
+ private extractCode;
25
+ }
26
+ export declare const hunchErrorMapper: HunchErrorMapper;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.hunchErrorMapper = exports.HunchErrorMapper = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const error_mapper_1 = require("../../utils/error-mapper");
9
+ const errors_1 = require("../../errors");
10
+ /**
11
+ * Maps Hunch agent-API error bodies to pmxt unified errors.
12
+ *
13
+ * Hunch follows an "errors-as-documentation" convention: every 4xx/5xx carries
14
+ * `{ error, message, hint?, docsUrl?, retriable? }` where `error` is a STABLE
15
+ * machine code (the AGENT_ERROR_CODES catalogue). We branch on that code first
16
+ * (precise), then fall back to the base mapper's status-code routing.
17
+ *
18
+ * Catalogue (src/agent/errors.ts): invalid_wallet, invalid_request,
19
+ * market_not_found, market_closed, market_resolved, invalid_side,
20
+ * size_below_min, size_above_simple_tier, quote_required, quote_expired,
21
+ * quote_mismatch, slippage_exceeded, insufficient_balance, payment_required,
22
+ * payment_invalid, pool_impact_exceeded, trading_paused, rate_limited,
23
+ * internal_error.
24
+ */
25
+ class HunchErrorMapper extends error_mapper_1.ErrorMapper {
26
+ constructor() {
27
+ super('Hunch');
28
+ }
29
+ mapError(error) {
30
+ const code = this.extractCode(error);
31
+ const message = this.extractErrorMessage(error);
32
+ if (code) {
33
+ switch (code) {
34
+ case 'insufficient_balance':
35
+ return new errors_1.InsufficientFunds(message, this.exchangeName);
36
+ case 'invalid_side':
37
+ case 'size_below_min':
38
+ case 'size_above_simple_tier':
39
+ case 'quote_required':
40
+ case 'quote_expired':
41
+ case 'quote_mismatch':
42
+ case 'slippage_exceeded':
43
+ case 'pool_impact_exceeded':
44
+ return new errors_1.InvalidOrder(message, this.exchangeName);
45
+ case 'market_not_found':
46
+ return new errors_1.NotFound(`Market not found: ${message}`, this.exchangeName);
47
+ // market_closed / market_resolved / trading_paused / payment_* /
48
+ // invalid_wallet / invalid_request / rate_limited / internal_error
49
+ // fall through to the status-code base mapping below.
50
+ default:
51
+ break;
52
+ }
53
+ }
54
+ return super.mapError(error);
55
+ }
56
+ extractErrorMessage(error) {
57
+ if (axios_1.default.isAxiosError(error) && error.response?.data) {
58
+ const data = error.response.data;
59
+ if (typeof data.message === 'string')
60
+ return data.message;
61
+ if (typeof data.error === 'string')
62
+ return data.error;
63
+ }
64
+ return super.extractErrorMessage(error);
65
+ }
66
+ mapBadRequestError(message, data) {
67
+ const lower = message.toLowerCase();
68
+ if (lower.includes('insufficient') || lower.includes('balance')) {
69
+ return new errors_1.InsufficientFunds(message, this.exchangeName);
70
+ }
71
+ if (lower.includes('side') || lower.includes('slippage') || lower.includes('quote')) {
72
+ return new errors_1.InvalidOrder(message, this.exchangeName);
73
+ }
74
+ return super.mapBadRequestError(message, data);
75
+ }
76
+ /** Pull Hunch's stable machine code out of the response body. */
77
+ extractCode(error) {
78
+ if (axios_1.default.isAxiosError(error) && error.response?.data) {
79
+ const data = error.response.data;
80
+ if (typeof data.error === 'string')
81
+ return data.error;
82
+ }
83
+ if (error && typeof error === 'object') {
84
+ const maybe = error;
85
+ if (maybe.body && typeof maybe.body.error === 'string')
86
+ return maybe.body.error;
87
+ if (typeof maybe.code === 'string')
88
+ return maybe.code;
89
+ }
90
+ return undefined;
91
+ }
92
+ }
93
+ exports.HunchErrorMapper = HunchErrorMapper;
94
+ exports.hunchErrorMapper = new HunchErrorMapper();
@@ -0,0 +1,204 @@
1
+ import { MarketFilterParams, EventFetchParams, OHLCVParams, TradesParams } from '../../BaseExchange';
2
+ import { IExchangeFetcher, FetcherContext } from '../interfaces';
3
+ export interface HunchRawOutcome {
4
+ key: string;
5
+ label: string;
6
+ shortLabel: string;
7
+ lowerUsd: number | null;
8
+ upperUsd: number | null;
9
+ startAt?: string | null;
10
+ endAt?: string | null;
11
+ }
12
+ export interface HunchRawMarketLinks {
13
+ app: string;
14
+ quote: string;
15
+ trade: string;
16
+ research: string;
17
+ }
18
+ export interface HunchRawMarket {
19
+ id: string;
20
+ slug: string;
21
+ question: string;
22
+ shortTitle: string;
23
+ summary: string;
24
+ category: string;
25
+ tokenSymbol: string;
26
+ chainId: string;
27
+ deadlineAt: string;
28
+ deadlineLabel: string;
29
+ status: string;
30
+ feeBps: number;
31
+ feeRecipientLabel: string;
32
+ defaultTicketUsd: number;
33
+ virtualLiquidityUsd: number;
34
+ /** Present in the schema; absent on the bare list endpoint — optional. */
35
+ volumeUsd?: number;
36
+ totalBets?: number;
37
+ targetMarketCapUsd: number | null;
38
+ outcomes: HunchRawOutcome[] | null;
39
+ headline?: string | null;
40
+ links: HunchRawMarketLinks;
41
+ [key: string]: unknown;
42
+ }
43
+ export interface HunchRawBinaryOdds {
44
+ yesPriceCents: number | null;
45
+ noPriceCents: number | null;
46
+ }
47
+ export interface HunchRawLadderOutcome extends HunchRawOutcome {
48
+ impliedPct: number;
49
+ backedUsd: number;
50
+ isCurrent: boolean;
51
+ }
52
+ export interface HunchRawLadder {
53
+ outcomes: HunchRawLadderOutcome[];
54
+ currentBucketKey: string | null;
55
+ currentMarketCapUsd: number | null;
56
+ totalBackedUsd: number;
57
+ }
58
+ export interface HunchRawTokenSnapshot {
59
+ tokenSymbol: string;
60
+ currentMarketCapUsd: number;
61
+ currentPriceUsd: number | null;
62
+ targetMarketCapUsd: number;
63
+ distanceToTargetPct: number;
64
+ reachedTarget: boolean;
65
+ source: string;
66
+ sourceUrl: string;
67
+ observedAt: string;
68
+ }
69
+ export interface HunchRawMarketStats {
70
+ totalBets: number;
71
+ totalPoolUsd: number;
72
+ yesPoolUsd: number;
73
+ noPoolUsd: number;
74
+ feeUsd: number;
75
+ }
76
+ export interface HunchRawOddsHistoryPoint {
77
+ at: string;
78
+ yesPct: number | null;
79
+ outcomeKey: string | null;
80
+ sizeUsd: number;
81
+ }
82
+ export interface HunchRawResearch {
83
+ market: HunchRawMarket;
84
+ resolutionRules: {
85
+ source: string;
86
+ sourceUrl: string | null;
87
+ metric: string;
88
+ comparator: string | null;
89
+ thresholdLabel: string | null;
90
+ deadlineAt: string;
91
+ earlyResolvable: boolean;
92
+ description: string;
93
+ };
94
+ odds: HunchRawBinaryOdds;
95
+ stats: HunchRawMarketStats | null;
96
+ ladder: HunchRawLadder | null;
97
+ tokenSnapshot: HunchRawTokenSnapshot | null;
98
+ oddsHistory: HunchRawOddsHistoryPoint[];
99
+ observations: {
100
+ observedAt: string;
101
+ value: number | null;
102
+ label: string | null;
103
+ sourceUrl: string | null;
104
+ }[];
105
+ related: {
106
+ id: string;
107
+ slug: string;
108
+ question: string;
109
+ category: string;
110
+ deadlineAt: string;
111
+ }[];
112
+ impact: {
113
+ sizeUsd: number;
114
+ priceCents: number | null;
115
+ impactPct: number | null;
116
+ }[];
117
+ [key: string]: unknown;
118
+ }
119
+ export interface HunchRawQuote {
120
+ marketId: string;
121
+ side: string;
122
+ sizeUsd: number;
123
+ tier: 'simple' | 'locked';
124
+ quoteId: string;
125
+ expiresAt: string;
126
+ bookVersion: string;
127
+ priceCents: number;
128
+ estimatedShares: number;
129
+ suggestedMinSharesOut: number;
130
+ feeBps: number;
131
+ feeUsd: number;
132
+ netStakeUsd: number;
133
+ postTradeOdds: HunchRawBinaryOdds;
134
+ impactPct: number | null;
135
+ ladder: HunchRawLadder | null;
136
+ tokenSnapshot: HunchRawTokenSnapshot | null;
137
+ stats: HunchRawMarketStats | null;
138
+ [key: string]: unknown;
139
+ }
140
+ export interface HunchRawPosition {
141
+ marketId: string;
142
+ slug: string;
143
+ question: string;
144
+ side: string;
145
+ outcomeLabel: string;
146
+ shares: number;
147
+ stakedUsd: number;
148
+ avgEntryCents: number;
149
+ currentCents: number;
150
+ pnlUsd: number;
151
+ maxPayoutUsd: number;
152
+ status: 'open' | 'resolved-won' | 'resolved-lost';
153
+ appUrl: string;
154
+ proofUrl: string | null;
155
+ filledAt: string | null;
156
+ [key: string]: unknown;
157
+ }
158
+ export interface HunchRawReadiness {
159
+ wallet: string;
160
+ usdcBalanceUsd: number | null;
161
+ canBetMin: boolean | null;
162
+ minBetUsd: number;
163
+ simpleTierMaxUsd: number;
164
+ gasNeeded: false;
165
+ reason: string;
166
+ funding: {
167
+ network: 'base';
168
+ usdcAddress: string;
169
+ docsUrl: string;
170
+ };
171
+ hint: string | null;
172
+ [key: string]: unknown;
173
+ }
174
+ /**
175
+ * HunchFetcher — raw GETs against the live agent API. Hunch reads are keyless,
176
+ * so we hit the HTTP client directly (clearer + more robust than the implicit
177
+ * `callApi` for these path/query-param GETs). The trade POST (x402 money path)
178
+ * is handled in index.ts createOrder, not here.
179
+ */
180
+ export declare class HunchFetcher implements IExchangeFetcher<HunchRawMarket, HunchRawMarket, HunchRawPosition[]> {
181
+ private readonly ctx;
182
+ private readonly baseUrl;
183
+ constructor(ctx: FetcherContext, baseUrl?: string);
184
+ fetchRawMarkets(params?: MarketFilterParams): Promise<HunchRawMarket[]>;
185
+ /**
186
+ * Hunch has no Event tier (markets stand alone). `fetchRawEvents` returns
187
+ * the raw markets so the exchange can wrap each as a single-market event
188
+ * when the event API is used; honoring `series` by returning [].
189
+ */
190
+ fetchRawEvents(params: EventFetchParams): Promise<HunchRawMarket[]>;
191
+ /** Research payload — carries oddsHistory, the source for OHLCV/trades. */
192
+ fetchRawOHLCV(id: string, _params: OHLCVParams): Promise<HunchRawResearch>;
193
+ /** Quote + research drive the emulated orderbook (implied price + pool). */
194
+ fetchRawOrderBook(id: string): Promise<HunchRawResearch>;
195
+ /** oddsHistory (from research) doubles as the public trade tape. */
196
+ fetchRawTrades(id: string, _params: TradesParams): Promise<HunchRawOddsHistoryPoint[]>;
197
+ fetchRawPositions(walletAddress: string): Promise<HunchRawPosition[]>;
198
+ fetchRawBalance(walletAddress: string): Promise<HunchRawReadiness>;
199
+ fetchRawResearch(marketId: string): Promise<HunchRawResearch>;
200
+ fetchRawQuote(marketId: string, side: string, sizeUsd: number, wallet?: string): Promise<HunchRawQuote>;
201
+ private fetchRawMarketById;
202
+ /** outcomeId is `${marketId}:${side}`; strip the side to get the market id. */
203
+ private outcomeIdToMarketId;
204
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HunchFetcher = void 0;
4
+ const utils_1 = require("./utils");
5
+ const errors_1 = require("./errors");
6
+ const AGENT_PREFIX = '/api/agent/v1';
7
+ const DEFAULT_LIMIT = 200;
8
+ /**
9
+ * HunchFetcher — raw GETs against the live agent API. Hunch reads are keyless,
10
+ * so we hit the HTTP client directly (clearer + more robust than the implicit
11
+ * `callApi` for these path/query-param GETs). The trade POST (x402 money path)
12
+ * is handled in index.ts createOrder, not here.
13
+ */
14
+ class HunchFetcher {
15
+ ctx;
16
+ baseUrl;
17
+ constructor(ctx, baseUrl) {
18
+ this.ctx = ctx;
19
+ this.baseUrl = (baseUrl || utils_1.DEFAULT_BASE_URL).replace(/\/$/, '');
20
+ }
21
+ async fetchRawMarkets(params) {
22
+ try {
23
+ if (params?.marketId) {
24
+ const one = await this.fetchRawMarketById(params.marketId);
25
+ return one ? [one] : [];
26
+ }
27
+ if (params?.slug) {
28
+ const one = await this.fetchRawMarketById(params.slug);
29
+ return one ? [one] : [];
30
+ }
31
+ const query = {
32
+ limit: params?.limit ?? DEFAULT_LIMIT,
33
+ };
34
+ const status = (0, utils_1.mapStatusToHunch)(params?.status);
35
+ if (status)
36
+ query.status = status;
37
+ if (params?.query)
38
+ query.token = params.query;
39
+ const res = await this.ctx.http.get(`${this.baseUrl}${AGENT_PREFIX}/markets`, {
40
+ params: query,
41
+ headers: this.ctx.getHeaders(),
42
+ });
43
+ const markets = res.data?.markets ?? [];
44
+ return markets;
45
+ }
46
+ catch (error) {
47
+ throw errors_1.hunchErrorMapper.mapError(error);
48
+ }
49
+ }
50
+ /**
51
+ * Hunch has no Event tier (markets stand alone). `fetchRawEvents` returns
52
+ * the raw markets so the exchange can wrap each as a single-market event
53
+ * when the event API is used; honoring `series` by returning [].
54
+ */
55
+ async fetchRawEvents(params) {
56
+ if (params.series !== undefined)
57
+ return [];
58
+ return this.fetchRawMarkets({
59
+ limit: params.limit,
60
+ status: params.status,
61
+ query: params.query,
62
+ });
63
+ }
64
+ /** Research payload — carries oddsHistory, the source for OHLCV/trades. */
65
+ async fetchRawOHLCV(id, _params) {
66
+ return this.fetchRawResearch(this.outcomeIdToMarketId(id));
67
+ }
68
+ /** Quote + research drive the emulated orderbook (implied price + pool). */
69
+ async fetchRawOrderBook(id) {
70
+ return this.fetchRawResearch(this.outcomeIdToMarketId(id));
71
+ }
72
+ /** oddsHistory (from research) doubles as the public trade tape. */
73
+ async fetchRawTrades(id, _params) {
74
+ const research = await this.fetchRawResearch(this.outcomeIdToMarketId(id));
75
+ return research.oddsHistory ?? [];
76
+ }
77
+ async fetchRawPositions(walletAddress) {
78
+ try {
79
+ const res = await this.ctx.http.get(`${this.baseUrl}${AGENT_PREFIX}/positions`, {
80
+ params: { wallet: walletAddress },
81
+ headers: this.ctx.getHeaders(),
82
+ });
83
+ return res.data?.positions ?? [];
84
+ }
85
+ catch (error) {
86
+ throw errors_1.hunchErrorMapper.mapError(error);
87
+ }
88
+ }
89
+ async fetchRawBalance(walletAddress) {
90
+ try {
91
+ const res = await this.ctx.http.get(`${this.baseUrl}${AGENT_PREFIX}/wallet/${encodeURIComponent(walletAddress)}/readiness`, { headers: this.ctx.getHeaders() });
92
+ return res.data?.readiness ?? res.data;
93
+ }
94
+ catch (error) {
95
+ throw errors_1.hunchErrorMapper.mapError(error);
96
+ }
97
+ }
98
+ // -- Shared raw reads -----------------------------------------------------
99
+ async fetchRawResearch(marketId) {
100
+ try {
101
+ const res = await this.ctx.http.get(`${this.baseUrl}${AGENT_PREFIX}/markets/${encodeURIComponent(marketId)}/research`, { headers: this.ctx.getHeaders() });
102
+ return res.data?.research ?? res.data;
103
+ }
104
+ catch (error) {
105
+ throw errors_1.hunchErrorMapper.mapError(error);
106
+ }
107
+ }
108
+ async fetchRawQuote(marketId, side, sizeUsd, wallet) {
109
+ try {
110
+ const res = await this.ctx.http.get(`${this.baseUrl}${AGENT_PREFIX}/quote`, {
111
+ params: { marketId, side, sizeUsd, ...(wallet ? { wallet } : {}) },
112
+ headers: this.ctx.getHeaders(),
113
+ });
114
+ return res.data?.quote ?? res.data;
115
+ }
116
+ catch (error) {
117
+ throw errors_1.hunchErrorMapper.mapError(error);
118
+ }
119
+ }
120
+ async fetchRawMarketById(id) {
121
+ const res = await this.ctx.http.get(`${this.baseUrl}${AGENT_PREFIX}/markets/${encodeURIComponent(id)}`, { headers: this.ctx.getHeaders() });
122
+ return res.data?.market ?? res.data ?? null;
123
+ }
124
+ /** outcomeId is `${marketId}:${side}`; strip the side to get the market id. */
125
+ outcomeIdToMarketId(id) {
126
+ const idx = id.lastIndexOf(':');
127
+ return idx > 0 ? id.slice(0, idx) : id;
128
+ }
129
+ }
130
+ exports.HunchFetcher = HunchFetcher;
@@ -0,0 +1,51 @@
1
+ import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, EventFetchParams } from '../../BaseExchange';
2
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, Balance, Order, Position, CreateOrderParams } from '../../types';
3
+ import { HunchCredentials } from './auth';
4
+ export declare class HunchExchange extends PredictionMarketExchange {
5
+ protected readonly capabilityOverrides: {
6
+ fetchOrderBook: "emulated";
7
+ createOrder: true;
8
+ cancelOrder: false;
9
+ fetchOrder: false;
10
+ fetchOpenOrders: false;
11
+ fetchBalance: true;
12
+ fetchPositions: true;
13
+ fetchSeries: false;
14
+ watchOrderBook: "emulated";
15
+ watchTrades: "emulated";
16
+ };
17
+ private readonly auth;
18
+ private readonly fetcher;
19
+ private readonly normalizer;
20
+ private readonly hunchBaseUrl;
21
+ private ws?;
22
+ constructor(credentials?: HunchCredentials);
23
+ get name(): string;
24
+ private getHeaders;
25
+ protected sign(_method: string, _path: string, _params: Record<string, any>): Record<string, string>;
26
+ protected mapImplicitApiError(error: any): any;
27
+ protected fetchMarketsImpl(params?: MarketFilterParams): Promise<UnifiedMarket[]>;
28
+ protected fetchEventsImpl(params: EventFetchParams): Promise<UnifiedEvent[]>;
29
+ fetchOHLCV(outcomeId: string, params: OHLCVParams): Promise<PriceCandle[]>;
30
+ fetchOrderBook(outcomeId: string, _limit?: number, _params?: Record<string, any>): Promise<OrderBook>;
31
+ fetchTrades(outcomeId: string, params: TradesParams | HistoryFilterParams): Promise<Trade[]>;
32
+ createOrder(params: CreateOrderParams): Promise<Order>;
33
+ cancelOrder(_orderId: string): Promise<Order>;
34
+ fetchOrder(_orderId: string): Promise<Order>;
35
+ fetchOpenOrders(_marketId?: string): Promise<Order[]>;
36
+ fetchPositions(): Promise<Position[]>;
37
+ fetchBalance(): Promise<Balance[]>;
38
+ watchOrderBook(outcomeId: string, _limit?: number, _params?: Record<string, any>): Promise<OrderBook>;
39
+ watchTrades(outcomeId: string, _address?: string, _since?: number, _limit?: number): Promise<Trade[]>;
40
+ close(): Promise<void>;
41
+ private makeWs;
42
+ /**
43
+ * POST the trade body via the axios client, NOT throwing on non-2xx so the
44
+ * 402 challenge can be read (validateStatus: always-true). Mirrors the SDK's
45
+ * fetch-based `post()` that inspects `res.status === 402`.
46
+ */
47
+ private postTrade;
48
+ /** Deterministic-but-unique idempotency key (≥8 chars per the schema). */
49
+ private buildIdemKey;
50
+ private receiptToOrder;
51
+ }