be-components 6.2.2 → 6.2.3
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/Competition/components/CompetitionPlay.js +8 -1
- package/lib/commonjs/Competition/components/CompetitionPlay.js.map +1 -1
- package/lib/commonjs/Competition/components/MarketsCard.js +1 -0
- package/lib/commonjs/Competition/components/MarketsCard.js.map +1 -1
- package/lib/commonjs/MarketComponents/api/index.js +189 -0
- package/lib/commonjs/MarketComponents/api/index.js.map +1 -1
- package/lib/commonjs/MarketComponents/components/CreateMarketForm.js +736 -0
- package/lib/commonjs/MarketComponents/components/CreateMarketForm.js.map +1 -0
- package/lib/commonjs/MarketComponents/components/WeightProgress.js +53 -0
- package/lib/commonjs/MarketComponents/components/WeightProgress.js.map +1 -0
- package/lib/commonjs/MarketComponents/index.js +2 -0
- package/lib/commonjs/MarketComponents/index.js.map +1 -1
- package/lib/commonjs/MarketMaker/api/index.js +3 -0
- package/lib/commonjs/MarketMaker/api/index.js.map +1 -1
- package/lib/commonjs/Poll/components/PollCard.js +3 -0
- package/lib/commonjs/Poll/components/PollCard.js.map +1 -1
- package/lib/module/Competition/components/CompetitionPlay.js +8 -1
- package/lib/module/Competition/components/CompetitionPlay.js.map +1 -1
- package/lib/module/Competition/components/MarketsCard.js +1 -0
- package/lib/module/Competition/components/MarketsCard.js.map +1 -1
- package/lib/module/MarketComponents/api/index.js +189 -0
- package/lib/module/MarketComponents/api/index.js.map +1 -1
- package/lib/module/MarketComponents/components/CreateMarketForm.js +727 -0
- package/lib/module/MarketComponents/components/CreateMarketForm.js.map +1 -0
- package/lib/module/MarketComponents/components/WeightProgress.js +45 -0
- package/lib/module/MarketComponents/components/WeightProgress.js.map +1 -0
- package/lib/module/MarketComponents/index.js +2 -0
- package/lib/module/MarketComponents/index.js.map +1 -1
- package/lib/module/MarketMaker/api/index.js +3 -0
- package/lib/module/MarketMaker/api/index.js.map +1 -1
- package/lib/module/Poll/components/PollCard.js +3 -0
- package/lib/module/Poll/components/PollCard.js.map +1 -1
- package/lib/typescript/lib/commonjs/Competition/components/CompetitionPlay.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/Competition/components/MarketsCard.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/MarketComponents/api/index.d.ts +6 -0
- package/lib/typescript/lib/commonjs/MarketComponents/api/index.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/MarketComponents/components/CreateMarketForm.d.ts +20 -0
- package/lib/typescript/lib/commonjs/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/MarketComponents/components/WeightProgress.d.ts +8 -0
- package/lib/typescript/lib/commonjs/MarketComponents/components/WeightProgress.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/MarketComponents/index.d.ts +1 -0
- package/lib/typescript/lib/commonjs/MarketMaker/api/index.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/Poll/components/PollCard.d.ts.map +1 -1
- package/lib/typescript/lib/module/Competition/components/CompetitionPlay.d.ts.map +1 -1
- package/lib/typescript/lib/module/Competition/components/MarketsCard.d.ts.map +1 -1
- package/lib/typescript/lib/module/MarketComponents/api/index.d.ts +6 -0
- package/lib/typescript/lib/module/MarketComponents/api/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/MarketComponents/components/CreateMarketForm.d.ts +20 -0
- package/lib/typescript/lib/module/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
- package/lib/typescript/lib/module/MarketComponents/components/WeightProgress.d.ts +8 -0
- package/lib/typescript/lib/module/MarketComponents/components/WeightProgress.d.ts.map +1 -0
- package/lib/typescript/lib/module/MarketComponents/index.d.ts +2 -0
- package/lib/typescript/lib/module/MarketComponents/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/MarketMaker/api/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/Poll/components/PollCard.d.ts.map +1 -1
- package/lib/typescript/src/Competition/components/MarketsCard.d.ts.map +1 -1
- package/lib/typescript/src/MarketComponents/api/index.d.ts +6 -0
- package/lib/typescript/src/MarketComponents/api/index.d.ts.map +1 -1
- package/lib/typescript/src/MarketComponents/components/CreateMarketForm.d.ts +27 -0
- package/lib/typescript/src/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
- package/lib/typescript/src/MarketComponents/components/WeightProgress.d.ts +12 -0
- package/lib/typescript/src/MarketComponents/components/WeightProgress.d.ts.map +1 -0
- package/lib/typescript/src/MarketComponents/index.d.ts +21 -0
- package/lib/typescript/src/MarketComponents/index.d.ts.map +1 -1
- package/lib/typescript/src/MarketMaker/api/index.d.ts +1 -1
- package/lib/typescript/src/MarketMaker/api/index.d.ts.map +1 -1
- package/lib/typescript/src/Poll/components/PollCard.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Competition/components/CompetitionPlay.tsx +6 -6
- package/src/Competition/components/MarketsCard.tsx +1 -0
- package/src/MarketComponents/api/index.ts +166 -3
- package/src/MarketComponents/components/CreateMarketForm.tsx +444 -0
- package/src/MarketComponents/components/WeightProgress.tsx +32 -0
- package/src/MarketComponents/index.tsx +2 -0
- package/src/MarketMaker/api/index.ts +2 -1
- package/src/Poll/components/PollCard.tsx +1 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Button, Text, TextInput, View } from "../../Components/Themed"
|
|
3
|
+
import type { BestAvailableOrderProps, EventProps, ExternalPriceProps, LocationProps, MarketProps, MatchProps, OrderProps, TournamentProps, TradeProps } from '../../types';
|
|
4
|
+
import { MarketComponentApi, MarketComponentHelpers } from '../api';
|
|
5
|
+
import { ActivityIndicator, FlatList, type ViewStyle } from 'react-native';
|
|
6
|
+
import { Icons } from '../../Components';
|
|
7
|
+
import { useColors } from '../../constants/useColors';
|
|
8
|
+
import { MarketMaketHelpers } from '../../MarketMaker/api';
|
|
9
|
+
import OrderGradeBar from './OrderGradeBar';
|
|
10
|
+
import WeightProgress from './WeightProgress';
|
|
11
|
+
|
|
12
|
+
type CreateMarketFormProps = {
|
|
13
|
+
float?:boolean,
|
|
14
|
+
style?:ViewStyle
|
|
15
|
+
contest_type:'team'|'tournament'|'match',
|
|
16
|
+
contest_id:string,
|
|
17
|
+
best_available_orders:BestAvailableOrderProps[],
|
|
18
|
+
my_orders:OrderProps[],
|
|
19
|
+
action_loading?:boolean,
|
|
20
|
+
market_id:string,
|
|
21
|
+
unit_size?:number,
|
|
22
|
+
location?:LocationProps,
|
|
23
|
+
coordinates?:{ latitude:number, longitude:number, [key:string]:any }
|
|
24
|
+
side_type?:'side'|'team'|'athlete',
|
|
25
|
+
side_id?:string,
|
|
26
|
+
onCancel:() => void,
|
|
27
|
+
onSubmitOrders:(orders:OrderProps[]) => void
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
const sections = ['o_side', 'submit', 'trade_side', 'draft_orders','my_orders', 'what_if'];
|
|
32
|
+
const CreateMarketForm = ({ float, action_loading, unit_size, location, coordinates, style, my_orders, best_available_orders, contest_type, contest_id, market_id, side_id, side_type, onCancel, onSubmitOrders }:CreateMarketFormProps) => {
|
|
33
|
+
const Colors = useColors();
|
|
34
|
+
const [ draft_orders, setDraftOrders ] = useState<OrderProps[]>([]);
|
|
35
|
+
const [ draft_data, setDraftData ] = useState<{
|
|
36
|
+
stake:string,
|
|
37
|
+
o_side_margin:number,
|
|
38
|
+
trade_side_margin:number
|
|
39
|
+
}>({
|
|
40
|
+
stake:unit_size?.toFixed(2) ?? '10',
|
|
41
|
+
o_side_margin: 0.02,
|
|
42
|
+
trade_side_margin: 0.02
|
|
43
|
+
});
|
|
44
|
+
const { o_side_margin, trade_side_margin, stake } = draft_data;
|
|
45
|
+
const [ form_data, setFormData ] = useState<{
|
|
46
|
+
loading:boolean,
|
|
47
|
+
markets:MarketProps[],
|
|
48
|
+
prices:ExternalPriceProps[],
|
|
49
|
+
trades:TradeProps[],
|
|
50
|
+
event?:EventProps,
|
|
51
|
+
tournament?:TournamentProps,
|
|
52
|
+
match?:MatchProps
|
|
53
|
+
}>({
|
|
54
|
+
loading:false,
|
|
55
|
+
markets: [],
|
|
56
|
+
prices: [],
|
|
57
|
+
trades: []
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const { loading, markets, prices, event, tournament, match } = form_data;
|
|
61
|
+
|
|
62
|
+
const { contest_title } = MarketComponentHelpers.getContestDetails(contest_type, event, tournament, match);
|
|
63
|
+
const market = markets.find(mk => mk.market_id == market_id);
|
|
64
|
+
|
|
65
|
+
const orders = MarketComponentHelpers.setMarket(parseFloat(stake), contest_type, best_available_orders, prices, o_side_margin, trade_side_margin, market, event, tournament, match, undefined, undefined)
|
|
66
|
+
const no_vig_data = MarketMaketHelpers.getNoVigPrice(prices, market);
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
MarketComponentApi.setEnvironment();
|
|
71
|
+
getFormData();
|
|
72
|
+
},[]);
|
|
73
|
+
|
|
74
|
+
const getFormData = async() => {
|
|
75
|
+
setFormData({ ...form_data, loading:true })
|
|
76
|
+
const mks = await MarketComponentApi.getMarkets();
|
|
77
|
+
let ev:EventProps | undefined, tourn:TournamentProps | undefined, mtch:MatchProps|undefined
|
|
78
|
+
if(contest_type == 'team'){
|
|
79
|
+
let evs = await MarketComponentApi.getEventsByEventIds([contest_id]);
|
|
80
|
+
ev = evs[0]
|
|
81
|
+
}
|
|
82
|
+
if(contest_type == 'tournament'){
|
|
83
|
+
let tourns = await MarketComponentApi.getTournamentsByTournamentIds([contest_id]);
|
|
84
|
+
tourn = tourns[0]
|
|
85
|
+
}
|
|
86
|
+
if(contest_type == 'match'){
|
|
87
|
+
let mtchs = await MarketComponentApi.getMatchesByMatchIds([contest_id]);
|
|
88
|
+
mtch = mtchs[0]
|
|
89
|
+
if(mtch){
|
|
90
|
+
let mtch_tourns = await MarketComponentApi.getTournamentsByTournamentIds([mtch.tournament_id]);
|
|
91
|
+
tourn = mtch_tourns[0]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
let contest_prices = await MarketComponentApi.getExternalPrices(contest_type, contest_id, market_id);
|
|
95
|
+
//Get the correct prices
|
|
96
|
+
if(side_type){ contest_prices = contest_prices.filter(p => p.participant_type == side_type && p.participant_id == side_id) }
|
|
97
|
+
//First try to get consensus
|
|
98
|
+
contest_prices = contest_prices.filter(p => p.external_name == 'Consensus');
|
|
99
|
+
if(contest_prices.length == 0){
|
|
100
|
+
let available_books = [ ...new Set(contest_prices.map(p => p.external_name)) ]
|
|
101
|
+
contest_prices = contest_prices.filter(p => p.external_name == available_books[0]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let contest_trades = await MarketComponentApi.getLatestTradesByEvents(contest_type, [contest_id]);
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
setFormData({
|
|
108
|
+
...form_data,
|
|
109
|
+
loading:false,
|
|
110
|
+
markets: mks,
|
|
111
|
+
match: mtch,
|
|
112
|
+
event: ev,
|
|
113
|
+
tournament: tourn,
|
|
114
|
+
prices: contest_prices,
|
|
115
|
+
trades: contest_trades
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const handleSubmitOrder = () => {
|
|
120
|
+
if(action_loading){ return }
|
|
121
|
+
if(draft_orders.length == 0){ return alert('Unable to submit!') }
|
|
122
|
+
if(!location){ return alert('Unable to create order without location') }
|
|
123
|
+
if(!location.legal_ind){ return alert('Unable to create order in this location') }
|
|
124
|
+
if(!coordinates?.latitude){ return alert('Need coordinates') }
|
|
125
|
+
let new_orders = draft_orders.map(o => {
|
|
126
|
+
o.region = location.label
|
|
127
|
+
o.location = coordinates
|
|
128
|
+
return o
|
|
129
|
+
});
|
|
130
|
+
onSubmitOrders(new_orders)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const handleUpdateMargin = (side:'other'|'trade', direction: 'increase'|'decrease') => {
|
|
134
|
+
let o_side = o_side_margin
|
|
135
|
+
let trade_side = trade_side_margin
|
|
136
|
+
if(side == 'other' && direction == 'increase'){ o_side += 0.001 }
|
|
137
|
+
if(side == 'other' && direction == 'decrease'){ o_side -= 0.001 }
|
|
138
|
+
|
|
139
|
+
if(side == 'trade' && direction == 'increase'){ trade_side += 0.001 }
|
|
140
|
+
if(side == 'trade' && direction == 'decrease'){ trade_side -= 0.001 }
|
|
141
|
+
let total_margin = o_side + trade_side
|
|
142
|
+
if(total_margin < 0.001){ return } //Cant go negative!!
|
|
143
|
+
setDraftData({ o_side_margin: o_side, trade_side_margin: trade_side, stake })
|
|
144
|
+
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const renderOrders = (data:{ item:OrderProps, index:number }) => {
|
|
148
|
+
return (
|
|
149
|
+
<View style={{ flexGrow:1 }}>
|
|
150
|
+
<View style={{ padding:10 }}>
|
|
151
|
+
<Text theme='h1' textAlign='center'>{data.item.title}</Text>
|
|
152
|
+
</View>
|
|
153
|
+
</View>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const renderSections = (data:{item:string, index:number}) => {
|
|
158
|
+
switch(data.item){
|
|
159
|
+
case 'my_orders':
|
|
160
|
+
if(!market){ return <></> }
|
|
161
|
+
const hedges = MarketMaketHelpers.getHedgesFromPositions(my_orders, markets);
|
|
162
|
+
const hedge = hedges[0]
|
|
163
|
+
const o_side_stats = MarketMaketHelpers.getOrderStats(my_orders.filter(o => o.side != market.trade_side));
|
|
164
|
+
const t_side_stats = MarketMaketHelpers.getOrderStats(my_orders.filter(o => o.side == market.trade_side));
|
|
165
|
+
const stake_weight = MarketMaketHelpers.getWeight(o_side_stats.stake_potential_winnings, t_side_stats.stake_potential_winnings, market);
|
|
166
|
+
const at_risk = o_side_stats.stake_potential_winnings - t_side_stats.stake_potential_winnings
|
|
167
|
+
return (
|
|
168
|
+
<View type='footer' style={{ padding:10 }}>
|
|
169
|
+
<View transparent style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
|
|
170
|
+
<View transparent style={{ flex:1 }}>
|
|
171
|
+
<Text theme='h1'>My Current Position</Text>
|
|
172
|
+
</View>
|
|
173
|
+
{hedge?
|
|
174
|
+
<View transparent>
|
|
175
|
+
{hedge.delayed_cash_draw ?
|
|
176
|
+
<Text theme='error' size={14}>-${hedge.delayed_cash_draw.toFixed(2)}</Text>
|
|
177
|
+
:
|
|
178
|
+
<Text theme='success' size={14}>${hedge.delayed_cash_no_draw.toFixed(2)}</Text>
|
|
179
|
+
}
|
|
180
|
+
<Text theme='description'>Hedged</Text>
|
|
181
|
+
</View>
|
|
182
|
+
:<></>}
|
|
183
|
+
</View>
|
|
184
|
+
<View transparent type='row'>
|
|
185
|
+
<View transparent style={{ flex:1, padding:5 }}>
|
|
186
|
+
<Text theme='h2' textAlign='center'>{o_side_stats.stake_potential_winnings.toFixed(2)}</Text>
|
|
187
|
+
</View>
|
|
188
|
+
<View transparent style={{ flex:1, padding:5 }}>
|
|
189
|
+
<Text theme='h2' textAlign='center'>{t_side_stats.stake_potential_winnings.toFixed(2)}</Text>
|
|
190
|
+
</View>
|
|
191
|
+
</View>
|
|
192
|
+
<WeightProgress
|
|
193
|
+
style={{ margin:10 }}
|
|
194
|
+
min_value={0}
|
|
195
|
+
max_value={100}
|
|
196
|
+
value={stake_weight.weighted_pct}
|
|
197
|
+
bar_height={18}
|
|
198
|
+
/>
|
|
199
|
+
<View transparent type='row'>
|
|
200
|
+
{at_risk > 0 ?
|
|
201
|
+
<View transparent style={{ flex:1, padding:5 }}>
|
|
202
|
+
<Text theme='error' textAlign='center' style={{ marginTop:3 }}>${at_risk.toFixed(2)}</Text>
|
|
203
|
+
<Text theme='description' textAlign='center' style={{ marginTop:3 }}>At Risk</Text>
|
|
204
|
+
</View>
|
|
205
|
+
:<View style={{ flex:1 }} />}
|
|
206
|
+
{at_risk < 0 ?
|
|
207
|
+
<View transparent style={{ flex:1, padding:5 }}>
|
|
208
|
+
<Text theme='error' textAlign='center' style={{ marginTop:3 }}>${at_risk.toFixed(2)}</Text>
|
|
209
|
+
<Text theme='description' textAlign='center' style={{ marginTop:3 }}>At Risk</Text>
|
|
210
|
+
</View>
|
|
211
|
+
:<View style={{ flex:1 }} />}
|
|
212
|
+
</View>
|
|
213
|
+
</View>
|
|
214
|
+
)
|
|
215
|
+
case 'o_side':
|
|
216
|
+
if(draft_orders.length > 0){ return <></> }
|
|
217
|
+
if(!market){ return <></> }
|
|
218
|
+
let o_side_option = market.side_options.find(so => so.side != market.trade_side);
|
|
219
|
+
if(!o_side_option){ return <></> }
|
|
220
|
+
const o_side_order = orders.find(o => o.side != market.trade_side);
|
|
221
|
+
if(!o_side_order){ return <></> }
|
|
222
|
+
const o_side_price = prices.find(p => p.side != market.trade_side);
|
|
223
|
+
const o_side_no_vig = no_vig_data?.o_side_odds
|
|
224
|
+
const o_best_available = best_available_orders.find(o => o.market_id == market_id && o.side != market.trade_side)
|
|
225
|
+
//const my_o_side_open = my_orders.filter(o => o.market_id == market_id && o.side != market.trade_side);
|
|
226
|
+
//const my_open_stats = MarketMaketHelpers.getOrderStats(my_o_side_open, o_best_available);
|
|
227
|
+
return (
|
|
228
|
+
<View style={{ borderWidth:1, borderColor:Colors.borders.light, margin:10 }}>
|
|
229
|
+
<View type='row' style={{ padding:10, borderBottomWidth:1, borderColor:Colors.borders.light }}>
|
|
230
|
+
<View transparent style={{ flex:1 }}>
|
|
231
|
+
<Text theme='h2'>{o_side_order.title}</Text>
|
|
232
|
+
<Text theme='description' style={{ marginTop:3 }}>${o_side_order.open_amt.toFixed(2)} to win ${o_side_order.potential_winnings.toFixed(2)}</Text>
|
|
233
|
+
</View>
|
|
234
|
+
<Text theme='h1'>${o_side_order.open_amt.toFixed(2)}</Text>
|
|
235
|
+
<View type='row' style={{ marginLeft:10 }}>
|
|
236
|
+
<Button float onPress={() => handleUpdateMargin('other', 'increase')}>
|
|
237
|
+
<Icons.ChevronIcon direction='left' size={8} color={Colors.text.h1} />
|
|
238
|
+
</Button>
|
|
239
|
+
<View style={{ paddingLeft:10, paddingRight:10 }}>
|
|
240
|
+
<Text theme='h1' textAlign='center'>{(o_side_order.probability * 100).toFixed(2)}%</Text>
|
|
241
|
+
<Text theme='light' style={{ marginTop:3 }} textAlign='center'>{MarketComponentHelpers.getOddsLabel(o_side_order.odds)}</Text>
|
|
242
|
+
</View>
|
|
243
|
+
<Button float onPress={() => handleUpdateMargin('other', 'decrease')}>
|
|
244
|
+
<Icons.ChevronIcon direction='right' size={8} color={Colors.text.h1} />
|
|
245
|
+
</Button>
|
|
246
|
+
</View>
|
|
247
|
+
</View>
|
|
248
|
+
{o_best_available ?
|
|
249
|
+
<View type='row' style={{ padding:10 }}>
|
|
250
|
+
<View transparent style={{flex:1}}>
|
|
251
|
+
<Text theme='h1'>{o_best_available.title}</Text>
|
|
252
|
+
{o_best_available.grade ?
|
|
253
|
+
<OrderGradeBar style={{ alignSelf:'flex-start', marginTop:3 }} grade={o_best_available.grade} view_type='card' onSelectGrade={() => console.log('')}/>
|
|
254
|
+
:<></>}
|
|
255
|
+
</View>
|
|
256
|
+
<View style={{ alignItems:'flex-end' }}>
|
|
257
|
+
<Text theme='h2'>{MarketComponentHelpers.getOddsLabel(o_best_available.odds)}</Text>
|
|
258
|
+
<Text theme='success'>${o_best_available.open_amt.toFixed(2)} Available</Text>
|
|
259
|
+
</View>
|
|
260
|
+
<Button
|
|
261
|
+
title='BUY'
|
|
262
|
+
type='success'
|
|
263
|
+
loading={action_loading}
|
|
264
|
+
style={{ padding:10, marginLeft:10, opacity: action_loading ? 0.5:1 }}
|
|
265
|
+
disabled={action_loading}
|
|
266
|
+
onPress={() => {
|
|
267
|
+
let side_ids = MarketComponentHelpers.getSideIds(contest_type, o_side_option, market, event, tournament, match, undefined, undefined);
|
|
268
|
+
if(!side_ids){ return }
|
|
269
|
+
let trade = MarketMaketHelpers.getTradeFromAvailableOrder(o_best_available, side_ids.reversed_side_id);
|
|
270
|
+
let order = MarketMaketHelpers.getOrderFromTrade(trade, unit_size ?? 10, o_best_available.order_id);
|
|
271
|
+
order.title = o_best_available.title
|
|
272
|
+
setDraftOrders([order])
|
|
273
|
+
}}
|
|
274
|
+
/>
|
|
275
|
+
</View>
|
|
276
|
+
:<></>}
|
|
277
|
+
{o_side_price && o_side_no_vig ?
|
|
278
|
+
<View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
|
|
279
|
+
<View transparent style={{ flex:1 }}>
|
|
280
|
+
<Text theme='h1'>{o_side_price.external_name}</Text>
|
|
281
|
+
<Text theme='light' style={{ marginTop:3 }}>External price with vig removed</Text>
|
|
282
|
+
</View>
|
|
283
|
+
<Text theme='h2'>{MarketComponentHelpers.getOddsLabel(o_side_no_vig)}</Text>
|
|
284
|
+
</View>
|
|
285
|
+
:<></>}
|
|
286
|
+
</View>
|
|
287
|
+
|
|
288
|
+
)
|
|
289
|
+
case 'submit':
|
|
290
|
+
if(draft_orders.length > 0){ return <></> }
|
|
291
|
+
return (
|
|
292
|
+
<View type='header' style={{ flexDirection:'row', padding:10 }}>
|
|
293
|
+
<TextInput
|
|
294
|
+
value={stake}
|
|
295
|
+
style={{ width:100, textAlign:'center' }}
|
|
296
|
+
onChangeText={(text) => setDraftData({ ...draft_data, stake:text })}
|
|
297
|
+
/>
|
|
298
|
+
<Button
|
|
299
|
+
style={{ flex:2, marginLeft:10, opacity: action_loading?0.5:1 }}
|
|
300
|
+
type='success'
|
|
301
|
+
loading={action_loading}
|
|
302
|
+
disabled={action_loading}
|
|
303
|
+
title='SET MARKET'
|
|
304
|
+
onPress={() => setDraftOrders(orders)}
|
|
305
|
+
/>
|
|
306
|
+
</View>
|
|
307
|
+
)
|
|
308
|
+
case 'trade_side':
|
|
309
|
+
if(draft_orders.length > 0){ return <></> }
|
|
310
|
+
if(!market){ return <></> }
|
|
311
|
+
let trade_side_option = market.side_options.find(so => so.side == market.trade_side);
|
|
312
|
+
if(!trade_side_option){ return <></> }
|
|
313
|
+
const trade_side_order = orders.find(o => o.side == market.trade_side);
|
|
314
|
+
if(!trade_side_order){ return <></> }
|
|
315
|
+
const trade_side_price = prices.find(p => p.side == market.trade_side);
|
|
316
|
+
const trade_side_no_vig_odds = no_vig_data?.trade_side_odds
|
|
317
|
+
const t_best_available = best_available_orders.find(o => o.market_id == market_id && o.side == market.trade_side)
|
|
318
|
+
return (
|
|
319
|
+
<View style={{ borderWidth:1, borderColor:Colors.borders.light, margin:10 }}>
|
|
320
|
+
<View type='row' style={{ padding:10 }}>
|
|
321
|
+
<View transparent style={{ flex:1 }}>
|
|
322
|
+
<Text theme='h2'>{trade_side_order.title}</Text>
|
|
323
|
+
<Text theme='description' style={{ marginTop:3 }}>${trade_side_order.open_amt.toFixed(2)} to win ${trade_side_order.potential_winnings.toFixed(2)}</Text>
|
|
324
|
+
</View>
|
|
325
|
+
<Text theme='h1'>${trade_side_order.open_amt.toFixed(2)}</Text>
|
|
326
|
+
<View type='row' style={{ marginLeft:10 }}>
|
|
327
|
+
<Button float onPress={() => handleUpdateMargin('trade', 'increase')}>
|
|
328
|
+
<Icons.ChevronIcon direction='left' size={8} color={Colors.text.h1} />
|
|
329
|
+
</Button>
|
|
330
|
+
<View style={{ paddingLeft:10, paddingRight:10 }}>
|
|
331
|
+
<Text theme='h1'>{(trade_side_order.probability * 100).toFixed(2)}%</Text>
|
|
332
|
+
<Text theme='light' style={{ marginTop:3 }} textAlign='center'>{MarketComponentHelpers.getOddsLabel(trade_side_order.odds)}</Text>
|
|
333
|
+
</View>
|
|
334
|
+
<Button float onPress={() => handleUpdateMargin('trade', 'decrease')}>
|
|
335
|
+
<Icons.ChevronIcon direction='right' size={8} color={Colors.text.h1} />
|
|
336
|
+
</Button>
|
|
337
|
+
</View>
|
|
338
|
+
</View>
|
|
339
|
+
{t_best_available ?
|
|
340
|
+
<View type='row' style={{ padding:10 }}>
|
|
341
|
+
<View transparent style={{flex:1}}>
|
|
342
|
+
<Text theme='h1'>{t_best_available.title}</Text>
|
|
343
|
+
{t_best_available.grade ?
|
|
344
|
+
<OrderGradeBar style={{ alignSelf:'flex-start', marginTop:3 }} grade={t_best_available.grade} view_type='card' onSelectGrade={() => console.log('')}/>
|
|
345
|
+
:<></>}
|
|
346
|
+
</View>
|
|
347
|
+
<View style={{ alignItems:'flex-end' }}>
|
|
348
|
+
<Text theme='h2'>{MarketComponentHelpers.getOddsLabel(t_best_available.odds)}</Text>
|
|
349
|
+
<Text theme='success'>${t_best_available.open_amt.toFixed(2)} Available</Text>
|
|
350
|
+
</View>
|
|
351
|
+
<Button
|
|
352
|
+
title='BUY'
|
|
353
|
+
type='success'
|
|
354
|
+
style={{ padding:10, marginLeft:10, opacity: action_loading ? 0.5:1 }}
|
|
355
|
+
disabled={action_loading}
|
|
356
|
+
onPress={() => {
|
|
357
|
+
let side_ids = MarketComponentHelpers.getSideIds(contest_type, trade_side_option, market, event, tournament, match, undefined, undefined);
|
|
358
|
+
if(!side_ids){ return }
|
|
359
|
+
let trade = MarketMaketHelpers.getTradeFromAvailableOrder(t_best_available, side_ids.reversed_side_id);
|
|
360
|
+
let order = MarketMaketHelpers.getOrderFromTrade(trade, unit_size ?? 10, t_best_available.order_id);
|
|
361
|
+
order.title = t_best_available.title
|
|
362
|
+
setDraftOrders([order])
|
|
363
|
+
}}
|
|
364
|
+
/>
|
|
365
|
+
</View>
|
|
366
|
+
:<></>}
|
|
367
|
+
{trade_side_price && trade_side_no_vig_odds ?
|
|
368
|
+
<View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
|
|
369
|
+
<View transparent style={{ flex:1 }}>
|
|
370
|
+
<Text theme='h1'>{trade_side_price.external_name}</Text>
|
|
371
|
+
<Text theme='light' style={{ marginTop:3 }}>External price with vig removed</Text>
|
|
372
|
+
</View>
|
|
373
|
+
<Text theme='h2'>{MarketComponentHelpers.getOddsLabel(trade_side_no_vig_odds)}</Text>
|
|
374
|
+
</View>
|
|
375
|
+
:<></>}
|
|
376
|
+
</View>
|
|
377
|
+
)
|
|
378
|
+
case 'draft_orders':
|
|
379
|
+
if(draft_orders.length == 0){ return <></> }
|
|
380
|
+
return (
|
|
381
|
+
<View style={{ flexDirection:'row', flexWrap:'wrap' }}>
|
|
382
|
+
{draft_orders.map((o,i) => {
|
|
383
|
+
return renderOrders({ item: o, index:i })
|
|
384
|
+
})}
|
|
385
|
+
</View>
|
|
386
|
+
)
|
|
387
|
+
case 'what_if':return <></>
|
|
388
|
+
default: return <></>
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const total_margin = o_side_margin + trade_side_margin
|
|
393
|
+
return (
|
|
394
|
+
<View float={float} style={{ ...style }}>
|
|
395
|
+
<View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopLeftRadius:8, borderTopRightRadius:8 }}>
|
|
396
|
+
<View transparent style={{ flex:1 }}>
|
|
397
|
+
<Text theme='h1'>{contest_title}</Text>
|
|
398
|
+
</View>
|
|
399
|
+
<View transparent style={{ justifyContent:'center', alignItems:'center' }}>
|
|
400
|
+
<Text theme='h2' color={total_margin > 0.06 ? Colors.text.error : total_margin > 0.045 ? Colors.text.warning : Colors.text.success}>{(total_margin*100).toFixed(2)}%</Text>
|
|
401
|
+
<Text theme='description' textAlign='center'>Margin</Text>
|
|
402
|
+
</View>
|
|
403
|
+
</View>
|
|
404
|
+
<View type='body' style={{ flex:1 }}>
|
|
405
|
+
{loading ?
|
|
406
|
+
<ActivityIndicator size='large' color={Colors.text.h1} />
|
|
407
|
+
:<></>}
|
|
408
|
+
<FlatList
|
|
409
|
+
key={'create_market_sections'}
|
|
410
|
+
keyExtractor={item => item}
|
|
411
|
+
renderItem={renderSections}
|
|
412
|
+
data={sections}
|
|
413
|
+
/>
|
|
414
|
+
</View>
|
|
415
|
+
{draft_orders.length == 0 ?
|
|
416
|
+
<View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
|
|
417
|
+
<Button
|
|
418
|
+
style={{ flex:1 }}
|
|
419
|
+
type='action'
|
|
420
|
+
title='CLOSE'
|
|
421
|
+
onPress={() => onCancel()}
|
|
422
|
+
/>
|
|
423
|
+
</View>
|
|
424
|
+
:
|
|
425
|
+
<View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
|
|
426
|
+
<Button
|
|
427
|
+
style={{ flex:1 }}
|
|
428
|
+
type='error'
|
|
429
|
+
title='CANCEL'
|
|
430
|
+
onPress={() => setDraftOrders([])}
|
|
431
|
+
/>
|
|
432
|
+
<Button
|
|
433
|
+
style={{ flex:2, marginLeft:5 }}
|
|
434
|
+
type='success'
|
|
435
|
+
title='SUBMIT ORDERS'
|
|
436
|
+
onPress={() => handleSubmitOrder()}
|
|
437
|
+
/>
|
|
438
|
+
</View>
|
|
439
|
+
}
|
|
440
|
+
</View>
|
|
441
|
+
)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export default CreateMarketForm
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View } from '../../Components/Themed';
|
|
3
|
+
import { useColors } from '../../constants/useColors';
|
|
4
|
+
import type { ViewStyle } from 'react-native';
|
|
5
|
+
|
|
6
|
+
type WeightProgressProps = {
|
|
7
|
+
min_value:number,
|
|
8
|
+
max_value:number,
|
|
9
|
+
style?:ViewStyle,
|
|
10
|
+
value: number,
|
|
11
|
+
bar_height?:number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const WeightProgress = ({ value, bar_height, style }:WeightProgressProps) => {
|
|
15
|
+
const Colors = useColors();
|
|
16
|
+
const [ width, setWidth ] = useState(0);
|
|
17
|
+
let progress_width = value * width / 2
|
|
18
|
+
let start_point = width/2
|
|
19
|
+
if(progress_width < 0){
|
|
20
|
+
start_point += progress_width
|
|
21
|
+
}
|
|
22
|
+
return (
|
|
23
|
+
<View style={{ borderRadius:2, height: bar_height ? bar_height + 2: 6, backgroundColor:Colors.borders.light, padding:1, justifyContent:'center', ...style }} onLayout={(ev) => {
|
|
24
|
+
const { width } = ev.nativeEvent.layout;
|
|
25
|
+
setWidth(width)
|
|
26
|
+
}}>
|
|
27
|
+
<View style={{ position:'absolute', top:1, bottom:1, left:start_point, width:Math.abs(progress_width), backgroundColor:Colors.text.h1, height:bar_height??4, borderRadius:4 }}/>
|
|
28
|
+
</View>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default WeightProgress
|
|
@@ -14,6 +14,7 @@ import MyOrderList from './components/MyOrderList';
|
|
|
14
14
|
import ExternalPriceComparison from './components/ExternalPriceComparison';
|
|
15
15
|
import OrderGradeBar from './components/OrderGradeBar';
|
|
16
16
|
import MarketManager from './components/MarketManager';
|
|
17
|
+
import CreateMarketForm from './components/CreateMarketForm';
|
|
17
18
|
|
|
18
19
|
export default {
|
|
19
20
|
TeamEventMarket,
|
|
@@ -22,6 +23,7 @@ export default {
|
|
|
22
23
|
BestAvailableOrderCard,
|
|
23
24
|
EventMarket,
|
|
24
25
|
OrderBookCard,
|
|
26
|
+
CreateMarketForm,
|
|
25
27
|
MarketManager,
|
|
26
28
|
OrderBookChart,
|
|
27
29
|
AthleteTournamentMarket,
|
|
@@ -936,7 +936,8 @@ const MarketMaketHelpers = {
|
|
|
936
936
|
}
|
|
937
937
|
return cash
|
|
938
938
|
},
|
|
939
|
-
getNoVigPrice: (prices:ExternalPriceProps[], market
|
|
939
|
+
getNoVigPrice: (prices:ExternalPriceProps[], market?:MarketProps) => {
|
|
940
|
+
if(!market){ return undefined }
|
|
940
941
|
if(!prices || prices.length != 2){ return undefined }
|
|
941
942
|
let external_name = prices[0]?.external_name
|
|
942
943
|
if(!external_name){ return undefined }
|
|
@@ -199,6 +199,7 @@ const PollCard = ({ poll_id, height, width, view_mode, poll_response, action_loa
|
|
|
199
199
|
)
|
|
200
200
|
case 'correct_select':
|
|
201
201
|
if(!poll || poll.poll_type != 'select' || !correct_option){ return <></> }
|
|
202
|
+
if(poll.status != 'closed' && correct_option && !poll_response){ return <></> }
|
|
202
203
|
return (
|
|
203
204
|
<View nativeID='selected_option' style={{ marginBottom:10, padding:10 }}>
|
|
204
205
|
<Text style={{ marginBottom:5 }} size={14} theme='description' weight='semibold'>CORRECT ANSWER</Text>
|