Skip to content
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

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d345c90
adding iframe flow
gianfra-t Sep 2, 2024
93f3bf6
move signing modal to progress screem, mock responses to test UI
gianfra-t Sep 2, 2024
a2f475b
show failure screen on initial process
gianfra-t Sep 2, 2024
6172629
make mobile iframe larger
gianfra-t Sep 2, 2024
cddc8ca
adjust size for large screen
gianfra-t Sep 2, 2024
171066d
delay mock 15 seconds only
gianfra-t Sep 2, 2024
9d5fc4e
remove second confirmation button
gianfra-t Sep 3, 2024
dc6f6d0
don't store mocked data in sheet
gianfra-t Sep 3, 2024
bda9638
first card iteration
gianfra-t Sep 5, 2024
f253afc
adjusting summary card
gianfra-t Sep 9, 2024
52d2749
refinements to card design, element props
gianfra-t Sep 9, 2024
bc019e6
fix iframe height to 50%
gianfra-t Sep 9, 2024
1ef6395
fix missing eur icon
gianfra-t Sep 9, 2024
24afd1e
fix asset text for large screens
gianfra-t Sep 9, 2024
0080740
adressing review improvements
gianfra-t Sep 20, 2024
942a397
breaking summary card into inner cards
gianfra-t Sep 20, 2024
3d52961
solving merge conflicts
gianfra-t Sep 20, 2024
9647226
readd iframe to swap page
gianfra-t Sep 20, 2024
e7635cd
add remarked section to summary card:
gianfra-t Sep 20, 2024
4ced67a
fixing lower summary card issue
gianfra-t Sep 20, 2024
88e5887
Adjust styling of summary cards
ebma Sep 23, 2024
fc92db8
Add gas icon
ebma Sep 23, 2024
8b08240
Commit to form values to avoid fluctuations of the exchange rates whe…
ebma Sep 23, 2024
37304c5
remove mocked values
gianfra-t Sep 23, 2024
f78ae4c
remove mock sep 24 second response
gianfra-t Sep 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions signer-service/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1203,13 +1203,6 @@ __metadata:
languageName: node
linkType: hard

"big.js@npm:^6.2.1":
version: 6.2.1
resolution: "big.js@npm:6.2.1"
checksum: 1d4b621451de712cab20464a26f22b2eee5e7daf0ee88c49dfbfa76061ec37cff2257751e8c3fc183c231bcffac2f006e33af930d8f49b03c758890080b76ada
languageName: node
linkType: hard

"bignumber.js@npm:^9.0.0, bignumber.js@npm:^9.1.2":
version: 9.1.2
resolution: "bignumber.js@npm:9.1.2"
Expand Down
41 changes: 41 additions & 0 deletions src/components/Iframe/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { useState, useEffect } from 'react';
Copy link
Contributor

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

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(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

@gianfra-t gianfra-t Sep 20, 2024

Choose a reason for hiding this comment

The 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;
2 changes: 1 addition & 1 deletion src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const config = {
projectId: '299fda67fbf3b60a31ba8695524534cd',
},
test: {
mockSep24: false,
mockSep24: true,
overwriteMinimumTransferAmount: false,
},
};
28 changes: 23 additions & 5 deletions src/hooks/useMainProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
import { EventStatus, GenericEvent } from '../components/GenericEvent';
import Big from 'big.js';
import { createTransactionEvent, useEventsContext } from '../contexts/events';
import { storageService } from '../services/storage/local';
import { OFFRAMPING_STATE_LOCAL_STORAGE_KEY } from '../services/offrampingFlow';

export type SigningPhase = 'started' | 'approved' | 'signed' | 'finished';

Expand Down Expand Up @@ -90,6 +92,7 @@ export const useMainProcess = () => {
from_amount: amountInUnits,
to_amount: Big(minAmountOutUnits).round(2, 0).toFixed(2, 0),
});


try {
const stellarEphemeralSecret = createStellarEphemeralSecret();
Expand All @@ -110,7 +113,6 @@ export const useMainProcess = () => {
const firstSep24Response = await sep24First(anchorSessionParams);
console.log('sep24 url:', firstSep24Response.url);
setSep24Url(firstSep24Response.url);

const secondSep24Response = await sep24Second(firstSep24Response, anchorSessionParams!);

console.log('secondSep24Response', secondSep24Response);
Expand All @@ -127,17 +129,35 @@ export const useMainProcess = () => {
trackEvent(createTransactionEvent('kyc_completed', initialState));

updateHookStateFromState(initialState);

} catch (error) {
let initialStateFailure = await constructInitialState({
gianfra-t marked this conversation as resolved.
Show resolved Hide resolved
sep24Id: 'null',
inputTokenType,
outputTokenType,
amountIn: amountInUnits,
amountOut: minAmountOutUnits,
sepResult: {
amount: '0',
memo: '0',
memoType: '0',
offrampingAccount: '0',
},
});
initialStateFailure.phase = 'failure';
storageService.set(OFFRAMPING_STATE_LOCAL_STORAGE_KEY, initialStateFailure);
setOfframpingPhase('failure');

console.error('Some error occurred initializing the offramping process', error);
setOfframpingStarted(false);
}
})();
},
[offrampingPhase, offrampingStarted, trackEvent, updateHookStateFromState],
[offrampingPhase, offrampingStarted, trackEvent, updateHookStateFromState, setOfframpingPhase],
);

const finishOfframping = useCallback(() => {
(async () => {
setSep24Url(undefined);
await clearOfframpingState();
setOfframpingStarted(false);
updateHookStateFromState(undefined);
Expand All @@ -151,7 +171,6 @@ export const useMainProcess = () => {
})();
}, [offrampingPhase, updateHookStateFromState, wagmiConfig]);

const resetSep24Url = () => setSep24Url(undefined);

return {
setOfframpingPhase,
Expand All @@ -161,7 +180,6 @@ export const useMainProcess = () => {
offrampingStarted,
sep24Id,
finishOfframping,
resetSep24Url,
signingPhase,
};
};
6 changes: 5 additions & 1 deletion src/pages/progress/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Copy link
Collaborator

Choose a reason for hiding this comment

The 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',
Expand All @@ -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(() => {
Expand All @@ -49,6 +52,7 @@ export const ProgressPage: FC<ProgressPageProps> = ({ setOfframpingPhase, offram

const main = (
<main>
<SigningBox step={signingPhase} />
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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" />
Expand Down
115 changes: 65 additions & 50 deletions src/pages/swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is unused


const { isDisconnected } = useAccount();

Expand All @@ -58,10 +60,13 @@ export const SwapPage = () => {
sep24Id,
offrampingPhase,
setOfframpingPhase,
resetSep24Url,
signingPhase,
} = useMainProcess();

const handleSubmitButtonClick = () => {
setIframVisible(true);
}

const {
tokensModal: [modalType, setModalType],
onFromChange,
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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>
);

Expand Down
10 changes: 6 additions & 4 deletions src/services/anchor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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;
Expand Down Expand Up @@ -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",
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/services/offrampingFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Copy link
Collaborator

Choose a reason for hiding this comment

The 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;
Expand Down
Loading
Loading