Skip to content
This repository has been archived by the owner on Jun 16, 2022. It is now read-only.

LL-8181 Render FTX Login/KYC widgets inside WebView #1996

Draft
wants to merge 9 commits into
base: develop
Choose a base branch
from
18 changes: 17 additions & 1 deletion src/components/RootNavigator/SwapNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import SwapKYCStates from "../../screens/Swap/KYC/StateSelect";
import Swap from "../../screens/Swap";
import Swap2 from "../../screens/Swap2";
import SwapOperationDetails from "../../screens/Swap/FormOrHistory/OperationDetails";
import { BackButton } from "../../screens/OperationDetails";
import { BackButton, CloseButton } from "../../screens/OperationDetails";
import SwapPendingOperation from "../../screens/Swap/FormOrHistory/Form/PendingOperation";
import SwapFormSelectCrypto from "../../screens/Swap/FormOrHistory/Form/SelectAccount/01-SelectCrypto";
import SwapFormSelectAccount from "../../screens/Swap/FormOrHistory/Form/SelectAccount/02-SelectAccount";
import { SwapConnectFTX } from "../../screens/Swap/FTX";
import { getStackNavigatorConfig } from "../../navigation/navigatorConfig";
import styles from "../../navigation/styles";
import StepHeader from "../StepHeader";
Expand Down Expand Up @@ -140,6 +141,21 @@ export default function SwapNavigator() {
headerRight: null,
})}
/>
<Stack.Screen
name={ScreenName.SwapConnectFTX}
component={SwapConnectFTX}
options={({ navigation }) => ({
headerTitle: () => <StepHeader title={t("transfer.swap.title")} />,
headerLeft: null,
headerRight: () => (
<CloseButton
navigation={navigation}
onPress={() => navigation.pop()}
/>
),
presentation: "modal",
})}
/>
</Stack.Navigator>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/const/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const ScreenName = {
StellarEditMemoType: "StellarEditMemoType",
StellarEditMemoValue: "StellarEditMemoValue",
Swap: "Swap",
SwapConnectFTX: "SwapConnectFTX",
SwapError: "SwapError",
SwapFormOrHistory: "SwapFormOrHistory",
SwapForm: "SwapForm",
Expand Down
8 changes: 8 additions & 0 deletions src/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ async function unsafeSaveCountervalues(
}
}

export async function getFTXToken(): Promise<{ authToken?: string }> {
return store.get("ftxToken");
}

export async function saveFTXToken(token: string): Promise<void> {
await store.save("ftxToken", token);
}

export async function getBle(): Promise<*> {
const ble = await store.get("ble");
return ble;
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1963,6 +1963,10 @@
"tos": "Terms & conditions",
"accept": "Accept",
"reject": "Close"
},
"connect": {
"title": "Login or sign up to FTX to continue",
"cta": "connect"
}
}
},
Expand Down
21 changes: 18 additions & 3 deletions src/screens/OperationDetails/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* @flow */
import React from "react";
import React, { useCallback } from "react";
import { View, StyleSheet, TouchableOpacity } from "react-native";
import SafeAreaView from "react-native-safe-area-view";
import { useSelector } from "react-redux";
Expand Down Expand Up @@ -45,13 +45,28 @@ export const BackButton = ({ navigation }: { navigation: * }) => {
);
};

export const CloseButton = ({ navigation }: { navigation: * }) => {
export const CloseButton = ({
navigation,
onPress,
}: {
navigation: *,
onPress?: () => void,
}) => {
const { colors } = useTheme();

const handlePress = useCallback(() => {
if (onPress) {
onPress();
return;
}

navigation.popToTop();
}, [navigation, onPress]);

return (
<TouchableOpacity
// $FlowFixMe
onPress={() => navigation.popToTop()}
onPress={handlePress}
style={styles.buttons}
>
<Close size={18} color={colors.grey} />
Expand Down
112 changes: 112 additions & 0 deletions src/screens/Swap/FTX/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { NavigationProp, useTheme } from "@react-navigation/native";
import { StyleSheet } from "react-native";
import { WebView } from "react-native-webview";
import { getFTXToken, saveFTXToken } from "../../../db";

export function SwapConnectFTX({
route,
navigation,
}: {
route: { params: { uri: string } },
navigation: NavigationProp,
}) {
const { dark } = useTheme();
const { uri } = route.params;
const { token, saveToken } = useFTXToken();

const preload = useMemo(() => {
const isKYC = new URL(uri).pathname.split("/")[1] === "kyc";

return `
(function() {
window.ledger = { postMessage: window.ReactNativeWebView.postMessage };

window.ledger.setToken = token => {
const message = JSON.stringify({
type: "setToken",
token,
});
window.ledger.postMessage(message);
}

window.ledger.closeWidget = () => {
const message = JSON.stringify({
type: "closeWidget",
});
window.ledger.postMessage(message);
}

${isKYC && `localStorage.setItem("authToken", "${token}");`}
localStorage.setItem("theme", "${dark ? "dark" : "light"}");
})();
`;
}, [uri, token, dark]);

const handleError = useCallback(e => {
// TODO: tracking
console.error(e);
}, []);

const handleMessage = useCallback(
({ nativeEvent: { data: dataStr } }) => {
try {
const data: Message = JSON.parse(dataStr);
switch (data.type) {
case "setToken":
saveToken(data.token);
break;
case "closeWidget":
navigation.pop();
break;
default:
break;
}
} catch (e) {
// TODO: tracking
console.error(e);
}
},
[navigation, saveToken],
);

return (
<WebView
style={styles.root}
source={{ uri: route.params.uri }}
injectedJavaScriptBeforeContentLoaded={preload}
onError={handleError}
onMessage={handleMessage}
/>
);
}

function useFTXToken() {
const [token, setToken] = useState();

const saveToken = useCallback((token: string) => {
saveFTXToken(token);
}, []);

useEffect(() => {
async function setup() {
const token = await getFTXToken();
setToken(token);
}

setup();
}, []);

return {
token,
saveToken,
};
}

type Message = { type: "setToken", token: string } | { type: "closeWidget" };

const styles = StyleSheet.create({
root: {
flex: 1,
},
});
Loading