181 lines
5.9 KiB
TypeScript
181 lines
5.9 KiB
TypeScript
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
|
import { OrderSide } from '@dydxprotocol/v4-client-js';
|
|
|
|
import type { TradeInputSummary } from '@/constants/abacus';
|
|
import { ButtonAction, ButtonSize, ButtonType } from '@/constants/buttons';
|
|
import { DialogTypes } from '@/constants/dialogs';
|
|
import { STRING_KEYS } from '@/constants/localization';
|
|
import { TRADE_TYPE_STRINGS, MobilePlaceOrderSteps } from '@/constants/trade';
|
|
|
|
import { useStringGetter } from '@/hooks';
|
|
|
|
import { AssetIcon } from '@/components/AssetIcon';
|
|
import { Button } from '@/components/Button';
|
|
import { Output, OutputType, ShowSign } from '@/components/Output';
|
|
import { WithDetailsReceipt } from '@/components/WithDetailsReceipt';
|
|
import { WithTooltip } from '@/components/WithTooltip';
|
|
|
|
import { OnboardingTriggerButton } from '@/views/dialogs/OnboardingTriggerButton';
|
|
|
|
import { calculateCanAccountTrade } from '@/state/accountCalculators';
|
|
import { getSubaccountId } from '@/state/accountSelectors';
|
|
import { openDialog } from '@/state/dialogs';
|
|
import { getCurrentInput, getInputTradeData } from '@/state/inputsSelectors';
|
|
|
|
import { getSelectedOrderSide, getSelectedTradeType } from '@/lib/tradeData';
|
|
|
|
type ElementProps = {
|
|
isLoading: boolean;
|
|
isClosePosition?: boolean;
|
|
actionStringKey?: string;
|
|
summary?: TradeInputSummary;
|
|
hasValidationErrors?: boolean;
|
|
currentStep?: MobilePlaceOrderSteps;
|
|
showDeposit?: boolean;
|
|
showConnectWallet?: boolean;
|
|
};
|
|
|
|
export const PlaceOrderButtonAndReceipt = ({
|
|
isLoading,
|
|
isClosePosition,
|
|
actionStringKey,
|
|
summary,
|
|
hasValidationErrors,
|
|
currentStep,
|
|
showDeposit,
|
|
showConnectWallet,
|
|
}: ElementProps) => {
|
|
const stringGetter = useStringGetter();
|
|
const dispatch = useDispatch();
|
|
|
|
const canAccountTrade = useSelector(calculateCanAccountTrade);
|
|
const subaccountNumber = useSelector(getSubaccountId);
|
|
const currentInput = useSelector(getCurrentInput);
|
|
const currentTradeData = useSelector(getInputTradeData, shallowEqual);
|
|
|
|
const hasMissingData = subaccountNumber === undefined;
|
|
|
|
const shouldEnableTrade =
|
|
canAccountTrade && !hasMissingData && !hasValidationErrors && currentInput !== 'transfer';
|
|
|
|
const { side, type } = currentTradeData || {};
|
|
|
|
const selectedTradeType = getSelectedTradeType(type);
|
|
const selectedOrderSide = getSelectedOrderSide(side);
|
|
|
|
const { fee, price: expectedPrice, total, reward } = summary || {};
|
|
|
|
const items = [
|
|
{
|
|
key: 'expected-price',
|
|
label: (
|
|
<WithTooltip tooltip="expected-price" side="right">
|
|
{stringGetter({ key: STRING_KEYS.EXPECTED_PRICE })}
|
|
</WithTooltip>
|
|
),
|
|
value: <Output type={OutputType.Fiat} value={expectedPrice} useGrouping />,
|
|
},
|
|
{
|
|
key: 'fee',
|
|
label: stringGetter({ key: STRING_KEYS.FEE }),
|
|
value: <Output type={OutputType.Fiat} value={fee} useGrouping />,
|
|
},
|
|
{
|
|
key: 'max-reward',
|
|
label: (
|
|
<>
|
|
{stringGetter({ key: STRING_KEYS.MAXIMUM_REWARDS })}
|
|
{/* <AssetIcon symbol="DYDX" /> */}
|
|
</>
|
|
),
|
|
value: <Output type={OutputType.Asset} value={reward} useGrouping tag={reward ? "Dv4TNT" : ''} />,
|
|
tooltip: 'max-reward',
|
|
},
|
|
{
|
|
key: 'total',
|
|
label: stringGetter({ key: STRING_KEYS.TOTAL }),
|
|
value: <Output type={OutputType.Fiat} value={total} showSign={ShowSign.None} useGrouping />,
|
|
},
|
|
];
|
|
|
|
const orderSideAction = {
|
|
[OrderSide.BUY]: ButtonAction.Create,
|
|
[OrderSide.SELL]: ButtonAction.Destroy,
|
|
}[selectedOrderSide];
|
|
|
|
const buttonStatesPerStep = {
|
|
[MobilePlaceOrderSteps.EditOrder]: {
|
|
buttonTextStringKey: shouldEnableTrade
|
|
? STRING_KEYS.PREVIEW_ORDER
|
|
: actionStringKey
|
|
? actionStringKey
|
|
: STRING_KEYS.UNAVAILABLE,
|
|
buttonAction: ButtonAction.Primary,
|
|
buttonState: { isDisabled: !shouldEnableTrade },
|
|
},
|
|
|
|
[MobilePlaceOrderSteps.PreviewOrder]: {
|
|
buttonTextStringKey: STRING_KEYS.CONFIRM_ORDER,
|
|
buttonAction: isClosePosition ? ButtonAction.Destroy : orderSideAction,
|
|
buttonState: { isLoading },
|
|
},
|
|
[MobilePlaceOrderSteps.PlacingOrder]: {
|
|
buttonTextStringKey: STRING_KEYS.RETURN_TO_MARKET,
|
|
buttonAction: ButtonAction.Secondary,
|
|
buttonState: {},
|
|
},
|
|
[MobilePlaceOrderSteps.Confirmation]: {
|
|
buttonTextStringKey: STRING_KEYS.RETURN_TO_MARKET,
|
|
buttonAction: ButtonAction.Secondary,
|
|
buttonState: {},
|
|
},
|
|
};
|
|
|
|
const buttonAction = currentStep
|
|
? buttonStatesPerStep[currentStep].buttonAction
|
|
: isClosePosition
|
|
? ButtonAction.Destroy
|
|
: orderSideAction;
|
|
|
|
let buttonTextStringKey = STRING_KEYS.UNAVAILABLE;
|
|
if (currentStep) {
|
|
buttonTextStringKey = buttonStatesPerStep[currentStep].buttonTextStringKey;
|
|
} else if (shouldEnableTrade) {
|
|
buttonTextStringKey = isClosePosition ? STRING_KEYS.CLOSE_POSITION : STRING_KEYS.PLACE_ORDER;
|
|
} else if (actionStringKey) {
|
|
buttonTextStringKey = actionStringKey;
|
|
}
|
|
|
|
const buttonState = currentStep
|
|
? buttonStatesPerStep[currentStep].buttonState
|
|
: { isDisabled: !shouldEnableTrade || isLoading, isLoading };
|
|
|
|
return (
|
|
<WithDetailsReceipt detailItems={items}>
|
|
{!canAccountTrade || showConnectWallet ? (
|
|
<OnboardingTriggerButton size={ButtonSize.Base} />
|
|
) : showDeposit ? (
|
|
<Button
|
|
action={ButtonAction.Primary}
|
|
onClick={() => dispatch(openDialog({ type: DialogTypes.Deposit }))}
|
|
>
|
|
{stringGetter({ key: STRING_KEYS.DEPOSIT_FUNDS })}
|
|
</Button>
|
|
) : (
|
|
<Button state={buttonState} type={ButtonType.Submit} action={buttonAction}>
|
|
{stringGetter({
|
|
key: buttonTextStringKey,
|
|
params: {
|
|
ORDER: stringGetter({
|
|
key: isClosePosition
|
|
? STRING_KEYS.CLOSE_ORDER
|
|
: TRADE_TYPE_STRINGS[selectedTradeType].tradeTypeKey,
|
|
}),
|
|
},
|
|
})}
|
|
</Button>
|
|
)}
|
|
</WithDetailsReceipt>
|
|
);
|
|
};
|