uniswap-interface learning

repo 不会 React 只能看个大概

website

Start
1
2
3
4
git clone repo-git
cd repo-name
yarn
yarn start
Entry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/index.tsx

ReactDOM.render(
<StrictMode>
<FixedGlobalStyle />
<Web3ReactProvider getLibrary={getLibrary}>
<Web3ProviderNetwork getLibrary={getLibrary}>
<Provider store={store}>
<Updaters />
<ThemeProvider>
<ThemedGlobalStyle />
<App />
</ThemeProvider>
</Provider>
</Web3ProviderNetwork>
</Web3ReactProvider>
</StrictMode>,
document.getElementById('root')
)
  1. StrictMode React StrictMode 解释

  2. FixedGlobalStyle theme file

    1
    import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from './theme'
  3. Web3ReactProvider、Web3ProviderNetwork https://github.com/NoahZinsmeister/web3-react/tree/v6/docs

    1
    import { createWeb3ReactRoot, Web3ReactProvider } from '@web3-react/core'

    Example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import { Web3ReactProvider, createWeb3ReactRoot } from '@web3-react/core'
    // import your favorite web3 convenience library here

    function getLibrary(provider) {
    return new Web3Provider(provider) // this will vary according to whether you use e.g. ethers or web3.js
    }

    const Web3ReactProviderReloaded = createWeb3ReactRoot('anotherOne')

    function App () {
    return (
    <Web3ReactProvider getLibrary={getLibrary}>
    <Web3ReactProviderReloaded getLibrary={getLibrary}>
    {/* <...> */}
    </Web3ReactProviderReloaded>
    </Web3ReactProvider>
    )
    }
  1. Provider

    1
    import { Provider } from 'react-redux'

    Example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import React from 'react'
    import ReactDOM from 'react-dom'

    import { Provider } from 'react-redux'
    import store from './store'

    import App from './App'

    const rootElement = document.getElementById('root')
    ReactDOM.render(
    <Provider store={store}>
    <App />
    </Provider>,
    rootElement
    )
  2. Updaters

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <Updaters />

    // ...

    function Updaters() {
    return (
    <>
    <ListsUpdater />
    <UserUpdater />
    <ApplicationUpdater />
    <TransactionUpdater />
    <MulticallUpdater />
    </>
    )
    }

    // ...

    import store from './state'
    import ApplicationUpdater from './state/application/updater'
    import ListsUpdater from './state/lists/updater'
    import MulticallUpdater from './state/multicall/updater'
    import TransactionUpdater from './state/transactions/updater'
    import UserUpdater from './state/user/updater'
  3. ThemeProvider

    1
    2
    3
    import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from './theme'
    // ...
    <ThemeProvider>
  4. App 内容

    1
    2
    3
    4
    5
    import App from './pages/App'

    // ...

    <App />
