Skip to content

Commit

Permalink
Merge pull request #22 from chain-notes-brussels/mynewbranch
Browse files Browse the repository at this point in the history
Mynewbranch
  • Loading branch information
sandrotbilisi authored Jul 13, 2024
2 parents 42eafbd + ac882de commit 8c3b580
Show file tree
Hide file tree
Showing 59 changed files with 727 additions and 5 deletions.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/_components/BackButton.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx
100644 → 100755
Empty file.
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/_components/SearchBar.tsx
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/_components/index.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/address/[address]/page.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/layout.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/page.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx
100644 → 100755
Empty file.
Empty file.
1 change: 1 addition & 0 deletions packages/nextjs/app/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { defaultSnapOrigin } from './snap';
11 changes: 11 additions & 0 deletions packages/nextjs/app/config/snap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* The snap origin to use.
* Will default to the local hosted snap if no value is provided in environment.
*
* You may be tempted to change this to the URL where your production snap is hosted, but please
* don't. Instead, rename `.env.production.dist` to `.env.production` and set the production URL
* there. Running `yarn build` will automatically use the production environment variables.
*/
export const defaultSnapOrigin =
// eslint-disable-next-line no-restricted-globals
process.env.SNAP_ORIGIN ?? `local:http://localhost:8080`;
187 changes: 187 additions & 0 deletions packages/nextjs/app/config/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import type { DefaultTheme } from 'styled-components';
import { createGlobalStyle } from 'styled-components';

const breakpoints = ['600px', '768px', '992px'];

/**
* Common theme properties.
*/
const theme = {
fonts: {
default:
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
code: 'ui-monospace,Menlo,Monaco,"Cascadia Mono","Segoe UI Mono","Roboto Mono","Oxygen Mono","Ubuntu Monospace","Source Code Pro","Fira Mono","Droid Sans Mono","Courier New", monospace',
},
fontSizes: {
heading: '5.2rem',
mobileHeading: '3.6rem',
title: '2.4rem',
large: '2rem',
text: '1.6rem',
small: '1.4rem',
},
radii: {
default: '24px',
button: '8px',
},
breakpoints,
mediaQueries: {
small: `@media screen and (max-width: ${breakpoints[0] as string})`,
medium: `@media screen and (min-width: ${breakpoints[1] as string})`,
large: `@media screen and (min-width: ${breakpoints[2] as string})`,
},
shadows: {
default: '0px 7px 42px rgba(0, 0, 0, 0.1)',
button: '0px 0px 16.1786px rgba(0, 0, 0, 0.15);',
},
};

/**
* Light theme color properties.
*/
export const light: DefaultTheme = {
colors: {
background: {
default: '#FFFFFF',
alternative: '#F2F4F6',
inverse: '#141618',
},
icon: {
default: '#141618',
alternative: '#BBC0C5',
},
text: {
default: '#24272A',
muted: '#6A737D',
alternative: '#535A61',
inverse: '#FFFFFF',
},
border: {
default: '#BBC0C5',
},
primary: {
default: '#6F4CFF',
inverse: '#FFFFFF',
},
card: {
default: '#FFFFFF',
},
error: {
default: '#d73a49',
alternative: '#b92534',
muted: '#d73a4919',
},
},
...theme,
};

/**
* Dark theme color properties
*/
export const dark: DefaultTheme = {
colors: {
background: {
default: '#24272A',
alternative: '#141618',
inverse: '#FFFFFF',
},
icon: {
default: '#FFFFFF',
alternative: '#BBC0C5',
},
text: {
default: '#FFFFFF',
muted: '#FFFFFF',
alternative: '#D6D9DC',
inverse: '#24272A',
},
border: {
default: '#848C96',
},
primary: {
default: '#6F4CFF',
inverse: '#FFFFFF',
},
card: {
default: '#141618',
},
error: {
default: '#d73a49',
alternative: '#b92534',
muted: '#d73a4919',
},
},
...theme,
};

/**
* Default style applied to the app.
*
* @param props - Styled Components props.
* @returns Global style React component.
*/
export const GlobalStyle = createGlobalStyle`
html {
/* 62.5% of the base size of 16px = 10px.*/
font-size: 62.5%;
}
body {
background-color: ${(props) => props.theme.colors.background?.default};
color: ${(props) => props.theme.colors.text?.default};
font-family: ${(props) => props.theme.fonts.default};
font-size: ${(props) => props.theme.fontSizes.text};
margin: 0;
}
* {
transition: background-color .1s linear;
}
h1, h2, h3, h4, h5, h6 {
font-size: ${(props) => props.theme.fontSizes.heading};
${(props) => props.theme.mediaQueries.small} {
font-size: ${(props) => props.theme.fontSizes.mobileHeading};
}
}
code {
background-color: ${(props) => props.theme.colors.background?.alternative};
font-family: ${(props) => props.theme.fonts.code};
padding: 1.2rem;
font-weight: normal;
font-size: ${(props) => props.theme.fontSizes.text};
}
button {
font-size: ${(props) => props.theme.fontSizes.small};
border-radius: ${(props) => props.theme.radii.button};
background-color: ${(props) => props.theme.colors.background?.inverse};
color: ${(props) => props.theme.colors.text?.inverse};
border: 1px solid ${(props) => props.theme.colors.background?.inverse};
font-weight: bold;
padding: 1rem;
min-height: 4.2rem;
cursor: pointer;
transition: all .2s ease-in-out;
&:hover {
background-color: transparent;
border: 1px solid ${(props) => props.theme.colors.background?.inverse};
color: ${(props) => props.theme.colors.text?.default};
}
&:disabled,
&[disabled] {
border: 1px solid ${(props) => props.theme.colors.background?.inverse};
cursor: not-allowed;
}
&:disabled:hover,
&[disabled]:hover {
background-color: ${(props) => props.theme.colors.background?.inverse};
color: ${(props) => props.theme.colors.text?.inverse};
border: 1px solid ${(props) => props.theme.colors.background?.inverse};
}
}
`;
Empty file modified packages/nextjs/app/create/page.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/debug/_components/DebugContracts.tsx
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file modified packages/nextjs/app/debug/_components/contract/ContractUI.tsx
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file modified packages/nextjs/app/debug/_components/contract/Tuple.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/debug/_components/contract/TupleArray.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/debug/_components/contract/TxReceipt.tsx
100644 → 100755
Empty file.
Empty file.
Empty file modified packages/nextjs/app/debug/_components/contract/index.tsx
100644 → 100755
Empty file.
Empty file.
Empty file modified packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx
100644 → 100755
Empty file.
Empty file modified packages/nextjs/app/debug/page.tsx
100644 → 100755
Empty file.
74 changes: 74 additions & 0 deletions packages/nextjs/app/hooks/MetamaskContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { MetaMaskInpageProvider } from '@metamask/providers';
import type { ReactNode } from 'react';
import { createContext, useContext, useEffect, useState } from 'react';

