diff --git a/src/components/modal/components/Chat/components/EscalateModal/steps/EscalateStepTwo.tsx b/src/components/modal/components/Chat/components/EscalateModal/steps/EscalateStepTwo.tsx
index 8359162ef..8fa1b2815 100644
--- a/src/components/modal/components/Chat/components/EscalateModal/steps/EscalateStepTwo.tsx
+++ b/src/components/modal/components/Chat/components/EscalateModal/steps/EscalateStepTwo.tsx
@@ -511,9 +511,9 @@ function EscalateStepTwo({
values?.disputeId || "",
[FormModel.formFields.buyerAddress.name]:
values?.buyerAddress ? values?.buyerAddress : "",
- [`Unsigned message: ${FormModel.formFields.message.name}`]:
+ [`Signed message: ${FormModel.formFields.message.name}`]:
values?.message
- ? `Unsigned message: ${values?.message}`
+ ? `Signed message: ${values?.message}`
: "",
[FormModel.formFields.signature.name]:
values?.signature || ""
@@ -524,7 +524,7 @@ function EscalateStepTwo({
diff --git a/src/lib/utils/dispute.ts b/src/lib/utils/dispute.ts
new file mode 100644
index 000000000..30647e214
--- /dev/null
+++ b/src/lib/utils/dispute.ts
@@ -0,0 +1,18 @@
+import { subgraph } from "@bosonprotocol/react-kit";
+
+import { getDateTimestamp } from "./getDateTimestamp";
+
+export const getDisputeDates = (
+ dispute: subgraph.DisputeFieldsFragment | undefined
+) => {
+ const endOfResolutionPeriod = dispute?.timeout
+ ? getDateTimestamp(dispute?.timeout)
+ : undefined;
+ const finishedResolutionPeriod = endOfResolutionPeriod
+ ? Date.now() > endOfResolutionPeriod
+ : false;
+ return {
+ endOfResolutionPeriod,
+ finishedResolutionPeriod
+ };
+};
diff --git a/src/lib/utils/exchange.ts b/src/lib/utils/exchange.ts
index 521d9c826..89b3c7d51 100644
--- a/src/lib/utils/exchange.ts
+++ b/src/lib/utils/exchange.ts
@@ -39,12 +39,28 @@ export const getHasExchangeDisputeResolutionElapsed = (
return false;
}
return (
- Number(exchange.redeemedDate) * 1000 +
- Number(offer.disputePeriodDuration) * 1000 <
+ getDateTimestamp(exchange.redeemedDate) +
+ getDateTimestamp(offer.disputePeriodDuration) <
Date.now()
);
};
+export const getHasExchangeEscalationPeriodElapsed = (
+ escalationResponsePeriod: string | undefined | null,
+ escalatedDate: string | undefined | null
+): boolean => {
+ if (!escalationResponsePeriod || !escalatedDate) {
+ return false;
+ }
+ const fixedEscalatedDate = getDateTimestamp(escalatedDate);
+ const escalationPeriodSecondsNumber = Number(escalationResponsePeriod);
+ if (!fixedEscalatedDate || isNaN(escalationPeriodSecondsNumber)) {
+ return false;
+ }
+ const escalationPeriodInMs = escalationPeriodSecondsNumber * 1000;
+ return fixedEscalatedDate + escalationPeriodInMs < Date.now();
+};
+
const PROTOCOL_DEPLOYMENT_TIMES = {
v221: {
local: 0,
@@ -69,10 +85,10 @@ export const getExchangeTokenId = (
};
export const getExchangeDisputeDates = (exchange: Exchange) => {
- const raisedDisputeAt = new Date(Number(exchange.disputedDate) * 1000);
+ const raisedDisputeAt = new Date(getDateTimestamp(exchange.disputedDate));
const lastDayToResolveDispute = new Date(
raisedDisputeAt.getTime() +
- Number(exchange.offer.resolutionPeriodDuration) * 1000
+ getDateTimestamp(exchange.offer.resolutionPeriodDuration)
);
const totalDaysToResolveDispute = dayjs(lastDayToResolveDispute).diff(
raisedDisputeAt,
diff --git a/src/lib/utils/getDateTimestamp.ts b/src/lib/utils/getDateTimestamp.ts
index 3f2c2db65..f64587144 100644
--- a/src/lib/utils/getDateTimestamp.ts
+++ b/src/lib/utils/getDateTimestamp.ts
@@ -1,4 +1,4 @@
-export const getDateTimestamp = (date: string) => {
+export const getDateTimestamp = (date: string | undefined | null): number => {
const number = Number(date);
return !isNaN(number) ? number * 1000 : 0;
diff --git a/src/lib/utils/hooks/useDisputeResolver.ts b/src/lib/utils/hooks/useDisputeResolver.ts
index 083190a56..0931c5e63 100644
--- a/src/lib/utils/hooks/useDisputeResolver.ts
+++ b/src/lib/utils/hooks/useDisputeResolver.ts
@@ -28,12 +28,15 @@ interface Props {
};
}
-export function useDisputeResolver(id: string) {
+export function useDisputeResolver(id: string | undefined | null) {
const { config } = useConfigContext();
const { subgraphUrl } = config.envConfig;
const props = { id };
const result = useQuery(["disputeResolver", props, subgraphUrl], async () => {
+ if (!id) {
+ return;
+ }
const result = await fetchSubgraph(
subgraphUrl,
gql`
diff --git a/src/pages/chat/components/ExchangeSidePreview.tsx b/src/pages/chat/components/ExchangeSidePreview.tsx
index 1d8e06cb5..d4ad5f219 100644
--- a/src/pages/chat/components/ExchangeSidePreview.tsx
+++ b/src/pages/chat/components/ExchangeSidePreview.tsx
@@ -7,6 +7,8 @@ import {
buyerAndSellerAgreementIncluding,
customisedExchangePolicy
} from "lib/constants/policies";
+import { getDisputeDates } from "lib/utils/dispute";
+import { useDisputeResolver } from "lib/utils/hooks/useDisputeResolver";
import { getExchangePolicyName } from "lib/utils/policy/getExchangePolicyName";
import { ArrowSquareOut } from "phosphor-react";
import {
@@ -44,6 +46,7 @@ import { calcPercentage } from "../../../lib/utils/calcPrice";
import {
getExchangeDisputeDates,
getHasExchangeDisputeResolutionElapsed,
+ getHasExchangeEscalationPeriodElapsed,
isExchangeCompletableByBuyer,
isExchangeCompletableBySeller
} from "../../../lib/utils/exchange";
@@ -377,7 +380,15 @@ export default memo(function ExchangeSidePreview({
},
{ enabled: !!exchange }
);
+ const { disputeResolver } = useDisputeResolver(
+ exchange?.offer.disputeResolverId
+ );
+
const dispute = disputes?.[0];
+ const isElapsedEscalation = getHasExchangeEscalationPeriodElapsed(
+ disputeResolver?.escalationResponsePeriod,
+ dispute?.escalatedDate
+ );
const offer = exchange?.offer;
const { showModal, modalTypes } = useModal();
const OFFER_DETAIL_DATA = useMemo(
@@ -438,6 +449,7 @@ export default memo(function ExchangeSidePreview({
const isEscalated = !!dispute?.escalatedDate;
const isRetracted = !!dispute?.retractedDate;
const isFinalized = !!dispute?.finalizedDate;
+ const { finishedResolutionPeriod } = getDisputeDates(dispute);
const { totalDaysToResolveDispute, daysLeftToResolveDispute } =
getExchangeDisputeDates(exchange);
@@ -521,7 +533,7 @@ export default memo(function ExchangeSidePreview({
- {isInDispute && iAmTheBuyer && !isEscalated && !isRetracted ? (
+ {isInDispute && iAmTheBuyer && !isRetracted && !isElapsedEscalation ? (
-
+ {!finishedResolutionPeriod && !isEscalated && (
+
+ )}
{CompleteExchangeButton}
) : isInRedeemed && iAmTheBuyer ? (