-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MOBILE-192: Add new app to connect mobile app to web wallet (#592)
* MOBILE-192: Add new app to connect mobile app to web wallet * MOBILE-192: Remove qrcode blob from state and creating code from the frontend instead of fetching it * MOBILE-192: Update scan code page with PR feedback
- Loading branch information
1 parent
3efb7ec
commit f6105f2
Showing
58 changed files
with
2,024 additions
and
284 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"extends": [ | ||
"plugin:@nx/react-typescript", | ||
"next", | ||
"next/core-web-vitals", | ||
"../../.eslintrc.json" | ||
], | ||
"ignorePatterns": ["!**/*", ".next/**/*"], | ||
"overrides": [ | ||
{ | ||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], | ||
"rules": { | ||
"@next/next/no-html-link-for-pages": [ | ||
"error", | ||
"apps/mobile-wallet-connector/pages" | ||
] | ||
} | ||
}, | ||
{ | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.js", "*.jsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"], | ||
"env": { | ||
"jest": true | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
declare module "*.svg" { | ||
const content: any; | ||
export const ReactComponent: any; | ||
export default content; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* eslint-disable */ | ||
export default { | ||
displayName: "mobile-wallet-connector", | ||
preset: "../../jest.preset.js", | ||
transform: { | ||
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "@nx/react/plugins/jest", | ||
"^.+\\.[tj]sx?$": ["babel-jest", { presets: ["@nx/next/babel"] }], | ||
}, | ||
moduleFileExtensions: ["ts", "tsx", "js", "jsx"], | ||
coverageDirectory: "../../coverage/apps/mobile-wallet-connector", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/basic-features/typescript for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//@ts-check | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const { composePlugins, withNx } = require("@nx/next"); | ||
|
||
/** | ||
* @type {import('@nx/next/plugins/with-nx').WithNxOptions} | ||
**/ | ||
const nextConfig = { | ||
nx: { | ||
// Set this to true if you would like to to use SVGR | ||
// See: https://github.com/gregberge/svgr | ||
svgr: false, | ||
}, | ||
|
||
compiler: { | ||
// For other options, see https://styled-components.com/docs/tooling#babel-plugin | ||
styledComponents: true, | ||
}, | ||
}; | ||
|
||
const plugins = [ | ||
// Add more Next.js plugins to this list if needed. | ||
withNx, | ||
]; | ||
|
||
module.exports = composePlugins(...plugins)(nextConfig); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
{ | ||
"name": "mobile-wallet-connector", | ||
"$schema": "../../node_modules/nx/schemas/project-schema.json", | ||
"sourceRoot": "apps/mobile-wallet-connector", | ||
"projectType": "application", | ||
"targets": { | ||
"build": { | ||
"executor": "@nx/next:build", | ||
"outputs": ["{options.outputPath}"], | ||
"defaultConfiguration": "production", | ||
"options": { | ||
"outputPath": "dist/apps/mobile-wallet-connector" | ||
}, | ||
"configurations": { | ||
"development": { | ||
"outputPath": "apps/mobile-wallet-connector" | ||
}, | ||
"production": {} | ||
} | ||
}, | ||
"serve": { | ||
"executor": "@nx/next:server", | ||
"defaultConfiguration": "development", | ||
"options": { | ||
"buildTarget": "mobile-wallet-connector:build", | ||
"dev": true | ||
}, | ||
"configurations": { | ||
"development": { | ||
"buildTarget": "mobile-wallet-connector:build:development", | ||
"dev": true, | ||
"port": 4300 | ||
}, | ||
"production": { | ||
"buildTarget": "mobile-wallet-connector:build:production", | ||
"dev": false | ||
} | ||
} | ||
}, | ||
"export": { | ||
"executor": "@nx/next:export", | ||
"options": { | ||
"buildTarget": "mobile-wallet-connector:build:production" | ||
} | ||
}, | ||
"test": { | ||
"executor": "@nx/jest:jest", | ||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"], | ||
"options": { | ||
"jestConfig": "apps/mobile-wallet-connector/jest.config.ts" | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nx/eslint:lint" | ||
} | ||
}, | ||
"tags": [] | ||
} |
Empty file.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* Maps RTKQuery API endpoint names with name that | ||
* back-end expects for recaptcha action argument. | ||
*/ | ||
export const recaptchaEndpointActionMap: Record<string, string> = { | ||
answerChallenge: "answer_challenge", | ||
generateChallenge: "generate_challenge", | ||
getQRCode: "qrcode", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { newmApi } from "./newm/api"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { createApi } from "@reduxjs/toolkit/query/react"; | ||
import { baseUrls } from "../../buildParams"; | ||
import { axiosBaseQuery, prepareHeaders } from "../utils"; | ||
|
||
export const baseQuery = axiosBaseQuery({ | ||
baseUrl: baseUrls.newm, | ||
prepareHeaders, | ||
}); | ||
|
||
export const newmApi = createApi({ | ||
baseQuery, | ||
endpoints: () => ({}), | ||
reducerPath: "newmApi", | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { BaseQueryApi } from "@reduxjs/toolkit/dist/query/baseQueryTypes"; | ||
import axios, { AxiosError, AxiosRequestConfig } from "axios"; | ||
import { executeRecaptcha } from "@newm-web/utils"; | ||
import { AxiosBaseQueryParams, BaseQuery } from "@newm-web/types"; | ||
import { recaptchaEndpointActionMap } from "./constants"; | ||
|
||
/** | ||
* Returns recaptcha headers for unauthenticated requests. | ||
*/ | ||
export const getRecaptchaHeaders = async (api: BaseQueryApi) => { | ||
const { endpoint } = api; | ||
const action = recaptchaEndpointActionMap[endpoint] || endpoint; | ||
|
||
return { | ||
"g-recaptcha-platform": "Web", | ||
"g-recaptcha-token": await executeRecaptcha(action), | ||
}; | ||
}; | ||
|
||
/** | ||
* Adds necessary authentication headers to requests. | ||
*/ | ||
export const prepareHeaders = async ( | ||
api: BaseQueryApi, | ||
headers: AxiosRequestConfig["headers"] | ||
) => { | ||
const recaptchaHeaders = await getRecaptchaHeaders(api); | ||
|
||
return { | ||
...recaptchaHeaders, | ||
...headers, | ||
}; | ||
}; | ||
|
||
/** | ||
* Sets up base query using axios request library (allows for tracking | ||
* upload progress, which the native fetch library does not). | ||
*/ | ||
export const axiosBaseQuery = ( | ||
{ baseUrl, prepareHeaders }: AxiosBaseQueryParams = { baseUrl: "" } | ||
): BaseQuery => { | ||
return async ( | ||
{ url, method, body, params, headers = {}, onUploadProgress }, | ||
api | ||
) => { | ||
try { | ||
const axiosInstance = axios.create({ | ||
headers: prepareHeaders ? await prepareHeaders(api, headers) : headers, | ||
|
||
// convert array params to comma separated strings | ||
paramsSerializer: (params) => { | ||
const searchParams = new URLSearchParams(); | ||
for (const key of Object.keys(params)) { | ||
const param = params[key]; | ||
if (Array.isArray(param)) { | ||
for (const p of param) { | ||
searchParams.append(key, p); | ||
} | ||
} else { | ||
searchParams.append(key, param); | ||
} | ||
} | ||
|
||
return searchParams.toString(); | ||
}, | ||
}); | ||
|
||
const result = await axiosInstance({ | ||
data: body, | ||
headers, | ||
method, | ||
onUploadProgress, | ||
params, | ||
url: baseUrl + url, | ||
}); | ||
|
||
return { data: result.data }; | ||
} catch (axiosError) { | ||
const err = axiosError as AxiosError; | ||
|
||
return { | ||
error: { | ||
data: err.response?.data || err.message, | ||
status: err.response?.status, | ||
}, | ||
}; | ||
} | ||
}; | ||
}; |
88 changes: 88 additions & 0 deletions
88
apps/mobile-wallet-connector/src/app/connect-wallet/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
"use client"; | ||
import { FunctionComponent, useEffect, useState } from "react"; | ||
import { Stack } from "@mui/material"; | ||
import { useRouter } from "next/navigation"; | ||
import { Form, Formik, FormikValues } from "formik"; | ||
import { useConnectWallet } from "@newm.io/cardano-dapp-wallet-connector"; | ||
import { Button, SwitchInputField } from "@newm-web/elements"; | ||
import { setToastMessage } from "../../modules/ui"; | ||
import { selectWallet, useConnectFromMobileThunk } from "../../modules/wallet"; | ||
import { useAppDispatch, useAppSelector } from "../../common"; | ||
|
||
const Page: FunctionComponent = () => { | ||
const router = useRouter(); | ||
const dispatch = useAppDispatch(); | ||
const { isConnected, wallet } = useConnectWallet(); | ||
const { connectionData } = useAppSelector(selectWallet); | ||
|
||
const [connectFromMobile, { isLoading: isConnectFromMobileLoading }] = | ||
useConnectFromMobileThunk(); | ||
|
||
const [isFormSubmitDisabled, setIsFormSubmitDisabled] = useState(true); | ||
|
||
const initialValues = { | ||
isHardwareWallet: false, | ||
}; | ||
|
||
const handleWalletConnect = async ({ isHardwareWallet }: FormikValues) => { | ||
if (wallet) { | ||
await connectFromMobile({ | ||
isHardwareWallet, | ||
wallet, | ||
}); | ||
} else { | ||
dispatch( | ||
setToastMessage({ | ||
message: | ||
"There is a problem with your wallet. Please try disconnecting and reconnecting it.", | ||
severity: "error", | ||
}) | ||
); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
if (isConnected) { | ||
setIsFormSubmitDisabled(false); | ||
} else { | ||
router.replace("/"); | ||
} | ||
}, [isConnected, router]); | ||
|
||
useEffect(() => { | ||
if (connectionData.connectionId) { | ||
router.push("/connect-wallet/scan-code"); | ||
} | ||
}, [connectionData, router]); | ||
|
||
return ( | ||
<> | ||
<Formik initialValues={ initialValues } onSubmit={ handleWalletConnect }> | ||
{ ({ isSubmitting }) => ( | ||
<Form> | ||
<Stack alignItems="center" px={ [2, 2, 0] } rowGap={ 3.5 }> | ||
<Button | ||
disabled={ isFormSubmitDisabled || isSubmitting } | ||
isLoading={ isConnectFromMobileLoading } | ||
type="submit" | ||
width="compact" | ||
> | ||
Connect from Mobile app | ||
</Button> | ||
<SwitchInputField | ||
description={ | ||
"If you are trying to connect a hardware wallet, please select this option." | ||
} | ||
disabled={ isSubmitting } | ||
name="isHardwareWallet" | ||
title="HARDWARE WALLET" | ||
/> | ||
</Stack> | ||
</Form> | ||
) } | ||
</Formik> | ||
</> | ||
); | ||
}; | ||
|
||
export default Page; |
Oops, something went wrong.