import type { Snap } from '../types';
import { getSnapsProvider } from '../utils';

type MetaMaskContextType = {
provider: MetaMaskInpageProvider | null;
installedSnap: Snap | null;
error: Error | null;
setInstalledSnap: (snap: Snap | null) => void;
setError: (error: Error) => void;
};

export const MetaMaskContext = createContext<MetaMaskContextType>({
provider: null,
installedSnap: null,
error: null,
setInstalledSnap: () => {
/* no-op */
},
setError: () => {
/* no-op */
},
});

/**
* MetaMask context provider to handle MetaMask and snap status.
*
* @param props - React Props.
* @param props.children - React component to be wrapped by the Provider.
* @returns JSX.
*/
export const MetaMaskProvider = ({ children }: { children: ReactNode }) => {
const [provider, setProvider] = useState<MetaMaskInpageProvider | null>(null);
const [installedSnap, setInstalledSnap] = useState<Snap | null>(null);
const [error, setError] = useState<Error | null>(null);

useEffect(() => {
getSnapsProvider().then(setProvider).catch(console.error);
}, []);

useEffect(() => {
if (error) {
const timeout = setTimeout(() => {
setError(null);
}, 10000);

return () => {
clearTimeout(timeout);
};
}

return undefined;
}, [error]);

return (
<MetaMaskContext.Provider
value={{ provider, error, setError, installedSnap, setInstalledSnap }}
>
{children}
</MetaMaskContext.Provider>
);
};

/**
* Utility hook to consume the MetaMask context.
*
* @returns The MetaMask context.
*/
export function useMetaMaskContext() {
return useContext(MetaMaskContext);
}
5 changes: 5 additions & 0 deletions packages/nextjs/app/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './MetamaskContext';
export * from './useInvokeSnap';
export * from './useMetaMask';
export * from './useRequest';
export * from './useRequestSnap';
37 changes: 37 additions & 0 deletions packages/nextjs/app/hooks/useInvokeSnap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { defaultSnapOrigin } from '../config';
import { useRequest } from './useRequest';

export type InvokeSnapParams = {
method: string;
params?: Record<string, unknown>;
};

/**
* Utility hook to wrap the `wallet_invokeSnap` method.
*
* @param snapId - The Snap ID to invoke. Defaults to the snap ID specified in the
* config.
* @returns The invokeSnap wrapper method.
*/
export const useInvokeSnap = (snapId = defaultSnapOrigin) => {
const request = useRequest();

/**
* Invoke the requested Snap method.
*
* @param params - The invoke params.
* @param params.method - The method name.
* @param params.params - The method params.
* @returns The Snap response.
*/
const invokeSnap = async ({ method, params }: InvokeSnapParams) =>
request({
method: 'wallet_invokeSnap',
params: {
snapId,
request: params ? { method, params } : { method },
},
});

return invokeSnap;
};
56 changes: 56 additions & 0 deletions packages/nextjs/app/hooks/useMetaMask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useEffect, useState } from 'react';

import { defaultSnapOrigin } from '../config';
import type { GetSnapsResponse } from '../types';
import { useMetaMaskContext } from './MetamaskContext';
import { useRequest } from './useRequest';

/**
* A Hook to retrieve useful data from MetaMask.
* @returns The informations.
*/
export const useMetaMask = () => {
const { provider, setInstalledSnap, installedSnap } = useMetaMaskContext();
const request = useRequest();

const [isFlask, setIsFlask] = useState(false);

const snapsDetected = provider !== null;

/**
* Detect if the version of MetaMask is Flask.
*/
const detectFlask = async () => {
const clientVersion = await request({
method: 'web3_clientVersion',
});

const isFlaskDetected = (clientVersion as string[])?.includes('flask');

setIsFlask(isFlaskDetected);
};

/**
* Get the Snap informations from MetaMask.
*/
const getSnap = async () => {
const snaps = (await request({
method: 'wallet_getSnaps',
})) as GetSnapsResponse;

setInstalledSnap(snaps[defaultSnapOrigin] ?? null);
};

useEffect(() => {
const detect = async () => {
if (provider) {
await detectFlask();
await getSnap();
}
};

detect().catch(console.error);
}, [provider]);

return { isFlask, snapsDetected, installedSnap, getSnap };
};
Loading

0 comments on commit 8c3b580

Please sign in to comment.