@baozi.bet/mcp-server 4.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.
Files changed (60) hide show
  1. package/README.md +294 -0
  2. package/dist/__tests__/full-test.d.ts +1 -0
  3. package/dist/__tests__/full-test.js +291 -0
  4. package/dist/builders/affiliate-transaction.d.ts +41 -0
  5. package/dist/builders/affiliate-transaction.js +123 -0
  6. package/dist/builders/bet-transaction.d.ts +70 -0
  7. package/dist/builders/bet-transaction.js +323 -0
  8. package/dist/builders/claim-transaction.d.ts +57 -0
  9. package/dist/builders/claim-transaction.js +196 -0
  10. package/dist/builders/creator-transaction.d.ts +49 -0
  11. package/dist/builders/creator-transaction.js +177 -0
  12. package/dist/builders/dispute-transaction.d.ts +81 -0
  13. package/dist/builders/dispute-transaction.js +215 -0
  14. package/dist/builders/index.d.ts +14 -0
  15. package/dist/builders/index.js +15 -0
  16. package/dist/builders/market-creation-tx.d.ts +65 -0
  17. package/dist/builders/market-creation-tx.js +362 -0
  18. package/dist/builders/market-management-transaction.d.ts +85 -0
  19. package/dist/builders/market-management-transaction.js +239 -0
  20. package/dist/builders/race-transaction.d.ts +67 -0
  21. package/dist/builders/race-transaction.js +242 -0
  22. package/dist/builders/resolution-transaction.d.ts +108 -0
  23. package/dist/builders/resolution-transaction.js +250 -0
  24. package/dist/builders/whitelist-transaction.d.ts +72 -0
  25. package/dist/builders/whitelist-transaction.js +179 -0
  26. package/dist/config.d.ts +138 -0
  27. package/dist/config.js +307 -0
  28. package/dist/handlers/agent-network.d.ts +81 -0
  29. package/dist/handlers/agent-network.js +332 -0
  30. package/dist/handlers/claims.d.ts +47 -0
  31. package/dist/handlers/claims.js +218 -0
  32. package/dist/handlers/market-creation.d.ts +154 -0
  33. package/dist/handlers/market-creation.js +290 -0
  34. package/dist/handlers/markets.d.ts +41 -0
  35. package/dist/handlers/markets.js +319 -0
  36. package/dist/handlers/positions.d.ts +40 -0
  37. package/dist/handlers/positions.js +244 -0
  38. package/dist/handlers/quote.d.ts +33 -0
  39. package/dist/handlers/quote.js +144 -0
  40. package/dist/handlers/race-markets.d.ts +54 -0
  41. package/dist/handlers/race-markets.js +308 -0
  42. package/dist/handlers/resolution.d.ts +43 -0
  43. package/dist/handlers/resolution.js +194 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.js +109 -0
  46. package/dist/resources.d.ts +13 -0
  47. package/dist/resources.js +336 -0
  48. package/dist/tools.d.ts +3109 -0
  49. package/dist/tools.js +1956 -0
  50. package/dist/validation/bet-rules.d.ts +82 -0
  51. package/dist/validation/bet-rules.js +276 -0
  52. package/dist/validation/creation-rules.d.ts +69 -0
  53. package/dist/validation/creation-rules.js +302 -0
  54. package/dist/validation/index.d.ts +6 -0
  55. package/dist/validation/index.js +7 -0
  56. package/dist/validation/market-rules.d.ts +60 -0
  57. package/dist/validation/market-rules.js +237 -0
  58. package/dist/validation/parimutuel-rules.d.ts +117 -0
  59. package/dist/validation/parimutuel-rules.js +270 -0
  60. package/package.json +52 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Positions handler for MCP server
