├── .circleci └── config.yml ├── .dockerignore ├── .editorconfig ├── .env.example ├── .eslintrc.json ├── .gitignore ├── .nvmrc ├── .prettierrc ├── CONFIG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── THEMES.md ├── package.json ├── public ├── _redirects ├── assets │ └── icons │ │ ├── dai.svg │ │ ├── dgx.svg │ │ ├── mkr.svg │ │ ├── mln.svg │ │ ├── rep.svg │ │ ├── weth.svg │ │ └── zrx.svg ├── favicons │ ├── favicon-114.png │ ├── favicon-120.png │ ├── favicon-144.png │ ├── favicon-152.png │ ├── favicon-16.png │ ├── favicon-256.png │ ├── favicon-32.png │ ├── favicon-48.png │ ├── favicon-57.png │ ├── favicon-64.png │ ├── favicon-72.png │ ├── favicon.html │ └── favicon.ico ├── index.html └── manifest.json ├── src ├── assets │ └── icons │ │ ├── ae.svg │ │ ├── agi.svg │ │ ├── ant.svg │ │ ├── ast.svg │ │ ├── bat.svg │ │ ├── cvc.svg │ │ ├── dai.svg │ │ ├── dgd.svg │ │ ├── dgx.svg │ │ ├── dnt.svg │ │ ├── erc20_logo.svg │ │ ├── erc721_logo.svg │ │ ├── fun.svg │ │ ├── gno.svg │ │ ├── gnt.svg │ │ ├── install_metamask.svg │ │ ├── knc.svg │ │ ├── link.svg │ │ ├── lpt.svg │ │ ├── mana.svg │ │ ├── mkr.svg │ │ ├── mln.svg │ │ ├── omg.svg │ │ ├── powr.svg │ │ ├── red_exclamation_sign.svg │ │ ├── ren.svg │ │ ├── rep.svg │ │ ├── req.svg │ │ ├── salt.svg │ │ ├── snt.svg │ │ ├── spank.svg │ │ ├── wax.svg │ │ ├── weth.svg │ │ ├── zil.svg │ │ └── zrx.svg ├── common │ ├── config.ts │ ├── configSchema.ts │ ├── constants.ts │ ├── markets.ts │ └── tokens_meta_data.ts ├── components │ ├── account │ │ ├── index.ts │ │ ├── wallet_connection_status.tsx │ │ ├── wallet_connections_status_dot.tsx │ │ ├── wallet_token_balances.tsx │ │ ├── wallet_weth_balance.tsx │ │ └── wallet_weth_modal.tsx │ ├── app.tsx │ ├── common │ │ ├── adblock_detector.tsx │ │ ├── big_number_input.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── card_base.tsx │ │ ├── card_tab_selector.tsx │ │ ├── centered_wrapper.tsx │ │ ├── check_metamask_state_modal_container.tsx │ │ ├── column_narrow.tsx │ │ ├── column_wide.tsx │ │ ├── dropdown.tsx │ │ ├── dropdown_text_item.tsx │ │ ├── empty_content.tsx │ │ ├── error_card.tsx │ │ ├── footer.tsx │ │ ├── icons │ │ │ ├── arrow_up_down_icon.tsx │ │ │ ├── bell_icon.tsx │ │ │ ├── chevron_down_icon.tsx │ │ │ ├── chevron_right_icon.tsx │ │ │ ├── close_icon.tsx │ │ │ ├── close_modal_button.tsx │ │ │ ├── filter_icon.tsx │ │ │ ├── icon_metamask_large.tsx │ │ │ ├── info_icon.tsx │ │ │ ├── info_icon_full.tsx │ │ │ ├── lock_icon.tsx │ │ │ ├── magnifier_icon.tsx │ │ │ ├── metamask_side_icon.tsx │ │ │ ├── notification_cancel_icon.tsx │ │ │ ├── notification_checkmark_icon.tsx │ │ │ ├── outside_url_icon.tsx │ │ │ ├── processing_icon.tsx │ │ │ ├── radio_icon.tsx │ │ │ ├── radio_icon_active.tsx │ │ │ ├── sad_icon.tsx │ │ │ ├── sort_icon.tsx │ │ │ ├── token_icon.tsx │ │ │ ├── view_all_icon.tsx │ │ │ ├── warning_icon.tsx │ │ │ └── warning_small_icon.tsx │ │ ├── interval.tsx │ │ ├── loading.tsx │ │ ├── logo.tsx │ │ ├── main_scrollable_wrapper.tsx │ │ ├── metamask_error_modal.tsx │ │ ├── pending_time.tsx │ │ ├── show_number_with_colors.tsx │ │ ├── spinner.tsx │ │ ├── steps_modal │ │ │ ├── base_step_modal.tsx │ │ │ ├── buy_sell_collectible_step.tsx │ │ │ ├── buy_sell_token_step.tsx │ │ │ ├── sign_order_step.tsx │ │ │ ├── step_pending_time.tsx │ │ │ ├── steps_common.tsx │ │ │ ├── steps_modal.tsx │ │ │ ├── steps_progress.tsx │ │ │ ├── toggle_token_lock_step.tsx │ │ │ ├── unlock_collectibles_step.tsx │ │ │ └── wrap_eth_step.tsx │ │ ├── table.tsx │ │ ├── toolbar.tsx │ │ ├── tooltip.tsx │ │ └── view_all.tsx │ ├── erc20 │ │ ├── account │ │ │ └── wallet_connection_content.tsx │ │ ├── common │ │ │ ├── content_wrapper.tsx │ │ │ ├── markets_dropdown.tsx │ │ │ └── toolbar_content.tsx │ │ ├── erc20_app.tsx │ │ ├── marketplace │ │ │ ├── buy_sell.tsx │ │ │ ├── cancel_order_button.tsx │ │ │ ├── grid_row_spread.tsx │ │ │ ├── order_book.tsx │ │ │ ├── order_details.tsx │ │ │ ├── order_history.tsx │ │ │ └── wallet_balance.tsx │ │ └── pages │ │ │ ├── marketplace.tsx │ │ │ └── my_wallet.tsx │ ├── erc721 │ │ ├── account │ │ │ └── wallet_connection_content.tsx │ │ ├── collectibles │ │ │ ├── collectible_card.tsx │ │ │ ├── collectible_details_item_list.tsx │ │ │ ├── collectible_details_item_tile.tsx │ │ │ ├── collectible_details_list.tsx │ │ │ ├── collectible_list_modal.tsx │ │ │ ├── collectible_sell_modal.tsx │ │ │ ├── collectibles_all.tsx │ │ │ ├── collectibles_card_list.tsx │ │ │ ├── collectibles_dropdown_button.tsx │ │ │ ├── collectibles_dropdown_container.tsx │ │ │ ├── collectibles_list.tsx │ │ │ ├── collectibles_list_filter.tsx │ │ │ ├── collectibles_list_sort.tsx │ │ │ ├── collectibles_search.tsx │ │ │ ├── owner_badge.tsx │ │ │ └── price_badge.tsx │ │ ├── common │ │ │ ├── content_wrapper.tsx │ │ │ ├── declining_price_graph.tsx │ │ │ ├── input_search.tsx │ │ │ └── toolbar_content.tsx │ │ ├── erc721_app.tsx │ │ ├── marketplace │ │ │ ├── collectible_buy_sell.tsx │ │ │ ├── collectible_description.tsx │ │ │ ├── dutch_auction_price_chart_card.tsx │ │ │ ├── marketplace_common.tsx │ │ │ ├── sell_collectibles_button.tsx │ │ │ └── trade_button.tsx │ │ ├── modals │ │ │ └── search-modal.tsx │ │ └── pages │ │ │ ├── all_collectibles.tsx │ │ │ ├── individual_collectible.tsx │ │ │ ├── list_collectibles.tsx │ │ │ └── my_collectibles.tsx │ ├── general_layout.tsx │ └── notifications │ │ ├── notification_item.tsx │ │ └── notifications_dropdown.tsx ├── config.json ├── exceptions │ ├── common.ts │ ├── component_unmounted_exception.ts │ ├── convert_balance_must_not_be_equal_exception.ts │ ├── insufficient_eth_deposit_balance_exception.ts │ ├── insufficient_fee_balance_exception.ts │ ├── insufficient_orders_amount_exception.ts │ ├── insufficient_token_balance_exception.ts │ ├── relayer_exception.ts │ ├── signature_failed_exception.ts │ ├── signed_order_exception.ts │ └── user_denied_transaction_exception.ts ├── global.d.ts ├── index.css ├── index.tsx ├── react-app-env.d.ts ├── serviceWorker.js ├── services │ ├── collectibles_metadata_gateway.ts │ ├── collectibles_metadata_sources │ │ ├── index.ts │ │ ├── mocked.ts │ │ └── opensea.ts │ ├── contract_wrappers.ts │ ├── exchange.ts │ ├── gas_price_estimation.ts │ ├── local_storage.ts │ ├── markets.ts │ ├── orders.ts │ ├── relayer.ts │ ├── tokens.ts │ └── web3_wrapper.ts ├── setupProxy.js ├── setupTests.js ├── store │ ├── actions.ts │ ├── blockchain │ │ ├── actions.ts │ │ └── reducers.ts │ ├── collectibles │ │ ├── actions.ts │ │ └── reducers.ts │ ├── index.ts │ ├── market │ │ ├── actions.ts │ │ └── reducers.ts │ ├── middlewares.ts │ ├── reducers.ts │ ├── relayer │ │ ├── actions.ts │ │ └── reducers.ts │ ├── router │ │ └── actions.ts │ ├── selectors.ts │ └── ui │ │ ├── actions.ts │ │ └── reducers.ts ├── styled.d.ts ├── tests │ ├── components │ │ ├── account │ │ │ ├── __snapshots__ │ │ │ │ └── wallet_token_balances.test.tsx.snap │ │ │ └── wallet_token_balances.test.tsx │ │ ├── common │ │ │ ├── __snapshots__ │ │ │ │ ├── show_number_with_colors.test.tsx.snap │ │ │ │ └── toolbar.test.tsx.snap │ │ │ ├── big_number_input.test.tsx │ │ │ ├── icons │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── token_icon.test.tsx.snap │ │ │ │ └── token_icon.test.tsx │ │ │ ├── markets_dropdown.test.tsx │ │ │ ├── pending_time.test.tsx │ │ │ ├── show_number_with_colors.test.tsx │ │ │ └── toolbar.test.tsx │ │ ├── erc20 │ │ │ └── marketplace │ │ │ │ ├── __snapshots__ │ │ │ │ └── order_book.test.tsx.snap │ │ │ │ ├── order_book.test.tsx │ │ │ │ ├── order_details.test.tsx │ │ │ │ └── wallet_balance.test.tsx │ │ └── erc721 │ │ │ ├── collectibles │ │ │ ├── __snapshots__ │ │ │ │ └── owner_badge.test.tsx.snap │ │ │ └── owner_badge.test.tsx │ │ │ └── marketplace │ │ │ └── trade_button.test.tsx │ ├── services │ │ └── collectibles_metadata_gateways.test.ts │ ├── store │ │ ├── actions │ │ │ └── blockchain.test.ts │ │ └── selectors.test.ts │ └── util │ │ ├── known_tokens.test.ts │ │ ├── logger.test.ts │ │ ├── markets.test.ts │ │ ├── notifications.test.ts │ │ ├── number_utils.test.ts │ │ ├── orders.test.ts │ │ ├── steps.test.ts │ │ ├── steps_modals_generation.test.ts │ │ ├── test_with_theme.tsx │ │ ├── tokens.test.ts │ │ └── ui_orders.test.ts ├── themes │ ├── commons.ts │ ├── dark_theme.ts │ ├── default_theme.ts │ ├── theme_meta_data.ts │ └── theme_meta_data_utils.ts └── util │ ├── cancelable_promises.ts │ ├── collectibles.ts │ ├── error_messages.ts │ ├── filterable_collectibles.ts │ ├── known_tokens.ts │ ├── logger.ts │ ├── markets.ts │ ├── notifications.ts │ ├── number_utils.ts │ ├── orders.ts │ ├── sleep.ts │ ├── sortable_collectibles.ts │ ├── steps.ts │ ├── steps_modals_generation.ts │ ├── test-utils.ts │ ├── time_utils.ts │ ├── token_meta_data.ts │ ├── tokens.ts │ ├── transaction_link.ts │ ├── transactions.ts │ ├── types.ts │ └── ui_orders.ts ├── tsconfig.json ├── tslint.json └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:10 6 | steps: 7 | - checkout 8 | - restore_cache: # special step to restore the dependency cache 9 | name: Restore Yarn Package Cache 10 | keys: 11 | - yarn-packages-{{ checksum "yarn.lock" }} 12 | - run: 13 | name: Setup Yarn Dependencies #install all the dependencies 14 | command: yarn install --frozen-lockfile 15 | - save_cache: #saves a cache of the installed dependencies 16 | name: Save Yarn Package Cache 17 | key: yarn-packages-{{ checksum "yarn.lock" }} 18 | paths: 19 | - ~/.cache/yarn 20 | - run: 21 | name: Lint checks 22 | command: yarn run lint 23 | - run: 24 | name: Tests 25 | command: yarn run test-once --maxWorkers 2 26 | - run: 27 | name: Coveralls 28 | command: COVERALLS_REPO_TOKEN=${COVERALLS_REPO_TOKEN} && yarn run coveralls 29 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | build 4 | /coverage 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # All files 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | charset = utf-8 11 | indent_style = space 12 | indent_size = 4 13 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_RELAYER_URL='http://localhost:3000/v3' 2 | REACT_APP_RELAYER_WS_URL='ws://localhost:3000/' 3 | REACT_APP_NETWORK_ID=50 4 | REACT_APP_CHAIN_ID=1337 5 | REACT_APP_FEE_PERCENTAGE='0' 6 | REACT_APP_FEE_RECIPIENT='0x0000000000000000000000000000000000000000' 7 | REACT_APP_DEFAULT_ORDER_EXPIRY_SECONDS=86400 8 | REACT_APP_NOTIFICATIONS_LIMIT=20 9 | REACT_APP_START_BLOCK_LIMIT=100000 10 | # 0 is disabled 11 | REACT_APP_UI_UPDATE_CHECK_INTERVAL=5000 12 | # 0 is disabled 13 | REACT_APP_UPDATE_ETHER_PRICE_INTERVAL=3600000 14 | REACT_APP_LOGGER_ID='0x-launch-kit-frontend' 15 | REACT_APP_STEP_MODAL_DONE_STATUS_VISIBILITY_TIME='3500' 16 | REACT_APP_COLLECTIBLES_SOURCE='opensea' 17 | REACT_APP_OPENSEA_API_KEY='abcdef0123456789abcdef0123456789' 18 | # Axie mainnet address 19 | REACT_APP_COLLECTIBLE_ADDRESS='0xf5b0a3efb8e8e4c201e2a935f110eaaf3ffecb8d' 20 | REACT_APP_COLLECTIBLE_NAME='CryptoKitties' 21 | REACT_APP_COLLECTIBLE_DESCRIPTION='CryptoKitties is a state of the art blockchain-based game, enabling users to trade and sell their cards freely, with the same level of ownership as if they were real, tangible cards.' 22 | REACT_APP_ERC20_THEME_NAME = 'DARK_THEME' 23 | REACT_APP_ERC721_THEME_NAME = 'LIGHT_THEME' 24 | REACT_APP_DEFAULT_BASE_PATH='/erc721' 25 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | #Webstorm 27 | .idea 28 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v10.15 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "printWidth": 120, 4 | "trailingComma": all, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12-alpine as yarn-install 2 | WORKDIR /app 3 | COPY package.json yarn.lock ./ 4 | RUN apk update && \ 5 | apk upgrade && \ 6 | apk add --no-cache --virtual build-dependencies bash git openssh python make g++ && \ 7 | yarn --no-cache || \ 8 | apk del build-dependencies && \ 9 | yarn cache clean 10 | 11 | # Stage 1 12 | FROM node:12-alpine as react-build 13 | WORKDIR /app 14 | COPY --from=yarn-install /app/node_modules /app/node_modules 15 | COPY . . 16 | RUN yarn build 17 | 18 | # Stage 2 - the production environment 19 | FROM nginx:alpine 20 | COPY --from=react-build /app/build /usr/share/nginx/html 21 | EXPOSE 80 22 | CMD ["nginx", "-g", "daemon off;"] 23 | -------------------------------------------------------------------------------- /THEMES.md: -------------------------------------------------------------------------------- 1 | # Custom themes guide 2 | 3 | ## How to add new themes 4 | 5 | By default the app uses a `LIGHT THEME` and there is also available a `DARK THEME`. 6 | 7 | If you want to customize the app with a custom theme you can add your own. 8 | 9 | ### How to create a new theme 10 | 11 | Note: All the relevant files are in the `src/themes` folder. 12 | 13 | For this example our new theme will be called `NEW THEME`. 14 | 15 | 1. Copy default_theme.ts to new_theme.ts 16 | 2. Change `export class DefaultTheme` to `export class NewTheme` in `new_theme.ts` 17 | 3. Add: 18 | `{ name: 'NEW_THEME', theme: new NewTheme(), },` 19 | in the `KNOWN_THEMES_META_DATA` array found in `themes/theme_meta_data.ts` 20 | 21 | 4. In your `.env` file change the value of `REACT_APP_THEME_NAME` from `DEFAULT_THEME` to `NEW_THEME` 22 | 23 | #### Dark Theme example 24 | 25 | dark_theme.ts: 26 | 27 | ```typescript 28 | const modalThemeStyle: ThemeModalStyle = { 29 | content: { 30 | ...... 31 | }, 32 | overlay: { 33 | ...... 34 | }, 35 | }; 36 | 37 | const darkThemeColors: ThemeProperties = { 38 | background: '#000', 39 | borderColor: '#5A5A5A', 40 | boxShadow: '0 10px 10px rgba(0, 0, 0, 0.1)', 41 | buttonConvertBackgroundColor: '#343434', 42 | buttonConvertBorderColor: '#000', 43 | buttonConvertTextColor: '#fff', 44 | ....... 45 | }; 46 | export class DarkTheme extends DefaultTheme { 47 | constructor() { 48 | super(); 49 | this.componentsTheme = darkThemeColors; 50 | this.modalTheme = modalThemeStyle; 51 | } 52 | } 53 | ``` 54 | 55 | theme_meta_data.ts object: 56 | 57 | ```typescript 58 | export const KNOWN_THEMES_META_DATA: ThemeMetaData[] = [ 59 | { 60 | name: 'DEFAULT_THEME', 61 | theme: new DefaultTheme(), 62 | }, 63 | { 64 | name: 'DARK_THEME', 65 | theme: new DarkTheme(), 66 | }, 67 | ]; 68 | ``` 69 | 70 | .env file: 71 | 72 | ``` 73 | ... 74 | REACT_APP_ERC20_THEME_NAME = 'DARK_THEME' 75 | REACT_APP_ERC721_THEME_NAME = 'LIGHT_THEME' 76 | 77 | ``` 78 | 79 | Note: you can configure the themes for the ERC20 and ERC721 app separately using those env vars. 80 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /public/assets/icons/dai.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/assets/icons/dgx.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/assets/icons/mkr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/assets/icons/mln.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/assets/icons/rep.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/assets/icons/weth.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/assets/icons/zrx.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/favicons/favicon-114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-114.png -------------------------------------------------------------------------------- /public/favicons/favicon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-120.png -------------------------------------------------------------------------------- /public/favicons/favicon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-144.png -------------------------------------------------------------------------------- /public/favicons/favicon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-152.png -------------------------------------------------------------------------------- /public/favicons/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-16.png -------------------------------------------------------------------------------- /public/favicons/favicon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-256.png -------------------------------------------------------------------------------- /public/favicons/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-32.png -------------------------------------------------------------------------------- /public/favicons/favicon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-48.png -------------------------------------------------------------------------------- /public/favicons/favicon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-57.png -------------------------------------------------------------------------------- /public/favicons/favicon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-64.png -------------------------------------------------------------------------------- /public/favicons/favicon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon-72.png -------------------------------------------------------------------------------- /public/favicons/favicon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /public/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xProject/0x-launch-kit-frontend/44272c9c22ed0e9e4cbdcdb880cfaffd086905cd/public/favicons/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 0x Launch Kit Frontend 25 | 26 | 27 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/assets/icons/ae.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/agi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/ant.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/ast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/bat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/cvc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/dai.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/dgd.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/dgx.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/dnt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/gno.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/gnt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/knc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/lpt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/assets/icons/mkr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/mln.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/powr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/red_exclamation_sign.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/icons/ren.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/icons/rep.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/icons/req.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/salt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/snt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/spank.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/wax.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/weth.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/icons/zil.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/zrx.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/common/config.ts: -------------------------------------------------------------------------------- 1 | import { Validator } from 'jsonschema'; 2 | 3 | import configFile from '../config.json'; 4 | import { ConfigFile } from '../util/types'; 5 | 6 | import { configSchema, schemas } from './configSchema'; 7 | 8 | export class Config { 9 | private static _instance: Config; 10 | private readonly _validator: Validator; 11 | private readonly _config: ConfigFile; 12 | public static getInstance(): Config { 13 | if (!Config._instance) { 14 | Config._instance = new Config(); 15 | } 16 | return Config._instance; 17 | } 18 | public static getConfig(): ConfigFile { 19 | return this.getInstance()._config; 20 | } 21 | constructor() { 22 | this._validator = new Validator(); 23 | for (const schema of schemas) { 24 | this._validator.addSchema(schema, schema.id); 25 | } 26 | this._validator.validate(configFile, configSchema, { throwError: true }); 27 | this._config = configFile; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/common/configSchema.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from 'jsonschema'; 2 | 3 | export const configSchema: Schema = { 4 | id: '/configSchema', 5 | properties: { 6 | tokens: { type: 'array', items: { $ref: '/tokenMetaDataSchema' } }, 7 | pairs: { type: 'array', items: { $ref: '/pairSchema' } }, 8 | }, 9 | required: ['tokens', 'pairs'], 10 | type: 'object', 11 | }; 12 | 13 | export const schemas: Schema[] = [ 14 | { 15 | id: '/addressSchema', 16 | type: 'string', 17 | pattern: '^0x[0-9a-f]{40}$', 18 | }, 19 | { 20 | id: '/wholeNumberSchema', 21 | anyOf: [ 22 | { 23 | type: 'string', 24 | pattern: '^\\d+$', 25 | }, 26 | { 27 | type: 'integer', 28 | }, 29 | ], 30 | }, 31 | { 32 | id: '/marketFilterSchema', 33 | properties: { 34 | text: { type: 'string' }, 35 | valute: { type: 'string' }, 36 | }, 37 | required: ['text', 'value'], 38 | type: 'object', 39 | }, 40 | { 41 | id: '/pairSchema', 42 | properties: { 43 | base: { type: 'string' }, 44 | quote: { type: 'string' }, 45 | }, 46 | required: ['base', 'quote'], 47 | type: 'object', 48 | }, 49 | { 50 | id: '/tokenMetaDataSchema', 51 | properties: { 52 | symbol: { type: 'string' }, 53 | name: { type: 'string' }, 54 | icon: { type: 'string' }, 55 | primaryColor: { type: 'string' }, 56 | decimals: { $ref: '/wholeNumberSchema' }, 57 | displayDecimals: { $ref: '/wholeNumberSchema' }, 58 | }, 59 | required: ['decimals', 'symbol', 'name', 'addresses'], 60 | type: 'object', 61 | }, 62 | { 63 | id: '/configSchema', 64 | properties: { 65 | tokens: { type: 'array', items: { $ref: '/tokenMetaDataSchema' } }, 66 | pairs: { type: 'array', items: { $ref: '/pairSchema' } }, 67 | marketFilters: { type: 'array', items: { $ref: '/marketFilterSchema' } }, 68 | }, 69 | required: ['tokens', 'pairs'], 70 | type: 'object', 71 | }, 72 | ]; 73 | -------------------------------------------------------------------------------- /src/common/markets.ts: -------------------------------------------------------------------------------- 1 | import { Filter } from '../util/types'; 2 | 3 | import { Config } from './config'; 4 | 5 | export const availableMarkets = Config.getConfig().pairs; 6 | const allFilter = { 7 | text: 'ALL', 8 | value: null, 9 | }; 10 | const suppliedMarketFilters = Config.getConfig().marketFilters; 11 | export const marketFilters: Filter[] = suppliedMarketFilters ? [allFilter, ...suppliedMarketFilters] : []; 12 | -------------------------------------------------------------------------------- /src/common/tokens_meta_data.ts: -------------------------------------------------------------------------------- 1 | import { Config } from './config'; 2 | 3 | export interface TokenMetaData { 4 | addresses: { [key: number]: string }; 5 | symbol: string; 6 | decimals: number; 7 | name: string; 8 | primaryColor: string; 9 | icon?: string; 10 | displayDecimals?: number; 11 | } 12 | export const KNOWN_TOKENS_META_DATA: TokenMetaData[] = Config.getConfig().tokens; 13 | -------------------------------------------------------------------------------- /src/components/account/index.ts: -------------------------------------------------------------------------------- 1 | export * from './wallet_token_balances'; 2 | export * from './wallet_weth_balance'; 3 | -------------------------------------------------------------------------------- /src/components/account/wallet_connection_status.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { Dropdown, DropdownPositions } from '../common/dropdown'; 5 | import { ChevronDownIcon } from '../common/icons/chevron_down_icon'; 6 | 7 | import { WalletConnectionStatusDot } from './wallet_connections_status_dot'; 8 | 9 | const WalletConnectionStatusWrapper = styled.div` 10 | align-items: center; 11 | cursor: pointer; 12 | display: flex; 13 | `; 14 | 15 | const WalletConnectionStatusDotStyled = styled(WalletConnectionStatusDot)` 16 | margin-right: 10px; 17 | `; 18 | 19 | const WalletConnectionStatusText = styled.span` 20 | color: ${props => props.theme.componentsTheme.textColorCommon}; 21 | font-feature-settings: 'calt' 0; 22 | font-size: 16px; 23 | font-weight: 500; 24 | margin-right: 10px; 25 | `; 26 | 27 | interface OwnProps extends HTMLAttributes { 28 | walletConnectionContent: React.ReactNode; 29 | shouldCloseDropdownOnClickOutside?: boolean; 30 | headerText: string; 31 | ethAccount: string; 32 | } 33 | 34 | type Props = OwnProps; 35 | 36 | export class WalletConnectionStatusContainer extends React.PureComponent { 37 | public render = () => { 38 | const { 39 | headerText, 40 | walletConnectionContent, 41 | ethAccount, 42 | shouldCloseDropdownOnClickOutside, 43 | ...restProps 44 | } = this.props; 45 | const status: string = ethAccount ? 'active' : ''; 46 | const header = ( 47 | 48 | 49 | {headerText} 50 | 51 | 52 | ); 53 | 54 | const body = <>{walletConnectionContent}; 55 | return ( 56 | 63 | ); 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /src/components/account/wallet_connections_status_dot.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | interface StatusProps { 4 | status?: string; 5 | } 6 | 7 | export const WalletConnectionStatusDot = styled.div` 8 | background-color: ${props => (props.status ? '#55BC65' : '#ccc')}; 9 | border-radius: 50%; 10 | height: 10px; 11 | width: 10px; 12 | `; 13 | -------------------------------------------------------------------------------- /src/components/common/card.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeDimensions } from '../../themes/commons'; 5 | 6 | import { CardBase } from './card_base'; 7 | 8 | interface Props extends HTMLAttributes { 9 | title?: string; 10 | action?: React.ReactNode; 11 | children: React.ReactNode; 12 | minHeightBody?: string; 13 | } 14 | 15 | const CardWrapper = styled(CardBase)` 16 | display: flex; 17 | flex-direction: column; 18 | margin-bottom: ${themeDimensions.verticalSeparationSm}; 19 | max-height: 100%; 20 | 21 | &:last-child { 22 | margin-bottom: 0; 23 | } 24 | `; 25 | 26 | const CardHeader = styled.div` 27 | align-items: center; 28 | border-bottom: 1px solid ${props => props.theme.componentsTheme.cardBorderColor}; 29 | display: flex; 30 | flex-grow: 0; 31 | flex-shrink: 0; 32 | justify-content: space-between; 33 | padding: ${themeDimensions.verticalPadding} ${themeDimensions.horizontalPadding}; 34 | `; 35 | 36 | const CardTitle = styled.h1` 37 | color: ${props => props.theme.componentsTheme.cardTitleColor}; 38 | font-size: 16px; 39 | font-style: normal; 40 | font-weight: 600; 41 | line-height: 1.2; 42 | margin: 0; 43 | padding: 0 20px 0 0; 44 | `; 45 | 46 | const CardBody = styled.div<{ minHeightBody?: string }>` 47 | margin: 0; 48 | min-height: ${props => props.minHeightBody}; 49 | overflow-x: auto; 50 | padding: ${themeDimensions.verticalPadding} ${themeDimensions.horizontalPadding}; 51 | position: relative; 52 | `; 53 | 54 | CardBody.defaultProps = { 55 | minHeightBody: '140px', 56 | }; 57 | 58 | export const Card: React.FC = props => { 59 | const { title, action, children, minHeightBody, ...restProps } = props; 60 | 61 | return ( 62 | 63 | {title || action ? ( 64 | 65 | {title} 66 | {action ? action : null} 67 | 68 | ) : null} 69 | {children} 70 | 71 | ); 72 | }; 73 | -------------------------------------------------------------------------------- /src/components/common/card_base.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeDimensions } from '../../themes/commons'; 5 | 6 | interface Props extends HTMLAttributes { 7 | children: React.ReactNode; 8 | } 9 | 10 | const CardWrapper = styled.div` 11 | background-color: ${props => props.theme.componentsTheme.cardBackgroundColor}; 12 | border-radius: ${themeDimensions.borderRadius}; 13 | border: 1px solid ${props => props.theme.componentsTheme.cardBorderColor}; 14 | `; 15 | 16 | export const CardBase: React.FC = props => { 17 | const { children, ...restProps } = props; 18 | 19 | return {children}; 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/common/card_tab_selector.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { TabItem } from '../../util/types'; 5 | 6 | interface Props extends HTMLAttributes { 7 | tabs: TabItem[]; 8 | } 9 | 10 | interface ItemProps { 11 | active?: boolean; 12 | } 13 | 14 | const CardTabSelectorWrapper = styled.div` 15 | align-items: center; 16 | color: ${props => props.theme.componentsTheme.lightGray}; 17 | display: flex; 18 | font-size: 14px; 19 | font-weight: 500; 20 | justify-content: space-between; 21 | line-height: 1.2; 22 | `; 23 | 24 | const CardTabSelectorItem = styled.span` 25 | color: ${props => 26 | props.active ? props.theme.componentsTheme.textColorCommon : props.theme.componentsTheme.lightGray}; 27 | cursor: ${props => (props.active ? 'default' : 'pointer')}; 28 | user-select: none; 29 | `; 30 | 31 | const CardTabSelectorItemSeparator = styled.span` 32 | color: #dedede; 33 | cursor: default; 34 | font-weight: 400; 35 | padding: 0 5px; 36 | user-select: none; 37 | 38 | &:last-child { 39 | display: none; 40 | } 41 | `; 42 | 43 | export const CardTabSelector: React.FC = props => { 44 | const { tabs, ...restProps } = props; 45 | 46 | return ( 47 | 48 | {tabs.map((item, index) => { 49 | return ( 50 | 51 | 52 | {item.text} 53 | 54 | / 55 | 56 | ); 57 | })} 58 | 59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /src/components/common/centered_wrapper.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints } from '../../themes/commons'; 5 | 6 | interface Props extends HTMLAttributes { 7 | children: React.ReactNode; 8 | } 9 | 10 | const Centered = styled.div` 11 | display: flex; 12 | flex-direction: column; 13 | flex-grow: 1; 14 | margin: 0 auto; 15 | max-width: 100%; 16 | width: ${themeBreakPoints.xxl}; 17 | `; 18 | 19 | export const CenteredWrapper: React.FC = props => { 20 | const { children, ...restProps } = props; 21 | 22 | return {children}; 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/common/column_narrow.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints, themeDimensions } from '../../themes/commons'; 5 | 6 | interface Props extends HTMLAttributes { 7 | children: React.ReactNode; 8 | } 9 | 10 | const ColumnNarrowWrapper = styled.div` 11 | display: flex; 12 | flex-direction: column; 13 | flex-shrink: 0; 14 | max-width: 100%; 15 | width: 100%; 16 | 17 | @media (min-width: ${themeBreakPoints.xl}) { 18 | min-width: ${themeDimensions.sidebarWidth}; 19 | width: ${themeDimensions.sidebarWidth}; 20 | } 21 | 22 | &:first-child { 23 | @media (min-width: ${themeBreakPoints.xl}) { 24 | margin-right: 10px; 25 | } 26 | } 27 | 28 | &:last-child { 29 | @media (min-width: ${themeBreakPoints.xl}) { 30 | margin-left: 10px; 31 | } 32 | } 33 | `; 34 | 35 | export const ColumnNarrow: React.FC = props => { 36 | const { children, ...restProps } = props; 37 | 38 | return {children}; 39 | }; 40 | -------------------------------------------------------------------------------- /src/components/common/column_wide.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints } from '../../themes/commons'; 5 | 6 | interface Props extends HTMLAttributes { 7 | children: React.ReactNode; 8 | } 9 | 10 | const ColumnWideWrapper = styled.div` 11 | flex-grow: 0; 12 | flex-shrink: 1; 13 | max-width: 100%; 14 | min-width: 0; 15 | 16 | @media (min-width: ${themeBreakPoints.xl}) { 17 | flex-grow: 1; 18 | } 19 | 20 | &:first-child { 21 | @media (min-width: ${themeBreakPoints.xl}) { 22 | margin-right: 10px; 23 | } 24 | } 25 | 26 | &:last-child { 27 | @media (min-width: ${themeBreakPoints.xl}) { 28 | margin-left: 10px; 29 | } 30 | } 31 | `; 32 | 33 | export const ColumnWide: React.FC = props => { 34 | const { children, ...restProps } = props; 35 | 36 | return {children}; 37 | }; 38 | -------------------------------------------------------------------------------- /src/components/common/dropdown_text_item.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeDimensions } from '../../themes/commons'; 5 | 6 | interface Props extends HTMLAttributes { 7 | active?: boolean; 8 | onClick?: any; 9 | text: string; 10 | } 11 | 12 | export const DropdownTextItemWrapper = styled.div<{ active?: boolean }>` 13 | background-color: ${props => 14 | props.active ? props.theme.componentsTheme.rowActive : props.theme.componentsTheme.dropdownBackgroundColor}; 15 | border-bottom: 1px solid ${props => props.theme.componentsTheme.dropdownBorderColor}; 16 | color: ${props => props.theme.componentsTheme.dropdownTextColor}; 17 | cursor: pointer; 18 | font-size: 14px; 19 | font-weight: normal; 20 | line-height: 1.3; 21 | padding: 12px ${themeDimensions.horizontalPadding}; 22 | 23 | &:hover { 24 | background-color: ${props => props.theme.componentsTheme.rowActive}; 25 | } 26 | 27 | &:first-child { 28 | border-top-left-radius: ${themeDimensions.borderRadius}; 29 | border-top-right-radius: ${themeDimensions.borderRadius}; 30 | } 31 | 32 | &:last-child { 33 | border-bottom-left-radius: ${themeDimensions.borderRadius}; 34 | border-bottom-right-radius: ${themeDimensions.borderRadius}; 35 | border-bottom: none; 36 | } 37 | `; 38 | 39 | export const DropdownTextItem: React.FC = props => { 40 | const { text, onClick, ...restProps } = props; 41 | 42 | return ( 43 | 44 | {text} 45 | 46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /src/components/common/empty_content.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | interface EmptyWrapperProps { 5 | alignAbsoluteCenter?: boolean; 6 | } 7 | 8 | interface Props extends HTMLAttributes, EmptyWrapperProps { 9 | text: string; 10 | } 11 | 12 | const EmptyContentWrapper = styled.div` 13 | align-items: center; 14 | color: ${props => props.theme.componentsTheme.lightGray}; 15 | display: flex; 16 | font-size: 16px; 17 | font-weight: 500; 18 | height: 100%; 19 | justify-content: center; 20 | width: 100%; 21 | 22 | ${props => 23 | props.alignAbsoluteCenter 24 | ? ` 25 | bottom: 0; 26 | left: 0; 27 | position: absolute; 28 | right: 0; 29 | top: 0; 30 | ` 31 | : ''} 32 | `; 33 | 34 | export const EmptyContent: React.FC = props => { 35 | const { text, ...restProps } = props; 36 | 37 | return {text}; 38 | }; 39 | -------------------------------------------------------------------------------- /src/components/common/error_card.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeDimensions } from '../../themes/commons'; 5 | 6 | import { LockIcon } from './icons/lock_icon'; 7 | import { MetamaskSideIcon } from './icons/metamask_side_icon'; 8 | import { SadIcon } from './icons/sad_icon'; 9 | import { WarningIcon } from './icons/warning_icon'; 10 | 11 | interface Props extends HTMLAttributes, ErrorProps { 12 | text: string; 13 | } 14 | 15 | interface ErrorProps { 16 | fontSize?: FontSize; 17 | icon?: ErrorIcons; 18 | textAlign?: string; 19 | } 20 | 21 | export enum ErrorIcons { 22 | Lock = 1, 23 | Sad = 2, 24 | Metamask = 3, 25 | Warning = 4, 26 | } 27 | 28 | export enum FontSize { 29 | Large = 1, 30 | Medium = 2, 31 | } 32 | 33 | const ErrorCardContainer = styled.div` 34 | align-items: center; 35 | background-color: ${props => props.theme.componentsTheme.errorCardBackground}; 36 | border-radius: ${themeDimensions.borderRadius}; 37 | border: 1px solid ${props => props.theme.componentsTheme.errorCardBorder}; 38 | color: ${props => props.theme.componentsTheme.errorCardText}; 39 | display: flex; 40 | font-size: ${props => (props.fontSize === FontSize.Large ? '16px' : '14px')}; 41 | line-height: 1.2; 42 | padding: 10px 15px; 43 | ${props => (props.textAlign === 'center' ? 'justify-content: center;' : '')} 44 | `; 45 | 46 | const IconContainer = styled.span` 47 | margin-right: 10px; 48 | `; 49 | 50 | const getIcon = (icon: ErrorIcons) => { 51 | let theIcon: any; 52 | 53 | if (icon === ErrorIcons.Lock) { 54 | theIcon = ; 55 | } 56 | if (icon === ErrorIcons.Metamask) { 57 | theIcon = ; 58 | } 59 | if (icon === ErrorIcons.Sad) { 60 | theIcon = ; 61 | } 62 | if (icon === ErrorIcons.Warning) { 63 | theIcon = ; 64 | } 65 | 66 | return {theIcon}; 67 | }; 68 | 69 | export const ErrorCard: React.FC = props => { 70 | const { text, icon, ...restProps } = props; 71 | const errorIcon = icon ? getIcon(icon) : null; 72 | 73 | return ( 74 | 75 | {errorIcon} 76 | {text} 77 | 78 | ); 79 | }; 80 | -------------------------------------------------------------------------------- /src/components/common/icons/arrow_up_down_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ArrowUpDownIcon = () => { 4 | return ( 5 | 6 | 10 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/common/icons/bell_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const BellIcon = () => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/common/icons/chevron_down_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ChevronDownIcon = () => { 4 | return ( 5 | 6 | 7 | 8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/common/icons/chevron_right_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ChevronRight = () => { 4 | return ( 5 | 6 | 7 | 8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/common/icons/close_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const CloseIcon = () => { 4 | return ( 5 | 6 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/common/icons/close_modal_button.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const CloseButton = styled.span` 5 | align-items: center; 6 | cursor: pointer; 7 | display: flex; 8 | height: 100%; 9 | justify-content: center; 10 | width: 20px; 11 | `; 12 | 13 | const CloseButtonContainer = styled.div` 14 | align-items: center; 15 | display: flex; 16 | height: 20px; 17 | justify-content: flex-end; 18 | margin-right: -10px; 19 | margin-top: -10px; 20 | `; 21 | 22 | const CloseButtonSVG = () => { 23 | return ( 24 | 25 | 31 | 32 | ); 33 | }; 34 | 35 | interface Props extends HTMLAttributes { 36 | onClick?: any; 37 | } 38 | 39 | export const CloseModalButton: React.FC = props => { 40 | const { onClick, ...restProps } = props; 41 | 42 | return ( 43 | 44 | 45 | 46 | 47 | 48 | ); 49 | }; 50 | -------------------------------------------------------------------------------- /src/components/common/icons/filter_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const FilterIcon = () => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/common/icons/info_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const InfoIcon = () => { 4 | return ( 5 | 6 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/common/icons/info_icon_full.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const InfoIconFull = () => { 4 | return ( 5 | 6 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/common/icons/lock_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const LockIcon = () => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/common/icons/magnifier_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const MagnifierIcon = () => { 4 | return ( 5 | 6 | 7 | 8 | 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /src/components/common/icons/notification_cancel_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotificationCancelIcon = () => { 4 | return ( 5 | 6 | 7 | 14 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/common/icons/notification_checkmark_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotificationCheckmarkIcon = () => { 4 | return ( 5 | 6 | 7 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/common/icons/outside_url_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const OutsideUrlIcon = () => { 4 | return ( 5 | 6 | 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /src/components/common/icons/processing_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ProcessingIcon = () => { 4 | return ( 5 | 6 | 7 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/common/icons/radio_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const RadioIcon = () => ( 4 | 5 | 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /src/components/common/icons/radio_icon_active.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const RadioIconActive = () => ( 4 | 5 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /src/components/common/icons/sort_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const SortIcon = () => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/common/icons/token_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactSVG from 'react-svg'; 3 | import styled, { withTheme } from 'styled-components'; 4 | 5 | import { Theme } from '../../../themes/commons'; 6 | 7 | interface Props { 8 | symbol: string; 9 | primaryColor?: string; 10 | isInline?: boolean; 11 | icon?: string; 12 | theme: Theme; 13 | } 14 | 15 | const IconContainer = styled.div<{ color: string; isInline?: boolean }>` 16 | align-items: center; 17 | background-color: ${props => (props.color ? props.color : 'transparent')}; 18 | border-radius: 50%; 19 | display: ${props => (props.isInline ? 'inline-flex' : 'flex')}; 20 | height: 26px; 21 | justify-content: center; 22 | width: 26px; 23 | `; 24 | 25 | const Label = styled.label` 26 | color: #fff; 27 | font-size: 0.7em; 28 | font-weight: 500; 29 | line-height: normal; 30 | margin: 0; 31 | `; 32 | 33 | const TokenIconContainer = (props: Props) => { 34 | const { symbol, primaryColor, theme, icon, ...restProps } = props; 35 | const fallBack = ; 36 | const Icon = 37 | // tslint:disable-next-line:jsx-no-lambda 38 | icon ? fallBack} /> : fallBack; 39 | return ( 40 | 41 | {Icon} 42 | 43 | ); 44 | }; 45 | 46 | const TokenIcon = withTheme(TokenIconContainer); 47 | 48 | export { TokenIcon }; 49 | -------------------------------------------------------------------------------- /src/components/common/icons/view_all_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ViewAllIcon = () => { 4 | return ( 5 | 6 | 7 | 8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/common/icons/warning_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const WarningIcon = () => ( 4 | 5 | 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /src/components/common/icons/warning_small_icon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const WarningSmallIcon = () => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/common/interval.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface Props { 4 | delay: number; 5 | children: (now: Date) => React.ReactNode; 6 | } 7 | 8 | export class Interval extends React.Component { 9 | private _interval: any = null; 10 | 11 | public componentDidMount = () => { 12 | this._interval = setInterval(() => this.forceUpdate(), this.props.delay); 13 | }; 14 | 15 | public componentWillUnmount = () => { 16 | if (this._interval) { 17 | clearInterval(this._interval); 18 | } 19 | }; 20 | 21 | public render = () => { 22 | return this.props.children(new Date()); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/components/common/loading.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { Spinner } from './spinner'; 5 | 6 | interface Props extends HTMLAttributes { 7 | minHeight?: string; 8 | } 9 | 10 | export const Loading: React.FC = props => { 11 | return ( 12 |
13 | 14 |
15 | ); 16 | }; 17 | 18 | const LoadingContainer = styled.div` 19 | ${props => `min-height: ${props.minHeight}`}; 20 | position: relative; 21 | `; 22 | 23 | LoadingContainer.defaultProps = { 24 | minHeight: '200px', 25 | }; 26 | 27 | const CenteredLoading = styled(Loading)` 28 | left: 50%; 29 | position: absolute; 30 | top: 50%; 31 | transform: translate(-50%, -50%); 32 | `; 33 | 34 | export const LoadingWrapper: React.FC = props => { 35 | const { ...restProps } = props; 36 | 37 | return ( 38 | 39 | 40 | 41 | ); 42 | }; 43 | -------------------------------------------------------------------------------- /src/components/common/logo.tsx: -------------------------------------------------------------------------------- 1 | import React, { MouseEvent } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints } from '../../themes/commons'; 5 | 6 | interface Props { 7 | image: React.ReactNode; 8 | text: string; 9 | textColor?: string; 10 | onClick: (event: MouseEvent) => void; 11 | } 12 | 13 | const LogoLink = styled.a` 14 | align-items: center; 15 | cursor: pointer; 16 | display: flex; 17 | height: 33px; 18 | font-family: 'Inter var', sans-serif; 19 | text-decoration: none; 20 | `; 21 | 22 | const LogoText = styled.h1<{ textColor?: string }>` 23 | color: ${props => props.textColor}; 24 | display: none; 25 | font-size: 18px; 26 | font-weight: 500; 27 | margin-left: 10px; 28 | text-decoration: none; 29 | 30 | @media (min-width: ${themeBreakPoints.xxl}) { 31 | display: block; 32 | } 33 | `; 34 | 35 | LogoText.defaultProps = { 36 | textColor: '#000', 37 | }; 38 | 39 | export const Logo: React.FC = props => { 40 | const { image, text, textColor, onClick, ...restProps } = props; 41 | return ( 42 | 43 | {image} 44 | {text} 45 | 46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /src/components/common/main_scrollable_wrapper.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeDimensions } from '../../themes/commons'; 5 | 6 | interface Props extends HTMLAttributes { 7 | children: React.ReactNode; 8 | } 9 | 10 | const MainScrollable = styled.div` 11 | display: flex; 12 | flex-direction: column; 13 | flex-grow: 1; 14 | margin: -${themeDimensions.mainPadding}; 15 | overflow: auto; 16 | padding: ${themeDimensions.mainPadding}; 17 | `; 18 | 19 | export const MainScrollableWrapper: React.FC = props => { 20 | const { children, ...restProps } = props; 21 | 22 | return {children}; 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/common/pending_time.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | interface Props { 5 | estimatedTimeMs: number; 6 | now: Date; 7 | startTime: Date; 8 | } 9 | 10 | const PendingTimeWrapper = styled.span` 11 | color: ${props => props.theme.componentsTheme.textLight}; 12 | `; 13 | 14 | export const PendingTime: React.FC = ({ estimatedTimeMs, now, startTime, ...restProps }) => { 15 | const estimatedSeconds = Math.round(estimatedTimeMs / 1000); 16 | const finishTime = new Date(startTime.valueOf() + estimatedTimeMs); 17 | 18 | const totalPendingSeconds = now < finishTime ? Math.round((finishTime.valueOf() - now.valueOf()) / 1000) : 0; 19 | 20 | const pendingMinutes = Math.floor(totalPendingSeconds / 60); 21 | const pendingSeconds = totalPendingSeconds % 60; 22 | 23 | const pendingMinutesStr = pendingMinutes < 10 ? `0${pendingMinutes}` : pendingMinutes.toString(); 24 | const pendingSecondsStr = pendingSeconds < 10 ? `0${pendingSeconds}` : pendingSeconds.toString(); 25 | 26 | return ( 27 | 28 | {pendingMinutesStr}:{pendingSecondsStr} (Est. {estimatedSeconds} seconds) 29 | 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/common/show_number_with_colors.tsx: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@0x/utils'; 2 | import React from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | import { padRightSplitted } from '../../util/number_utils'; 6 | 7 | interface ShowNumberWithColorsProps { 8 | num: BigNumber; 9 | isHover?: boolean; 10 | } 11 | 12 | interface SpanRightProps { 13 | isHover?: boolean; 14 | } 15 | 16 | class ShowNumberWithColors extends React.Component { 17 | public render = () => { 18 | const { num, isHover } = this.props; 19 | const numSplitted = padRightSplitted(num); 20 | const SpanLeft = styled.span` 21 | color: ${props => props.theme.componentsTheme.textColorCommon}; 22 | `; 23 | const SpanRight = styled.span` 24 | color: ${props => 25 | props.isHover 26 | ? props.theme.componentsTheme.textColorCommon 27 | : props.theme.componentsTheme.numberDecimalsColor}; 28 | `; 29 | 30 | return ( 31 | <> 32 | {numSplitted.num} 33 | {numSplitted.diff} 34 | 35 | ); 36 | }; 37 | } 38 | 39 | export { ShowNumberWithColors }; 40 | -------------------------------------------------------------------------------- /src/components/common/spinner.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled, { keyframes } from 'styled-components'; 3 | 4 | import { SpinnerSize } from '../../themes/commons'; 5 | 6 | import { ProcessingIcon } from './icons/processing_icon'; 7 | 8 | const rotate = keyframes` 9 | from { 10 | transform: rotate(0deg); 11 | } 12 | to { 13 | transform: rotate(360deg); 14 | } 15 | `; 16 | 17 | const IconSpin = styled.div` 18 | animation: ${rotate} 1.5s linear infinite; 19 | svg { 20 | ${props => ` 21 | height: ${props.size ? props.size : SpinnerSize.Small}; 22 | width: ${props.size ? props.size : SpinnerSize.Small}; 23 | `} 24 | } 25 | `; 26 | 27 | interface Props { 28 | size?: SpinnerSize; 29 | } 30 | 31 | const Spinner = (props: Props) => ( 32 | 33 | 34 | 35 | ); 36 | 37 | export { Spinner }; 38 | -------------------------------------------------------------------------------- /src/components/common/steps_modal/step_pending_time.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { PendingTime } from '../../common/pending_time'; 4 | import { Interval } from '../interval'; 5 | 6 | import { StepStatus } from './steps_common'; 7 | 8 | interface Props { 9 | estimatedTxTimeMs: number; 10 | stepStatus: StepStatus; 11 | txStarted: number | null; 12 | } 13 | 14 | export const StepPendingTime: React.FC = props => { 15 | const { estimatedTxTimeMs, stepStatus, txStarted } = props; 16 | 17 | if (stepStatus === StepStatus.Loading && txStarted) { 18 | const startTime = new Date(txStarted); 19 | return ( 20 | 21 | {now => } 22 | 23 | ); 24 | } 25 | 26 | return null; 27 | }; 28 | -------------------------------------------------------------------------------- /src/components/common/tooltip.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import ReactTooltip from 'react-tooltip'; 3 | import styled from 'styled-components'; 4 | 5 | import { InfoIcon } from './icons/info_icon'; 6 | import { InfoIconFull } from './icons/info_icon_full'; 7 | 8 | export enum IconType { 9 | Line, 10 | Fill, 11 | } 12 | 13 | interface Props extends HTMLAttributes { 14 | description?: string; 15 | iconType?: IconType; 16 | } 17 | 18 | const TooltipPopup = styled.div` 19 | cursor: pointer; 20 | display: flex; 21 | justify-content: center; 22 | outline: none; 23 | position: relative; 24 | 25 | .reactTooltip { 26 | background-color: ${props => props.theme.componentsTheme.tooltipBackgroundColor}; 27 | color: ${props => props.theme.componentsTheme.tooltipTextColor}; 28 | max-width: 250px; 29 | opacity: 1; 30 | text-align: left; 31 | 32 | &.place-left:after { 33 | border-left-color: ${props => props.theme.componentsTheme.tooltipBackgroundColor}; 34 | } 35 | 36 | &.place-right:after { 37 | border-right-color: ${props => props.theme.componentsTheme.tooltipBackgroundColor}; 38 | } 39 | 40 | &.place-top:after { 41 | border-top-color: ${props => props.theme.componentsTheme.tooltipBackgroundColor}; 42 | } 43 | 44 | &.place-bottom:after { 45 | border-bottom-color: ${props => props.theme.componentsTheme.tooltipBackgroundColor}; 46 | } 47 | 48 | .multi-line { 49 | text-align: left; 50 | } 51 | } 52 | `; 53 | 54 | export const Tooltip: React.FC = props => { 55 | const { iconType = IconType.Line, description, ...restProps } = props; 56 | const tooltipIcon = iconType === IconType.Fill ? : ; 57 | 58 | return ( 59 | 60 | {tooltipIcon} 61 | 62 | 63 | ); 64 | }; 65 | -------------------------------------------------------------------------------- /src/components/common/view_all.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import styled from 'styled-components'; 4 | 5 | import { ViewAllIcon } from './icons/view_all_icon'; 6 | 7 | interface Props { 8 | to: string; 9 | text: string; 10 | } 11 | 12 | const ViewAllWrapper = styled(Link)` 13 | align-items: center; 14 | color: ${props => props.theme.componentsTheme.textColorCommon}; 15 | display: flex; 16 | font-size: 14px; 17 | font-weight: 500; 18 | line-height: 1.2; 19 | text-decoration: none; 20 | 21 | svg { 22 | margin: 0 0 0 8px; 23 | } 24 | `; 25 | 26 | export const ViewAll: React.FC = props => { 27 | const { to, text, ...restProps } = props; 28 | return ( 29 | 30 | {text} 31 | 32 | 33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/erc20/account/wallet_connection_content.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import CopyToClipboard from 'react-copy-to-clipboard'; 3 | import { connect } from 'react-redux'; 4 | import styled from 'styled-components'; 5 | 6 | import { getEthAccount } from '../../../store/selectors'; 7 | import { truncateAddress } from '../../../util/number_utils'; 8 | import { StoreState } from '../../../util/types'; 9 | import { WalletConnectionStatusContainer } from '../../account/wallet_connection_status'; 10 | import { CardBase } from '../../common/card_base'; 11 | import { DropdownTextItem } from '../../common/dropdown_text_item'; 12 | 13 | interface OwnProps extends HTMLAttributes {} 14 | 15 | interface StateProps { 16 | ethAccount: string; 17 | } 18 | 19 | type Props = StateProps & OwnProps; 20 | 21 | const connectToWallet = () => { 22 | alert('connect to another wallet'); 23 | }; 24 | 25 | const goToURL = () => { 26 | alert('go to url'); 27 | }; 28 | 29 | const DropdownItems = styled(CardBase)` 30 | box-shadow: ${props => props.theme.componentsTheme.boxShadow}; 31 | min-width: 240px; 32 | `; 33 | 34 | class WalletConnectionContent extends React.PureComponent { 35 | public render = () => { 36 | const { ethAccount, ...restProps } = this.props; 37 | const ethAccountText = ethAccount ? `${truncateAddress(ethAccount)}` : 'Not connected'; 38 | 39 | const content = ( 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ); 48 | 49 | return ( 50 | 56 | ); 57 | }; 58 | } 59 | 60 | const mapStateToProps = (state: StoreState): StateProps => { 61 | return { 62 | ethAccount: getEthAccount(state), 63 | }; 64 | }; 65 | 66 | const WalletConnectionContentContainer = connect( 67 | mapStateToProps, 68 | {}, 69 | )(WalletConnectionContent); 70 | 71 | export { WalletConnectionContent, WalletConnectionContentContainer }; 72 | -------------------------------------------------------------------------------- /src/components/erc20/common/content_wrapper.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import { themeBreakPoints, themeDimensions } from '../../../themes/commons'; 4 | 5 | export const Content = styled.div` 6 | display: flex; 7 | flex-direction: column; 8 | flex-grow: 1; 9 | padding: ${themeDimensions.mainPadding}; 10 | 11 | @media (min-width: ${themeBreakPoints.xl}) { 12 | flex-direction: row; 13 | height: calc(100% - ${themeDimensions.footerHeight}); 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /src/components/erc20/erc20_app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Switch } from 'react-router'; 3 | import { ThemeProvider } from 'styled-components'; 4 | 5 | import { ERC20_APP_BASE_PATH } from '../../common/constants'; 6 | import { AdBlockDetector } from '../../components/common/adblock_detector'; 7 | import { GeneralLayout } from '../../components/general_layout'; 8 | import { getThemeByMarketplace } from '../../themes/theme_meta_data_utils'; 9 | import { MARKETPLACES } from '../../util/types'; 10 | 11 | import { ToolbarContentContainer } from './common/toolbar_content'; 12 | import { Marketplace } from './pages/marketplace'; 13 | import { MyWallet } from './pages/my_wallet'; 14 | 15 | const toolbar = ; 16 | 17 | export const Erc20App = () => { 18 | const themeColor = getThemeByMarketplace(MARKETPLACES.ERC20); 19 | 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/erc20/marketplace/cancel_order_button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import styled from 'styled-components'; 4 | 5 | import { cancelOrder } from '../../../store/actions'; 6 | import { UIOrder } from '../../../util/types'; 7 | import { CloseIcon } from '../../common/icons/close_icon'; 8 | 9 | interface OwnProps { 10 | order: UIOrder; 11 | } 12 | 13 | interface DispatchProps { 14 | onCancelOrder: (order: UIOrder) => Promise; 15 | } 16 | 17 | type Props = OwnProps & DispatchProps; 18 | 19 | interface State { 20 | isLoading: boolean; 21 | } 22 | 23 | const Button = styled.button` 24 | align-items: center; 25 | background: none; 26 | border: none; 27 | display: flex; 28 | height: 17px; 29 | justify-content: flex-end; 30 | margin-left: auto; 31 | outline: 0; 32 | padding: 0; 33 | width: 25px; 34 | 35 | &:hover { 36 | cursor: pointer; 37 | } 38 | 39 | &[disabled] { 40 | cursor: default; 41 | } 42 | `; 43 | 44 | class CancelOrderButton extends React.Component { 45 | public state = { 46 | isLoading: false, 47 | }; 48 | 49 | public render = () => { 50 | const { isLoading } = this.state; 51 | return ( 52 | 55 | ); 56 | }; 57 | 58 | private readonly _cancelOrder = async () => { 59 | this.setState({ isLoading: true }); 60 | try { 61 | const { order, onCancelOrder } = this.props; 62 | await onCancelOrder(order); 63 | } catch (err) { 64 | alert(`Could not cancel the specified order`); 65 | } finally { 66 | this.setState({ isLoading: false }); 67 | } 68 | }; 69 | } 70 | 71 | const mapDispatchToProps = { 72 | onCancelOrder: cancelOrder, 73 | }; 74 | 75 | const CancelOrderButtonContainer = connect( 76 | null, 77 | mapDispatchToProps, 78 | )(CancelOrderButton); 79 | 80 | export { CancelOrderButton, CancelOrderButtonContainer }; 81 | -------------------------------------------------------------------------------- /src/components/erc20/pages/marketplace.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { CheckMetamaskStateModalContainer } from '../../common/check_metamask_state_modal_container'; 4 | import { ColumnNarrow } from '../../common/column_narrow'; 5 | import { ColumnWide } from '../../common/column_wide'; 6 | import { Content } from '../common/content_wrapper'; 7 | import { BuySellContainer } from '../marketplace/buy_sell'; 8 | import { OrderBookTableContainer } from '../marketplace/order_book'; 9 | import { OrderHistoryContainer } from '../marketplace/order_history'; 10 | import { WalletBalanceContainer } from '../marketplace/wallet_balance'; 11 | 12 | class Marketplace extends React.PureComponent { 13 | public render = () => { 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | }; 30 | } 31 | 32 | export { Marketplace }; 33 | -------------------------------------------------------------------------------- /src/components/erc20/pages/my_wallet.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { WalletTokenBalancesContainer, WalletWethBalanceContainer } from '../../account'; 5 | import { CheckMetamaskStateModalContainer } from '../../common/check_metamask_state_modal_container'; 6 | import { ColumnNarrow } from '../../common/column_narrow'; 7 | import { ColumnWide } from '../../common/column_wide'; 8 | import { Content } from '../common/content_wrapper'; 9 | 10 | const ColumnWideMyWallet = styled(ColumnWide)` 11 | margin-left: 0; 12 | 13 | &:last-child { 14 | margin-left: 0; 15 | } 16 | `; 17 | 18 | export const MyWallet = () => ( 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectible_details_item_list.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeDimensions } from '../../../themes/commons'; 5 | import { ChevronRight } from '../../common/icons/chevron_right_icon'; 6 | 7 | interface Props extends HTMLAttributes { 8 | color: string; 9 | image: string; 10 | name: string; 11 | onClick: (event: React.MouseEvent) => any; 12 | } 13 | 14 | const CollectibleAssetWrapper = styled.div` 15 | border-bottom: 1px solid ${props => props.theme.componentsTheme.cardBorderColor}; 16 | cursor: pointer; 17 | display: flex; 18 | padding: 12px ${props => props.theme.modalTheme.content.padding}; 19 | 20 | &:hover { 21 | background-color: rgba(0, 0, 0, 0.03); 22 | } 23 | 24 | &:last-child { 25 | border-bottom: none; 26 | } 27 | `; 28 | 29 | const ImageWrapper = styled.div<{ color: string; image: string }>` 30 | background-color: ${props => props.color || props.theme.componentsTheme.cardBackgroundColor}; 31 | background-image: url('${props => props.image}'); 32 | background-position: 50% 50%; 33 | background-size: contain; 34 | border-radius: ${themeDimensions.borderRadius}; 35 | border: 1px solid ${props => props.theme.componentsTheme.cardBorderColor}; 36 | height: 72px; 37 | margin-right: 15px; 38 | width: 72px; 39 | `; 40 | 41 | const TextContainer = styled.div` 42 | align-items: center; 43 | display: flex; 44 | flex-grow: 1; 45 | padding: 0 10px 0 0; 46 | overflow: hidden; 47 | `; 48 | 49 | const Title = styled.h3` 50 | color: ${props => props.theme.componentsTheme.cardTitleColor}; 51 | font-size: 16px; 52 | font-weight: 600; 53 | line-height: 1.2; 54 | margin: 0 0 5px; 55 | overflow: hidden; 56 | padding: 0; 57 | text-overflow: ellipsis; 58 | white-space: nowrap; 59 | 60 | &:last-child { 61 | margin-bottom: 0; 62 | } 63 | `; 64 | 65 | const ChevronContainer = styled.div` 66 | align-items: center; 67 | display: flex; 68 | flex-shrink: 0; 69 | `; 70 | 71 | export const ListItem: React.FC = (props: Props) => { 72 | const { onClick, color, image, name } = props; 73 | return ( 74 | 75 | 76 | 77 | {name} 78 | 79 | 80 | 81 | 82 | 83 | ); 84 | }; 85 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectible_details_item_tile.tsx: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@0x/utils'; 2 | import React, { HTMLAttributes } from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | import { themeDimensions, themeFeatures } from '../../../themes/commons'; 6 | 7 | import { PriceBadge } from './price_badge'; 8 | 9 | interface Props extends HTMLAttributes { 10 | color: string; 11 | image: string; 12 | name: string; 13 | onClick: (event: React.MouseEvent) => any; 14 | price: BigNumber | null; 15 | } 16 | 17 | const CollectibleAssetWrapper = styled.div` 18 | background: ${props => props.theme.componentsTheme.cardBackgroundColor}; 19 | border-radius: ${themeDimensions.borderRadius}; 20 | border: 1px solid ${props => props.theme.componentsTheme.cardBorderColor}; 21 | box-sizing: border-box; 22 | cursor: pointer; 23 | position: relative; 24 | transition: box-shadow 0.15s linear; 25 | 26 | &:hover { 27 | box-shadow: ${themeFeatures.boxShadow}; 28 | } 29 | `; 30 | 31 | const ImageWrapper = styled.div<{ color: string; image: string }>` 32 | background-color: ${props => props.color || props.theme.componentsTheme.cardBackgroundColor}; 33 | background-image: url('${props => props.image}'); 34 | background-position: 50% 50%; 35 | background-size: contain; 36 | border-top-left-radius: ${themeDimensions.borderRadius}; 37 | border-top-right-radius: ${themeDimensions.borderRadius}; 38 | height: 272px; 39 | `; 40 | 41 | const Title = styled.h2` 42 | color: ${props => props.theme.componentsTheme.cardTitleColor}; 43 | font-size: 14px; 44 | font-weight: 500; 45 | line-height: 1.2; 46 | margin: 0; 47 | overflow: hidden; 48 | padding: 10px 12px; 49 | text-overflow: ellipsis; 50 | white-space: nowrap; 51 | `; 52 | 53 | export const TileItem: React.FC = (props: Props) => { 54 | const { onClick, color, image, price, name } = props; 55 | return ( 56 | 57 | 58 | 59 | 60 | {name} 61 | 62 | ); 63 | }; 64 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectible_details_list.tsx: -------------------------------------------------------------------------------- 1 | import React, { HTMLAttributes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | import { selectCollectible } from '../../../store/collectibles/actions'; 5 | import { getCollectiblePrice } from '../../../util/collectibles'; 6 | import { Collectible } from '../../../util/types'; 7 | 8 | import { ListItem } from './collectible_details_item_list'; 9 | import { TileItem } from './collectible_details_item_tile'; 10 | 11 | interface OwnProps extends HTMLAttributes { 12 | collectible: Collectible; 13 | isListItem?: boolean; 14 | onClick: () => any; 15 | } 16 | 17 | interface DispatchProps { 18 | updateSelectedCollectible: (collectible: Collectible) => any; 19 | } 20 | 21 | type Props = DispatchProps & OwnProps; 22 | 23 | export const CollectibleOnList: React.FC = (props: Props) => { 24 | const { collectible, onClick, isListItem } = props; 25 | const { color, image, name } = collectible; 26 | const price = getCollectiblePrice(collectible); 27 | 28 | const handleAssetClick: React.EventHandler = (event: React.MouseEvent) => { 29 | event.preventDefault(); 30 | onClick(); 31 | try { 32 | props.updateSelectedCollectible(collectible); 33 | } catch (err) { 34 | window.alert(`Could not sell the specified order`); 35 | } 36 | }; 37 | 38 | return isListItem ? ( 39 | 40 | ) : ( 41 | 42 | ); 43 | }; 44 | 45 | const mapDispatchToProps = (dispatch: any): DispatchProps => { 46 | return { 47 | updateSelectedCollectible: (collectible: Collectible) => dispatch(selectCollectible(collectible)), 48 | }; 49 | }; 50 | 51 | export const CollectibleOnListContainer = connect( 52 | null, 53 | mapDispatchToProps, 54 | )(CollectibleOnList); 55 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectibles_dropdown_button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { ChevronDownIcon } from '../../common/icons/chevron_down_icon'; 5 | 6 | interface Props { 7 | text: string; 8 | extraIcon: any; 9 | } 10 | 11 | const DropdownButtonContainer = styled.div` 12 | align-items: center; 13 | display: flex; 14 | justify-content: space-between; 15 | user-select: none; 16 | `; 17 | 18 | const Text = styled.span` 19 | margin: 0 10px; 20 | `; 21 | 22 | export class DropdownButton extends React.Component { 23 | public render = () => { 24 | const { text, extraIcon } = this.props; 25 | 26 | return ( 27 | 28 | {extraIcon} 29 | {text} 30 | 31 | 32 | ); 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectibles_dropdown_container.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { CardBase } from '../../common/card_base'; 5 | 6 | interface Props { 7 | children: React.ReactNode; 8 | } 9 | 10 | const DropdownItemsContainer = styled(CardBase)` 11 | box-shadow: ${props => props.theme.componentsTheme.boxShadow}; 12 | min-width: 240px; 13 | `; 14 | 15 | export class DropdownContainer extends React.Component { 16 | public render = () => { 17 | const { children } = this.props; 18 | 19 | return {children}; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectibles_list_filter.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { CollectibleFilterType } from '../../../util/filterable_collectibles'; 5 | import { Dropdown, DropdownPositions } from '../../common/dropdown'; 6 | import { DropdownTextItemWrapper } from '../../common/dropdown_text_item'; 7 | import { FilterIcon } from '../../common/icons/filter_icon'; 8 | 9 | import { DropdownButton } from './collectibles_dropdown_button'; 10 | import { DropdownContainer } from './collectibles_dropdown_container'; 11 | 12 | interface Props { 13 | currentValue: CollectibleFilterType; 14 | onChange: (evt: React.ChangeEvent) => void; 15 | } 16 | 17 | const options: { [key: string]: string } = { 18 | [CollectibleFilterType.ShowAll]: 'Show all', 19 | [CollectibleFilterType.FixedPrice]: 'Fixed Price', 20 | [CollectibleFilterType.DecliningAuction]: 'Declining Auction', 21 | }; 22 | 23 | const DropdownItemFilter = styled(DropdownTextItemWrapper)` 24 | ${props => (props.active ? 'cursor: default;' : '')} 25 | position: relative; 26 | 27 | input[type='radio'] { 28 | cursor: pointer; 29 | height: 100%; 30 | left: 0; 31 | opacity: 0; 32 | position: absolute; 33 | top: 0; 34 | width: 100%; 35 | z-index: 5; 36 | 37 | &:checked { 38 | cursor: default; 39 | pointer-events: none; 40 | } 41 | 42 | &:checked + span { 43 | font-weight: 500; 44 | } 45 | } 46 | `; 47 | 48 | const Text = styled.span` 49 | position: relative; 50 | z-index: 1; 51 | `; 52 | 53 | export const CollectiblesListFilter = (props: Props) => { 54 | const { currentValue, onChange, ...restProps } = props; 55 | const filterTypes = Object.keys(options) as CollectibleFilterType[]; 56 | const header = } />; 57 | 58 | const body = ( 59 | 60 | {filterTypes.map(filterType => ( 61 | 62 | 63 | {options[filterType]} 64 | 65 | ))} 66 | 67 | ); 68 | 69 | return ; 70 | }; 71 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectibles_list_sort.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { CollectibleSortType } from '../../../util/sortable_collectibles'; 5 | import { Dropdown, DropdownPositions } from '../../common/dropdown'; 6 | import { DropdownTextItemWrapper } from '../../common/dropdown_text_item'; 7 | import { SortIcon } from '../../common/icons/sort_icon'; 8 | 9 | import { DropdownButton } from './collectibles_dropdown_button'; 10 | import { DropdownContainer } from './collectibles_dropdown_container'; 11 | 12 | interface Props { 13 | currentValue: CollectibleSortType; 14 | onChange: (evt: React.ChangeEvent) => void; 15 | } 16 | 17 | const options: { [key: string]: string } = { 18 | [CollectibleSortType.NewestAdded]: 'Newest Added', 19 | [CollectibleSortType.PriceLowToHigh]: 'Price: low to high', 20 | [CollectibleSortType.PriceHighToLow]: 'Price: high to low', 21 | }; 22 | 23 | const DropdownItemFilter = styled(DropdownTextItemWrapper)` 24 | ${props => (props.active ? 'cursor: default;' : '')} 25 | position: relative; 26 | 27 | input[type='radio'] { 28 | cursor: pointer; 29 | height: 100%; 30 | left: 0; 31 | opacity: 0; 32 | position: absolute; 33 | top: 0; 34 | width: 100%; 35 | z-index: 5; 36 | 37 | &:checked { 38 | cursor: default; 39 | pointer-events: none; 40 | } 41 | 42 | &:checked + span { 43 | font-weight: 500; 44 | } 45 | } 46 | `; 47 | 48 | const Text = styled.span` 49 | position: relative; 50 | z-index: 1; 51 | `; 52 | 53 | export const CollectiblesListSort = (props: Props) => { 54 | const { currentValue, onChange, ...restProps } = props; 55 | const sortTypes = Object.keys(options) as CollectibleSortType[]; 56 | const header = } />; 57 | 58 | const body = ( 59 | 60 | {sortTypes.map(sortType => ( 61 | 62 | 63 | {options[sortType]} 64 | 65 | ))} 66 | 67 | ); 68 | 69 | return ; 70 | }; 71 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/collectibles_search.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | import { Theme } from '../../../themes/commons'; 4 | import { InputSearch } from '../common/input_search'; 5 | import { SearchModalContainer } from '../modals/search-modal'; 6 | 7 | interface Props { 8 | theme: Theme; 9 | } 10 | 11 | export const CollectiblesSearch: React.FC = props => { 12 | const [isModalOpen, setIsModalOpen] = useState(false); 13 | 14 | const showModal = () => setIsModalOpen(true); 15 | const hideModal = () => setIsModalOpen(false); 16 | 17 | return ( 18 | <> 19 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/owner_badge.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const Badge = styled.div` 5 | align-items: center; 6 | background: ${props => props.theme.componentsTheme.cardBackgroundColor}; 7 | border-radius: 16px; 8 | box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.04); 9 | display: flex; 10 | height: 31px; 11 | justify-content: center; 12 | min-width: 84px; 13 | padding: 8px 12px; 14 | position: absolute; 15 | left: 10px; 16 | top: 10px; 17 | `; 18 | 19 | const BadgeValue = styled.span` 20 | color: ${props => props.theme.componentsTheme.cardTitleOwnerColor}; 21 | font-size: 14px; 22 | font-weight: 400; 23 | line-height: 14px; 24 | `; 25 | 26 | export const OwnerBadge = () => { 27 | return ( 28 | 29 | You Own 30 | 31 | ); 32 | }; 33 | -------------------------------------------------------------------------------- /src/components/erc721/collectibles/price_badge.tsx: -------------------------------------------------------------------------------- 1 | import { BigNumber } from '@0x/utils'; 2 | import React from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | import { ETH_DECIMALS } from '../../../common/constants'; 6 | import { tokenAmountInUnits } from '../../../util/tokens'; 7 | 8 | interface Props { 9 | price: BigNumber | null; 10 | } 11 | 12 | const Badge = styled.div` 13 | align-items: center; 14 | background: ${props => props.theme.componentsTheme.cardBackgroundColor}; 15 | border-radius: 16px; 16 | box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.04); 17 | display: flex; 18 | height: 31px; 19 | justify-content: center; 20 | padding: 8px 12px; 21 | position: absolute; 22 | right: 10px; 23 | top: 10px; 24 | `; 25 | 26 | const BadgeValue = styled.span` 27 | color: ${props => props.theme.componentsTheme.cardTitleColor}; 28 | font-feature-settings: 'tnum' on, 'onum' on; 29 | font-size: 14px; 30 | font-weight: 400; 31 | line-height: 14px; 32 | margin-right: 6px; 33 | `; 34 | 35 | const BadgeAsset = styled.span` 36 | color: ${props => props.theme.componentsTheme.cardTitleColor}; 37 | font-feature-settings: 'tnum' on, 'onum' on; 38 | font-size: 10px; 39 | font-weight: 400; 40 | line-height: 10px; 41 | `; 42 | 43 | export const PriceBadge = (props: Props) => { 44 | const { price } = props; 45 | if (price === null) { 46 | return null; 47 | } 48 | return ( 49 | 50 | {tokenAmountInUnits(price, ETH_DECIMALS)} 51 | ETH 52 | 53 | ); 54 | }; 55 | -------------------------------------------------------------------------------- /src/components/erc721/common/content_wrapper.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import { themeBreakPoints, themeDimensions } from '../../../themes/commons'; 4 | 5 | export const Content = styled.div` 6 | display: flex; 7 | flex-direction: column; 8 | flex-grow: 1; 9 | padding: ${themeDimensions.mainPadding}; 10 | 11 | @media (min-width: ${themeBreakPoints.xl}) { 12 | flex-direction: row; 13 | } 14 | `; 15 | -------------------------------------------------------------------------------- /src/components/erc721/common/input_search.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled, { css } from 'styled-components'; 3 | 4 | import { themeBreakPoints, themeDimensions } from '../../../themes/commons'; 5 | 6 | const noFocusOutline = css` 7 | :focus { 8 | outline: none; 9 | } 10 | `; 11 | 12 | const SearchInput = styled.input` 13 | background-color: #f9fafc; 14 | background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxNCAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjQiIHN0cm9rZT0iI0RFREVERSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0xMi41IDExLjVMOCA3IiBzdHJva2U9IiNERURFREUiIHN0cm9rZS13aWR0aD0iMiIvPgo8L3N2Zz4K'); 15 | background-position: 12px 50%; 16 | background-repeat: no-repeat; 17 | border-radius: ${themeDimensions.borderRadius}; 18 | border: 1px solid ${props => props.theme.componentsTheme.cardBorderColor}; 19 | box-sizing: border-box; 20 | color: #666; 21 | font-size: 14px; 22 | height: 32px; 23 | margin: 0 auto 0 10px; 24 | padding-left: 35px; 25 | width: 140px; 26 | 27 | @media (min-width: ${themeBreakPoints.md}) { 28 | margin-left: 20px; 29 | width: 250px; 30 | } 31 | 32 | @media (min-width: ${themeBreakPoints.xxl}) { 33 | margin: 0; 34 | width: 466px; 35 | } 36 | 37 | ::placeholder { 38 | color: #bfbfbf; 39 | font-size: 14px; 40 | text-align: center; 41 | } 42 | 43 | ${props => (props.focusOutline ? '' : noFocusOutline)} 44 | `; 45 | 46 | SearchInput.defaultProps = { 47 | focusOutline: true, 48 | }; 49 | 50 | interface Props { 51 | placeholder: string; 52 | onChange?: (event: React.ChangeEvent) => any; 53 | onClick?: (event: React.MouseEvent) => any; 54 | autoFocus?: boolean; 55 | readOnly?: boolean; 56 | focusOutline?: boolean; 57 | } 58 | 59 | export const InputSearch = (props: Props) => { 60 | return ; 61 | }; 62 | -------------------------------------------------------------------------------- /src/components/erc721/erc721_app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Switch } from 'react-router'; 3 | import styled, { ThemeProvider } from 'styled-components'; 4 | 5 | import { ERC721_APP_BASE_PATH } from '../../common/constants'; 6 | import { getThemeByMarketplace } from '../../themes/theme_meta_data_utils'; 7 | import { MARKETPLACES } from '../../util/types'; 8 | import { AdBlockDetector } from '../common/adblock_detector'; 9 | import { CheckMetamaskStateModalContainer } from '../common/check_metamask_state_modal_container'; 10 | import { GeneralLayout } from '../general_layout'; 11 | 12 | import { CollectibleSellModal } from './collectibles/collectible_sell_modal'; 13 | import { ToolbarContentContainer } from './common/toolbar_content'; 14 | import { AllCollectibles } from './pages/all_collectibles'; 15 | import { IndividualCollectible } from './pages/individual_collectible'; 16 | import { ListCollectibles } from './pages/list_collectibles'; 17 | import { MyCollectibles } from './pages/my_collectibles'; 18 | 19 | const toolbar = ; 20 | 21 | const GeneralLayoutERC721 = styled(GeneralLayout)` 22 | background-color: ${props => props.theme.componentsTheme.backgroundERC721}; 23 | `; 24 | 25 | export const Erc721App = () => { 26 | const themeColor = getThemeByMarketplace(MARKETPLACES.ERC721); 27 | return ( 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 42 | {({ match }) => match && } 43 | 44 | 45 | 46 | 47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /src/components/erc721/marketplace/marketplace_common.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const TitleText = styled.h3` 4 | font-size: 14px; 5 | line-height: 17px; 6 | font-weight: 500; 7 | `; 8 | -------------------------------------------------------------------------------- /src/components/erc721/marketplace/sell_collectibles_button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints } from '../../../themes/commons'; 5 | import { ButtonVariant } from '../../../util/types'; 6 | import { Button } from '../../common/button'; 7 | import { CollectibleListModal } from '../collectibles/collectible_list_modal'; 8 | 9 | const ButtonStyled = styled(Button)` 10 | min-width: 195px; 11 | @media (min-width: ${themeBreakPoints.md}) { 12 | margin-left: auto; 13 | } 14 | `; 15 | 16 | export class SellCollectiblesButton extends React.Component { 17 | public state = { 18 | isModalOpen: false, 19 | }; 20 | public render = () => { 21 | return ( 22 | <> 23 | 24 | 25 | Sell collectibles 26 | 27 | 28 | ); 29 | }; 30 | 31 | private readonly _handleModalToggle = () => { 32 | this.setState({ 33 | isModalOpen: !this.state.isModalOpen, 34 | }); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/components/erc721/pages/all_collectibles.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { COLLECTIBLE_DESCRIPTION, COLLECTIBLE_NAME } from '../../../common/constants'; 4 | import { AllCollectiblesContainer } from '../collectibles/collectibles_all'; 5 | import { Content } from '../common/content_wrapper'; 6 | 7 | export const AllCollectibles = () => ( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /src/components/erc721/pages/individual_collectible.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints } from '../../../themes/commons'; 5 | import { Content } from '../common/content_wrapper'; 6 | import { CollectibleBuySellContainer } from '../marketplace/collectible_buy_sell'; 7 | import { CollectibleDescriptionContainer } from '../marketplace/collectible_description'; 8 | 9 | const IndividualCollectibleWrapper = styled.div` 10 | align-items: center; 11 | display: flex; 12 | flex-direction: column; 13 | flex-grow: 1; 14 | margin: 0 auto; 15 | max-width: ${themeBreakPoints.xxl}; 16 | width: 100%; 17 | 18 | @media (min-width: ${themeBreakPoints.md}) { 19 | align-items: flex-start; 20 | flex-direction: row; 21 | justify-content: center; 22 | } 23 | `; 24 | 25 | const CollectibleBuySell = styled(CollectibleBuySellContainer)` 26 | flex-grow: 0; 27 | flex-shrink: 0; 28 | 29 | @media (min-width: ${themeBreakPoints.md}) { 30 | margin-right: 12px; 31 | } 32 | `; 33 | 34 | const CollectibleDescription = styled(CollectibleDescriptionContainer)` 35 | display: flex; 36 | flex-direction: column; 37 | max-width: 586px; 38 | min-width: 0; 39 | width: 100%; 40 | `; 41 | 42 | interface OwnProps { 43 | collectibleId: string; 44 | } 45 | 46 | type Props = OwnProps; 47 | 48 | export const IndividualCollectible = (props: Props) => { 49 | const { collectibleId } = props; 50 | if (!collectibleId) { 51 | return null; 52 | } 53 | 54 | return ( 55 | 56 | 57 | 58 | 59 | 60 | 61 | ); 62 | }; 63 | -------------------------------------------------------------------------------- /src/components/erc721/pages/list_collectibles.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { COLLECTIBLE_NAME } from '../../../common/constants'; 4 | import { AllCollectiblesListContainer } from '../collectibles/collectibles_list'; 5 | import { Content } from '../common/content_wrapper'; 6 | 7 | export const ListCollectibles = () => ( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /src/components/erc721/pages/my_collectibles.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { MyCollectiblesListContainer } from '../collectibles/collectibles_list'; 4 | import { Content } from '../common/content_wrapper'; 5 | 6 | export const MyCollectibles = () => ( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/general_layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { themeBreakPoints, themeDimensions } from '../themes/commons'; 5 | 6 | import { Footer } from './common/footer'; 7 | import { StepsModalContainer } from './common/steps_modal/steps_modal'; 8 | 9 | const General = styled.div` 10 | background: ${props => props.theme.componentsTheme.background}; 11 | display: flex; 12 | flex-direction: column; 13 | min-height: 100%; 14 | 15 | @media (min-width: ${themeBreakPoints.xl}) { 16 | height: 100%; 17 | } 18 | `; 19 | 20 | const ContentScroll = styled.div` 21 | display: flex; 22 | flex-direction: column; 23 | flex-grow: 1; 24 | 25 | @media (min-width: ${themeBreakPoints.xl}) { 26 | height: calc(100% - ${themeDimensions.toolbarHeight}); 27 | overflow: auto; 28 | } 29 | `; 30 | 31 | interface OwnProps { 32 | children: React.ReactNode; 33 | toolbar: React.ReactNode; 34 | } 35 | 36 | type Props = OwnProps; 37 | 38 | export const GeneralLayout = (props: Props) => { 39 | const { children, toolbar, ...restProps } = props; 40 | return ( 41 | 42 | {toolbar} 43 | 44 | {children} 45 |