Skip to content

Commit cf7d75f

Browse files
committed
update
1 parent 6c95e74 commit cf7d75f

File tree

8 files changed

+179
-40
lines changed

8 files changed

+179
-40
lines changed

docs/screenshot.png

109 KB
Loading

public/manifest.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
"default_popup": "index.html",
1313
"default_title": "Bybit Risk:Reward Calculator"
1414
},
15-
"permissions": [
16-
"activeTab"
17-
],
15+
"permissions": ["activeTab", "storage"],
1816
"content_scripts": [
1917
{
2018
"matches": ["https://*.bybit.com/*"],

src/App.tsx

+130-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useEffect, useState } from "react";
2+
import { SaveIcon } from "./components/SaveIcon";
23
import { Input } from "./components/Input";
34
import { Toggle } from "./components/Toggle";
45
import {
@@ -8,6 +9,12 @@ import {
89
MessageResponse,
910
} from "./types";
1011

12+
enum PersistableSetting {
13+
MARGIN,
14+
STOPLOSS,
15+
RISK,
16+
}
17+
1118
// 5% (stoploss) von margin 20€ sind 1€. 1€ sind 10% vom risk 10€. also brauche ich 10x leverage um auf 10€ risk zu kommen.
1219

1320
function App() {
@@ -23,24 +30,31 @@ function App() {
2330
const [leverage, setLeverage] = useState(1);
2431
const [marketPrice, setMarketPrice] = useState(0);
2532
const [tradeType, setTradeType] = useState<TradeType>(TradeType.LONG);
33+
const [marginStored, setMarginStored] = useState(true);
34+
const [stoplossStored, setStoplossStored] = useState(true);
35+
const [riskStored, setRiskStored] = useState(true);
2636

2737
useEffect(() => {
2838
if (stoplossRelative) {
39+
console.log("OVERWRITE STOPLOSS");
2940
setStoplossAbsolute(marketPrice - (marketPrice * stoplossRelative) / 100);
3041
}
31-
}, [marketPrice, stoplossRelative, setStoplossAbsolute]);
42+
// eslint-disable-next-line react-hooks/exhaustive-deps
43+
}, [marketPrice]);
3244

3345
useEffect(() => {
3446
if (marginRelative) {
3547
setMarginAbsolute((equity * marginRelative) / 100);
3648
}
37-
}, [equity, marginRelative, setMarginAbsolute]);
49+
// eslint-disable-next-line react-hooks/exhaustive-deps
50+
}, [equity]);
3851

3952
useEffect(() => {
4053
if (riskRelative) {
4154
setRiskAbsolute((equity * riskRelative) / 100);
4255
}
43-
}, [equity, riskRelative, setRiskAbsolute]);
56+
// eslint-disable-next-line react-hooks/exhaustive-deps
57+
}, [equity]);
4458

4559
useEffect(() => {
4660
setLeverage(
@@ -71,8 +85,21 @@ function App() {
7185
setEquity(response.equity.val);
7286
setUnit(response.equity.unit);
7387
setMarketPrice(response.marketPrice.val);
74-
setStoplossAbsolute(response.stoploss.val);
7588
setTradeType(response.tradeType ?? TradeType.LONG);
89+
90+
// market price is changed and useEffect then overwrites stoploss and margin
91+
setTimeout(() => {
92+
if (response.stoploss.val) {
93+
console.log("INITIAL SET STOPLOSS");
94+
setStoplossAbsolute(response.stoploss.val);
95+
// TODO relative stoploss
96+
}
97+
98+
if (response.margin.val) {
99+
setMarginAbsolute(response.margin.val);
100+
// TODO relative margin
101+
}
102+
}, 0);
76103
}
77104
);
78105
}
@@ -108,6 +135,43 @@ function App() {
108135
}
109136
}, [tabID, tradeType]);
110137

