be-components 7.7.2 β†’ 7.7.4

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 (24) hide show
  1. package/lib/commonjs/Assets/fonts/Barlow-Bold.ttf +0 -0
  2. package/lib/commonjs/Assets/fonts/Barlow-Regular.ttf +0 -0
  3. package/lib/commonjs/Assets/fonts/Barlow-SemiBold.ttf +0 -0
  4. package/lib/commonjs/Assets/images/powered_by_be.webp +0 -0
  5. package/lib/commonjs/BetRouter/components/MyOpportunities.tsx.bak +440 -0
  6. package/lib/commonjs/BetRouter/types/ADMIN_PORTAL.md +863 -0
  7. package/lib/commonjs/BetRouter/types/ADMIN_PORTAL_SIMPLIFIED.md +1881 -0
  8. package/lib/commonjs/BetRouter/types/CREDENTIALS_EXAMPLE.md +350 -0
  9. package/lib/commonjs/BetRouter/types/LIQUIDITY_CLIENT_GUIDE.md +399 -0
  10. package/lib/commonjs/BetRouter/types/MARKET_LINKING_WORKFLOW.md +682 -0
  11. package/lib/commonjs/BetRouter/types/MARKET_LINKING_WORKFLOW_V2.md +627 -0
  12. package/lib/commonjs/BetRouter/types/README.md +249 -0
  13. package/lib/commonjs/Charts/README.md +310 -0
  14. package/lib/commonjs/NotificationManager/components/ScheduleNotification.js +1 -16
  15. package/lib/commonjs/NotificationManager/components/ScheduleNotification.js.map +1 -1
  16. package/lib/commonjs/NotificationManager/components/shared/GroupSelector.js +74 -4
  17. package/lib/commonjs/NotificationManager/components/shared/GroupSelector.js.map +1 -1
  18. package/lib/commonjs/NotificationManager/index.js +49 -5
  19. package/lib/commonjs/NotificationManager/index.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/ApiOverrides/index.ts +2 -2
  22. package/src/NotificationManager/components/ScheduleNotification.tsx +1 -17
  23. package/src/NotificationManager/components/shared/GroupSelector.tsx +83 -6
  24. package/src/NotificationManager/index.tsx +52 -5
