Skip to content

Commit

Permalink
Adding Matchday UI changes (solana-labs#4)
Browse files Browse the repository at this point in the history
* Adding Matchday

* Adding Matchday-related UI

* Adding the additional scopes for Matchday

* Removing .env
  • Loading branch information
jnwng committed Dec 12, 2022
1 parent 9c6f9d7 commit f79f64d
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 70 deletions.
10 changes: 10 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Run in context of one realm: starts with default realm and disables realms page navigation
# REALM=MNGO
MAINNET_RPC=https://mango.rpcpool.com
DEVNET_RPC=https://mango.devnet.rpcpool.com

DEFAULT_GOVERNANCE_PROGRAM_ID=GTesTBiEWE32WHXXE2S4XbZvA5CrEc4xs6ZgRe895dP

NEXT_PUBLIC_API_ENDPOINT=http://localhost:3001/graphql
NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID=1042836142560645130
NEXT_PUBLIC_DISCORD_MATCHDAY_CLIENT_ID=1044361939322683442
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ DEFAULT_GOVERNANCE_PROGRAM_ID=GTesTBiEWE32WHXXE2S4XbZvA5CrEc4xs6ZgRe895dP

NEXT_PUBLIC_API_ENDPOINT=https://api.realms.today/graphql
NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID=1042836142560645130
NEXT_PUBLIC_DISCORD_MATCHDAY_CLIENT_ID=1044361939322683442
5 changes: 4 additions & 1 deletion pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ export default function App({ Component, pageProps, router }: AppProps) {
return <Component {...pageProps} />
}

if (router.pathname.startsWith('/verify-wallet')) {
if (
router.pathname.startsWith('/verify-wallet') ||
router.pathname.startsWith('/matchday/verify-wallet')
) {
return (
<HubApp minimal>
<Component {...pageProps} />
Expand Down
17 changes: 17 additions & 0 deletions pages/matchday/verify-wallet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Application } from '@verify-wallet/constants'
import VerifyPage from '@verify-wallet/components'

const MatchdayVerifyPage = () => {
const parsedLocationHash = new URLSearchParams(
window.location.search.substring(1)
)

return (
<VerifyPage
application={Application.MATCHDAY}
discordCode={parsedLocationHash.get('code')}
/>
)
}

export default MatchdayVerifyPage
59 changes: 7 additions & 52 deletions pages/verify-wallet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,15 @@
import { GlobalFooter } from '@verify-wallet/components/footer'
import cx from '@hub/lib/cx'
import VerifyWallet from '@verify-wallet/components'
import { Application } from '@verify-wallet/constants'

import React from 'react'
import { StepOne } from '@verify-wallet/components/step-one'
import { StepTwo } from '@verify-wallet/components/step-two'
import { StepThree } from '@verify-wallet/components/step-three'
import { useQuery } from '@hub/hooks/useQuery'
import * as gql from '@hub/components/GlobalHeader/User/gql'

enum VerifyWalletSteps {
SIGN_IN_WITH_SOLANA, // Step one
AUTHORIZE_DISCORD_OAUTH, // Step two
UPDATE_DISCORD_METADATA, // Step three
}

const getCurrentStep = ({ user }, accessToken) => {
if (user && !user.error) {
if (accessToken) {
return VerifyWalletSteps.UPDATE_DISCORD_METADATA
} else {
return VerifyWalletSteps.AUTHORIZE_DISCORD_OAUTH
}
}
return VerifyWalletSteps.SIGN_IN_WITH_SOLANA
}

const VerifyWallet = (/* props: Props */) => {
export default () => {
const parsedLocationHash = new URLSearchParams(
window.location.search.substring(1)
)
const [user] = useQuery(gql.getUserResp, { query: gql.getUser })

const currentStep = getCurrentStep({ user }, parsedLocationHash.get('code'))

return (
<>
<div
className={cx('grid', 'overflow-x-visible', 'pt-14', 'min-h-screen')}
>
<div className={cx('overflow-hidden', 'w-full', 'py-8')}>
<div className="grid justify-items-center">
{currentStep === VerifyWalletSteps.SIGN_IN_WITH_SOLANA && (
<StepOne />
)}
{currentStep === VerifyWalletSteps.AUTHORIZE_DISCORD_OAUTH && (
<StepTwo />
)}
{currentStep === VerifyWalletSteps.UPDATE_DISCORD_METADATA && (
<StepThree />
)}
</div>
</div>
</div>
<GlobalFooter className="absolute bottom-0 w-full mx-auto pt-8 bg-white h-[138px]" />
</>
<VerifyWallet
application={Application.SOLANA}
discordCode={parsedLocationHash.get('code')}
/>
)
}

export default VerifyWallet
Binary file added public/verify-wallet/img/logo-matchday.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions verify-wallet/components/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const VerifyWalletResponse = IT.type({
});

export const verifyWallet = gql`
mutation($code: String!) {
verifyWallet(code: $code) {
mutation($code: String!, $application: DiscordApplication = SOLANA) {
verifyWallet(code: $code, application: $application) {
publicKey
}
}
Expand Down
61 changes: 61 additions & 0 deletions verify-wallet/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { GlobalFooter } from '@verify-wallet/components/footer';
import { StepOne } from '@verify-wallet/components/step-one';
import { StepThree } from '@verify-wallet/components/step-three';
import { StepTwo } from '@verify-wallet/components/step-two';
import { Application } from '@verify-wallet/constants';

import { useJWT } from '@hub/hooks/useJWT';
import cx from '@hub/lib/cx';

enum VerifyWalletSteps {
SIGN_IN_WITH_SOLANA, // Step one
AUTHORIZE_DISCORD_OAUTH, // Step two
UPDATE_DISCORD_METADATA, // Step three
}

const getCurrentStep = (jwt: string | null, oauthCode: string | null) => {
if (jwt) {
if (oauthCode) {
return VerifyWalletSteps.UPDATE_DISCORD_METADATA;
} else {
return VerifyWalletSteps.AUTHORIZE_DISCORD_OAUTH;
}
}
return VerifyWalletSteps.SIGN_IN_WITH_SOLANA;
};

interface Props {
application: Application;
discordCode: string | null;
}

const VerifyWallet = (props: Props) => {
const [jwt] = useJWT();

const currentStep = getCurrentStep(jwt, props.discordCode);

return (
<>
<div
className={cx('grid', 'overflow-x-visible', 'pt-14', 'min-h-screen')}
>
<div className={cx('overflow-hidden', 'w-full', 'py-8')}>
<div className="grid justify-items-center">
{currentStep === VerifyWalletSteps.SIGN_IN_WITH_SOLANA && (
<StepOne application={props.application} />
)}
{currentStep === VerifyWalletSteps.AUTHORIZE_DISCORD_OAUTH && (
<StepTwo application={props.application} />
)}
{currentStep === VerifyWalletSteps.UPDATE_DISCORD_METADATA && (
<StepThree application={props.application} />
)}
</div>
</div>
</div>
<GlobalFooter className="absolute bottom-0 w-full mx-auto pt-8 bg-white h-[138px]" />
</>
);
};

export default VerifyWallet;
23 changes: 21 additions & 2 deletions verify-wallet/components/step-one.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { SignInWithSolana as SignInWithSolanaButton } from '@verify-wallet/components/sign-in-with-solana';

import { Application } from '@verify-wallet/constants';

import { SolanaLogo } from '@hub/components/branding/SolanaLogo';

const DirectionRightIcon = () => (
Expand All @@ -20,10 +22,27 @@ const DiscordLogo = () => (
/>
);

export const StepOne = () => (
const MatchdayLogo = () => (
<img
src="/verify-wallet/img/logo-matchday.png"
alt="Matchday"
height="64px"
width="64px"
/>
);

interface Props {
application: Application;
}

export const StepOne = (props: Props) => (
<>
<div className="flex align-middle gap-2">
<SolanaLogo height="64px" />
{props.application === Application.SOLANA ? (
<SolanaLogo height="64px" />
) : (
<MatchdayLogo />
)}
<DirectionRightIcon />
<DiscordLogo />
</div>
Expand Down
30 changes: 23 additions & 7 deletions verify-wallet/components/step-three.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { XIcon } from '@heroicons/react/solid';
import { Application } from '@verify-wallet/constants';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';

Expand Down Expand Up @@ -27,13 +28,26 @@ const ConnectedIcon = () => (
/>
);

const MatchdayLogo = () => (
<img
src="/verify-wallet/img/logo-matchday.png"
alt="Matchday"
height="64px"
width="64px"
/>
);

enum VerifyWalletState {
FAILED,
VERIFYING,
VERIFIED,
}

const Prompt = () => {
interface Props {
application: Application;
}

export const StepThree = (props: Props) => {
const [, verifyWallet] = useMutation(
gqlWallet.verifyWalletResp,
gqlWallet.verifyWallet,
Expand All @@ -50,14 +64,16 @@ const Prompt = () => {
try {
const verifyWalletResult = await verifyWallet({
code: parsedLocationHash.get('code'),
application:
props.application == Application.MATCHDAY ? 'MATCHDAY' : 'SOLANA',
});

if (RE.isFailed(verifyWalletResult)) {
// Likely an issue like the Discord code has already been used
setStatus(VerifyWalletState.FAILED);
console.error(verifyWalletResult.error);
setTimeout(() => {
router.push('/verify-wallet');
router.push(window.location.pathname);
}, 5000);
throw verifyWalletResult.error;
}
Expand Down Expand Up @@ -95,7 +111,11 @@ const Prompt = () => {
return (
<>
<div className="flex align-middle gap-2">
<SolanaLogo height="64px" />
{props.application === Application.MATCHDAY ? (
<MatchdayLogo />
) : (
<SolanaLogo height="64px" />
)}
<ConnectedIcon />
<ConnectedDiscordIcon />
</div>
Expand All @@ -109,7 +129,3 @@ const Prompt = () => {
);
}
};

export const StepThree = () => {
return <Prompt />;
};
30 changes: 24 additions & 6 deletions verify-wallet/components/step-two.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Application } from '@verify-wallet/constants';

const SolanaConnectedIcon = () => (
<img
src="/verify-wallet/img/icon-solana-connected.svg"
Expand All @@ -7,15 +9,31 @@ const SolanaConnectedIcon = () => (
/>
);

export const StepTwo = () => {
interface Props {
application: Application;
}

export const StepTwo = (props: Props) => {
const DISCORD_CLIENT_ID =
props.application === Application.SOLANA
? process.env.NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID!
: process.env.NEXT_PUBLIC_DISCORD_MATCHDAY_CLIENT_ID!;

const discordRedirectURI = encodeURI(
`${window.location.protocol}//${window.location.host}${window.location.pathname}`,
);

const scopes = ['role_connections.write'];
if (props.application === Application.MATCHDAY) {
scopes.push('identify');
}

const DISCORD_AUTHORIZE_URL = `https://discord.com/api/oauth2/authorize?${new URLSearchParams(
{
client_id: process.env.NEXT_PUBLIC_DISCORD_APPLICATION_CLIENT_ID!,
redirect_uri: encodeURI(
`${window.location.protocol}//${window.location.host}/verify-wallet`,
),
client_id: DISCORD_CLIENT_ID,
redirect_uri: discordRedirectURI,
response_type: 'code',
scope: ['role_connections.write'].join(' '),
scope: scopes.join(' '),
},
)}`;

Expand Down
4 changes: 4 additions & 0 deletions verify-wallet/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Application {
SOLANA,
MATCHDAY,
}

0 comments on commit f79f64d

Please sign in to comment.