138+
const storeSetting = (setting: PersistableSetting, value: any) => {
139+
chrome.storage.sync.set({ [String(setting)]: value }, function () {
140+
console.log("Value is set to " + value);
141+
chrome.storage.sync.get(String(setting), function (result) {
142+
console.log("result", result);
143+
value = result[String(setting)];
144+
});
145+
});
146+
};
147+
148+
const getSetting = (setting: PersistableSetting): Promise<any> => {
149+
return new Promise((resolve) => {
150+
chrome.storage.sync.get(String(setting), function (result) {
151+
resolve(result[String(setting)]);
152+
});
153+
});
154+
};
155+
156+
useEffect(() => {
157+
(async () => {
158+
const margin = await getSetting(PersistableSetting.MARGIN);
159+
if (margin) {
160+
setMarginRelative(margin);
161+
}
162+
163+
const stoploss = await getSetting(PersistableSetting.STOPLOSS);
164+
if (stoploss) {
165+
setStoplossRelative(stoploss);
166+
}
167+
168+
const risk = await getSetting(PersistableSetting.RISK);
169+
if (risk) {
170+
setRiskRelative(risk);
171+
}
172+
})();
173+
}, []);
174+
111175
return (
112176
<div className="flex flex-col h-full p-8">
113177
<div>
@@ -146,7 +210,7 @@ function App() {
146210
className="mb-4"
147211
showLabel
148212
/>
149-
<fieldset>
213+
<fieldset className="my-4">
150214
<legend>Stoploss</legend>
151215
<Input
152216
label="Stoploss Absolute"
@@ -157,9 +221,10 @@ function App() {
157221
onChange={(e) => {
158222
setStoplossRelative((100 * Number(e.target.value)) / marketPrice);
159223
setStoplossAbsolute(Number(e.target.value));
224+
setStoplossStored(false);
160225
}}
161226
value={stoplossAbsolute}
162-
className="mb-4"
227+
className="mb-2"
163228
/>
164229
<Input
165230
label="Stoploss Relative"
@@ -171,13 +236,25 @@ function App() {
171236
marketPrice - (marketPrice * Number(e.target.value)) / 100
172237
);
173238
setStoplossRelative(Number(e.target.value));
239+
setStoplossStored(false);
174240
}}
241+
append={
242+
!stoplossStored && (
243+
<SaveIcon
244+
className="w-6 h-6 cursor-pointer"
245+
onClick={() => {
246+
storeSetting(PersistableSetting.STOPLOSS, stoplossRelative);
247+
setStoplossStored(true);
248+
}}
249+
/>
250+
)
251+
}
175252
value={stoplossRelative.toFixed(2)}
176-
className="mb-4"
253+
className="mb-2"
177254
step={0.1}
178255
/>
179256
</fieldset>
180-
<fieldset>
257+
<fieldset className="my-4">
181258
<legend>Margin</legend>
182259
<Input
183260
label="Margin Absolute"
@@ -189,9 +266,10 @@ function App() {
189266
onChange={(e) => {
190267
setMarginRelative((100 * Number(e.target.value)) / equity);
191268
setMarginAbsolute(Number(e.target.value));
269+
setMarginStored(false);
192270
}}
193271
step={0.1}
194-
className="mb-4"
272+
className="mb-2"
195273
/>
196274
<Input
197275
label="Margin Relative"
@@ -202,12 +280,24 @@ function App() {
202280
onChange={(e) => {
203281
setMarginRelative(Number(e.target.value));
204282
setMarginAbsolute((equity * Number(e.target.value)) / 100);
283+
setMarginStored(false);
205284
}}
206285
step={0.1}
207-
className="mb-4"
286+
append={
287+
!marginStored && (
288+
<SaveIcon
289+
className="w-6 h-6 cursor-pointer"
290+
onClick={() => {
291+
storeSetting(PersistableSetting.MARGIN, marginRelative);
292+
setMarginStored(true);
293+
}}
294+
/>
295+
)
296+
}
297+
className="mb-2"
208298
/>
209299
</fieldset>
210-
<fieldset>
300+
<fieldset className="my-4">
211301
<legend>Risk</legend>
212302
<Input
213303
label="Risk Absolute"
@@ -218,10 +308,11 @@ function App() {
218308
onChange={(e) => {
219309
setRiskRelative((100 * Number(e.target.value)) / equity);
220310
setRiskAbsolute(Number(e.target.value));
311+
setRiskStored(false);
221312
}}
222313
prepend="$"
223314
append={unit}
224-
className="mb-4"
315+
className="mb-2"
225316
/>
226317
<Input
227318
label="Risk Relative"
@@ -232,9 +323,21 @@ function App() {
232323
onChange={(e) => {
233324
setRiskRelative(Number(e.target.value));
234325
setRiskAbsolute((equity * Number(e.target.value)) / 100);
326+
setRiskStored(false);
235327
}}
236328
prepend="%"
237-
className="mb-4"
329+
append={
330+
!riskStored && (
331+
<SaveIcon
332+
className="w-6 h-6 cursor-pointer"
333+
onClick={() => {
334+
storeSetting(PersistableSetting.RISK, riskRelative);
335+
setRiskStored(true);
336+
}}
337+
/>
338+
)
339+
}
340+
className="mb-2"
238341
/>
239342
</fieldset>
240343
<Input
@@ -267,8 +370,22 @@ function App() {
267370
>
268371
Marc Mintel
269372
</a>
373+
. Available open source on{" "}
374+
<a
375+
href="https://github.com/mmintel/chrome-bybit-extension"
376+
target="_blank"
377+
rel="noreferrer"
378+
className="underline"
379+
>
380+
Github
381+
</a>
270382
.
271383
</p>
384+
<p className="py-4 mt-auto text-xs text-center text-gray-500">
385+
<a className="underline" href="#">
386+
Buy me a coffe if you like this.
387+
</a>
388+
</p>
272389
</div>
273390
);
274391
}

src/components/Input.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import clsx from "clsx";
2-
import { InputHTMLAttributes } from "react";
2+
import { InputHTMLAttributes, ReactNode } from "react";
33

44
export const Input: React.FC<
55
{
@@ -8,8 +8,8 @@ export const Input: React.FC<
88
type?: string;
99
placeholder?: string;
1010
helptext?: string;
11-
prepend?: string;
12-
append?: string;
11+
prepend?: ReactNode;
12+
append?: ReactNode;
1313
showLabel?: boolean;
1414
} & InputHTMLAttributes<HTMLInputElement>
1515
> = ({
@@ -29,18 +29,18 @@ export const Input: React.FC<
2929
</label>
3030
<div className="relative mt-1 rounded-md shadow-sm">
3131
{prepend && (
32-
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
32+
<div className="absolute inset-y-0 left-0 flex items-center pl-3 select-none">
3333
<span className="text-gray-500 sm:text-sm">{prepend}</span>
3434
</div>
3535
)}
3636
<input
3737
name={id}
3838
id={id}
39-
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm pl-7 pr-12 disabled:cursor-not-allowed disabled:border-gray-200 disabled:bg-gray-50 disabled:text-gray-500"
39+
className="block w-full pr-12 border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm pl-7 disabled:cursor-not-allowed disabled:border-gray-200 disabled:bg-gray-50 disabled:text-gray-500"
4040
{...props}
4141
/>
4242
{append && (
43-
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
43+
<div className="absolute inset-y-0 right-0 flex items-center pr-3 select-none">
4444
<span className="text-gray-500 sm:text-sm" id="price-currency">
4545
{append}
4646
</span>

src/components/SaveIcon.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { HTMLAttributes } from "react";
2+
3+
export const SaveIcon: React.FC<HTMLAttributes<HTMLOrSVGElement>> = (props) => {
4+
return (
5+
<svg viewBox="0 0 24 24" {...props}>
6+
<path
7+
fill="currentColor"
8+
d="M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z"
9+
/>
10+
</svg>
11+
);
12+
};

src/content.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ const messagesFromReactAppListener = (msg: MessageRequest, sender: chrome.runtim
1515
const stoploss = parseVal(String(stoplossContent));
1616
const long = $('.by-checkbox--long').hasClass('by-checkbox--checked');
1717
const short = $('.by-checkbox--short').hasClass('by-checkbox--checked');
18-
19-
console.log('long or short', long, short)
20-
18+
const marginContent = $('.by-popover__el:contains("Order by")').closest('.oc__row-bottom--12').find('.by-input__inner').val()
19+
const margin = parseVal(String(marginContent));
20+
21+
console.log(marginContent, margin)
22+
2123
const response: MessageResponse[MessageType.GET_DOM] = {
2224
equity,
2325
marketPrice,
2426
stoploss,
27+
margin,
2528
tradeType: long ? TradeType.LONG : short ? TradeType.SHORT : null,
2629
};
2730

src/types.ts

+9-12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ export enum MessageType {
44
SET_STOPLOSS = 'SET_STOPLOSS'
55
}
66

7+
export type ValueUnit = {
8+
val: number;
9+
unit: string;
10+
}
11+
712
type GetDOMMessageRequest = {
813
type: MessageType.GET_DOM,
914
}
@@ -38,18 +43,10 @@ export interface MessagePayload extends Record<MessageType, Record<string, any>>
3843

3944
export interface MessageResponse extends Record<MessageType, Record<string, any>> {
4045
[MessageType.GET_DOM]: {
41-
equity: {
42-
val: number,
43-
unit: string,
44-
};
45-
marketPrice: {
46-
val: number,
47-
unit: string,
48-
}
49-
stoploss: {
50-
val: number,
51-
unit: string,
52-
},
46+
equity: ValueUnit;
47+
marketPrice: ValueUnit
48+
stoploss: ValueUnit,
49+
margin: ValueUnit,
5350
tradeType: TradeType | null
5451
},
5552
[MessageType.SET_TRADE_TYPE]: {

0 commit comments

Comments
 (0)