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,350 @@
1
+ # Partner Credentials - Client Usage Guide
2
+
3
+ This guide shows how to build dynamic credential forms in your client based on partner types.
4
+
5
+ ## 🎯 Usage in Client
6
+
7
+ ### Example 1: Dynamic Form Builder
8
+
9
+ ```typescript
10
+ import {
11
+ RouterPartnerProps,
12
+ KalshiCredentialProps,
13
+ BettorEdgeCredentialProps,
14
+ BetOpenlyCredentialProps,
15
+ getRequiredCredentialFields,
16
+ getCredentialFieldLabels,
17
+ getCredentialFieldTypes
18
+ } from './types/betrouter';
19
+
20
+ interface CredentialFormProps {
21
+ partner: RouterPartnerProps;
22
+ onSubmit: (credentials: any) => void;
23
+ }
24
+
25
+ function CredentialForm({ partner, onSubmit }: CredentialFormProps) {
26
+ const fields = getRequiredCredentialFields(partner.name);
27
+ const labels = getCredentialFieldLabels(partner.name);
28
+ const types = getCredentialFieldTypes(partner.name);
29
+
30
+ const [formData, setFormData] = useState<Record<string, string>>({});
31
+
32
+ const handleSubmit = (e: React.FormEvent) => {
33
+ e.preventDefault();
34
+ onSubmit(formData);
35
+ };
36
+
37
+ return (
38
+ <form onSubmit={handleSubmit}>
39
+ <h2>Connect to {partner.name}</h2>
40
+ {fields.map(field => (
41
+ <div key={field}>
42
+ <label>{labels[field]}</label>
43
+ {types[field] === 'textarea' ? (
44
+ <textarea
45
+ value={formData[field] || ''}
46
+ onChange={(e) => setFormData({ ...formData, [field]: e.target.value })}
47
+ required
48
+ />
49
+ ) : (
50
+ <input
51
+ type={types[field]}
52
+ value={formData[field] || ''}
53
+ onChange={(e) => setFormData({ ...formData, [field]: e.target.value })}
54
+ required
55
+ />
56
+ )}
57
+ </div>
58
+ ))}
59
+ <button type="submit">Connect</button>
60
+ </form>
61
+ );
62
+ }
63
+ ```
64
+
65
+ ### Example 2: Type-Safe Credential Update
66
+
67
+ ```typescript
68
+ import {
69
+ ApiContracts,
70
+ ExtractRequestBody,
71
+ ExtractSuccessResponse,
72
+ KalshiCredentialProps,
73
+ BettorEdgeCredentialProps,
74
+ BetOpenlyCredentialProps
75
+ } from './types/betrouter';
76
+
77
+ type UpdateCredentialsBody = ExtractRequestBody<'POST /accounts/partner/credentials/update'>;
78
+ type UpdateCredentialsResponse = ExtractSuccessResponse<'POST /accounts/partner/credentials/update'>;
79
+
80
+ async function updatePartnerCredentials(
81
+ partnerId: string,
82
+ credentials: KalshiCredentialProps | BettorEdgeCredentialProps | BetOpenlyCredentialProps
83
+ ): Promise<UpdateCredentialsResponse> {
84
+ const body: UpdateCredentialsBody = {
85
+ partner_id: partnerId,
86
+ credentials
87
+ };
88
+
89
+ const response = await fetch('/api/accounts/partner/credentials/update', {
90
+ method: 'POST',
91
+ headers: {
92
+ 'Content-Type': 'application/json',
93
+ 'Authorization': `Bearer ${token}`
94
+ },
95
+ body: JSON.stringify(body)
96
+ });
97
+
98
+ return response.json();
99
+ }
100
+ ```
101
+
102
+ ### Example 3: Partner-Specific Forms
103
+
104
+ ```typescript
105
+ import { KalshiCredentialProps, BettorEdgeCredentialProps, BetOpenlyCredentialProps } from './types/betrouter';
106
+
107
+ // Kalshi Form
108
+ function KalshiCredentialsForm() {
109
+ const [credentials, setCredentials] = useState<KalshiCredentialProps>({
110
+ api_key: '',
111
+ private_key_pem: ''
112
+ });
113
+
114
+ return (
115
+ <form>
116
+ <input
117
+ type="text"
118
+ placeholder="API Key"
119
+ value={credentials.api_key}
120
+ onChange={(e) => setCredentials({ ...credentials, api_key: e.target.value })}
121
+ />
122
+ <textarea
123
+ placeholder="Private Key (PEM format)"
124
+ value={credentials.private_key_pem}
125
+ onChange={(e) => setCredentials({ ...credentials, private_key_pem: e.target.value })}
126
+ />
127
+ </form>
128
+ );
129
+ }
130
+
131
+ // BettorEdge Form
132
+ function BettorEdgeCredentialsForm() {
133
+ const [credentials, setCredentials] = useState<BettorEdgeCredentialProps>({
134
+ username: '',
135
+ password: '',
136
+ device_id: ''
137
+ });
138
+
139
+ return (
140
+ <form>
141
+ <input
142
+ type="text"
143
+ placeholder="Username"
144
+ value={credentials.username}
145
+ onChange={(e) => setCredentials({ ...credentials, username: e.target.value })}
146
+ />
147
+ <input
148
+ type="password"
149
+ placeholder="Password"
150
+ value={credentials.password}
151
+ onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
152
+ />
153
+ <input
154
+ type="text"
155
+ placeholder="Device ID"
156
+ value={credentials.device_id}
157
+ onChange={(e) => setCredentials({ ...credentials, device_id: e.target.value })}
158
+ />
159
+ </form>
160
+ );
161
+ }
162
+
163
+ // BetOpenly Form
164
+ function BetOpenlyCredentialsForm() {
165
+ const [credentials, setCredentials] = useState<BetOpenlyCredentialProps>({
166
+ username: '',
167
+ password: ''
168
+ });
169
+
170
+ return (
171
+ <form>
172
+ <input
173
+ type="text"
174
+ placeholder="Username"
175
+ value={credentials.username}
176
+ onChange={(e) => setCredentials({ ...credentials, username: e.target.value })}
177
+ />
178
+ <input
179
+ type="password"
180
+ placeholder="Password"
181
+ value={credentials.password}
182
+ onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
183
+ />
184
+ </form>
185
+ );
186
+ }
187
+ ```
188
+
189
+ ### Example 4: Complete Flow with React Query
190
+
191
+ ```typescript
192
+ import { useMutation } from '@tanstack/react-query';
193
+ import {
194
+ RouterPartnerProps,
195
+ KalshiCredentialProps,
196
+ BettorEdgeCredentialProps,
197
+ BetOpenlyCredentialProps,
198
+ ExtractRequestBody,
199
+ ExtractSuccessResponse
200
+ } from './types/betrouter';
201
+
202
+ type UpdateCredentialsBody = ExtractRequestBody<'POST /accounts/partner/credentials/update'>;
203
+ type UpdateCredentialsResponse = ExtractSuccessResponse<'POST /accounts/partner/credentials/update'>;
204
+
205
+ function useUpdateCredentials() {
206
+ return useMutation({
207
+ mutationFn: async (body: UpdateCredentialsBody): Promise<UpdateCredentialsResponse> => {
208
+ const response = await fetch('/api/accounts/partner/credentials/update', {
209
+ method: 'POST',
210
+ headers: {
211
+ 'Content-Type': 'application/json',
212
+ 'Authorization': `Bearer ${token}`
213
+ },
214
+ body: JSON.stringify(body)
215
+ });
216
+
217
+ if (!response.ok) throw new Error('Failed to update credentials');
218
+ return response.json();
219
+ }
220
+ });
221
+ }
222
+
223
+ function ConnectPartnerPage({ partner }: { partner: RouterPartnerProps }) {
224
+ const updateCredentials = useUpdateCredentials();
225
+ const [formData, setFormData] = useState<Record<string, string>>({});
226
+
227
+ const handleSubmit = async (e: React.FormEvent) => {
228
+ e.preventDefault();
229
+
230
+ // Type-safe credentials based on partner
231
+ let credentials: KalshiCredentialProps | BettorEdgeCredentialProps | BetOpenlyCredentialProps;
232
+
233
+ if (partner.name === 'Kalshi') {
234
+ credentials = {
235
+ api_key: formData.api_key,
236
+ private_key_pem: formData.private_key_pem
237
+ };
238
+ } else if (partner.name === 'BettorEdge') {
239
+ credentials = {
240
+ username: formData.username,
241
+ password: formData.password,
242
+ device_id: formData.device_id
243
+ };
244
+ } else if (partner.name === 'BetOpenly') {
245
+ credentials = {
246
+ username: formData.username,
247
+ password: formData.password
248
+ };
249
+ } else {
250
+ return;
251
+ }
252
+
253
+ await updateCredentials.mutateAsync({
254
+ partner_id: partner.partner_id,
255
+ credentials
256
+ });
257
+ };
258
+
259
+ // Use the helper functions for dynamic form rendering
260
+ // (see Example 1)
261
+ }
262
+ ```
263
+
264
+ ## 📋 Available Helper Functions
265
+
266
+ ### `getRequiredCredentialFields(partnerName: string): string[]`
267
+ Returns array of required field names for a partner.
268
+
269
+ ```typescript
270
+ getRequiredCredentialFields('Kalshi')
271
+ // Returns: ['api_key', 'private_key_pem']
272
+
273
+ getRequiredCredentialFields('BettorEdge')
274
+ // Returns: ['username', 'password', 'device_id']
275
+
276
+ getRequiredCredentialFields('BetOpenly')
277
+ // Returns: ['username', 'password']
278
+ ```
279
+
280
+ ### `getCredentialFieldLabels(partnerName: string): Record<string, string>`
281
+ Returns human-readable labels for each field.
282
+
283
+ ```typescript
284
+ getCredentialFieldLabels('Kalshi')
285
+ // Returns: { api_key: 'API Key', private_key_pem: 'Private Key (PEM format)' }
286
+
287
+ getCredentialFieldLabels('BetOpenly')
288
+ // Returns: { username: 'Username', password: 'Password' }
289
+ ```
290
+
291
+ ### `getCredentialFieldTypes(partnerName: string): Record<string, 'text' | 'password' | 'textarea'>`
292
+ Returns input types for each field.
293
+
294
+ ```typescript
295
+ getCredentialFieldTypes('Kalshi')
296
+ // Returns: { api_key: 'text', private_key_pem: 'textarea' }
297
+
298
+ getCredentialFieldTypes('BetOpenly')
299
+ // Returns: { username: 'text', password: 'password' }
300
+ ```
301
+
302
+ ## 🔐 Type Guards
303
+
304
+ ```typescript
305
+ import { isKalshiCredentials, isBettorEdgeCredentials, isBetOpenlyCredentials } from './types/betrouter';
306
+
307
+ function processCredentials(credentials: any) {
308
+ if (isKalshiCredentials(credentials)) {
309
+ // TypeScript knows this is KalshiCredentialProps
310
+ console.log(credentials.api_key);
311
+ console.log(credentials.private_key_pem);
312
+ } else if (isBettorEdgeCredentials(credentials)) {
313
+ // TypeScript knows this is BettorEdgeCredentialProps
314
+ console.log(credentials.username);
315
+ console.log(credentials.password);
316
+ console.log(credentials.device_id);
317
+ } else if (isBetOpenlyCredentials(credentials)) {
318
+ // TypeScript knows this is BetOpenlyCredentialProps
319
+ console.log(credentials.username);
320
+ console.log(credentials.password);
321
+ }
322
+ }
323
+ ```
324
+
325
+ ## 🆕 Adding New Partner Credentials
326
+
327
+ When you add a new partner:
328
+
329
+ 1. **Add the credential interface in `src/types/credentials.ts`:**
330
+ ```typescript
331
+ export interface NewPartnerCredentialProps {
332
+ field1: string
333
+ field2: string
334
+ }
335
+ ```
336
+
337
+ 2. **Update the union type:**
338
+ ```typescript
339
+ export type PartnerCredentialProps =
340
+ KalshiCredentialProps |
341
+ BettorEdgeCredentialProps |
342
+ BetOpenlyCredentialProps |
343
+ NewPartnerCredentialProps
344
+ ```
345
+
346
+ 3. **Update the helper functions** in the same file
347
+
348
+ 4. **Copy to your client** - `cp -r ../betrouter/src/types ./src/types/betrouter`
349
+
350
+ 5. **Your client automatically gets the new partner support!**