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.
- package/lib/commonjs/Assets/fonts/Barlow-Bold.ttf +0 -0
- package/lib/commonjs/Assets/fonts/Barlow-Regular.ttf +0 -0
- package/lib/commonjs/Assets/fonts/Barlow-SemiBold.ttf +0 -0
- package/lib/commonjs/Assets/images/powered_by_be.webp +0 -0
- package/lib/commonjs/BetRouter/components/MyOpportunities.tsx.bak +440 -0
- package/lib/commonjs/BetRouter/types/ADMIN_PORTAL.md +863 -0
- package/lib/commonjs/BetRouter/types/ADMIN_PORTAL_SIMPLIFIED.md +1881 -0
- package/lib/commonjs/BetRouter/types/CREDENTIALS_EXAMPLE.md +350 -0
- package/lib/commonjs/BetRouter/types/LIQUIDITY_CLIENT_GUIDE.md +399 -0
- package/lib/commonjs/BetRouter/types/MARKET_LINKING_WORKFLOW.md +682 -0
- package/lib/commonjs/BetRouter/types/MARKET_LINKING_WORKFLOW_V2.md +627 -0
- package/lib/commonjs/BetRouter/types/README.md +249 -0
- package/lib/commonjs/Charts/README.md +310 -0
- package/lib/commonjs/NotificationManager/components/ScheduleNotification.js +1 -16
- package/lib/commonjs/NotificationManager/components/ScheduleNotification.js.map +1 -1
- package/lib/commonjs/NotificationManager/components/shared/GroupSelector.js +74 -4
- package/lib/commonjs/NotificationManager/components/shared/GroupSelector.js.map +1 -1
- package/lib/commonjs/NotificationManager/index.js +49 -5
- package/lib/commonjs/NotificationManager/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ApiOverrides/index.ts +2 -2
- package/src/NotificationManager/components/ScheduleNotification.tsx +1 -17
- package/src/NotificationManager/components/shared/GroupSelector.tsx +83 -6
- 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!** π
|