diff --git a/src/components/TradingComponents/Chart/Chart.tsx b/src/components/TradingComponents/Chart/Chart.tsx
index 0019f4f..e448523 100644
--- a/src/components/TradingComponents/Chart/Chart.tsx
+++ b/src/components/TradingComponents/Chart/Chart.tsx
@@ -20,7 +20,6 @@ export const Chart = observer(() => {
} = chartStore;
const derivAPI = getDerivAPI();
const [isConnected, setIsConnected] = useState(derivAPI.isConnected());
-
// Initialize chart store
useEffect(() => {
setSymbol("1HZ10V");
diff --git a/src/components/TradingComponents/DurationSection/DurationSection.tsx b/src/components/TradingComponents/DurationSection/DurationSection.tsx
index 47539ee..efa7946 100644
--- a/src/components/TradingComponents/DurationSection/DurationSection.tsx
+++ b/src/components/TradingComponents/DurationSection/DurationSection.tsx
@@ -56,7 +56,7 @@ export const DurationSection = ({
message={durationError}
/>
- Range: 1 - 1,440 minutes
+ Range: 15 - 1,440 minutes
) : (
diff --git a/src/components/TradingComponents/TradingPanel/TradingPanel.scss b/src/components/TradingComponents/TradingPanel/TradingPanel.scss
index 75bd3f5..e7e7877 100644
--- a/src/components/TradingComponents/TradingPanel/TradingPanel.scss
+++ b/src/components/TradingComponents/TradingPanel/TradingPanel.scss
@@ -81,8 +81,13 @@
.equals-section {
display: flex;
align-items: center;
- gap: 8px;
- padding: 12px 0;
+ gap: 0.5rem;
+ margin-bottom: 1rem;
+ }
+
+ .error-message {
+ margin: 1rem;
+ text-align: center;
}
.payout-section {
diff --git a/src/components/TradingComponents/TradingPanel/TradingPanel.tsx b/src/components/TradingComponents/TradingPanel/TradingPanel.tsx
index 4a91a72..0667334 100644
--- a/src/components/TradingComponents/TradingPanel/TradingPanel.tsx
+++ b/src/components/TradingComponents/TradingPanel/TradingPanel.tsx
@@ -1,14 +1,13 @@
-import { Button, Text, Tooltip, Checkbox } from "@deriv-com/quill-ui";
+import { Button, Text } from "@deriv-com/quill-ui";
import {
LabelPairedBackwardSmBoldIcon,
TradeTypesUpsAndDownsRiseIcon,
TradeTypesUpsAndDownsFallIcon,
- LabelPairedCircleInfoSmBoldIcon,
} from "@deriv/quill-icons";
import { observer } from "mobx-react-lite";
import { tradingPanelStore } from "../../../stores/TradingPanelStore";
import { chartStore } from "../../../stores/ChartStore";
-import { usePriceProposal } from "../../../hooks/usePriceProposal";
+import { useRiseFallTrading } from "../../../hooks/useRiseFallTrading";
import { DurationSection } from "../DurationSection/DurationSection";
import { StakeSection } from "../StakeSection/StakeSection";
import { TradeButton } from "../TradeButton/TradeButton";
@@ -29,15 +28,17 @@ export const TradingPanel = observer(() => {
setSelectedStakeTab,
durationError,
priceError,
+ is_rise_fall_valid,
} = tradingPanelStore;
- const { proposal, clearProposal, isLoading } = usePriceProposal(
+ const { proposal, clearProposal, isLoading } = useRiseFallTrading(
+ chartStore.symbol,
price,
duration,
selectedStakeTab,
- chartStore.symbol,
durationError,
- priceError
+ priceError,
+ is_rise_fall_valid
);
const getAmount = (type: "rise" | "fall"): string => {
@@ -88,54 +89,66 @@ export const TradingPanel = observer(() => {
-
-
-
-
+ {!is_rise_fall_valid ? (
+
+
+ This contract type is not valid for Rise/Fall
+
+
+ ) : (
+ <>
+
+
+
+
-
-
- setAllowEquals((e.target as HTMLInputElement).checked)
- }
- label="Allow equals"
- />
-
-
-
-
+ {/* Equals section temporarily hidden
+
+
+ setAllowEquals((e.target as HTMLInputElement).checked)
+ }
+ label="Allow equals"
+ />
+
+
+
+
+ */}
-
+ >
+ )}
);
});
diff --git a/src/hooks/useContractsFor.ts b/src/hooks/useContractsFor.ts
new file mode 100644
index 0000000..27e9a04
--- /dev/null
+++ b/src/hooks/useContractsFor.ts
@@ -0,0 +1,32 @@
+import { useEffect } from "react";
+import { getDerivAPI } from "../services/deriv-api.instance";
+import { tradingPanelStore } from "../stores/TradingPanelStore";
+
+export const useContractsFor = (symbol: string) => {
+ const derivAPI = getDerivAPI();
+
+ useEffect(() => {
+ const checkContractsAvailability = async () => {
+ if (!symbol) return;
+
+ try {
+ const contractsResponse = await derivAPI.getContractsForSymbol(symbol);
+
+ const hasRiseFallContracts =
+ contractsResponse.contracts_for.available.some(
+ (contract) =>
+ contract.contract_category === "callput" &&
+ contract.barriers === 0 &&
+ contract.barrier_category === "euro_atm"
+ );
+
+ tradingPanelStore.setIsRiseFallValid(hasRiseFallContracts);
+ } catch (error) {
+ console.error("Error fetching contracts:", error);
+ tradingPanelStore.setIsRiseFallValid(false);
+ }
+ };
+
+ checkContractsAvailability();
+ }, [symbol, derivAPI]);
+};
diff --git a/src/hooks/usePriceProposal.ts b/src/hooks/usePriceProposal.ts
index f8d4249..3315c17 100644
--- a/src/hooks/usePriceProposal.ts
+++ b/src/hooks/usePriceProposal.ts
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
import { getDerivAPI } from "../services/deriv-api.instance";
import { PriceProposalResponse } from "../types/deriv-api.types";
import useDebounce from "./useDebounce";
+import { tradingPanelStore } from "../stores/TradingPanelStore";
interface ProposalState {
rise?: PriceProposalResponse["proposal"];
@@ -18,8 +19,9 @@ export const usePriceProposal = (
duration: number,
basis: string,
symbol: string,
- durationError: string,
- priceError: string
+ durationError: string | null,
+ priceError: string | null,
+ is_rise_fall_valid: boolean
) => {
const [proposal, setProposal] = useState({});
const [isLoading, setIsLoading] = useState({
@@ -71,15 +73,22 @@ export const usePriceProposal = (
setIsLoading((prev) => ({ ...prev, [type]: false }));
if (response.error) {
console.error(`${type} proposal error:`, response.error);
+ tradingPanelStore.priceError =
+ response.error.message || "Invalid contract parameters";
} else if (response.proposal) {
setProposal((prev) => ({ ...prev, [type]: response.proposal }));
}
},
`PROPOSAL_${type.toUpperCase()}`
);
- } catch (err) {
+ } catch (err: any) {
console.error(`${type} subscription error:`, err);
setIsLoading((prev) => ({ ...prev, [type]: false }));
+
+ if (err.code === "ContractBuyValidationError") {
+ tradingPanelStore.priceError =
+ err.message || "Invalid contract parameters";
+ }
}
};
@@ -91,18 +100,25 @@ export const usePriceProposal = (
setProposal({});
setIsLoading({ rise: false, fall: false });
-
if (
debouncedPrice &&
duration &&
basis &&
symbol &&
!durationError &&
- !priceError
+ !priceError &&
+ is_rise_fall_valid
) {
handleProposal();
}
- }, [debouncedPrice, debouncedDuration, basis, symbol, derivAPI]);
+ }, [
+ debouncedPrice,
+ debouncedDuration,
+ basis,
+ symbol,
+ derivAPI,
+ is_rise_fall_valid,
+ ]);
return { proposal, clearProposal, isLoading };
};
diff --git a/src/hooks/useRiseFallTrading.ts b/src/hooks/useRiseFallTrading.ts
new file mode 100644
index 0000000..fb5e41b
--- /dev/null
+++ b/src/hooks/useRiseFallTrading.ts
@@ -0,0 +1,30 @@
+import { useContractsFor } from "./useContractsFor";
+import { usePriceProposal } from "./usePriceProposal";
+
+export const useRiseFallTrading = (
+ symbol: string,
+ price: string,
+ duration: number,
+ basis: string,
+ durationError: string | null,
+ priceError: string | null,
+ isRiseFallValid: boolean
+) => {
+ // Use both hooks internally
+ useContractsFor(symbol);
+ const { proposal, clearProposal, isLoading } = usePriceProposal(
+ price,
+ duration,
+ basis,
+ symbol,
+ durationError,
+ priceError,
+ isRiseFallValid
+ );
+
+ return {
+ proposal,
+ clearProposal,
+ isLoading,
+ };
+};
diff --git a/src/stores/ChartStore.ts b/src/stores/ChartStore.ts
index a646805..0d4d46b 100644
--- a/src/stores/ChartStore.ts
+++ b/src/stores/ChartStore.ts
@@ -1,4 +1,5 @@
import { makeAutoObservable } from "mobx";
+import { tradingPanelStore } from "./TradingPanelStore";
export class ChartStore {
symbol: string = "";
@@ -10,7 +11,10 @@ export class ChartStore {
}
setSymbol = (symbol: string) => {
+ tradingPanelStore.setIsRiseFallValid(false);
this.symbol = symbol;
+ tradingPanelStore.priceError = null;
+ tradingPanelStore.durationError = null;
};
setChartStatus = (status: boolean) => {
diff --git a/src/stores/TradingPanelStore.ts b/src/stores/TradingPanelStore.ts
index b1146d1..61e4bc2 100644
--- a/src/stores/TradingPanelStore.ts
+++ b/src/stores/TradingPanelStore.ts
@@ -1,13 +1,14 @@
import { makeAutoObservable } from "mobx";
export class TradingPanelStore {
- duration = 1;
+ duration = 15;
price = "10";
allowEquals = false;
selectedDurationTab: "duration" | "endtime" = "duration";
selectedStakeTab: "stake" | "payout" = "stake";
durationError: string | null = null;
priceError: string | null = null;
+ is_rise_fall_valid: boolean = true;
constructor() {
makeAutoObservable(this);
@@ -26,8 +27,8 @@ export class TradingPanelStore {
return;
}
- if (numValue <= 0) {
- this.durationError = "Duration must be greater than 0";
+ if (numValue < 15) {
+ this.durationError = "Minimum duration is 15 minutes";
return;
}
@@ -73,6 +74,10 @@ export class TradingPanelStore {
setSelectedStakeTab = (value: "stake" | "payout") => {
this.selectedStakeTab = value;
};
+
+ setIsRiseFallValid = (value: boolean) => {
+ this.is_rise_fall_valid = value;
+ };
}
export const tradingPanelStore = new TradingPanelStore();