@@ -0,0 +1,399 @@
1
+ # Liquidity API - Client Integration Guide
2
+
3
+ This guide shows how to use the liquidity endpoint to build a contest liquidity dashboard component.
4
+
5
+ ---
6
+
7
+ ## πŸ“‹ Endpoint
8
+
9
+ **`GET /liquidity/contest/:router_contest_id`**
10
+
11
+ **Query Parameters:**
12
+ - `partner_ids` (optional): Comma-separated partner IDs to fetch liquidity from
13
+ - Example: `"partner1,partner2"`
14
+ - If omitted, fetches from all active partners
15
+ - `include_opportunities` (optional): Set to `'true'` to include calculated opportunities in response
16
+ - Example: `"true"`
17
+ - Default: `false` (opportunities not included)
18
+ - When `true`, the response includes `opportunity_count` and `opportunities` array
19
+
20
+ ---
21
+
22
+ ## 🎯 Use Case: Contest Liquidity Dashboard
23
+
24
+ Display all available betting opportunities for a specific contest with prices from different partners.
25
+
26
+ ---
27
+
28
+ ## πŸ’» TypeScript Example
29
+
30
+ ```typescript
31
+ import {
32
+ RouterLiquidityProps,
33
+ RouterContestProps,
34
+ RouterPartnerProps,
35
+ PartnerMarketProps,
36
+ RouterMarketProps,
37
+ RouterMarketSideProps,
38
+ RouterMarketVariableProps,
39
+ ApiContracts,
40
+ ExtractSuccessResponse
41
+ } from './types/betrouter';
42
+
43
+ // Type-safe response
44
+ type LiquidityResponse = ExtractSuccessResponse<'GET /liquidity/contest/:router_contest_id'>;
45
+
46
+ async function fetchContestLiquidity(
47
+ contestId: string,
48
+ partnerIds?: string[],
49
+ includeOpportunities: boolean = false
50
+ ): Promise<LiquidityResponse> {
51
+ const url = new URL(`/liquidity/contest/${contestId}`, 'https://api.example.com');
52
+
53
+ if (partnerIds && partnerIds.length > 0) {
54
+ url.searchParams.set('partner_ids', partnerIds.join(','));
55
+ }
56
+
57
+ if (includeOpportunities) {
58
+ url.searchParams.set('include_opportunities', 'true');
59
+ }
60
+
61
+ const response = await fetch(url.toString());
62
+ return response.json();
63
+ }
64
+ ```
65
+
66
+ ---
67
+
68
+ ## πŸ“Š Response Structure
69
+
70
+ ### Without Opportunities (default)
71
+
72
+ ```typescript
73
+ {
74
+ message: "Successfully fetched liquidity",
75
+ contest: {
76
+ router_contest_id: "contest-123",
77
+ contest_label: "Lakers vs Celtics",
78
+ scheduled_datetime: "2025-10-30T19:00:00Z",
79
+ status: "open"
80
+ },
81
+ partners: [
82
+ {
83
+ partner_id: "bettoredge-id",
84
+ name: "BettorEdge",
85
+ status: "active"
86
+ }
87
+ ],
88
+ liquidity_count: 42,
89
+ liquidities: [
90
+ {
91
+ router_liquidity_id: "liq-123",
92
+ liquidity_hash: "partner:contest:market:side:variable:participant:timeframe:price",
93
+ title: "Lakers to win Full Game", // 🎯 HUMAN-READABLE TITLE
94
+ router_contest_id: "contest-123",
95
+ partner_market_id: "pm-123",
96
+ price: 0.55,
97
+ available: 100,
98
+ expire_datetime: "2025-10-30T19:00:00Z",
99
+ buy_id: "order-456",
100
+ create_datetime: "2025-10-30T12:00:00Z",
101
+ last_update_datetime: "2025-10-30T12:00:00Z"
102
+ },
103
+ {
104
+ router_liquidity_id: "liq-124",
105
+ liquidity_hash: "partner:contest:market:side:variable:participant:timeframe:price",
106
+ title: "Lakers -3.5 Full Game", // 🎯 SPREAD WITH VARIABLE
107
+ router_contest_id: "contest-123",
108
+ partner_market_id: "pm-124",
109
+ price: 0.52,
110
+ available: 200,
111
+ expire_datetime: "2025-10-30T19:00:00Z",
112
+ buy_id: "order-457",
113
+ create_datetime: "2025-10-30T12:00:00Z",
114
+ last_update_datetime: "2025-10-30T12:00:00Z"
115
+ }
116
+ ],
117
+ partner_markets: [ /* All partner_markets for context */ ],
118
+ router_markets: [ /* All router_markets for grouping */ ],
119
+ router_market_sides: [ /* All sides for filtering */ ],
120
+ router_market_variables: [ /* All variables for display */ ]
121
+ }
122
+ ```
123
+
124
+ ### With Opportunities (include_opportunities=true)
125
+
126
+ When `include_opportunities=true`, the response includes two additional fields:
127
+
128
+ ```typescript
129
+ {
130
+ // ... all fields from above ...
131
+ opportunity_count: 3, // Number of arbitrage opportunities found
132
+ opportunities: [
133
+ {
134
+ opportunity_type: "arbitrage",
135
+ router_contest_id: "contest-123",
136
+ router_market_id: "rm-spread",
137
+ expected_profit: 15.50,
138
+ total_cost: 100,
139
+ legs: [
140
+ {
141
+ partner_id: "bettoredge-id",
142
+ partner_name: "BettorEdge",
143
+ router_liquidity_id: "liq-123",
144
+ amount: 50,
145
+ // ... leg details
146
+ },
147
+ {
148
+ partner_id: "kalshi-id",
149
+ partner_name: "Kalshi",
150
+ router_liquidity_id: "liq-456",
151
+ amount: 50,
152
+ // ... leg details
153
+ }
154
+ ]
155
+ }
156
+ // ... more opportunities
157
+ ]
158
+ }
159
+ ```
160
+
161
+ **Benefits of `include_opportunities=true`:**
162
+ - Single API call instead of two separate calls
163
+ - No duplicate data fetching - uses the same liquidity data
164
+ - Opportunities are calculated server-side with the same data already fetched
165
+ - Efficient and type-safe
166
+
167
+ ---
168
+
169
+ ## 🎨 Example React Component
170
+
171
+ ```tsx
172
+ import { useState, useEffect } from 'react';
173
+ import type { RouterLiquidityProps, RouterPartnerProps } from './types/betrouter';
174
+
175
+ interface ContestLiquidityProps {
176
+ contestId: string;
177
+ partnerIds?: string[];
178
+ }
179
+
180
+ export function ContestLiquidity({ contestId, partnerIds }: ContestLiquidityProps) {
181
+ const [liquidities, setLiquidities] = useState<RouterLiquidityProps[]>([]);
182
+ const [partners, setPartners] = useState<RouterPartnerProps[]>([]);
183
+ const [loading, setLoading] = useState(true);
184
+
185
+ useEffect(() => {
186
+ async function fetchData() {
187
+ const url = new URL(`/liquidity/contest/${contestId}`, window.location.origin);
188
+
189
+ if (partnerIds && partnerIds.length > 0) {
190
+ url.searchParams.set('partner_ids', partnerIds.join(','));
191
+ }
192
+
193
+ const response = await fetch(url.toString());
194
+ const data = await response.json();
195
+
196
+ setLiquidities(data.liquidities);
197
+ setPartners(data.partners);
198
+ setLoading(false);
199
+ }
200
+
201
+ fetchData();
202
+ }, [contestId, partnerIds]);
203
+
204
+ if (loading) return <div>Loading liquidity...</div>;
205
+
206
+ return (
207
+ <div className="liquidity-table">
208
+ <h2>Available Betting Opportunities</h2>
209
+ <p>Showing liquidity from: {partners.map(p => p.name).join(', ')}</p>
210
+
211
+ <table>
212
+ <thead>
213
+ <tr>
214
+ <th>Market</th>
215
+ <th>Price</th>
216
+ <th>Available</th>
217
+ <th>Partner</th>
218
+ </tr>
219
+ </thead>
220
+ <tbody>
221
+ {liquidities.map((liq) => (
222
+ <tr key={liq.router_liquidity_id}>
223
+ <td>{liq.title}</td> {/* 🎯 HUMAN-READABLE */}
224
+ <td>{(liq.price * 100).toFixed(1)}%</td>
225
+ <td>${liq.available}</td>
226
+ <td>
227
+ {partners.find(p =>
228
+ p.partner_id === liq.partner_market_id.split('-')[0]
229
+ )?.name}
230
+ </td>
231
+ </tr>
232
+ ))}
233
+ </tbody>
234
+ </table>
235
+ </div>
236
+ );
237
+ }
238
+ ```
239
+
240
+ ---
241
+
242
+ ## 🎯 Key Features
243
+
244
+ ### βœ… Pre-rendered Titles
245
+ The `title` field is **already rendered server-side** using the market side's `renderer` template:
246
+ - **Moneyline:** "Lakers to win Full Game"
247
+ - **Spread:** "Lakers -3.5 Full Game"
248
+ - **Totals:** "Total Points over 220.5 Full Game"
249
+
250
+ **You don't need to render titles client-side - just display `liquidity.title`!**
251
+
252
+ ### βœ… Type Safety
253
+ All types are available from the shared types folder:
254
+ ```typescript
255
+ import {
256
+ RouterLiquidityProps,
257
+ RouterContestProps,
258
+ PartnerMarketProps,
259
+ ApiContracts,
260
+ ExtractSuccessResponse
261
+ } from './types/betrouter';
262
+ ```
263
+
264
+ ### βœ… Partner Filtering
265
+ Fetch liquidity from specific partners only:
266
+ ```typescript
267
+ // Only BettorEdge
268
+ fetchContestLiquidity(contestId, ['bettoredge-partner-id']);
269
+
270
+ // BettorEdge and Kalshi
271
+ fetchContestLiquidity(contestId, ['bettoredge-id', 'kalshi-id']);
272
+
273
+ // All partners
274
+ fetchContestLiquidity(contestId);
275
+ ```
276
+
277
+ ### βœ… Rich Context Data
278
+ Response includes all related entities for building complex UIs:
279
+ - `partner_markets` - Link liquidity to markets
280
+ - `router_markets` - Group by market type
281
+ - `router_market_sides` - Filter by side (home/away/over/under)
282
+ - `router_market_variables` - Display spread/total values
283
+
284
+ ---
285
+
286
+ ## πŸ”„ Grouping Liquidity by Market
287
+
288
+ ```typescript
289
+ function groupLiquiditiesByMarket(
290
+ liquidities: RouterLiquidityProps[],
291
+ partnerMarkets: PartnerMarketProps[],
292
+ routerMarkets: RouterMarketProps[]
293
+ ) {
294
+ const grouped = new Map<string, RouterLiquidityProps[]>();
295
+
296
+ liquidities.forEach(liq => {
297
+ const partnerMarket = partnerMarkets.find(pm => pm.partner_market_id === liq.partner_market_id);
298
+ if (!partnerMarket) return;
299
+
300
+ const routerMarket = routerMarkets.find(rm => rm.router_market_id === partnerMarket.router_market_id);
301
+ if (!routerMarket) return;
302
+
303
+ const key = routerMarket.market_label; // "Moneyline", "Spread", etc.
304
+
305
+ if (!grouped.has(key)) {
306
+ grouped.set(key, []);
307
+ }
308
+ grouped.get(key)!.push(liq);
309
+ });
310
+
311
+ return grouped;
312
+ }
313
+ ```
314
+
315
+ ---
316
+
317
+ ## 🎨 Example UI Display
318
+
319
+ ```
320
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
321
+ β”‚ Lakers vs Celtics - October 30, 2025 7:00 PM β”‚
322
+ β”‚ Showing liquidity from: BettorEdge, Kalshi β”‚
323
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
324
+ β”‚ β”‚
325
+ β”‚ Moneyline β”‚
326
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
327
+ β”‚ β”‚ Market β”‚ Priceβ”‚Availableβ”‚ Partner β”‚ β”‚
328
+ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚
329
+ β”‚ β”‚ Lakers to win Full Gameβ”‚ 55% β”‚ $100 β”‚ BettorEdge β”‚ β”‚
330
+ β”‚ β”‚ Lakers to win Full Gameβ”‚ 54% β”‚ $200 β”‚ Kalshi β”‚ β”‚
331
+ β”‚ β”‚ Celtics to win Full...β”‚ 48% β”‚ $150 β”‚ BettorEdge β”‚ β”‚
332
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
333
+ β”‚ β”‚
334
+ β”‚ Spread β”‚
335
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
336
+ β”‚ β”‚ Market β”‚ Priceβ”‚Availableβ”‚ Partner β”‚ β”‚
337
+ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚
338
+ β”‚ β”‚ Lakers -3.5 Full Game β”‚ 52% β”‚ $250 β”‚ BettorEdge β”‚ β”‚
339
+ β”‚ β”‚ Lakers -3.5 Full Game β”‚ 51% β”‚ $300 β”‚ Kalshi β”‚ β”‚
340
+ β”‚ β”‚ Celtics +3.5 Full Gameβ”‚ 50% β”‚ $200 β”‚ BettorEdge β”‚ β”‚
341
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
342
+ β”‚ β”‚
343
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
344
+ ```
345
+
346
+ ---
347
+
348
+ ## πŸ“š Related Types Reference
349
+
350
+ ```typescript
351
+ interface RouterLiquidityProps {
352
+ router_liquidity_id: string;
353
+ liquidity_hash: string; // Unique identifier with all context
354
+ title: string; // 🎯 Human-readable title (pre-rendered)
355
+ router_contest_id: string;
356
+ partner_market_id: string;
357
+ price: number; // Probability (0-1)
358
+ available: number; // Amount available to bet
359
+ expire_datetime: string;
360
+ buy_id?: string; // Partner's order ID
361
+ create_datetime: string;
362
+ last_update_datetime: string;
363
+ }
364
+
365
+ interface RouterContestProps {
366
+ router_contest_id: string;
367
+ contest_label: string;
368
+ scheduled_datetime: string;
369
+ status: 'open' | 'closed' | 'settled';
370
+ // ... other fields
371
+ }
372
+
373
+ interface RouterPartnerProps {
374
+ partner_id: string;
375
+ name: string; // "BettorEdge", "Kalshi", "BetOpenly"
376
+ status: 'active' | 'inactive';
377
+ // ... other fields
378
+ }
379
+ ```
380
+
381
+ ---
382
+
383
+ ## βœ… Summary
384
+
385
+ **What you get:**
386
+ - βœ… Pre-rendered, human-readable titles for all liquidity
387
+ - βœ… Type-safe API contracts
388
+ - βœ… All related data for complex UIs
389
+ - βœ… Partner filtering support
390
+ - βœ… Real-time price and availability data
391
+
392
+ **What you need to do:**
393
+ 1. Copy the `/src/types` folder to your client project
394
+ 2. Import the types
395
+ 3. Fetch from `GET /liquidity/contest/:router_contest_id`
396
+ 4. Display `liquidity.title` (already formatted!)
397
+ 5. Build your UI
398
+
399
+ **No client-side title rendering needed!** πŸŽ‰