APP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
export default function App() {
return (
<Suspense fallback={null}>
<HashRouter>
<Route component={GoogleAnalyticsReporter} />
<Route component={DarkModeQueryParamReader} />
<AppWrapper>
<HeaderWrapper>
<Header />
</HeaderWrapper>
<BodyWrapper>
<Popups />
<Web3ReactManager>
<Switch>
<Route exact strict path="/swap" component={Swap} />
<Route exact strict path="/swap/:outputCurrency" component={RedirectToSwap} />
<Route exact strict path="/send" component={RedirectPathToSwapOnly} />
<Route exact strict path="/find" component={PoolFinder} />
<Route exact strict path="/pool" component={Pool} />
<Route exact strict path="/create" component={RedirectToAddLiquidity} />
<Route exact path="/add" component={AddLiquidity} />
<Route exact path="/add/:currencyIdA" component={RedirectOldAddLiquidityPathStructure} />
<Route exact path="/add/:currencyIdA/:currencyIdB" component={RedirectDuplicateTokenIds} />
<Route exact strict path="/remove/v1/:address" component={RemoveV1Exchange} />
<Route exact strict path="/remove/:tokens" component={RedirectOldRemoveLiquidityPathStructure} />
<Route exact strict path="/remove/:currencyIdA/:currencyIdB" component={RemoveLiquidity} />
<Route exact strict path="/migrate/v1" component={MigrateV1} />
<Route exact strict path="/migrate/v1/:address" component={MigrateV1Exchange} />
<Route component={RedirectPathToSwapOnly} />
</Switch>
</Web3ReactManager>
<Marginer />
</BodyWrapper>
</AppWrapper>
</HashRouter>
</Suspense>
)
}
  1. <Suspense fallback={null}>

    1
    <Suspense fallback={null}>

    https://reactjs.org/docs/concurrent-mode-suspense.html

  2. HashRouter、Route、Switch

    1
    import { HashRouter, Route, Switch } from 'react-router-dom'
  3. AppWrapper、HeaderWrapper、BodyWrapper、Marginer

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    const AppWrapper = styled.div`
    display: flex;
    flex-flow: column;
    align-items: flex-start;
    overflow-x: hidden;
    `

    const HeaderWrapper = styled.div`
    ${({ theme }) => theme.flexRowNoWrap}
    width: 100%;
    justify-content: space-between;
    `

    const BodyWrapper = styled.div`
    display: flex;
    flex-direction: column;
    width: 100%;
    padding-top: 160px;
    align-items: center;
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    z-index: 10;

    ${({ theme }) => theme.mediaWidth.upToExtraSmall`
    padding: 16px;
    `};

    z-index: 1;
    `

    const Marginer = styled.div`
    margin-top: 5rem;
    `
  4. Header、Popups Component

    1
    2
    3
    4
    5
    <Header />

    // ...

    <Popups />
  5. Web3ReactManager 应该是 web3 的代码 暂未理解

    1
    2
    3
    import Web3ReactManager from '../components/Web3ReactManager'
    /// ...
    <Web3ReactManager>
  6. Route

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <Route exact strict path="/swap" component={Swap} />
    <Route exact strict path="/swap/:outputCurrency" component={RedirectToSwap} />
    <Route exact strict path="/send" component={RedirectPathToSwapOnly} />
    <Route exact strict path="/find" component={PoolFinder} />
    <Route exact strict path="/pool" component={Pool} />
    <Route exact strict path="/create" component={RedirectToAddLiquidity} />
    <Route exact path="/add" component={AddLiquidity} />
    <Route exact path="/add/:currencyIdA" component={RedirectOldAddLiquidityPathStructure} />
    <Route exact path="/add/:currencyIdA/:currencyIdB" component={RedirectDuplicateTokenIds} />
    <Route exact strict path="/remove/v1/:address" component={RemoveV1Exchange} />
    <Route exact strict path="/remove/:tokens" component={RedirectOldRemoveLiquidityPathStructure} />
    <Route exact strict path="/remove/:currencyIdA/:currencyIdB" component={RemoveLiquidity} />
    <Route exact strict path="/migrate/v1" component={MigrateV1} />
    <Route exact strict path="/migrate/v1/:address" component={MigrateV1Exchange} />
    <Route component={RedirectPathToSwapOnly} />
    1. /swap page

      Imgur

    2. /swap/:outputCurrency 会 redirect

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      // Redirects from the /swap/:outputCurrency path to the /swap?outputCurrency=:outputCurrency format
      export function RedirectToSwap(props: RouteComponentProps<{ outputCurrency: string }>) {
      const {
      location: { search },
      match: {
      params: { outputCurrency }
      }
      } = props

      return (
      <Redirect
      to={{
      ...props.location,
      pathname: '/swap',
      search:
      search && search.length > 1
      ? `${search}&outputCurrency=${outputCurrency}`
      : `?outputCurrency=${outputCurrency}`
      }}
      />
      )
      }
    3. /send 会 redirect

      1
      2
      3
      4
      // Redirects to swap but only replace the pathname
      export function RedirectPathToSwapOnly({ location }: RouteComponentProps) {
      return <Redirect to={{ ...location, pathname: '/swap' }} />
      }
    4. /find Import Pool Select a token to find your liquidity. 导入 your pool

      Imgur


      Imgur

  7. /pool 界面和上面一样

  8. /create redirect

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import {
    RedirectDuplicateTokenIds,
    RedirectOldAddLiquidityPathStructure,
    RedirectToAddLiquidity
    } from './AddLiquidity/redirects'

    export function RedirectToAddLiquidity() {
    return <Redirect to="/add/" />
    }
  9. /add

    Imgur

  10. /add/:currencyIdA redirect

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const OLD_PATH_STRUCTURE = /^(0x[a-fA-F0-9]{40})-(0x[a-fA-F0-9]{40})$/
    export function RedirectOldAddLiquidityPathStructure(props: RouteComponentProps<{ currencyIdA: string }>) {
    const {
    match: {
    params: { currencyIdA }
    }
    } = props
    const match = currencyIdA.match(OLD_PATH_STRUCTURE)
    if (match?.length) {
    return <Redirect to={`/add/${match[1]}/${match[2]}`} />
    }

    return <AddLiquidity {...props} />
    }
  11. /add/:currencyIdA/:currencyIdB redirect

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    export function RedirectDuplicateTokenIds(props: RouteComponentProps<{ currencyIdA: string; currencyIdB: string }>) {
    const {
    match: {
    params: { currencyIdA, currencyIdB }
    }
    } = props
    if (currencyIdA.toLowerCase() === currencyIdB.toLowerCase()) {
    return <Redirect to={`/add/${currencyIdA}`} />
    }
    return <AddLiquidity {...props} />
    }
  12. /remove/v1/:address

    Imgur

  13. /remove/:tokens redirect

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    export function RedirectOldRemoveLiquidityPathStructure({
    match: {
    params: { tokens }
    }
    }: RouteComponentProps<{ tokens: string }>) {
    if (!OLD_PATH_STRUCTURE.test(tokens)) {
    return <Redirect to="/pool" />
    }
    const [currency0, currency1] = tokens.split('-')

    return <Redirect to={`/remove/${currency0}/${currency1}`} />
    }
  14. /remove/:currencyIdA/:currencyIdB

    Imgur

  15. /migrate/v1

    Imgur

  16. /migrate/v1/:address

    Imgur

  17. other route redirect

    1
    2
    3
    4
    // Redirects to swap but only replace the pathname
    export function RedirectPathToSwapOnly({ location }: RouteComponentProps) {
    return <Redirect to={{ ...location, pathname: '/swap' }} />
    }

更复杂的代码没有继续看了, 只看了一下大概的结构, 后续学习了会继续更新

打赏测试