mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-06-15 02:19:15 -04:00
166 lines
5.4 KiB
TypeScript
166 lines
5.4 KiB
TypeScript
import { Step, StepLabel, Stepper, Typography } from '@material-ui/core';
|
|
import { SwapSpawnType } from 'models/cliModel';
|
|
import { SwapStateName } from 'models/rpcModel';
|
|
import { useActiveSwapInfo, useAppSelector } from 'store/hooks';
|
|
import { exhaustiveGuard } from 'utils/typescriptUtils';
|
|
|
|
export enum PathType {
|
|
HAPPY_PATH = 'happy path',
|
|
UNHAPPY_PATH = 'unhappy path',
|
|
}
|
|
|
|
function getActiveStep(
|
|
stateName: SwapStateName | null,
|
|
processExited: boolean,
|
|
): [PathType, number, boolean] {
|
|
switch (stateName) {
|
|
/// // Happy Path
|
|
// Step: 0 (Waiting for Bitcoin lock tx to be published)
|
|
case null:
|
|
return [PathType.HAPPY_PATH, 0, false];
|
|
case SwapStateName.Started:
|
|
case SwapStateName.SwapSetupCompleted:
|
|
return [PathType.HAPPY_PATH, 0, processExited];
|
|
|
|
// Step: 1 (Waiting for Bitcoin Lock confirmation and XMR Lock Publication)
|
|
// We have locked the Bitcoin and are waiting for the other party to lock their XMR
|
|
case SwapStateName.BtcLocked:
|
|
return [PathType.HAPPY_PATH, 1, processExited];
|
|
|
|
// Step: 2 (Waiting for XMR Lock confirmation)
|
|
// We have locked the Bitcoin and the other party has locked their XMR
|
|
case SwapStateName.XmrLockProofReceived:
|
|
return [PathType.HAPPY_PATH, 1, processExited];
|
|
|
|
// Step: 3 (Sending Encrypted Signature and waiting for Bitcoin Redemption)
|
|
// The XMR lock transaction has been confirmed
|
|
// We now need to send the encrypted signature to the other party and wait for them to redeem the Bitcoin
|
|
case SwapStateName.XmrLocked:
|
|
case SwapStateName.EncSigSent:
|
|
return [PathType.HAPPY_PATH, 2, processExited];
|
|
|
|
// Step: 4 (Waiting for XMR Redemption)
|
|
case SwapStateName.BtcRedeemed:
|
|
return [PathType.HAPPY_PATH, 3, processExited];
|
|
|
|
// Step: 4 (Completed) (Swap completed, XMR redeemed)
|
|
case SwapStateName.XmrRedeemed:
|
|
return [PathType.HAPPY_PATH, 4, false];
|
|
|
|
// Edge Case of Happy Path where the swap is safely aborted. We "fail" at the first step.
|
|
case SwapStateName.SafelyAborted:
|
|
return [PathType.HAPPY_PATH, 0, true];
|
|
|
|
// // Unhappy Path
|
|
// Step: 1 (Cancelling swap, checking if cancel transaction has been published already by the other party)
|
|
case SwapStateName.CancelTimelockExpired:
|
|
return [PathType.UNHAPPY_PATH, 0, processExited];
|
|
|
|
// Step: 2 (Attempt to publish the Bitcoin refund transaction)
|
|
case SwapStateName.BtcCancelled:
|
|
return [PathType.UNHAPPY_PATH, 1, processExited];
|
|
|
|
// Step: 2 (Completed) (Bitcoin refunded)
|
|
case SwapStateName.BtcRefunded:
|
|
return [PathType.UNHAPPY_PATH, 2, false];
|
|
|
|
// Step: 2 (We failed to publish the Bitcoin refund transaction)
|
|
// We failed to publish the Bitcoin refund transaction because the timelock has expired.
|
|
// We will be punished. Nothing we can do about it now.
|
|
case SwapStateName.BtcPunished:
|
|
return [PathType.UNHAPPY_PATH, 1, true];
|
|
default:
|
|
return exhaustiveGuard(stateName);
|
|
}
|
|
}
|
|
|
|
function HappyPathStepper({
|
|
activeStep,
|
|
error,
|
|
}: {
|
|
activeStep: number;
|
|
error: boolean;
|
|
}) {
|
|
return (
|
|
<Stepper activeStep={activeStep}>
|
|
<Step key={0}>
|
|
<StepLabel
|
|
optional={<Typography variant="caption">~12min</Typography>}
|
|
error={error && activeStep === 0}
|
|
>
|
|
Locking your BTC
|
|
</StepLabel>
|
|
</Step>
|
|
<Step key={1}>
|
|
<StepLabel
|
|
optional={<Typography variant="caption">~18min</Typography>}
|
|
error={error && activeStep === 1}
|
|
>
|
|
They lock their XMR
|
|
</StepLabel>
|
|
</Step>
|
|
<Step key={2}>
|
|
<StepLabel
|
|
optional={<Typography variant="caption">~2min</Typography>}
|
|
error={error && activeStep === 2}
|
|
>
|
|
They redeem the BTC
|
|
</StepLabel>
|
|
</Step>
|
|
<Step key={3}>
|
|
<StepLabel
|
|
optional={<Typography variant="caption">~2min</Typography>}
|
|
error={error && activeStep === 3}
|
|
>
|
|
Redeeming your XMR
|
|
</StepLabel>
|
|
</Step>
|
|
</Stepper>
|
|
);
|
|
}
|
|
|
|
function UnhappyPathStepper({
|
|
activeStep,
|
|
error,
|
|
}: {
|
|
activeStep: number;
|
|
error: boolean;
|
|
}) {
|
|
return (
|
|
<Stepper activeStep={activeStep}>
|
|
<Step key={0}>
|
|
<StepLabel
|
|
optional={<Typography variant="caption">~20min</Typography>}
|
|
error={error && activeStep === 0}
|
|
>
|
|
Cancelling swap
|
|
</StepLabel>
|
|
</Step>
|
|
<Step key={1}>
|
|
<StepLabel
|
|
optional={<Typography variant="caption">~20min</Typography>}
|
|
error={error && activeStep === 1}
|
|
>
|
|
Refunding your BTC
|
|
</StepLabel>
|
|
</Step>
|
|
</Stepper>
|
|
);
|
|
}
|
|
|
|
export default function SwapStateStepper() {
|
|
const currentSwapSpawnType = useAppSelector((s) => s.swap.spawnType);
|
|
const stateName = useActiveSwapInfo()?.stateName ?? null;
|
|
const processExited = useAppSelector((s) => !s.swap.processRunning);
|
|
const [pathType, activeStep, error] = getActiveStep(stateName, processExited);
|
|
|
|
// If the current swap is being manually cancelled and refund, we want to show the unhappy path even though the current state is not a "unhappy" state
|
|
if (currentSwapSpawnType === SwapSpawnType.CANCEL_REFUND) {
|
|
return <UnhappyPathStepper activeStep={0} error={error} />;
|
|
}
|
|
|
|
if (pathType === PathType.HAPPY_PATH) {
|
|
return <HappyPathStepper activeStep={activeStep} error={error} />;
|
|
}
|
|
return <UnhappyPathStepper activeStep={activeStep} error={error} />;
|
|
}
|