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

Add Install MetaMask page and don't require signature on dydx #519

Merged
merged 9 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
4 changes: 4 additions & 0 deletions packages/backend/src/Application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { L2TransactionController } from './api/controllers/L2TransactionControll
import { MerkleProofController } from './api/controllers/MerkleProofController'
import { SearchController } from './api/controllers/SearchController'
import { StateUpdateController } from './api/controllers/StateUpdateController'
import { StaticPageController } from './api/controllers/StaticPageController'
import { TransactionController } from './api/controllers/TransactionController'
import { TransactionSubmitController } from './api/controllers/TransactionSubmitController'
import { TutorialController } from './api/controllers/TutorialController'
Expand Down Expand Up @@ -691,6 +692,8 @@ export class Application {
tutorialService
)

const staticPageController = new StaticPageController(pageContextService)

const apiServer = new ApiServer(config.port, logger, {
routers: [
createStatusRouter(statusService),
Expand All @@ -706,6 +709,7 @@ export class Application {
l2TransactionController,
escapeHatchController,
tutorialController,
staticPageController,
config
),
createTransactionRouter(
Expand Down
73 changes: 73 additions & 0 deletions packages/backend/src/api/controllers/StaticPageController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
renderInstallMetaMaskPage,
renderTermsOfServicePage,
renderUserNotAssociatedPage,
} from '@explorer/frontend'
import { UserDetails } from '@explorer/shared'

import { PageContextService } from '../../core/PageContextService'
import { getHtmlFromMarkdown } from '../../utils/markdown/getHtmlFromMarkdown'
import { ControllerResult } from './ControllerResult'

export class StaticPageController {
constructor(private readonly pageContextService: PageContextService) {}

async getTermsOfServicePage(
givenUser: Partial<UserDetails>
): Promise<ControllerResult> {
const context = await this.pageContextService.getPageContext(givenUser)
let contents: string
try {
const path = 'src/content/tos.md'
contents = getHtmlFromMarkdown(path)
} catch {
return {
type: 'not found',
message: 'The page you were looking for does not exist',
}
}

return {
type: 'success',
content: renderTermsOfServicePage({
context,
contents,
}),
}
}

async getInstallMetaMaskPage(
givenUser: Partial<UserDetails>
): Promise<ControllerResult> {
const context = await this.pageContextService.getPageContext(givenUser)

return {
type: 'success',
content: renderInstallMetaMaskPage({
context,
}),
}
}

async getUserNotAssociatedPage(
givenUser: Partial<UserDetails>
): Promise<ControllerResult> {
const context = await this.pageContextService.getPageContextWithUser(
givenUser
)

if (!context) {
return {
type: 'not found',
message: 'The page you were looking for does not exist',
}
}

return {
type: 'success',
content: renderUserNotAssociatedPage({
context,
}),
}
}
}
8 changes: 8 additions & 0 deletions packages/backend/src/api/controllers/UserController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ export class UserController {
}
}

const recoveryDoneAutomatically = context.instanceName === 'dYdX'
if (recoveryDoneAutomatically) {
return {
type: 'redirect',
url: '/users/not-associated',
}
}

const content = renderUserRecoverPage({
context,
})
Expand Down
19 changes: 19 additions & 0 deletions packages/backend/src/api/routers/FrontendRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { L2TransactionController } from '../controllers/L2TransactionController'
import { MerkleProofController } from '../controllers/MerkleProofController'
import { SearchController } from '../controllers/SearchController'
import { StateUpdateController } from '../controllers/StateUpdateController'
import { StaticPageController } from '../controllers/StaticPageController'
import { TransactionController } from '../controllers/TransactionController'
import { TutorialController } from '../controllers/TutorialController'
import { UserController } from '../controllers/UserController'
Expand All @@ -32,6 +33,7 @@ export function createFrontendRouter(
l2TransactionController: L2TransactionController,
escapeHatchController: EscapeHatchController,
tutorialController: TutorialController,
staticPageController: StaticPageController,
config: Config
) {
const router = new Router()
Expand Down Expand Up @@ -211,6 +213,15 @@ export function createFrontendRouter(
applyControllerResult(ctx, result)
})

router.get('/users/not-associated', async (ctx) => {
const givenUser = getGivenUser(ctx)
const result = await staticPageController.getUserNotAssociatedPage(
givenUser
)

applyControllerResult(ctx, result)
})

router.get(
'/users/:starkKey',
withTypedContext(
Expand Down Expand Up @@ -413,6 +424,14 @@ export function createFrontendRouter(
applyControllerResult(ctx, result)
})

router.get('/installMetamask', async (ctx) => {
const givenUser = getGivenUser(ctx)
const result = await escapeHatchController.getFreezeRequestActionPage(
givenUser
)
applyControllerResult(ctx, result)
})

router.get(
'/escape/:positionOrVaultId',
withTypedContext(
Expand Down
27 changes: 27 additions & 0 deletions packages/frontend/src/preview/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
renderHomePage,
renderHomeStateUpdatesPage,
renderHomeTransactionsPage,
renderInstallMetaMaskPage,
renderMerkleProofPage,
renderNewPerpetualForcedActionPage,
renderNewSpotForcedWithdrawPage,
Expand All @@ -36,6 +37,7 @@ import {
renderTutorialPage,
renderUserAssetsPage,
renderUserBalanceChangesPage,
renderUserNotAssociatedPage,
renderUserOffersPage,
renderUserPage,
renderUserRecoverPage,
Expand Down Expand Up @@ -284,6 +286,19 @@ const routes: Route[] = [
},
})
},
},
{
path: '/metamask-required',
description: 'Request to install MetaMask.',
render: (ctx) => {
const context = getPerpetualPageContext(ctx, {
fallbackToFakeUser: true,
})
context.freezeStatus = 'frozen'
ctx.body = renderInstallMetaMaskPage({
context,
})
},
breakAfter: true,
},
// #endregion
Expand Down Expand Up @@ -420,6 +435,18 @@ const routes: Route[] = [
})
},
},
{
path: '/users/not-associated',
description: 'User not associated with any position page.',
render: (ctx) => {
const context = getPerpetualPageContext(ctx, {
fallbackToFakeUser: true,
})
ctx.body = renderUserNotAssociatedPage({
context,
})
},
},
{
path: '/users/register',
description:
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/scripts/metamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function initMetamask() {
if (!provider) {
updateAccounts([])
connectButton?.addEventListener('click', () => {
window.open('https://metamask.io/download/')
window.open('/metamask-required', '_self')
})
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function TermsOfServiceAck({
return instanceName === 'dYdX' ? (
<div className="text-center">
{prefix ?? 'By accessing this website, you agree to our '}{' '}
<Link href="https://dydx.exchange/terms">Terms of Service</Link>
<Link href="https://dydx.exchange/terms">Terms of Use</Link>
</div>
) : null
}
2 changes: 2 additions & 0 deletions packages/frontend/src/view/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export * from './pages/home/HomeL2TransactionsPage'
export * from './pages/home/HomePage'
export * from './pages/home/HomeStateUpdatesPage'
export * from './pages/home/HomeTransactionsPage'
export * from './pages/InstallMetaMaskPage'
export * from './pages/l2-transaction/PerpetualL2TransactionDetailsPage'
export * from './pages/MerkleProofPage'
export * from './pages/RawL2TransactionPage'
Expand All @@ -37,6 +38,7 @@ export * from './pages/user/components/UserQuickActionsTable'
export * from './pages/user/UserAssetsPage'
export * from './pages/user/UserBalanceChangesPage'
export * from './pages/user/UserL2TransactionsPage'
export * from './pages/user/UserNotAssociatedPage'
export * from './pages/user/UserOffersPage'
export * from './pages/user/UserPage'
export * from './pages/user/UserRecoverPage'
Expand Down
63 changes: 63 additions & 0 deletions packages/frontend/src/view/pages/InstallMetaMaskPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { PageContext } from '@explorer/shared'
import React from 'react'

import { Button } from '../components/Button'
import { Card } from '../components/Card'
import { Link } from '../components/Link'
import { ContentWrapper } from '../components/page/ContentWrapper'
import { Page } from '../components/page/Page'
import { reactToHtml } from '../reactToHtml'

interface Props {
context: PageContext
}

function InstallMetaMaskPage(props: Props) {
return (
<Page
path="/metamask-required"
description="Install MetaMask"
context={props.context}
>
<ContentWrapper className="flex flex-col gap-8 md:gap-16">
<div className="flex flex-col gap-3">
<div className="text-xxl font-semibold">Please install MetaMask</div>
<span className="mt-3 font-medium">
To perform actions that require interaction with Ethereum blockchain
you need to install MetaMask (or compatible) wallet.
</span>
{props.context.freezeStatus === 'frozen' && (
<span className="font-medium">
Even if you haven't used MetaMask to create your account on the
exchange, you can trigger Escape Hatch operations for your
positions using a different Ethereum account. See our{' '}
<Link href="/faqescapehatch#what-if-i-don-t-have-a-metamask-compatible-wallet">
FAQ
</Link>{' '}
for more details.
</span>
)}
</div>
<Card>
<div className="flex flex-col items-center gap-4 md:flex-row md:justify-between">
<img
src="https://images.ctfassets.net/9sy2a0egs6zh/2qy1wS5MmZOXkXn9yFlGJp/f3797a512c283e6f71450abd408b7452/mm-logo-white.svg"
className="h-14"
/>
<Button
as="a"
href="https://metamask.io/"
className="h-14 w-[300px] !text-lg max-md:w-full"
>
Install
</Button>
</div>
</Card>
</ContentWrapper>
</Page>
)
}

export function renderInstallMetaMaskPage(props: Props) {
return reactToHtml(<InstallMetaMaskPage {...props} />)
}
36 changes: 36 additions & 0 deletions packages/frontend/src/view/pages/user/UserNotAssociatedPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PageContextWithUser } from '@explorer/shared'
import React from 'react'

import { ContentWrapper } from '../../components/page/ContentWrapper'
import { Page } from '../../components/page/Page'
import { reactToHtml } from '../../reactToHtml'

interface UserNotAssociatedPageProps {
context: PageContextWithUser
}

function UserNotAssociatedPage(props: UserNotAssociatedPageProps) {
return (
<Page
context={props.context}
description="Register your Stark key to your ethereum address"
path="/users/register"
>
<ContentWrapper>
<div className="text-xxl font-semibold">
The wallet is not associated with any active position
</div>
<div className="mt-6 font-medium leading-5">
It seems this wallet isn't associated with any active positions at the
moment. Please make sure you're connected to the correct wallet. If
you're a new user and have recently deposited funds to the exchange,
please allow some time for the blockchain to update.
</div>
</ContentWrapper>
</Page>
)
}

export function renderUserNotAssociatedPage(props: UserNotAssociatedPageProps) {
return reactToHtml(<UserNotAssociatedPage {...props} />)
}
Loading