3
+ * Fetches user positions from Solana V4.7.6 program (Mainnet)
4
+ */
5
+ import { Connection, PublicKey } from '@solana/web3.js';
6
+ import bs58 from 'bs58';
7
+ import { PROGRAM_ID, RPC_ENDPOINT, DISCRIMINATORS, lamportsToSol, } from '../config.js';
8
+ import { getMarket } from './markets.js';
9
+ // =============================================================================
10
+ // POSITION DECODER
11
+ // =============================================================================
12
+ /**
13
+ * Decode UserPosition account data from V4.7.6 struct
14
+ *
15
+ * UserPosition struct layout (from IDL):
16
+ * - discriminator (8)
17
+ * - user (Pubkey, 32)
18
+ * - market_id (u64, 8)
19
+ * - yes_amount (u64, 8)
20
+ * - no_amount (u64, 8)
21
+ * - claimed (bool, 1)
22
+ * - bump (u8, 1)
23
+ * - referred_by (Option<Pubkey>: 1 + 0/32)
24
+ * - affiliate_fee_paid (u64, 8)
25
+ * - reserved ([u8; 16], 16)
26
+ */
27
+ function decodePosition(data, pubkey) {
28
+ try {
29
+ let offset = 8; // Skip discriminator
30
+ // user (Pubkey, 32 bytes)
31
+ const user = new PublicKey(data.slice(offset, offset + 32));
32
+ offset += 32;
33
+ // market_id (u64, 8 bytes)
34
+ const marketId = data.readBigUInt64LE(offset);
35
+ offset += 8;
36
+ // yes_amount (u64, 8 bytes)
37
+ const yesAmount = data.readBigUInt64LE(offset);
38
+ offset += 8;
39
+ // no_amount (u64, 8 bytes)
40
+ const noAmount = data.readBigUInt64LE(offset);
41
+ offset += 8;
42
+ // claimed (bool, 1 byte)
43
+ const claimed = data.readUInt8(offset) === 1;
44
+ offset += 1;
45
+ // bump (u8, 1 byte)
46
+ offset += 1;
47
+ // referred_by (Option<Pubkey>: 1 byte discriminant + optional 32 bytes)
48
+ const hasReferrer = data.readUInt8(offset) === 1;
49
+ offset += 1;
50
+ let referredBy = null;
51
+ if (hasReferrer) {
52
+ referredBy = new PublicKey(data.slice(offset, offset + 32)).toBase58();
53
+ offset += 32;
54
+ }
55
+ // affiliate_fee_paid (u64, 8 bytes)
56
+ const affiliateFeePaid = data.readBigUInt64LE(offset);
57
+ // Derived fields
58
+ const yesAmountSol = round4(lamportsToSol(yesAmount));
59
+ const noAmountSol = round4(lamportsToSol(noAmount));
60
+ const totalAmountSol = round4(yesAmountSol + noAmountSol);
61
+ // Determine primary side
62
+ let side;
63
+ if (yesAmount > 0n && noAmount > 0n) {
64
+ side = 'Both';
65
+ }
66
+ else if (yesAmount > 0n) {
67
+ side = 'Yes';
68
+ }
69
+ else {
70
+ side = 'No';
71
+ }
72
+ return {
73
+ publicKey: pubkey.toBase58(),
74
+ user: user.toBase58(),
75
+ marketId: marketId.toString(),
76
+ yesAmountSol,
77
+ noAmountSol,
78
+ totalAmountSol,
79
+ side,
80
+ claimed,
81
+ referredBy,
82
+ affiliateFeePaidSol: round4(lamportsToSol(affiliateFeePaid)),
83
+ };
84
+ }
85
+ catch (err) {
86
+ console.error('Error decoding position:', err);
87
+ return null;
88
+ }
89
+ }
90
+ // =============================================================================
91
+ // PUBLIC API
92
+ // =============================================================================
93
+ /**
94
+ * Get all positions for a wallet
95
+ */
96
+ export async function getPositions(walletAddress) {
97
+ const connection = new Connection(RPC_ENDPOINT, 'confirmed');
98
+ try {
99
+ const wallet = new PublicKey(walletAddress);
100
+ // Get all position accounts for this user
101
+ // Note: Solana RPC expects base58 encoding for memcmp bytes
102
+ const accounts = await connection.getProgramAccounts(PROGRAM_ID, {
103
+ filters: [
104
+ {
105
+ memcmp: {
106
+ offset: 0,
107
+ bytes: bs58.encode(DISCRIMINATORS.USER_POSITION),
108
+ },
109
+ },
110
+ {
111
+ memcmp: {
112
+ offset: 8, // After discriminator
113
+ bytes: wallet.toBase58(),
114
+ },
115
+ },
116
+ ],
117
+ });
118
+ const positions = [];
119
+ for (const { account, pubkey } of accounts) {
120
+ const position = decodePosition(account.data, pubkey);
121
+ if (position) {
122
+ positions.push(position);
123
+ }
124
+ }
125
+ // Sort by market ID (newest markets first)
126
+ positions.sort((a, b) => Number(BigInt(b.marketId) - BigInt(a.marketId)));
127
+ return positions;
128
+ }
129
+ catch (err) {
130
+ console.error('Error fetching positions:', err);
131
+ return [];
132
+ }
133
+ }
134
+ /**
135
+ * Derive market PDA from market_id
136
+ */
137
+ function deriveMarketPda(marketId) {
138
+ const marketIdBigInt = BigInt(marketId);
139
+ const marketIdBuffer = Buffer.alloc(8);
140
+ marketIdBuffer.writeBigUInt64LE(marketIdBigInt);
141
+ const [pda] = PublicKey.findProgramAddressSync([Buffer.from('market'), marketIdBuffer], PROGRAM_ID);
142
+ return pda.toBase58();
143
+ }
144
+ /**
145
+ * Get positions with enriched market data
146
+ */
147
+ export async function getPositionsEnriched(walletAddress) {
148
+ const positions = await getPositions(walletAddress);
149
+ // Derive market PDAs from market_id
150
+ const positionsWithPda = positions.map(p => ({
151
+ ...p,
152
+ marketPda: deriveMarketPda(p.marketId),
153
+ }));
154
+ // Batch fetch market data for unique markets
155
+ const uniqueMarkets = [...new Set(positionsWithPda.map(p => p.marketPda))];
156
+ const marketData = new Map();
157
+ await Promise.all(uniqueMarkets.map(async (marketPda) => {
158
+ if (marketPda) {
159
+ const market = await getMarket(marketPda);
160
+ if (market) {
161
+ marketData.set(marketPda, market);
162
+ }
163
+ }
164
+ }));
165
+ // Enrich positions with market data
166
+ return positionsWithPda.map(position => {
167
+ const market = position.marketPda ? marketData.get(position.marketPda) : null;
168
+ if (!market)
169
+ return position;
170
+ // Calculate potential payout if position is winning
171
+ let potentialPayout;
172
+ const positionAmount = position.side === 'Yes' ? position.yesAmountSol : position.noAmountSol;
173
+ if (market.status === 'Resolved' && market.winningOutcome === position.side) {
174
+ const totalPool = market.yesPoolSol + market.noPoolSol;
175
+ const winningPool = position.side === 'Yes' ? market.yesPoolSol : market.noPoolSol;
176
+ if (winningPool > 0) {
177
+ const share = positionAmount / winningPool;
178
+ const grossPayout = share * totalPool;
179
+ const profit = grossPayout - positionAmount;
180
+ const fee = profit > 0 ? (profit * market.platformFeeBps) / 10000 : 0;
181
+ potentialPayout = round4(grossPayout - fee);
182
+ }
183
+ }
184
+ return {
185
+ ...position,
186
+ marketQuestion: market.question,
187
+ marketStatus: market.status,
188
+ marketOutcome: market.winningOutcome,
189
+ potentialPayout,
190
+ };
191
+ });
192
+ }
193
+ /**
194
+ * Get position summary with statistics
195
+ */
196
+ export async function getPositionsSummary(walletAddress) {
197
+ const positions = await getPositionsEnriched(walletAddress);
198
+ const totalBetSol = positions.reduce((sum, p) => sum + p.totalAmountSol, 0);
199
+ const activePositions = positions.filter(p => !p.claimed).length;
200
+ const claimedPositions = positions.filter(p => p.claimed).length;
201
+ // Count winning/losing/pending based on market status and outcome
202
+ let winningPositions = 0;
203
+ let losingPositions = 0;
204
+ let pendingPositions = 0;
205
+ for (const position of positions) {
206
+ if (!position.marketStatus || position.marketStatus === 'Active' || position.marketStatus === 'Closed') {
207
+ pendingPositions++;
208
+ }
209
+ else if (position.marketStatus === 'Resolved') {
210
+ if (position.marketOutcome === position.side) {
211
+ winningPositions++;
212
+ }
213
+ else if (position.marketOutcome === 'Invalid') {
214
+ // Refund case
215
+ pendingPositions++;
216
+ }
217
+ else {
218
+ losingPositions++;
219
+ }
220
+ }
221
+ else if (position.marketStatus === 'Cancelled') {
222
+ // Refund case
223
+ pendingPositions++;
224
+ }
225
+ }
226
+ return {
227
+ wallet: walletAddress,
228
+ totalPositions: positions.length,
229
+ totalBetSol: round4(totalBetSol),
230
+ activePositions,
231
+ claimedPositions,
232
+ winningPositions,
233
+ losingPositions,
234
+ pendingPositions,
235
+ positions,
236
+ };
237
+ }
238
+ // =============================================================================
239
+ // HELPERS
240
+ // =============================================================================
241
+ function round4(n) {
242
+ return Math.round(n * 10000) / 10000;
243
+ }
244
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zaXRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hhbmRsZXJzL3Bvc2l0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFDSCxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3hELE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQ0wsVUFBVSxFQUNWLFlBQVksRUFDWixjQUFjLEVBQ2QsYUFBYSxHQUNkLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFxQ3pDLGdGQUFnRjtBQUNoRixtQkFBbUI7QUFDbkIsZ0ZBQWdGO0FBRWhGOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsU0FBUyxjQUFjLENBQUMsSUFBWSxFQUFFLE1BQWlCO0lBQ3JELElBQUksQ0FBQztRQUNILElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLHFCQUFxQjtRQUVyQywwQkFBMEI7UUFDMUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUViLDJCQUEyQjtRQUMzQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlDLE1BQU0sSUFBSSxDQUFDLENBQUM7UUFFWiw0QkFBNEI7UUFDNUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQyxNQUFNLElBQUksQ0FBQyxDQUFDO1FBRVosMkJBQTJCO1FBQzNCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUMsTUFBTSxJQUFJLENBQUMsQ0FB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LEVBQUUsQ0FBQztZQUNoRCxJQUFJLFFBQVEsQ0FBQyxhQUFhLEtBQUssUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUM3QyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLENBQUM7aUJBQU0sSUFBSSxRQUFRLENBQUMsYUFBYSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNoRCxjQUFjO2dCQUNkLGdCQUFnQixFQUFFLENBQUM7WUFDckIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGVBQWUsRUFBRSxDQUFDO1lBQ3BCLENBQUM7UUFDSCxDQUFDO2FBQU0sSUFBSSxRQUFRLENBQUMsWUFBWSxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQ2pELGNBQWM7WUFDZCxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTztRQUNMLE1BQU0sRUFBRSxhQUFhO1FBQ3JCLGNBQWMsRUFBRSxTQUFTLENBQUMsTUFBTTtRQUNoQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQztRQUNoQyxlQUFlO1FBQ2YsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtRQUNoQixlQUFlO1FBQ2YsZ0JBQWdCO1FBQ2hCLFNBQVM7S0FDVixDQUFDO0FBQ0osQ0FBQztBQUVELGdGQUFnRjtBQUNoRixVQUFVO0FBQ1YsZ0ZBQWdGO0FBRWhGLFNBQVMsTUFBTSxDQUFDLENBQVM7SUFDdkIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDdkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUG9zaXRpb25zIGhhbmRsZXIgZm9yIE1DUCBzZXJ2ZXJcbiAqIEZldGNoZXMgdXNlciBwb3NpdGlvbnMgZnJvbSBTb2xhbmEgVjQuNy42IHByb2dyYW0gKE1haW5uZXQpXG4gKi9cbmltcG9ydCB7IENvbm5lY3Rpb24sIFB1YmxpY0tleSB9IGZyb20gJ0Bzb2xhbmEvd2ViMy5qcyc7XG5pbXBvcnQgYnM1OCBmcm9tICdiczU4JztcbmltcG9ydCB7XG4gIFBST0dSQU1fSUQsXG4gIFJQQ19FTkRQT0lOVCxcbiAgRElTQ1JJTUlOQVRPUlMsXG4gIGxhbXBvcnRzVG9Tb2wsXG59IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5pbXBvcnQgeyBnZXRNYXJrZXQgfSBmcm9tICcuL21hcmtldHMuanMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9zaXRpb24ge1xuICBwdWJsaWNLZXk6IHN0cmluZztcbiAgdXNlcjogc3RyaW5nO1xuICBtYXJrZXRJZDogc3RyaW5nO1xuICB5ZXNBbW91bnRTb2w6IG51bWJlcjtcbiAgbm9BbW91bnRTb2w6IG51bWJlcjtcbiAgdG90YWxBbW91bnRTb2w6IG51bWJlcjtcbiAgc2lkZTogJ1llcycgfCAnTm8nIHwgJ0JvdGgnOyAvLyBEZXJpdmVkOiB3aGljaCBzaWRlIGhhcyBtb3JlXG4gIGNsYWltZWQ6IGJvb2xlYW47XG4gIHJlZmVycmVkQnk6IHN0cmluZyB8IG51bGw7XG4gIGFmZmlsaWF0ZUZlZVBhaWRTb2w6IG51bWJlcjtcbiAgLy8gRW5yaWNoZWQgZmllbGRzIChvcHRpb25hbCwgZnJvbSBtYXJrZXQgbG9va3VwKVxuICBtYXJrZXRQZGE/OiBzdHJpbmc7XG4gIG1hcmtldFF1ZXN0aW9uPzogc3RyaW5nO1xuICBtYXJrZXRTdGF0dXM/OiBzdHJpbmc7XG4gIG1hcmtldE91dGNvbWU/OiBzdHJpbmcgfCBudWxsO1xuICBwb3RlbnRpYWxQYXlvdXQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9zaXRpb25TdW1tYXJ5IHtcbiAgd2FsbGV0OiBzdHJpbmc7XG4gIHRvdGFsUG9zaXRpb25zOiBudW1iZXI7XG4gIHRvdGFsQmV0U29sOiBudW1iZXI7XG4gIGFjdGl2ZVBvc2l0aW9uczogbnVtYmVyO1xuICBjbGFpbWVkUG9zaXRpb25zOiBudW1iZXI7XG4gIHdpbm5pbmdQb3NpdGlvbnM6IG51bWJlcjtcbiAgbG9zaW5nUG9zaXRpb25zOiBudW1iZXI7XG4gIHBlbmRpbmdQb3NpdGlvbnM6IG51bWJlcjtcbiAgcG9zaXRpb25zOiBQb3NpdGlvbltdO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUE9TSVRJT04gREVDT0RFUlxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBEZWNvZGUgVXNlclBvc2l0aW9uIGFjY291bnQgZGF0YSBmcm9tIFY0LjcuNiBzdHJ1Y3RcbiAqXG4gKiBVc2VyUG9zaXRpb24gc3RydWN0IGxheW91dCAoZnJvbSBJREwpOlxuICogLSBkaXNjcmltaW5hdG9yICg4KVxuICogLSB1c2VyIChQdWJrZXksIDMyKVxuICogLSBtYXJrZXRfaWQgKHU2NCwgOClcbiAqIC0geWVzX2Ftb3VudCAodTY0LCA4KVxuICogLSBub19hbW91bnQgKHU2NCwgOClcbiAqIC0gY2xhaW1lZCAoYm9vbCwgMSlcbiAqIC0gYnVtcCAodTgsIDEpXG4gKiAtIHJlZmVycmVkX2J5IChPcHRpb248UHVia2V5PjogMSArIDAvMzIpXG4gKiAtIGFmZmlsaWF0ZV9mZWVfcGFpZCAodTY0LCA4KVxuICogLSByZXNlcnZlZCAoW3U4OyAxNl0sIDE2KVxuICovXG5mdW5jdGlvbiBkZWNvZGVQb3NpdGlvbihkYXRhOiBCdWZmZXIsIHB1YmtleTogUHVibGljS2V5KTogUG9zaXRpb24gfCBudWxsIHtcbiAgdHJ5IHtcbiAgICBsZXQgb2Zmc2V0ID0gODsgLy8gU2tpcCBkaXNjcmltaW5hdG9yXG5cbiAgICAvLyB1c2VyIChQdWJrZXksIDMyIGJ5dGVzKVxuICAgIGNvbnN0IHVzZXIgPSBuZXcgUHVibGljS2V5KGRhdGEuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyAzMikpO1xuICAgIG9mZnNldCArPSAzMjtcblxuICAgIC8vIG1hcmtldF9pZCAodTY0LCA4IGJ5dGVzKVxuICAgIGNvbnN0IG1hcmtldElkID0gZGF0YS5yZWFkQmlnVUludDY0TEUob2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gODtcblxuICAgIC8vIHllc19hbW91bnQgKHU2NCwgOCBieXRlcylcbiAgICBjb25zdCB5ZXNBbW91bnQgPSBkYXRhLnJlYWRCaWdVSW50NjRMRShvZmZzZXQpO1xuICAgIG9mZnNldCArPSA4O1xuXG4gICAgLy8gbm9fYW1vdW50ICh1NjQsIDggYnl0ZXMpXG4gICAgY29uc3Qgbm9BbW91bnQgPSBkYXRhLnJlYWRCaWdVSW50NjRMRShvZmZzZXQpO1xuICAgIG9mZnNldCArPSA4O1xuXG4gICAgLy8gY2xhaW1lZCAoYm9vbCwgMSBieXRlKVxuICAgIGNvbnN0IGNsYWltZWQgPSBkYXRhLnJlYWRVSW50OChvZmZzZXQpID09PSAxO1xuICAgIG9mZnNldCArPSAxO1xuXG4gICAgLy8gYnVtcCAodTgsIDEgYnl0ZSlcbiAgICBvZmZzZXQgKz0gMTtcblxuICAgIC8vIHJlZmVycmVkX2J5IChPcHRpb248UHVia2V5PjogMSBieXRlIGRpc2NyaW1pbmFudCArIG9wdGlvbmFsIDMyIGJ5dGVzKVxuICAgIGNvbnN0IGhhc1JlZmVycmVyID0gZGF0YS5yZWFkVUludDgob2Zmc2V0KSA9PT0gMTtcbiAgICBvZmZzZXQgKz0gMTtcbiAgICBsZXQgcmVmZXJyZWRCeTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgaWYgKGhhc1JlZmVycmVyKSB7XG4gICAgICByZWZlcnJlZEJ5ID0gbmV3IFB1YmxpY0tleShkYXRhLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgMzIpKS50b0Jhc2U1OCgpO1xuICAgICAgb2Zmc2V0ICs9IDMyO1xuICAgIH1cblxuICAgIC8vIGFmZmlsaWF0ZV9mZWVfcGFpZCAodTY0LCA4IGJ5dGVzKVxuICAgIGNvbnN0IGFmZmlsaWF0ZUZlZVBhaWQgPSBkYXRhLnJlYWRCaWdVSW50NjRMRShvZmZzZXQpO1xuXG4gICAgLy8gRGVyaXZlZCBmaWVsZHNcbiAgICBjb25zdCB5ZXNBbW91bnRTb2wgPSByb3VuZDQobGFtcG9ydHNUb1NvbCh5ZXNBbW91bnQpKTtcbiAgICBjb25zdCBub0Ftb3VudFNvbCA9IHJvdW5kNChsYW1wb3J0c1RvU29sKG5vQW1vdW50KSk7XG4gICAgY29uc3QgdG90YWxBbW91bnRTb2wgPSByb3VuZDQoeWVzQW1vdW50U29sICsgbm9BbW91bnRTb2wpO1xuXG4gICAgLy8gRGV0ZXJtaW5lIHByaW1hcnkgc2lkZVxuICAgIGxldCBzaWRlOiAnWWVzJyB8ICdObycgfCAnQm90aCc7XG4gICAgaWYgKHllc0Ftb3VudCA+IDBuICYmIG5vQW1vdW50ID4gMG4pIHtcbiAgICAgIHNpZGUgPSAnQm90aCc7XG4gICAgfSBlbHNlIGlmICh5ZXNBbW91bnQgPiAwbikge1xuICAgICAgc2lkZSA9ICdZZXMnO1xuICAgIH0gZWxzZSB7XG4gICAgICBzaWRlID0gJ05vJztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcHVibGljS2V5OiBwdWJrZXkudG9CYXNlNTgoKSxcbiAgICAgIHVzZXI6IHVzZXIudG9CYXNlNTgoKSxcbiAgICAgIG1hcmtldElkOiBtYXJrZXRJZC50b1N0cmluZygpLFxuICAgICAgeWVzQW1vdW50U29sLFxuICAgICAgbm9BbW91bnRTb2wsXG4gICAgICB0b3RhbEFtb3VudFNvbCxcbiAgICAgIHNpZGUsXG4gICAgICBjbGFpbWVkLFxuICAgICAgcmVmZXJyZWRCeSxcbiAgICAgIGFmZmlsaWF0ZUZlZVBhaWRTb2w6IHJvdW5kNChsYW1wb3J0c1RvU29sKGFmZmlsaWF0ZUZlZVBhaWQpKSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBkZWNvZGluZyBwb3NpdGlvbjonLCBlcnIpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBQVUJMSUMgQVBJXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdldCBhbGwgcG9zaXRpb25zIGZvciBhIHdhbGxldFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UG9zaXRpb25zKHdhbGxldEFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8UG9zaXRpb25bXT4ge1xuICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24oUlBDX0VORFBPSU5ULCAnY29uZmlybWVkJyk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgUHVibGljS2V5KHdhbGxldEFkZHJlc3MpO1xuXG4gICAgLy8gR2V0IGFsbCBwb3NpdGlvbiBhY2NvdW50cyBmb3IgdGhpcyB1c2VyXG4gICAgLy8gTm90ZTogU29sYW5hIFJQQyBleHBlY3RzIGJhc2U1OCBlbmNvZGluZyBmb3IgbWVtY21wIGJ5dGVzXG4gICAgY29uc3QgYWNjb3VudHMgPSBhd2FpdCBjb25uZWN0aW9uLmdldFByb2dyYW1BY2NvdW50cyhQUk9HUkFNX0lELCB7XG4gICAgICBmaWx0ZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtZW1jbXA6IHtcbiAgICAgICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgICAgIGJ5dGVzOiBiczU4LmVuY29kZShESVNDUklNSU5BVE9SUy5VU0VSX1BPU0lUSU9OKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbWVtY21wOiB7XG4gICAgICAgICAgICBvZmZzZXQ6IDgsIC8vIEFmdGVyIGRpc2NyaW1pbmF0b3JcbiAgICAgICAgICAgIGJ5dGVzOiB3YWxsZXQudG9CYXNlNTgoKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHBvc2l0aW9uczogUG9zaXRpb25bXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCB7IGFjY291bnQsIHB1YmtleSB9IG9mIGFjY291bnRzKSB7XG4gICAgICBjb25zdCBwb3NpdGlvbiA9IGRlY29kZVBvc2l0aW9uKGFjY291bnQuZGF0YSBhcyBCdWZmZXIsIHB1YmtleSk7XG4gICAgICBpZiAocG9zaXRpb24pIHtcbiAgICAgICAgcG9zaXRpb25zLnB1c2gocG9zaXRpb24pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNvcnQgYnkgbWFya2V0IElEIChuZXdlc3QgbWFya2V0cyBmaXJzdClcbiAgICBwb3NpdGlvbnMuc29ydCgoYSwgYikgPT4gTnVtYmVyKEJpZ0ludChiLm1hcmtldElkKSAtIEJpZ0ludChhLm1hcmtldElkKSkpO1xuXG4gICAgcmV0dXJuIHBvc2l0aW9ucztcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcignRXJyb3IgZmV0Y2hpbmcgcG9zaXRpb25zOicsIGVycik7XG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbi8qKlxuICogRGVyaXZlIG1hcmtldCBQREEgZnJvbSBtYXJrZXRfaWRcbiAqL1xuZnVuY3Rpb24gZGVyaXZlTWFya2V0UGRhKG1hcmtldElkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBtYXJrZXRJZEJpZ0ludCA9IEJpZ0ludChtYXJrZXRJZCk7XG4gIGNvbnN0IG1hcmtldElkQnVmZmVyID0gQnVmZmVyLmFsbG9jKDgpO1xuICBtYXJrZXRJZEJ1ZmZlci53cml0ZUJpZ1VJbnQ2NExFKG1hcmtldElkQmlnSW50KTtcbiAgY29uc3QgW3BkYV0gPSBQdWJsaWNLZXkuZmluZFByb2dyYW1BZGRyZXNzU3luYyhcbiAgICBbQnVmZmVyLmZyb20oJ21hcmtldCcpLCBtYXJrZXRJZEJ1ZmZlcl0sXG4gICAgUFJPR1JBTV9JRFxuICApO1xuICByZXR1cm4gcGRhLnRvQmFzZTU4KCk7XG59XG5cbi8qKlxuICogR2V0IHBvc2l0aW9ucyB3aXRoIGVucmljaGVkIG1hcmtldCBkYXRhXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQb3NpdGlvbnNFbnJpY2hlZCh3YWxsZXRBZGRyZXNzOiBzdHJpbmcpOiBQcm9taXNlPFBvc2l0aW9uW10+IHtcbiAgY29uc3QgcG9zaXRpb25zID0gYXdhaXQgZ2V0UG9zaXRpb25zKHdhbGxldEFkZHJlc3MpO1xuXG4gIC8vIERlcml2ZSBtYXJrZXQgUERBcyBmcm9tIG1hcmtldF9pZFxuICBjb25zdCBwb3NpdGlvbnNXaXRoUGRhID0gcG9zaXRpb25zLm1hcChwID0+ICh7XG4gICAgLi4ucCxcbiAgICBtYXJrZXRQZGE6IGRlcml2ZU1hcmtldFBkYShwLm1hcmtldElkKSxcbiAgfSkpO1xuXG4gIC8vIEJhdGNoIGZldGNoIG1hcmtldCBkYXRhIGZvciB1bmlxdWUgbWFya2V0c1xuICBjb25zdCB1bmlxdWVNYXJrZXRzID0gWy4uLm5ldyBTZXQocG9zaXRpb25zV2l0aFBkYS5tYXAocCA9PiBwLm1hcmtldFBkYSkpXTtcbiAgY29uc3QgbWFya2V0RGF0YSA9IG5ldyBNYXA8c3RyaW5nLCBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIGdldE1hcmtldD4+PigpO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIHVuaXF1ZU1hcmtldHMubWFwKGFzeW5jIChtYXJrZXRQZGEpID0+IHtcbiAgICAgIGlmIChtYXJrZXRQZGEpIHtcbiAgICAgICAgY29uc3QgbWFya2V0ID0gYXdhaXQgZ2V0TWFya2V0KG1hcmtldFBkYSk7XG4gICAgICAgIGlmIChtYXJrZXQpIHtcbiAgICAgICAgICBtYXJrZXREYXRhLnNldChtYXJrZXRQZGEsIG1hcmtldCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KVxuICApO1xuXG4gIC8vIEVucmljaCBwb3NpdGlvbnMgd2l0aCBtYXJrZXQgZGF0YVxuICByZXR1cm4gcG9zaXRpb25zV2l0aFBkYS5tYXAocG9zaXRpb24gPT4ge1xuICAgIGNvbnN0IG1hcmtldCA9IHBvc2l0aW9uLm1hcmtldFBkYSA/IG1hcmtldERhdGEuZ2V0KHBvc2l0aW9uLm1hcmtldFBkYSkgOiBudWxsO1xuICAgIGlmICghbWFya2V0KSByZXR1cm4gcG9zaXRpb247XG5cbiAgICAvLyBDYWxjdWxhdGUgcG90ZW50aWFsIHBheW91dCBpZiBwb3NpdGlvbiBpcyB3aW5uaW5nXG4gICAgbGV0IHBvdGVudGlhbFBheW91dDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHBvc2l0aW9uQW1vdW50ID0gcG9zaXRpb24uc2lkZSA9PT0gJ1llcycgPyBwb3NpdGlvbi55ZXNBbW91bnRTb2wgOiBwb3NpdGlvbi5ub0Ftb3VudFNvbDtcbiAgICBpZiAobWFya2V0LnN0YXR1cyA9PT0gJ1Jlc29sdmVkJyAmJiBtYXJrZXQud2lubmluZ091dGNvbWUgPT09IHBvc2l0aW9uLnNpZGUpIHtcbiAgICAgIGNvbnN0IHRvdGFsUG9vbCA9IG1hcmtldC55ZXNQb29sU29sICsgbWFya2V0Lm5vUG9vbFNvbDtcbiAgICAgIGNvbnN0IHdpbm5pbmdQb29sID0gcG9zaXRpb24uc2lkZSA9PT0gJ1llcycgPyBtYXJrZXQueWVzUG9vbFNvbCA6IG1hcmtldC5ub1Bvb2xTb2w7XG4gICAgICBpZiAod2lubmluZ1Bvb2wgPiAwKSB7XG4gICAgICAgIGNvbnN0IHNoYXJlID0gcG9zaXRpb25BbW91bnQgLyB3aW5uaW5nUG9vbDtcbiAgICAgICAgY29uc3QgZ3Jvc3NQYXlvdXQgPSBzaGFyZSAqIHRvdGFsUG9vbDtcbiAgICAgICAgY29uc3QgcHJvZml0ID0gZ3Jvc3NQYXlvdXQgLSBwb3NpdGlvbkFtb3VudDtcbiAgICAgICAgY29uc3QgZmVlID0gcHJvZml0ID4gMCA/IChwcm9maXQgKiBtYXJrZXQucGxhdGZvcm1GZWVCcHMpIC8gMTAwMDAgOiAwO1xuICAgICAgICBwb3RlbnRpYWxQYXlvdXQgPSByb3VuZDQoZ3Jvc3NQYXlvdXQgLSBmZWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAuLi5wb3NpdGlvbixcbiAgICAgIG1hcmtldFF1ZXN0aW9uOiBtYXJrZXQucXVlc3Rpb24sXG4gICAgICBtYXJrZXRTdGF0dXM6IG1hcmtldC5zdGF0dXMsXG4gICAgICBtYXJrZXRPdXRjb21lOiBtYXJrZXQud2lubmluZ091dGNvbWUsXG4gICAgICBwb3RlbnRpYWxQYXlvdXQsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IHBvc2l0aW9uIHN1bW1hcnkgd2l0aCBzdGF0aXN0aWNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQb3NpdGlvbnNTdW1tYXJ5KHdhbGxldEFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8UG9zaXRpb25TdW1tYXJ5PiB7XG4gIGNvbnN0IHBvc2l0aW9ucyA9IGF3YWl0IGdldFBvc2l0aW9uc0VucmljaGVkKHdhbGxldEFkZHJlc3MpO1xuXG4gIGNvbnN0IHRvdGFsQmV0U29sID0gcG9zaXRpb25zLnJlZHVjZSgoc3VtLCBwKSA9PiBzdW0gKyBwLnRvdGFsQW1vdW50U29sLCAwKTtcbiAgY29uc3QgYWN0aXZlUG9zaXRpb25zID0gcG9zaXRpb25zLmZpbHRlcihwID0+ICFwLmNsYWltZWQpLmxlbmd0aDtcbiAgY29uc3QgY2xhaW1lZFBvc2l0aW9ucyA9IHBvc2l0aW9ucy5maWx0ZXIocCA9PiBwLmNsYWltZWQpLmxlbmd0aDtcblxuICAvLyBDb3VudCB3aW5uaW5nL2xvc2luZy9wZW5kaW5nIGJhc2VkIG9uIG1hcmtldCBzdGF0dXMgYW5kIG91dGNvbWVcbiAgbGV0IHdpbm5pbmdQb3NpdGlvbnMgPSAwO1xuICBsZXQgbG9zaW5nUG9zaXRpb25zID0gMDtcbiAgbGV0IHBlbmRpbmdQb3NpdGlvbnMgPSAwO1xuXG4gIGZvciAoY29uc3QgcG9zaXRpb24gb2YgcG9zaXRpb25zKSB7XG4gICAgaWYgKCFwb3NpdGlvbi5tYXJrZXRTdGF0dXMgfHwgcG9zaXRpb24ubWFya2V0U3RhdHVzID09PSAnQWN0aXZlJyB8fCBwb3NpdGlvbi5tYXJrZXRTdGF0dXMgPT09ICdDbG9zZWQnKSB7XG4gICAgICBwZW5kaW5nUG9zaXRpb25zKys7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbi5tYXJrZXRTdGF0dXMgPT09ICdSZXNvbHZlZCcpIHtcbiAgICAgIGlmIChwb3NpdGlvbi5tYXJrZXRPdXRjb21lID09PSBwb3NpdGlvbi5zaWRlKSB7XG4gICAgICAgIHdpbm5pbmdQb3NpdGlvbnMrKztcbiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24ubWFya2V0T3V0Y29tZSA9PT0gJ0ludmFsaWQnKSB7XG4gICAgICAgIC8vIFJlZnVuZCBjYXNlXG4gICAgICAgIHBlbmRpbmdQb3NpdGlvbnMrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvc2luZ1Bvc2l0aW9ucysrO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocG9zaXRpb24ubWFya2V0U3RhdHVzID09PSAnQ2FuY2VsbGVkJykge1xuICAgICAgLy8gUmVmdW5kIGNhc2VcbiAgICAgIHBlbmRpbmdQb3NpdGlvbnMrKztcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHdhbGxldDogd2FsbGV0QWRkcmVzcyxcbiAgICB0b3RhbFBvc2l0aW9uczogcG9zaXRpb25zLmxlbmd0aCxcbiAgICB0b3RhbEJldFNvbDogcm91bmQ0KHRvdGFsQmV0U29sKSxcbiAgICBhY3RpdmVQb3NpdGlvbnMsXG4gICAgY2xhaW1lZFBvc2l0aW9ucyxcbiAgICB3aW5uaW5nUG9zaXRpb25zLFxuICAgIGxvc2luZ1Bvc2l0aW9ucyxcbiAgICBwZW5kaW5nUG9zaXRpb25zLFxuICAgIHBvc2l0aW9ucyxcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhFTFBFUlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmZ1bmN0aW9uIHJvdW5kNChuOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5yb3VuZChuICogMTAwMDApIC8gMTAwMDA7XG59XG4iXX0=
@@ -0,0 +1,33 @@
1
+ export interface Quote {
2
+ valid: boolean;
3
+ error?: string;
4
+ warnings: string[];
5
+ market: string;
6
+ marketQuestion?: string;
7
+ side: 'Yes' | 'No';
8
+ betAmountSol: number;
9
+ expectedPayoutSol: number;
10
+ potentialProfitSol: number;
11
+ impliedOdds: number;
12
+ decimalOdds: number;
13
+ feeSol: number;
14
+ feeBps: number;
15
+ newYesPoolSol: number;
16
+ newNoPoolSol: number;
17
+ currentYesPercent: number;
18
+ currentNoPercent: number;
19
+ newYesPercent: number;
20
+ newNoPercent: number;
21
+ }
22
+ /**
23
+ * Calculate a quote for a potential bet
24
+ */
25
+ export declare function getQuote(marketPubkey: string, side: 'Yes' | 'No', amountSol: number): Promise<Quote>;
26
+ /**
27
+ * Calculate quote with additional market data for transaction building
28
+ */
29
+ export declare function getQuoteWithMarketData(marketPubkey: string, side: 'Yes' | 'No', amountSol: number): Promise<{
30
+ quote: Quote;
31
+ marketId?: bigint;
32
+ accessGate?: number;
33
+ }>;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Quote handler for MCP server
3
+ * Calculates expected payouts for bets using pari-mutuel math
4
+ */
5
+ import { getMarket, getMarketForBetting } from './markets.js';
6
+ import { validateBet } from '../validation/bet-rules.js';
7
+ // =============================================================================
8
+ // QUOTE CALCULATION
9
+ // =============================================================================
10
+ /**
11
+ * Calculate a quote for a potential bet
12
+ */
13
+ export async function getQuote(marketPubkey, side, amountSol) {
14
+ const baseQuote = {
15
+ valid: false,
16
+ warnings: [],
17
+ market: marketPubkey,
18
+ side,
19
+ betAmountSol: amountSol,
20
+ expectedPayoutSol: 0,
21
+ potentialProfitSol: 0,
22
+ impliedOdds: 0,
23
+ decimalOdds: 0,
24
+ feeSol: 0,
25
+ feeBps: 0,
26
+ newYesPoolSol: 0,
27
+ newNoPoolSol: 0,
28
+ currentYesPercent: 50,
29
+ currentNoPercent: 50,
30
+ newYesPercent: 50,
31
+ newNoPercent: 50,
32
+ };
33
+ // Fetch market
34
+ const market = await getMarket(marketPubkey);
35
+ if (!market) {
36
+ return {
37
+ ...baseQuote,
38
+ error: `Market ${marketPubkey} not found`,
39
+ };
40
+ }
41
+ baseQuote.marketQuestion = market.question;
42
+ baseQuote.feeBps = market.platformFeeBps;
43
+ baseQuote.currentYesPercent = market.yesPercent;
44
+ baseQuote.currentNoPercent = market.noPercent;
45
+ // Validate bet parameters
46
+ const validation = validateBet({
47
+ amountSol,
48
+ marketStatus: market.statusCode,
49
+ closingTime: new Date(market.closingTime),
50
+ isPaused: false, // Not tracked in current Market type, assume not paused
51
+ accessGate: market.accessGate === 'Whitelist' ? 1 : 0,
52
+ userWhitelisted: true, // Can't check without user wallet, assume whitelisted
53
+ layer: market.layerCode,
54
+ });
55
+ if (!validation.valid) {
56
+ return {
57
+ ...baseQuote,
58
+ error: validation.error,
59
+ warnings: validation.warnings,
60
+ };
61
+ }
62
+ // Calculate new pools after bet
63
+ const newYesPoolSol = side === 'Yes'
64
+ ? market.yesPoolSol + amountSol
65
+ : market.yesPoolSol;
66
+ const newNoPoolSol = side === 'No'
67
+ ? market.noPoolSol + amountSol
68
+ : market.noPoolSol;
69
+ const newTotalPool = newYesPoolSol + newNoPoolSol;
70
+ // Calculate expected payout (pari-mutuel)
71
+ const sidePool = side === 'Yes' ? newYesPoolSol : newNoPoolSol;
72
+ const expectedPayoutSol = sidePool > 0
73
+ ? (amountSol / sidePool) * newTotalPool
74
+ : 0;
75
+ // Calculate profit and fee
76
+ const grossProfit = expectedPayoutSol - amountSol;
77
+ const feeSol = grossProfit > 0
78
+ ? (grossProfit * market.platformFeeBps) / 10000
79
+ : 0;
80
+ const potentialProfitSol = grossProfit - feeSol;
81
+ // Calculate odds
82
+ const impliedOdds = newTotalPool > 0
83
+ ? (sidePool / newTotalPool) * 100
84
+ : 50;
85
+ const decimalOdds = sidePool > 0
86
+ ? newTotalPool / sidePool
87
+ : 2;
88
+ // Calculate new percentages
89
+ const newYesPercent = newTotalPool > 0
90
+ ? (newYesPoolSol / newTotalPool) * 100
91
+ : 50;
92
+ const newNoPercent = newTotalPool > 0
93
+ ? (newNoPoolSol / newTotalPool) * 100
94
+ : 50;
95
+ return {
96
+ valid: true,
97
+ warnings: validation.warnings,
98
+ market: marketPubkey,
99
+ marketQuestion: market.question,
100
+ side,
101
+ betAmountSol: round4(amountSol),
102
+ expectedPayoutSol: round4(expectedPayoutSol),
103
+ potentialProfitSol: round4(potentialProfitSol),
104
+ impliedOdds: round2(impliedOdds),
105
+ decimalOdds: round2(decimalOdds),
106
+ feeSol: round4(feeSol),
107
+ feeBps: market.platformFeeBps,
108
+ newYesPoolSol: round4(newYesPoolSol),
109
+ newNoPoolSol: round4(newNoPoolSol),
110
+ currentYesPercent: market.yesPercent,
111
+ currentNoPercent: market.noPercent,
112
+ newYesPercent: round2(newYesPercent),
113
+ newNoPercent: round2(newNoPercent),
114
+ };
115
+ }
116
+ /**
117
+ * Calculate quote with additional market data for transaction building
118
+ */
119
+ export async function getQuoteWithMarketData(marketPubkey, side, amountSol) {
120
+ const quote = await getQuote(marketPubkey, side, amountSol);
121
+ if (!quote.valid) {
122
+ return { quote };
123
+ }
124
+ // Get additional market data for tx building
125
+ const marketData = await getMarketForBetting(marketPubkey);
126
+ if (!marketData) {
127
+ return { quote };
128
+ }
129
+ return {
130
+ quote,
131
+ marketId: marketData.marketId,
132
+ accessGate: marketData.accessGate,
133
+ };
134
+ }
135
+ // =============================================================================
136
+ // HELPERS
137
+ // =============================================================================
138
+ function round2(n) {
139
+ return Math.round(n * 100) / 100;
140
+ }
141
+ function round4(n) {
142
+ return Math.round(n * 10000) / 10000;
143
+ }
144
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGFuZGxlcnMvcXVvdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsT0FBTyxFQUFFLFNBQVMsRUFBRSxtQkFBbUIsRUFBVSxNQUFNLGNBQWMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUE2QnpELGdGQUFnRjtBQUNoRixvQkFBb0I7QUFDcEIsZ0ZBQWdGO0FBRWhGOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxRQUFRLENBQzVCLFlBQW9CLEVBQ3BCLElBQWtCLEVBQ2xCLFNBQWlCO0lBRWpCLE1BQU0sU0FBUyxHQUFVO1FBQ3ZCLEtBQUssRUFBRSxLQUFLO1FBQ1osUUFBUSxFQUFFLEVBQUU7UUFDWixNQUFNLEVBQUUsWUFBWTtRQUNwQixJQUFJO1FBQ0osWUFBWSxFQUFFLFNBQVM7UUFDdkIsaUJBQWlCLEVBQUUsQ0FBQztRQUNwQixrQkFBa0IsRUFBRSxDQUFDO1FBQ3JCLFdBQVcsRUFBRSxDQUFDO1FBQ2QsV0FBVyxFQUFFLENBQUM7UUFDZCxNQUFNLEVBQUUsQ0FBQztRQUNULE1BQU0sRUFBRSxDQUFDO1FBQ1QsYUFBYSxFQUFFLENBQUM7UUFDaEIsWUFBWSxFQUFFLENBQUM7UUFDZixpQkFBaUIsRUFBRSxFQUFFO1FBQ3JCLGdCQUFnQixFQUFFLEVBQUU7UUFDcEIsYUFBYSxFQUFFLEVBQUU7UUFDakIsWUFBWSxFQUFFLEVBQUU7S0FDakIsQ0FBQztJQUVGLGVBQWU7SUFDZixNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUU3QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixPQUFPO1lBQ0wsR0FBRyxTQUFTO1lBQ1osS0FBSyxFQUFFLFVBQVUsWUFBWSxZQUFZO1NBQzFDLENBQUM7SUFDSixDQUFDO0lBRUQsU0FBUyxDQUFDLGNB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QyxZQUFZLENBQUMsQ0FBQztJQUUzRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEIsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFFRCxPQUFPO1FBQ0wsS0FBSztRQUNMLFFBQVEsRUFBRSxVQUFVLENBQUMsUUFBUTtRQUM3QixVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7S0FDbEMsQ0FBQztBQUNKLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsVUFBVTtBQUNWLGdGQUFnRjtBQUVoRixTQUFTLE1BQU0sQ0FBQyxDQUFTO0lBQ3ZCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0FBQ25DLENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxDQUFTO0lBQ3ZCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDO0FBQ3ZDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFF1b3RlIGhhbmRsZXIgZm9yIE1DUCBzZXJ2ZXJcbiAqIENhbGN1bGF0ZXMgZXhwZWN0ZWQgcGF5b3V0cyBmb3IgYmV0cyB1c2luZyBwYXJpLW11dHVlbCBtYXRoXG4gKi9cbmltcG9ydCB7IGdldE1hcmtldCwgZ2V0TWFya2V0Rm9yQmV0dGluZywgTWFya2V0IH0gZnJvbSAnLi9tYXJrZXRzLmpzJztcbmltcG9ydCB7IHZhbGlkYXRlQmV0IH0gZnJvbSAnLi4vdmFsaWRhdGlvbi9iZXQtcnVsZXMuanMnO1xuaW1wb3J0IHsgQkVUX0xJTUlUUyB9IGZyb20gJy4uL2NvbmZpZy5qcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBRdW90ZSB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcj86IHN0cmluZztcbiAgd2FybmluZ3M6IHN0cmluZ1tdO1xuICBtYXJrZXQ6IHN0cmluZztcbiAgbWFya2V0UXVlc3Rpb24/OiBzdHJpbmc7XG4gIHNpZGU6ICdZZXMnIHwgJ05vJztcbiAgYmV0QW1vdW50U29sOiBudW1iZXI7XG4gIGV4cGVjdGVkUGF5b3V0U29sOiBudW1iZXI7XG4gIHBvdGVudGlhbFByb2ZpdFNvbDogbnVtYmVyO1xuICBpbXBsaWVkT2RkczogbnVtYmVyO1xuICBkZWNpbWFsT2RkczogbnVtYmVyO1xuICBmZWVTb2w6IG51bWJlcjtcbiAgZmVlQnBzOiBudW1iZXI7XG4gIG5ld1llc1Bvb2xTb2w6IG51bWJlcjtcbiAgbmV3Tm9Qb29sU29sOiBudW1iZXI7XG4gIGN1cnJlbnRZZXNQZXJjZW50OiBudW1iZXI7XG4gIGN1cnJlbnROb1BlcmNlbnQ6IG51bWJlcjtcbiAgbmV3WWVzUGVyY2VudDogbnVtYmVyO1xuICBuZXdOb1BlcmNlbnQ6IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFFVT1RFIENBTENVTEFUSU9OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENhbGN1bGF0ZSBhIHF1b3RlIGZvciBhIHBvdGVudGlhbCBiZXRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFF1b3RlKFxuICBtYXJrZXRQdWJrZXk6IHN0cmluZyxcbiAgc2lkZTogJ1llcycgfCAnTm8nLFxuICBhbW91bnRTb2w6IG51bWJlclxuKTogUHJvbWlzZTxRdW90ZT4ge1xuICBjb25zdCBiYXNlUXVvdGU6IFF1b3RlID0ge1xuICAgIHZhbGlkOiBmYWxzZSxcbiAgICB3YXJuaW5nczogW10sXG4gICAgbWFya2V0OiBtYXJrZXRQdWJrZXksXG4gICAgc2lkZSxcbiAgICBiZXRBbW91bnRTb2w6IGFtb3VudFNvbCxcbiAgICBleHBlY3RlZFBheW91dFNvbDogMCxcbiAgICBwb3RlbnRpYWxQcm9maXRTb2w6IDAsXG4gICAgaW1wbGllZE9kZHM6IDAsXG4gICAgZGVjaW1hbE9kZHM6IDAsXG4gICAgZmVlU29sOiAwLFxuICAgIGZlZUJwczogMCxcbiAgICBuZXdZZXNQb29sU29sOiAwLFxuICAgIG5ld05vUG9vbFNvbDogMCxcbiAgICBjdXJyZW50WWVzUGVyY2VudDogNTAsXG4gICAgY3VycmVudE5vUGVyY2VudDogNTAsXG4gICAgbmV3WWVzUGVyY2VudDogNTAsXG4gICAgbmV3Tm9QZXJjZW50OiA1MCxcbiAgfTtcblxuICAvLyBGZXRjaCBtYXJrZXRcbiAgY29uc3QgbWFya2V0ID0gYXdhaXQgZ2V0TWFya2V0KG1hcmtldFB1YmtleSk7XG5cbiAgaWYgKCFtYXJrZXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uYmFzZVF1b3RlLFxuICAgICAgZXJyb3I6IGBNYXJrZXQgJHttYXJrZXRQdWJrZXl9IG5vdCBmb3VuZGAsXG4gICAgfTtcbiAgfVxuXG4gIGJhc2VRdW90ZS5tYXJrZXRRdWVzdGlvbiA9IG1hcmtldC5xdWVzdGlvbjtcbiAgYmFzZVF1b3RlLmZlZUJwcyA9IG1hcmtldC5wbGF0Zm9ybUZlZUJwcztcbiAgYmFzZVF1b3RlLmN1cnJlbnRZZXNQZXJjZW50ID0gbWFya2V0Lnllc1BlcmNlbnQ7XG4gIGJhc2VRdW90ZS5jdXJyZW50Tm9QZXJjZW50ID0gbWFya2V0Lm5vUGVyY2VudDtcblxuICAvLyBWYWxpZGF0ZSBiZXQgcGFyYW1ldGVyc1xuICBjb25zdCB2YWxpZGF0aW9uID0gdmFsaWRhdGVCZXQoe1xuICAgIGFtb3VudFNvbCxcbiAgICBtYXJrZXRTdGF0dXM6IG1hcmtldC5zdGF0dXNDb2RlLFxuICAgIGNsb3NpbmdUaW1lOiBuZXcgRGF0ZShtYXJrZXQuY2xvc2luZ1RpbWUpLFxuICAgIGlzUGF1c2VkOiBmYWxzZSwgLy8gTm90IHRyYWNrZWQgaW4gY3VycmVudCBNYXJrZXQgdHlwZSwgYXNzdW1lIG5vdCBwYXVzZWRcbiAgICBhY2Nlc3NHYXRlOiBtYXJrZXQuYWNjZXNzR2F0ZSA9PT0gJ1doaXRlbGlzdCcgPyAxIDogMCxcbiAgICB1c2VyV2hpdGVsaXN0ZWQ6IHRydWUsIC8vIENhbid0IGNoZWNrIHdpdGhvdXQgdXNlciB3YWxsZXQsIGFzc3VtZSB3aGl0ZWxpc3RlZFxuICAgIGxheWVyOiBtYXJrZXQubGF5ZXJDb2RlLFxuICB9KTtcblxuICBpZiAoIXZhbGlkYXRpb24udmFsaWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uYmFzZVF1b3RlLFxuICAgICAgZXJyb3I6IHZhbGlkYXRpb24uZXJyb3IsXG4gICAgICB3YXJuaW5nczogdmFsaWRhdGlvbi53YXJuaW5ncyxcbiAgICB9O1xuICB9XG5cbiAgLy8gQ2FsY3VsYXRlIG5ldyBwb29scyBhZnRlciBiZXRcbiAgY29uc3QgbmV3WWVzUG9vbFNvbCA9IHNpZGUgPT09ICdZZXMnXG4gICAgPyBtYXJrZXQueWVzUG9vbFNvbCArIGFtb3VudFNvbFxuICAgIDogbWFya2V0Lnllc1Bvb2xTb2w7XG4gIGNvbnN0IG5ld05vUG9vbFNvbCA9IHNpZGUgPT09ICdObydcbiAgICA/IG1hcmtldC5ub1Bvb2xTb2wgKyBhbW91bnRTb2xcbiAgICA6IG1hcmtldC5ub1Bvb2xTb2w7XG4gIGNvbnN0IG5ld1RvdGFsUG9vbCA9IG5ld1llc1Bvb2xTb2wgKyBuZXdOb1Bvb2xTb2w7XG5cbiAgLy8gQ2FsY3VsYXRlIGV4cGVjdGVkIHBheW91dCAocGFyaS1tdXR1ZWwpXG4gIGNvbnN0IHNpZGVQb29sID0gc2lkZSA9PT0gJ1llcycgPyBuZXdZZXNQb29sU29sIDogbmV3Tm9Qb29sU29sO1xuICBjb25zdCBleHBlY3RlZFBheW91dFNvbCA9IHNpZGVQb29sID4gMFxuICAgID8gKGFtb3VudFNvbCAvIHNpZGVQb29sKSAqIG5ld1RvdGFsUG9vbFxuICAgIDogMDtcblxuICAvLyBDYWxjdWxhdGUgcHJvZml0IGFuZCBmZWVcbiAgY29uc3QgZ3Jvc3NQcm9maXQgPSBleHBlY3RlZFBheW91dFNvbCAtIGFtb3VudFNvbDtcbiAgY29uc3QgZmVlU29sID0gZ3Jvc3NQcm9maXQgPiAwXG4gICAgPyAoZ3Jvc3NQcm9maXQgKiBtYXJrZXQucGxhdGZvcm1GZWVCcHMpIC8gMTAwMDBcbiAgICA6IDA7XG4gIGNvbnN0IHBvdGVudGlhbFByb2ZpdFNvbCA9IGdyb3NzUHJvZml0IC0gZmVlU29sO1xuXG4gIC8vIENhbGN1bGF0ZSBvZGRzXG4gIGNvbnN0IGltcGxpZWRPZGRzID0gbmV3VG90YWxQb29sID4gMFxuICAgID8gKHNpZGVQb29sIC8gbmV3VG90YWxQb29sKSAqIDEwMFxuICAgIDogNTA7XG4gIGNvbnN0IGRlY2ltYWxPZGRzID0gc2lkZVBvb2wgPiAwXG4gICAgPyBuZXdUb3RhbFBvb2wgLyBzaWRlUG9vbFxuICAgIDogMjtcblxuICAvLyBDYWxjdWxhdGUgbmV3IHBlcmNlbnRhZ2VzXG4gIGNvbnN0IG5ld1llc1BlcmNlbnQgPSBuZXdUb3RhbFBvb2wgPiAwXG4gICAgPyAobmV3WWVzUG9vbFNvbCAvIG5ld1RvdGFsUG9vbCkgKiAxMDBcbiAgICA6IDUwO1xuICBjb25zdCBuZXdOb1BlcmNlbnQgPSBuZXdUb3RhbFBvb2wgPiAwXG4gICAgPyAobmV3Tm9Qb29sU29sIC8gbmV3VG90YWxQb29sKSAqIDEwMFxuICAgIDogNTA7XG5cbiAgcmV0dXJuIHtcbiAgICB2YWxpZDogdHJ1ZSxcbiAgICB3YXJuaW5nczogdmFsaWRhdGlvbi53YXJuaW5ncyxcbiAgICBtYXJrZXQ6IG1hcmtldFB1YmtleSxcbiAgICBtYXJrZXRRdWVzdGlvbjogbWFya2V0LnF1ZXN0aW9uLFxuICAgIHNpZGUsXG4gICAgYmV0QW1vdW50U29sOiByb3VuZDQoYW1vdW50U29sKSxcbiAgICBleHBlY3RlZFBheW91dFNvbDogcm91bmQ0KGV4cGVjdGVkUGF5b3V0U29sKSxcbiAgICBwb3RlbnRpYWxQcm9maXRTb2w6IHJvdW5kNChwb3RlbnRpYWxQcm9maXRTb2wpLFxuICAgIGltcGxpZWRPZGRzOiByb3VuZDIoaW1wbGllZE9kZHMpLFxuICAgIGRlY2ltYWxPZGRzOiByb3VuZDIoZGVjaW1hbE9kZHMpLFxuICAgIGZlZVNvbDogcm91bmQ0KGZlZVNvbCksXG4gICAgZmVlQnBzOiBtYXJrZXQucGxhdGZvcm1GZWVCcHMsXG4gICAgbmV3WWVzUG9vbFNvbDogcm91bmQ0KG5ld1llc1Bvb2xTb2wpLFxuICAgIG5ld05vUG9vbFNvbDogcm91bmQ0KG5ld05vUG9vbFNvbCksXG4gICAgY3VycmVudFllc1BlcmNlbnQ6IG1hcmtldC55ZXNQZXJjZW50LFxuICAgIGN1cnJlbnROb1BlcmNlbnQ6IG1hcmtldC5ub1BlcmNlbnQsXG4gICAgbmV3WWVzUGVyY2VudDogcm91bmQyKG5ld1llc1BlcmNlbnQpLFxuICAgIG5ld05vUGVyY2VudDogcm91bmQyKG5ld05vUGVyY2VudCksXG4gIH07XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHF1b3RlIHdpdGggYWRkaXRpb25hbCBtYXJrZXQgZGF0YSBmb3IgdHJhbnNhY3Rpb24gYnVpbGRpbmdcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFF1b3RlV2l0aE1hcmtldERhdGEoXG4gIG1hcmtldFB1YmtleTogc3RyaW5nLFxuICBzaWRlOiAnWWVzJyB8ICdObycsXG4gIGFtb3VudFNvbDogbnVtYmVyXG4pOiBQcm9taXNlPHtcbiAgcXVvdGU6IFF1b3RlO1xuICBtYXJrZXRJZD86IGJpZ2ludDtcbiAgYWNjZXNzR2F0ZT86IG51bWJlcjtcbn0+IHtcbiAgY29uc3QgcXVvdGUgPSBhd2FpdCBnZXRRdW90ZShtYXJrZXRQdWJrZXksIHNpZGUsIGFtb3VudFNvbCk7XG5cbiAgaWYgKCFxdW90ZS52YWxpZCkge1xuICAgIHJldHVybiB7IHF1b3RlIH07XG4gIH1cblxuICAvLyBHZXQgYWRkaXRpb25hbCBtYXJrZXQgZGF0YSBmb3IgdHggYnVpbGRpbmdcbiAgY29uc3QgbWFya2V0RGF0YSA9IGF3YWl0IGdldE1hcmtldEZvckJldHRpbmcobWFya2V0UHVia2V5KTtcblxuICBpZiAoIW1hcmtldERhdGEpIHtcbiAgICByZXR1cm4geyBxdW90ZSB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBxdW90ZSxcbiAgICBtYXJrZXRJZDogbWFya2V0RGF0YS5tYXJrZXRJZCxcbiAgICBhY2Nlc3NHYXRlOiBtYXJrZXREYXRhLmFjY2Vzc0dhdGUsXG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBIRUxQRVJTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5mdW5jdGlvbiByb3VuZDIobjogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobiAqIDEwMCkgLyAxMDA7XG59XG5cbmZ1bmN0aW9uIHJvdW5kNChuOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5yb3VuZChuICogMTAwMDApIC8gMTAwMDA7XG59XG4iXX0=
@@ -0,0 +1,54 @@
1
+ export interface RaceOutcome {
2
+ index: number;
3
+ label: string;
4
+ poolSol: number;
5
+ percent: number;
6
+ }
7
+ export interface RaceMarket {
8
+ publicKey: string;
9
+ marketId: string;
10
+ question: string;
11
+ outcomes: RaceOutcome[];
12
+ closingTime: string;
13
+ resolutionTime: string;
14
+ status: string;
15
+ statusCode: number;
16
+ winningOutcomeIndex: number | null;
17
+ totalPoolSol: number;
18
+ layer: string;
19
+ layerCode: number;
20
+ accessGate: string;
21
+ creator: string;
22
+ platformFeeBps: number;
23
+ isBettingOpen: boolean;
24
+ }
25
+ export interface RacePosition {
26
+ publicKey: string;
27
+ user: string;
28
+ raceMarketPda: string;
29
+ marketId: string;
30
+ outcomeIndex: number;
31
+ amountSol: number;
32
+ claimed: boolean;
33
+ createdAt: string;
34
+ }
35
+ /**
36
+ * List all race markets
37
+ */
38
+ export declare function listRaceMarkets(status?: string): Promise<RaceMarket[]>;
39
+ /**
40
+ * Get a specific race market
41
+ */
42
+ export declare function getRaceMarket(publicKey: string): Promise<RaceMarket | null>;
43
+ /**
44
+ * Get race quote for a potential bet
45
+ */
46
+ export declare function getRaceQuote(market: RaceMarket, outcomeIndex: number, betAmountSol: number): {
47
+ valid: boolean;
48
+ error?: string;
49
+ outcomeLabel: string;
50
+ betAmountSol: number;
51
+ expectedPayoutSol: number;
52
+ impliedOdds: number;
53
+ newOutcomePercent: number;
54
+ };