-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DO NOT MERGE - Iceboxed] Add Iframe and Summary card for the KYC #127
Changes from 4 commits
d345c90
93f3bf6
a2f475b
6172629
cddc8ca
171066d
9d5fc4e
dc6f6d0
bda9638
f253afc
52d2749
bc019e6
1ef6395
24afd1e
0080740
942a397
3d52961
9647226
e7635cd
4ced67a
88e5887
fc92db8
8b08240
37304c5
f78ae4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { BaseLayout } from '../../layouts'; | ||
|
||
interface IframeProps { | ||
src: string; | ||
title: string; | ||
subtitle: string; | ||
} | ||
|
||
const IframeComponent: React.FC<IframeProps> = ({ | ||
src, title, subtitle | ||
}) => { | ||
const [cachedSrc, setCachedSrc] = useState<string | null>(null); | ||
|
||
useEffect(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can remove the whole cachedSrc logic. We are not using it anywhere There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, the idea was to save the kyc url since it was being reset, but since the iframe loads only once, we can remove this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Separated. Also added reusable inner cards. |
||
if ( src && !cachedSrc) { | ||
setCachedSrc(src); | ||
} | ||
}, [src, cachedSrc]); | ||
let main = | ||
<div className="flex justify-center items-center w-full h-full p-4"> | ||
<div className="max-w-lg w-full"> | ||
<div className="text-center"> | ||
<h1 className="text-2xl font-bold text-blue-700 mb-4">{title}</h1> | ||
<h2 className="text-md mb-4">{subtitle}</h2> | ||
<div className="relative pb-[150%] md:w-[535px] md:h-[550px]"> | ||
<iframe | ||
src={src} | ||
style={{ border: 'none' }} | ||
className="absolute top-0 left-0 w-full h-full " | ||
allowFullScreen | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
return <BaseLayout main={main} />; | ||
}; | ||
|
||
export default IframeComponent; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ import { ExclamationCircleIcon } from '@heroicons/react/20/solid'; | |
import { FinalOfframpingPhase, OfframpingPhase } from '../../services/offrampingFlow'; | ||
import { Box } from '../../components/Box'; | ||
import { BaseLayout } from '../../layouts'; | ||
import { SigningBox } from '../../components/SigningBox'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two imports are not used. |
||
import { SigningPhase } from '../../hooks/useMainProcess' | ||
|
||
const OFFRAMPING_PHASE_MESSAGES: Record<OfframpingPhase, string> = { | ||
prepareTransactions: '1/11: Preparing transactions', | ||
|
@@ -25,9 +27,10 @@ const handleTabClose = (event: Event) => { | |
interface ProgressPageProps { | ||
setOfframpingPhase: StateUpdater<OfframpingPhase | FinalOfframpingPhase | undefined>; | ||
offrampingPhase: OfframpingPhase | FinalOfframpingPhase | undefined; | ||
signingPhase: SigningPhase | undefined; | ||
} | ||
|
||
export const ProgressPage: FC<ProgressPageProps> = ({ setOfframpingPhase, offrampingPhase }) => { | ||
export const ProgressPage: FC<ProgressPageProps> = ({ setOfframpingPhase, offrampingPhase, signingPhase }) => { | ||
// After 15 minutes of waiting, we want to redirect user to the failure page. | ||
useEffect(() => { | ||
const timer = setTimeout(() => { | ||
|
@@ -49,6 +52,7 @@ export const ProgressPage: FC<ProgressPageProps> = ({ setOfframpingPhase, offram | |
|
||
const main = ( | ||
<main> | ||
<SigningBox step={signingPhase} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Signing now happens in the process page, as it would otherwise not be visible given the iframe screen has already popped up. |
||
<Box className="flex flex-col items-center justify-center mt-12"> | ||
<div className="flex flex-col items-center justify-center"> | ||
<ExclamationCircleIcon className="text-red-500 w-36" /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ import { SuccessPage } from '../success'; | |
import { FailurePage } from '../failure'; | ||
import { useInputTokenBalance } from '../../hooks/useInputTokenBalance'; | ||
import { UserBalance } from '../../components/UserBalance'; | ||
import IframeComponent from '../../components/Iframe'; | ||
|
||
const Arrow = () => ( | ||
<div className="flex justify-center w-full my-5"> | ||
|
@@ -36,6 +37,7 @@ export const SwapPage = () => { | |
const [isQuoteSubmitted, setIsQuoteSubmitted] = useState(false); | ||
const formRef = useRef<HTMLDivElement | null>(null); | ||
const [api, setApi] = useState<ApiPromise | null>(null); | ||
const [isIframVisible, setIframVisible] = useState(false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is unused |
||
|
||
const { isDisconnected } = useAccount(); | ||
|
||
|
@@ -58,10 +60,13 @@ export const SwapPage = () => { | |
sep24Id, | ||
offrampingPhase, | ||
setOfframpingPhase, | ||
resetSep24Url, | ||
signingPhase, | ||
} = useMainProcess(); | ||
|
||
const handleSubmitButtonClick = () => { | ||
setIframVisible(true); | ||
} | ||
|
||
const { | ||
tokensModal: [modalType, setModalType], | ||
onFromChange, | ||
|
@@ -161,11 +166,12 @@ export const SwapPage = () => { | |
// Do not show any error if the user is disconnected | ||
if (isDisconnected) return; | ||
|
||
if (typeof userInputTokenBalance === 'string') { | ||
if (Big(userInputTokenBalance).lt(fromAmount ?? 0)) { | ||
return `Insufficient balance. Your balance is ${userInputTokenBalance} ${fromToken?.assetSymbol}.`; | ||
} | ||
} | ||
// TESTING - TODO: Remove comment | ||
// if (typeof userInputTokenBalance === 'string') { | ||
// if (Big(userInputTokenBalance).lt(fromAmount ?? 0)) { | ||
// return `Insufficient balance. Your balance is ${userInputTokenBalance} ${fromToken?.assetSymbol}.`; | ||
// } | ||
// } | ||
|
||
const amountOut = tokenOutData.data?.amountOut; | ||
|
||
|
@@ -224,57 +230,66 @@ export const SwapPage = () => { | |
|
||
if (offrampingPhase !== undefined || offrampingStarted) { | ||
const showMainScreenAnyway = | ||
offrampingPhase === undefined || ['prepareTransactions', 'squidRouter'].includes(offrampingPhase); | ||
offrampingPhase === undefined; | ||
|
||
if (sep24Url && isIframVisible && showMainScreenAnyway ){ | ||
return ( | ||
<IframeComponent | ||
src={sep24Url} | ||
title="Verify Your Identity to Start Offramping" | ||
subtitle="Please follow the steps below to complete the identity verification." | ||
/> | ||
); | ||
} | ||
if (!showMainScreenAnyway) { | ||
return <ProgressPage setOfframpingPhase={setOfframpingPhase} offrampingPhase={offrampingPhase} />; | ||
return <ProgressPage setOfframpingPhase={setOfframpingPhase} offrampingPhase={offrampingPhase} signingPhase={signingPhase} />; | ||
} | ||
} | ||
|
||
const main = ( | ||
<main ref={formRef}> | ||
<SigningBox step={signingPhase} /> | ||
<form | ||
className="max-w-2xl px-4 py-8 mx-4 mt-12 mb-12 rounded-lg shadow-custom md:mx-auto md:w-2/3 lg:w-3/5 xl:w-1/2" | ||
onSubmit={onSubmit} | ||
> | ||
<h1 className="mb-5 text-3xl font-bold text-center text-blue-700">Withdraw</h1> | ||
<LabeledInput label="You withdraw" Input={WidthrawNumericInput} /> | ||
<Arrow /> | ||
<LabeledInput label="You receive" Input={ReceiveNumericInput} /> | ||
<p className="text-red-600">{getCurrentErrorMessage()}</p> | ||
<ExchangeRate | ||
{...{ | ||
tokenOutData, | ||
fromToken, | ||
toTokenSymbol: toToken.fiat.symbol, | ||
}} | ||
/> | ||
<FeeCollapse | ||
fromAmount={fromAmount?.toString()} | ||
toAmount={tokenOutData.data?.amountOut.preciseString} | ||
toToken={toToken} | ||
/> | ||
<section className="flex items-center justify-center w-full mt-5"> | ||
<BenefitsList amount={fromAmount} currency={from} /> | ||
</section> | ||
{sep24Url !== undefined ? ( | ||
<a | ||
href={sep24Url} | ||
target="_blank" | ||
rel="noreferrer" | ||
className="w-full mt-5 text-white bg-blue-700 btn rounded-xl" | ||
onClick={resetSep24Url} | ||
<form | ||
className="max-w-2xl px-4 py-8 mx-4 mt-12 mb-12 rounded-lg shadow-custom md:mx-auto md:w-2/3 lg:w-3/5 xl:w-1/2" | ||
onSubmit={onSubmit} | ||
> | ||
Start Offramping | ||
</a> | ||
) : ( | ||
<SwapSubmitButton | ||
text={offrampingStarted ? 'Offramping in Progress' : 'Confirm'} | ||
disabled={Boolean(getCurrentErrorMessage()) || !inputAmountIsStable} | ||
pending={offrampingStarted || offrampingPhase !== undefined} | ||
/> | ||
)} | ||
</form> | ||
<h1 className="mb-5 text-3xl font-bold text-center text-blue-700">Withdraw</h1> | ||
<LabeledInput label="You withdraw" Input={WidthrawNumericInput} /> | ||
<Arrow /> | ||
<LabeledInput label="You receive" Input={ReceiveNumericInput} /> | ||
<p className="text-red-600">{getCurrentErrorMessage()}</p> | ||
<ExchangeRate | ||
{...{ | ||
tokenOutData, | ||
fromToken, | ||
toTokenSymbol: toToken.fiat.symbol, | ||
}} | ||
/> | ||
<FeeCollapse | ||
fromAmount={fromAmount?.toString()} | ||
toAmount={tokenOutData.data?.amountOut.preciseString} | ||
toToken={toToken} | ||
/> | ||
<section className="flex items-center justify-center w-full mt-5"> | ||
<BenefitsList amount={fromAmount} currency={from} /> | ||
</section> | ||
{sep24Url !== undefined ? ( | ||
<button | ||
href={sep24Url} | ||
target="_blank" | ||
rel="noreferrer" | ||
className="w-full mt-5 text-white bg-blue-700 btn rounded-xl" | ||
onClick={handleSubmitButtonClick} | ||
> | ||
Start Offramping | ||
</button> | ||
) : ( | ||
<SwapSubmitButton | ||
text={offrampingStarted ? 'Offramping in Progress' : 'Confirm'} | ||
disabled={Boolean(getCurrentErrorMessage()) || !inputAmountIsStable} | ||
pending={offrampingStarted || offrampingPhase !== undefined} | ||
/> | ||
)} | ||
</form> | ||
</main> | ||
); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -186,9 +186,9 @@ export async function sep12First(sessionParams: IAnchorSessionParams): Promise<v | |
}*/ | ||
|
||
export async function sep24First(sessionParams: IAnchorSessionParams): Promise<ISep24Intermediate> { | ||
if (config.test.mockSep24) { | ||
return { url: 'https://www.example.com', id: '1234' }; | ||
} | ||
// if (config.test.mockSep24) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove, not comment out. |
||
// return { url: 'https://www.example.com', id: '1234' }; | ||
// } | ||
|
||
const { token, tomlValues } = sessionParams; | ||
const { sep24Url } = tomlValues; | ||
|
@@ -227,11 +227,13 @@ export async function sep24Second( | |
const { sep24Url } = tomlValues; | ||
|
||
if (config.test.mockSep24) { | ||
// sleep 10 seconds, mock user completion of KYC | ||
await new Promise((resolve) => setTimeout(resolve, 10000)); | ||
return { | ||
amount: sessionParams.offrampAmount, | ||
memo: 'MYK1722323689', | ||
memoType: 'text', | ||
offrampingAccount: (await fetchSigningServiceAccountId()).stellar.public, | ||
offrampingAccount: "GSAPDFASJFPASFOKNASOFKNAS", | ||
}; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,7 +104,7 @@ export interface ExecutionContext { | |
setSigningPhase: (n: SigningPhase) => void; | ||
} | ||
|
||
const OFFRAMPING_STATE_LOCAL_STORAGE_KEY = 'offrampingState'; | ||
export const OFFRAMPING_STATE_LOCAL_STORAGE_KEY = 'offrampingState'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this exported now? It is not used outside this file. |
||
|
||
export interface InitiateStateArguments { | ||
sep24Id: string; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use preact not react, please import preact/compat