aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website')
-rw-r--r--packages/website/md/docs/sol_cov/usage.md8
-rw-r--r--packages/website/package.json18
-rw-r--r--packages/website/public/images/eth_dollar.svg29
-rw-r--r--packages/website/public/images/eth_token.svg20
-rw-r--r--packages/website/public/images/eth_token_erc20.svg22
-rw-r--r--packages/website/public/images/ether_alt.svg7
-rw-r--r--packages/website/public/images/fake_toggle.svg4
-rw-r--r--packages/website/public/images/jobs/location1.pngbin0 -> 659608 bytes
-rw-r--r--packages/website/public/images/jobs/location2.pngbin0 -> 223872 bytes
-rw-r--r--packages/website/public/images/jobs/location3.pngbin0 -> 288733 bytes
-rw-r--r--packages/website/public/images/jobs/map.pngbin0 -> 271102 bytes
-rw-r--r--packages/website/public/images/jobs/office1.pngbin0 -> 482657 bytes
-rw-r--r--packages/website/public/images/jobs/office2.pngbin0 -> 479918 bytes
-rw-r--r--packages/website/public/images/jobs/office3.pngbin0 -> 480055 bytes
-rw-r--r--packages/website/public/images/zrx_ecosystem.svg253
-rw-r--r--packages/website/ts/blockchain.ts9
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx4
-rw-r--r--packages/website/ts/components/eth_wrappers.tsx6
-rw-r--r--packages/website/ts/components/fill_order.tsx2
-rw-r--r--packages/website/ts/components/footer.tsx2
-rw-r--r--packages/website/ts/components/generate_order/generate_order_form.tsx2
-rw-r--r--packages/website/ts/components/generate_order/new_token_form.tsx6
-rw-r--r--packages/website/ts/components/inputs/allowance_toggle.tsx9
-rw-r--r--packages/website/ts/components/inputs/balance_bounded_input.tsx2
-rw-r--r--packages/website/ts/components/inputs/expiration_input.tsx4
-rw-r--r--packages/website/ts/components/legacy_portal/legacy_portal.tsx4
-rw-r--r--packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx18
-rw-r--r--packages/website/ts/components/onboarding/congrats_onboarding_step.tsx15
-rw-r--r--packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx18
-rw-r--r--packages/website/ts/components/onboarding/intro_onboarding_step.tsx23
-rw-r--r--packages/website/ts/components/onboarding/onboarding_flow.tsx12
-rw-r--r--packages/website/ts/components/onboarding/onboarding_tooltip.tsx103
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx135
-rw-r--r--packages/website/ts/components/onboarding/set_allowances_onboarding_step.tsx27
-rw-r--r--packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx16
-rw-r--r--packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx73
-rw-r--r--packages/website/ts/components/portal/portal.tsx42
-rw-r--r--packages/website/ts/components/redirector.tsx (renamed from packages/website/ts/components/redirecter.tsx)4
-rw-r--r--packages/website/ts/components/relayer_index/relayer_grid_tile.tsx54
-rw-r--r--packages/website/ts/components/relayer_index/relayer_index.tsx39
-rw-r--r--packages/website/ts/components/token_balances.tsx7
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx3
-rw-r--r--packages/website/ts/components/ui/button.tsx21
-rw-r--r--packages/website/ts/components/ui/container.tsx7
-rw-r--r--packages/website/ts/components/ui/drop_down.tsx2
-rw-r--r--packages/website/ts/components/ui/filled_image.tsx18
-rw-r--r--packages/website/ts/components/ui/icon_button.tsx9
-rw-r--r--packages/website/ts/components/ui/image.tsx37
-rw-r--r--packages/website/ts/components/ui/pointer.tsx67
-rw-r--r--packages/website/ts/components/ui/retry.tsx32
-rw-r--r--packages/website/ts/components/ui/text.tsx35
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx17
-rw-r--r--packages/website/ts/components/wallet/wrap_ether_item.tsx2
-rw-r--r--packages/website/ts/containers/about.ts2
-rw-r--r--packages/website/ts/containers/connect_documentation.ts2
-rw-r--r--packages/website/ts/containers/ethereum_types_documentation.ts2
-rw-r--r--packages/website/ts/containers/faq.ts2
-rw-r--r--packages/website/ts/containers/generate_order_form.ts2
-rw-r--r--packages/website/ts/containers/inputs/allowance_toggle.ts41
-rw-r--r--packages/website/ts/containers/jobs.ts28
-rw-r--r--packages/website/ts/containers/json_schemas_documentation.ts2
-rw-r--r--packages/website/ts/containers/landing.ts2
-rw-r--r--packages/website/ts/containers/legacy_portal.ts2
-rw-r--r--packages/website/ts/containers/not_found.ts2
-rw-r--r--packages/website/ts/containers/order_utils_documentation.ts2
-rw-r--r--packages/website/ts/containers/portal.ts2
-rw-r--r--packages/website/ts/containers/portal_onboarding_flow.ts5
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.ts2
-rw-r--r--packages/website/ts/containers/sol_compiler_documentation.ts2
-rw-r--r--packages/website/ts/containers/sol_cov_documentation.ts2
-rw-r--r--packages/website/ts/containers/subproviders_documentation.ts2
-rw-r--r--packages/website/ts/containers/web3_wrapper_documentation.ts2
-rw-r--r--packages/website/ts/containers/wiki.ts2
-rw-r--r--packages/website/ts/containers/zero_ex_js_documentation.ts3
-rw-r--r--packages/website/ts/index.tsx11
-rw-r--r--packages/website/ts/local_storage/trade_history_storage.tsx2
-rw-r--r--packages/website/ts/pages/jobs/benefits.tsx109
-rw-r--r--packages/website/ts/pages/jobs/jobs.tsx81
-rw-r--r--packages/website/ts/pages/jobs/join_0x.tsx41
-rw-r--r--packages/website/ts/pages/jobs/list/header_item.tsx26
-rw-r--r--packages/website/ts/pages/jobs/list/list_item.tsx15
-rw-r--r--packages/website/ts/pages/jobs/mission.tsx56
-rw-r--r--packages/website/ts/pages/jobs/open_positions.tsx192
-rw-r--r--packages/website/ts/pages/jobs/photo_rail.tsx22
-rw-r--r--packages/website/ts/pages/jobs/teams.tsx90
-rw-r--r--packages/website/ts/pages/jobs/values.tsx60
-rw-r--r--packages/website/ts/pages/not_found.tsx2
-rw-r--r--packages/website/ts/pages/wiki/wiki.tsx4
-rw-r--r--packages/website/ts/style/colors.ts2
-rw-r--r--packages/website/ts/types.ts10
-rw-r--r--packages/website/ts/utils/backend_client.ts13
-rw-r--r--packages/website/ts/utils/constants.ts1
-rw-r--r--packages/website/ts/utils/error_reporter.ts2
-rw-r--r--packages/website/ts/utils/utils.ts28
94 files changed, 1872 insertions, 253 deletions
diff --git a/packages/website/md/docs/sol_cov/usage.md b/packages/website/md/docs/sol_cov/usage.md
index 59638f611..433cfad96 100644
--- a/packages/website/md/docs/sol_cov/usage.md
+++ b/packages/website/md/docs/sol_cov/usage.md
@@ -11,9 +11,6 @@ In order to use `CoverageSubprovider` with your favorite framework you need to p
If you are generating your artifacts with [@0xproject/sol-compiler](LINK) you can use the `SolCompilerArtifactsAdapter` we've implemented for you.
```typescript
-<<<<<<< HEAD
-import { CoverageSubprovider } from '@0xproject/sol-cov';
-=======
import { SolCompilerArtifactsAdapter } from '@0xproject/sol-cov';
const artifactsPath = 'src/artifacts';
const contractsPath = 'src/contracts';
@@ -42,7 +39,6 @@ Look at the code of the two adapters above for examples.
```typescript
import { CoverageSubprovider } from '@0xproject/sol-cov';
import ProviderEngine = require('web3-provider-engine');
->>>>>>> Improve sol-cov docs
const provider = new ProviderEngine();
@@ -51,12 +47,8 @@ const contractsPath = 'src/contracts';
const networkId = 50;
// Some calls might not have `from` address specified. Nevertheless - transactions need to be submitted from an address with at least some funds. defaultFromAddress is the address that will be used to submit those calls as transactions from.
const defaultFromAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
-<<<<<<< HEAD
-const coverageSubprovider = new CoverageSubprovider(artifactsPath, contractsPath, defaultFromAddress);
-=======
const isVerbose = true;
const coverageSubprovider = new CoverageSubprovider(artifactsAdapter, defaultFromAddress, isVerbose);
->>>>>>> Improve sol-cov docs
provider.addProvider(coverageSubprovider);
```
diff --git a/packages/website/package.json b/packages/website/package.json
index 5287414c7..a2ac617eb 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -1,6 +1,6 @@
{
"name": "@0xproject/website",
- "version": "0.0.33",
+ "version": "0.0.37",
"engines": {
"node": ">=6.12"
},
@@ -18,14 +18,14 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
- "@0xproject/contract-wrappers": "^0.0.2",
- "@0xproject/react-docs": "^0.0.12",
- "@0xproject/react-shared": "^0.1.7",
- "@0xproject/subproviders": "^0.10.2",
- "@0xproject/types": "0.7.0",
- "@0xproject/typescript-typings": "^0.3.2",
- "@0xproject/utils": "^0.6.2",
- "@0xproject/web3-wrapper": "^0.6.4",
+ "@0xproject/contract-wrappers": "^0.0.5",
+ "@0xproject/react-docs": "^0.0.14",
+ "@0xproject/react-shared": "^0.2.1",
+ "@0xproject/subproviders": "^0.10.4",
+ "@0xproject/types": "^0.8.1",
+ "@0xproject/typescript-typings": "^0.4.1",
+ "@0xproject/utils": "^0.7.1",
+ "@0xproject/web3-wrapper": "^0.7.1",
"accounting": "^0.4.1",
"basscss": "^8.0.3",
"blockies": "^0.0.2",
diff --git a/packages/website/public/images/eth_dollar.svg b/packages/website/public/images/eth_dollar.svg
new file mode 100644
index 000000000..0afec94fa
--- /dev/null
+++ b/packages/website/public/images/eth_dollar.svg
@@ -0,0 +1,29 @@
+<svg width="76" height="46" viewBox="0 0 76 46" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d)">
+<path d="M-2.34315e-08 10.7545L18.9187 -1.15499e-08L65.2081 26.3534L46.2894 37.1079L-2.34315e-08 10.7545Z" transform="translate(5.62109 1.17188)" fill="#DCD3EB"/>
+<path d="M20.5403 1.84086L65.2081 27.2738L47.911 37.1079L3.24321 11.6749L20.5403 1.84086ZM20.5403 0L0 11.6749L47.911 38.9487L68.4513 27.2738L20.5403 0Z" transform="translate(4 0.25)" fill="#AAA7C9"/>
+<path d="M9.92618 13.54C7.05152 13.54 4.44712 12.9587 2.62896 11.9171C0.90908 10.9483 3.74905e-07 9.66451 3.74905e-07 8.2112C3.74905e-07 6.27346 1.6216 4.23882 4.44712 2.64018C7.39549 0.944652 11.2775 3.69596e-07 15.0613 3.69596e-07C17.9359 3.69596e-07 20.5403 0.581324 22.3585 1.62286C24.0784 2.59174 24.9874 3.87549 24.9874 5.3288C24.9874 7.26655 23.3658 9.30118 20.5403 10.8998C17.5919 12.5711 13.7099 13.54 9.92618 13.54Z" transform="translate(26.3359 13.3047)" fill="#CAC3E5"/>
+<path d="M15.8578 1.59864C18.585 1.59864 21.042 2.13152 22.7619 3.1004C23.7692 3.68172 24.9731 4.67482 24.9731 6.1039C24.9731 7.72677 23.4744 9.5434 20.9437 10.9967C18.0936 12.6196 14.3836 13.54 10.7473 13.54C8.02001 13.54 5.56304 13.0071 3.84316 12.0383C2.8358 11.4569 1.63188 10.4638 1.63188 9.03475C1.63188 7.41188 3.13063 5.59524 5.66132 4.14193C8.48684 2.51907 12.1969 1.59864 15.8578 1.59864ZM15.8578 -3.69596e-07C12.0986 -3.69596e-07 8.04458 0.944652 4.85051 2.76129C-0.825098 5.98279 -1.6359 10.7545 3.03235 13.4189C5.07164 14.5815 7.82345 15.1386 10.7473 15.1386C14.5064 15.1386 18.5604 14.194 21.7545 12.3774C27.4301 9.15585 28.2409 4.38415 23.5727 1.71975C21.5088 0.557102 18.757 -3.69596e-07 15.8578 -3.69596e-07Z" transform="translate(25.5391 12.5078)" fill="#AAA7C9"/>
+<path d="M1.81816 5.69213L8.89425 6.73367L11.8426 0L-7.49809e-07 1.64709L1.81816 5.69213Z" transform="translate(34.3945 15.875)" fill="#AAA7C9"/>
+<path d="M3.74905e-07 6.07968L10.7124 5.03814L3.63632 4.02083L1.81816 3.69596e-07L3.74905e-07 6.07968Z" transform="translate(31.7422 18.0312)" fill="#AAA7C9"/>
+<path d="M2.9238 3.63328C2.01472 3.63328 1.20392 3.46372 0.638813 3.14884C0.343976 2.97929 -4.68631e-08 2.68862 -4.68631e-08 2.3253C-4.68631e-08 1.86508 0.491395 1.28376 1.27763 0.847764C2.23585 0.314884 3.46433 0 4.69282 0C5.6019 0 6.4127 0.169553 6.97781 0.484437C7.27265 0.65399 7.61662 0.944652 7.61662 1.30798C7.61662 1.76819 7.12523 2.34952 6.339 2.78551C5.40534 3.31839 4.15229 3.63328 2.9238 3.63328Z" transform="translate(7.85938 9.69531)" fill="#DCD3EB"/>
+<path d="M5.5202 1.59864C6.28186 1.59864 6.96981 1.74397 7.3875 1.98619C7.51035 2.05886 7.58406 2.1073 7.60863 2.15574C7.55949 2.27685 7.33836 2.59174 6.74868 2.93084C5.93788 3.39106 4.80767 3.68172 3.7266 3.68172C2.96494 3.68172 2.27699 3.53639 1.8593 3.29417C1.73645 3.2215 1.66275 3.17306 1.63818 3.12462C1.68732 3.00351 1.90844 2.68862 2.49812 2.34952C3.30892 1.8893 4.43913 1.59864 5.5202 1.59864ZM5.5202 0C4.218 0 2.79295 0.314884 1.68732 0.968874C-0.278265 2.08308 -0.573102 3.75438 1.0485 4.67482C1.76102 5.08659 2.71924 5.28036 3.7266 5.28036C5.0288 5.28036 6.45385 4.96548 7.55949 4.31149C9.52507 3.19728 9.8199 1.52598 8.1983 0.605546C7.48578 0.217997 6.52756 0 5.5202 0Z" transform="translate(7.05469 8.85156)" fill="#AAA7C9"/>
+<path d="M2.9238 3.63327C2.01472 3.63327 1.20392 3.46372 0.638815 3.14884C0.343978 2.97928 0 2.68862 0 2.3253C0 1.86508 0.491394 1.28376 1.27763 0.847763C2.23585 0.314882 3.46434 -1.47838e-06 4.69282 -1.47838e-06C5.6019 -1.47838e-06 6.4127 0.169551 6.97781 0.484435C7.27264 0.653988 7.61662 0.944652 7.61662 1.30798C7.61662 1.76819 7.12523 2.34952 6.339 2.78551C5.40535 3.31839 4.15229 3.63327 2.9238 3.63327Z" transform="translate(49.332 33.2891)" fill="#CAC3E5"/>
+<path d="M5.5202 1.59864C6.28186 1.59864 6.96981 1.74397 7.3875 1.98619C7.51035 2.05886 7.58405 2.1073 7.60862 2.15574C7.55948 2.27685 7.33836 2.59174 6.74868 2.93084C5.93788 3.39106 4.80767 3.68172 3.7266 3.68172C2.96494 3.68172 2.27699 3.53639 1.8593 3.29417C1.73646 3.22151 1.66274 3.17306 1.63817 3.12462C1.68731 3.00351 1.90844 2.68862 2.49812 2.34952C3.30892 1.86508 4.43913 1.59864 5.5202 1.59864ZM5.5202 0C4.218 0 2.79296 0.314884 1.68732 0.968874C-0.278264 2.08308 -0.573102 3.75439 1.0485 4.67482C1.76102 5.08659 2.71924 5.28036 3.7266 5.28036C5.0288 5.28036 6.45385 4.96548 7.55949 4.31149C9.52507 3.19728 9.8199 1.52598 8.1983 0.605546C7.48578 0.193775 6.52756 0 5.5202 0Z" transform="translate(48.5273 32.4648)" fill="#AAA7C9"/>
+<path d="M2.9238 3.63328C2.01472 3.63328 1.20392 3.46372 0.638813 3.14884C0.343976 2.97929 1.49962e-06 2.68862 1.49962e-06 2.3253C1.49962e-06 1.86508 0.491396 1.28376 1.27763 0.847764C2.23585 0.314884 3.46433 -3.69596e-07 4.69282 -3.69596e-07C5.6019 -3.69596e-07 6.4127 0.169553 6.97781 0.484436C7.27265 0.653989 7.61662 0.944652 7.61662 1.30798C7.61662 1.76819 7.12523 2.34952 6.33899 2.78551C5.40534 3.31839 4.15229 3.63328 2.9238 3.63328Z" transform="translate(61.3945 26.4336)" fill="#DCD3EB"/>
+<path d="M5.5202 1.59864C6.28186 1.59864 6.96981 1.74397 7.3875 1.98619C7.51034 2.05886 7.58405 2.1073 7.60862 2.15574C7.55948 2.27685 7.33836 2.59174 6.74868 2.93084C5.93788 3.39106 4.80767 3.68172 3.7266 3.68172C2.96494 3.68172 2.27699 3.53639 1.8593 3.29417C1.73645 3.2215 1.66275 3.17306 1.63818 3.12462C1.68732 3.00351 1.90844 2.68863 2.49812 2.34952C3.30892 1.8893 4.43913 1.59864 5.5202 1.59864ZM5.5202 -3.69596e-07C4.218 -3.69596e-07 2.79295 0.314884 1.68731 0.968873C-0.278266 2.08308 -0.5731 3.75439 1.0485 4.67482C1.76103 5.08659 2.71924 5.28036 3.7266 5.28036C5.0288 5.28036 6.45385 4.96548 7.55949 4.31149C9.52507 3.19728 9.81991 1.52598 8.1983 0.605546C7.48578 0.217996 6.52756 -3.69596e-07 5.5202 -3.69596e-07Z" transform="translate(60.5938 25.5859)" fill="#AAA7C9"/>
+<path d="M2.9238 3.63328C2.01472 3.63328 1.20392 3.46372 0.638814 3.14884C0.343977 2.97929 7.49809e-07 2.68862 7.49809e-07 2.3253C7.49809e-07 1.86508 0.491395 1.28376 1.27763 0.847764C2.23585 0.314884 3.46434 9.2399e-08 4.69282 9.2399e-08C5.6019 9.2399e-08 6.4127 0.169553 6.97781 0.484437C7.27264 0.65399 7.61662 0.944652 7.61662 1.30798C7.61662 1.76819 7.12523 2.34952 6.339 2.78551C5.40534 3.31839 4.15229 3.63328 2.9238 3.63328Z" transform="translate(19.9219 2.82031)" fill="#CAC3E5"/>
+<path d="M5.5202 1.59864C6.28186 1.59864 6.96981 1.74397 7.3875 1.98619C7.51035 2.05886 7.58406 2.1073 7.60863 2.15574C7.55949 2.27685 7.33836 2.59174 6.74868 2.93084C5.93788 3.39106 4.80767 3.68172 3.7266 3.68172C2.96494 3.68172 2.27699 3.53639 1.8593 3.29417C1.73645 3.2215 1.66274 3.17306 1.63817 3.12462C1.68731 3.00351 1.90844 2.68862 2.49812 2.34952C3.30892 1.86508 4.43913 1.59864 5.5202 1.59864ZM5.5202 -4.61995e-08C4.218 -4.61995e-08 2.79295 0.314884 1.68732 0.968874C-0.278265 2.08308 -0.573101 3.75439 1.0485 4.67482C1.76103 5.08659 2.71924 5.28036 3.7266 5.28036C5.0288 5.28036 6.45385 4.96548 7.55949 4.31149C9.52507 3.19728 9.8199 1.52598 8.1983 0.605546C7.48578 0.193775 6.52756 -4.61995e-08 5.5202 -4.61995e-08Z" transform="translate(19.1172 1.99219)" fill="#AAA7C9"/>
+</g>
+<defs>
+<filter id="filter0_d" x="0.799705" y="0.25" width="74.8519" height="45.3493" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="3.20029"/>
+<feGaussianBlur stdDeviation="1.60015"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
+</filter>
+</defs>
+</svg>
diff --git a/packages/website/public/images/eth_token.svg b/packages/website/public/images/eth_token.svg
new file mode 100644
index 000000000..9392692f9
--- /dev/null
+++ b/packages/website/public/images/eth_token.svg
@@ -0,0 +1,20 @@
+<svg width="54" height="36" viewBox="0 0 54 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M45.9288 8.37974H44.6437C43.5923 6.66375 41.7231 5.06216 39.2698 3.68937C30.2743 -1.22979 15.788 -1.22979 6.79252 3.68937C4.3392 5.06216 2.47001 6.66375 1.41859 8.37974H0.0166892V12.2693C-0.21696 15.5869 2.00271 19.0189 6.67569 21.5356C15.6712 26.4548 30.1575 26.4548 39.153 21.5356C43.8259 19.0189 46.0456 15.5869 45.812 12.2693V8.37974H45.9288Z" transform="translate(4.07422 6.77344)" fill="#AAA7C9"/>
+<path d="M39.2239 21.4212C30.2284 26.3404 15.7421 26.3404 6.74662 21.4212C-2.24888 16.5021 -2.24888 8.60854 6.74662 3.68937C15.7421 -1.22979 30.2284 -1.22979 39.2239 3.68937C48.2194 8.60854 48.2194 16.6165 39.2239 21.4212Z" transform="translate(4 3)" fill="#CAC3E6"/>
+<path d="M19.7434 21.2782C30.6473 21.2782 39.4867 16.5149 39.4867 10.6391C39.4867 4.7633 30.6473 0 19.7434 0C8.83941 0 0 4.7633 0 10.6391C0 16.5149 8.83941 21.2782 19.7434 21.2782Z" transform="translate(7.35938 4.51562)" fill="#DCD3EB"/>
+<path d="M2.45332 7.89354L12.6171 9.49513L16.8228 -2.18199e-07L-4.45651e-07 2.17358L2.45332 7.89354Z" transform="translate(20.3242 9.55078)" fill="#AAA7C9"/>
+<path d="M0 8.69434L15.304 7.43595L5.25711 5.71996L2.68697 4.36398e-07L0 8.69434Z" transform="translate(16.3516 12.2969)" fill="#AAA7C9"/>
+</g>
+<defs>
+<filter id="filter0_d" x="0.799705" y="0.599779" width="52.4036" height="35.399" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="0.800074"/>
+<feGaussianBlur stdDeviation="1.60015"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
+</filter>
+</defs>
+</svg>
diff --git a/packages/website/public/images/eth_token_erc20.svg b/packages/website/public/images/eth_token_erc20.svg
new file mode 100644
index 000000000..6313c826d
--- /dev/null
+++ b/packages/website/public/images/eth_token_erc20.svg
@@ -0,0 +1,22 @@
+<svg width="66" height="38" viewBox="0 0 66 38" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36.2389" height="14.3077" rx="2.40022" transform="translate(26.7617 0.457031)" fill="#3289F1"/>
+<path d="M3.01758 9.09766C2.20703 9.09766 1.55111 8.85677 1.0498 8.375C0.548503 7.88997 0.297852 7.26009 0.297852 6.48535V6.34863C0.297852 5.80827 0.397135 5.33138 0.595703 4.91797C0.797526 4.50456 1.09049 4.18555 1.47461 3.96094C1.85872 3.73307 2.31445 3.61914 2.8418 3.61914C3.58398 3.61914 4.16992 3.85026 4.59961 4.3125C5.0293 4.77148 5.24414 5.41276 5.24414 6.23633V6.87598H1.97266C2.03125 7.1722 2.15983 7.40495 2.3584 7.57422C2.55697 7.74349 2.81413 7.82812 3.12988 7.82812C3.65072 7.82812 4.05762 7.64583 4.35059 7.28125L5.10254 8.16992C4.89746 8.45312 4.60612 8.67936 4.22852 8.84863C3.85417 9.01465 3.45052 9.09766 3.01758 9.09766ZM2.83203 4.88867C2.35026 4.88867 2.0638 5.20768 1.97266 5.8457H3.63281V5.71875C3.63932 5.45508 3.57259 5.25163 3.43262 5.1084C3.29264 4.96191 3.09245 4.88867 2.83203 4.88867ZM9.31514 5.20605L8.77315 5.16699C8.25557 5.16699 7.92354 5.32975 7.77706 5.65527V9H6.13155V3.7168H7.67452L7.72823 4.39551C8.00492 3.87793 8.39066 3.61914 8.88545 3.61914C9.06123 3.61914 9.21423 3.63867 9.34444 3.67773L9.31514 5.20605ZM12.2533 7.82812C12.4844 7.82812 12.6635 7.76628 12.7904 7.64258C12.9174 7.51562 12.9792 7.33984 12.976 7.11523H14.519C14.519 7.69466 14.3106 8.16992 13.894 8.54102C13.4805 8.91211 12.9467 9.09766 12.2924 9.09766C11.5242 9.09766 10.9187 8.85677 10.476 8.375C10.0333 7.89323 9.81192 7.22591 9.81192 6.37305V6.30469C9.81192 5.77083 9.90958 5.30046 10.1049 4.89355C10.3035 4.4834 10.5883 4.16927 10.9594 3.95117C11.3305 3.72982 11.7699 3.61914 12.2777 3.61914C12.9646 3.61914 13.5098 3.80957 13.9135 4.19043C14.3171 4.57129 14.519 5.08724 14.519 5.73828H12.976C12.976 5.46484 12.9093 5.25488 12.7758 5.1084C12.6423 4.96191 12.4633 4.88867 12.2387 4.88867C11.8122 4.88867 11.5632 5.16048 11.4916 5.7041C11.4688 5.87663 11.4574 6.11426 11.4574 6.41699C11.4574 6.94759 11.5209 7.31543 11.6479 7.52051C11.7748 7.72559 11.9766 7.82812 12.2533 7.82812ZM20.3575 9H15.3966V7.92578L17.6818 5.52344C18.2449 4.88216 18.5265 4.37272 18.5265 3.99512C18.5265 3.68913 18.4597 3.45638 18.3263 3.29688C18.1928 3.13737 17.9991 3.05762 17.7452 3.05762C17.4946 3.05762 17.2911 3.16504 17.1349 3.37988C16.9786 3.59147 16.9005 3.85677 16.9005 4.17578H15.2501C15.2501 3.73958 15.3592 3.33757 15.5773 2.96973C15.7954 2.59863 16.0981 2.30892 16.4855 2.10059C16.8728 1.89225 17.3058 1.78809 17.7843 1.78809C18.5525 1.78809 19.1433 1.96549 19.5568 2.32031C19.9734 2.67513 20.1818 3.18457 20.1818 3.84863C20.1818 4.12858 20.1297 4.40202 20.0255 4.66895C19.9213 4.93262 19.7586 5.21094 19.5372 5.50391C19.3191 5.79362 18.9659 6.18262 18.4776 6.6709L17.5597 7.73047H20.3575V9ZM26.3328 6.09473C26.3328 7.05501 26.1164 7.79557 25.6834 8.31641C25.2537 8.83724 24.6466 9.09766 23.8621 9.09766C23.0711 9.09766 22.4591 8.83561 22.0262 8.31152C21.5932 7.78743 21.3768 7.0485 21.3768 6.09473V4.7959C21.3768 3.83561 21.5916 3.09505 22.0213 2.57422C22.4542 2.05339 23.0646 1.79297 23.8524 1.79297C24.6401 1.79297 25.2505 2.05501 25.6834 2.5791C26.1164 3.10319 26.3328 3.84375 26.3328 4.80078V6.09473ZM24.6873 4.58594C24.6873 4.07487 24.6206 3.69401 24.4871 3.44336C24.3537 3.18945 24.1421 3.0625 23.8524 3.0625C23.5692 3.0625 23.3625 3.17969 23.2322 3.41406C23.1053 3.64844 23.0369 4.00326 23.0272 4.47852V6.29492C23.0272 6.82552 23.0939 7.21452 23.2274 7.46191C23.3608 7.70605 23.5724 7.82812 23.8621 7.82812C24.1421 7.82812 24.3488 7.70931 24.4822 7.47168C24.6157 7.23079 24.6841 6.85482 24.6873 6.34375V4.58594Z" transform="translate(32 2.19922)" fill="white"/>
+<g filter="url(#filter0_d)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M36.9872 6.66078H35.9523C35.1056 5.2968 33.6003 4.02375 31.6246 2.93256C24.3804 -0.977521 12.7144 -0.977521 5.47013 2.93256C3.49443 4.02375 1.98914 5.2968 1.14241 6.66078H0.0134401V9.75247C-0.174722 12.3895 1.61281 15.1175 5.37605 17.118C12.6203 21.0281 24.2863 21.0281 31.5305 17.118C35.2938 15.1175 37.0813 12.3895 36.8931 9.75247V6.66078H36.9872Z" transform="translate(3.46484 12.9961)" fill="#AAA7C9"/>
+<path d="M31.5877 17.027C24.3434 20.9371 12.6774 20.9371 5.43317 17.027C-1.81106 13.117 -1.81106 6.84264 5.43317 2.93256C12.6774 -0.977521 24.3434 -0.977521 31.5877 2.93256C38.8319 6.84264 38.8319 13.2079 31.5877 17.027Z" transform="translate(3.40625 9.99609)" fill="#CAC3E6"/>
+<path d="M15.8997 16.9134C24.6808 16.9134 31.7993 13.1272 31.7993 8.45669C31.7993 3.78619 24.6808 0 15.8997 0C7.11853 0 0 3.78619 0 8.45669C0 13.1272 7.11853 16.9134 15.8997 16.9134Z" transform="translate(6.11328 11.1992)" fill="#DCD3EB"/>
+<path d="M1.9757 6.27432L10.1607 7.54737L13.5476 -1.73439e-07L-3.5889e-07 1.72771L1.9757 6.27432Z" transform="translate(16.5547 15.2031)" fill="#AAA7C9"/>
+<path d="M0 6.91084L12.3246 5.91059L4.23364 4.54661L2.16386 3.46879e-07L0 6.91084Z" transform="translate(13.3555 17.3867)" fill="#AAA7C9"/>
+</g>
+<defs>
+<filter id="filter0_d" x="0.205955" y="7.59587" width="43.4464" height="29.4511" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="0.800074"/>
+<feGaussianBlur stdDeviation="1.60015"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
+</filter>
+</defs>
+</svg>
diff --git a/packages/website/public/images/ether_alt.svg b/packages/website/public/images/ether_alt.svg
new file mode 100644
index 000000000..82199d14d
--- /dev/null
+++ b/packages/website/public/images/ether_alt.svg
@@ -0,0 +1,7 @@
+<svg width="29" height="47" viewBox="0 0 29 47" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.4883 6.11532e-07L0 6.49253L14.4883 14.9288L28.9665 6.49253L14.4883 6.11532e-07Z" transform="translate(0 17.1875)" fill="#267DFF"/>
+<path d="M0 23.6857L14.4883 32.122V0L0 23.6857Z" fill="#267DFF"/>
+<path d="M0 0V32.112L14.4782 23.6757L0 0Z" transform="translate(14.5039)" fill="#267DFF"/>
+<path d="M0 -1.22306e-06L14.4883 20.1088V8.43629L0 -1.22306e-06Z" transform="translate(0 26.8906)" fill="#267DFF"/>
+<path d="M0 8.43629V20.1088L14.4883 -1.22306e-06L0 8.43629Z" transform="translate(14.5117 26.8594)" fill="#267DFF"/>
+</svg>
diff --git a/packages/website/public/images/fake_toggle.svg b/packages/website/public/images/fake_toggle.svg
new file mode 100644
index 000000000..c9632d0da
--- /dev/null
+++ b/packages/website/public/images/fake_toggle.svg
@@ -0,0 +1,4 @@
+<svg width="36" height="23" viewBox="0 0 36 23" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M0 11.4379C0 5.12093 5.12093 0 11.4379 0H23.8494C30.1664 0 35.2873 5.12093 35.2873 11.4379V11.4379C35.2873 17.7549 30.1664 22.8758 23.8494 22.8758H11.4379C5.12092 22.8758 0 17.7549 0 11.4379V11.4379Z" fill="#E0E0E0"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M6.85185 13.8889C10.636 13.8889 13.7037 10.7798 13.7037 6.94444C13.7037 3.10913 10.636 0 6.85185 0C3.06768 0 0 3.10913 0 6.94444C0 10.7798 3.06768 13.8889 6.85185 13.8889Z" transform="translate(3.49609 4.53125)" fill="white"/>
+</svg>
diff --git a/packages/website/public/images/jobs/location1.png b/packages/website/public/images/jobs/location1.png
new file mode 100644
index 000000000..bfda47576
--- /dev/null
+++ b/packages/website/public/images/jobs/location1.png
Binary files differ
diff --git a/packages/website/public/images/jobs/location2.png b/packages/website/public/images/jobs/location2.png
new file mode 100644
index 000000000..c05f9403f
--- /dev/null
+++ b/packages/website/public/images/jobs/location2.png
Binary files differ
diff --git a/packages/website/public/images/jobs/location3.png b/packages/website/public/images/jobs/location3.png
new file mode 100644
index 000000000..34b2e5380
--- /dev/null
+++ b/packages/website/public/images/jobs/location3.png
Binary files differ
diff --git a/packages/website/public/images/jobs/map.png b/packages/website/public/images/jobs/map.png
new file mode 100644
index 000000000..7b85ff66e
--- /dev/null
+++ b/packages/website/public/images/jobs/map.png
Binary files differ
diff --git a/packages/website/public/images/jobs/office1.png b/packages/website/public/images/jobs/office1.png
new file mode 100644
index 000000000..f6e6d9163
--- /dev/null
+++ b/packages/website/public/images/jobs/office1.png
Binary files differ
diff --git a/packages/website/public/images/jobs/office2.png b/packages/website/public/images/jobs/office2.png
new file mode 100644
index 000000000..65f97dcad
--- /dev/null
+++ b/packages/website/public/images/jobs/office2.png
Binary files differ
diff --git a/packages/website/public/images/jobs/office3.png b/packages/website/public/images/jobs/office3.png
new file mode 100644
index 000000000..1dfcb9c58
--- /dev/null
+++ b/packages/website/public/images/jobs/office3.png
Binary files differ
diff --git a/packages/website/public/images/zrx_ecosystem.svg b/packages/website/public/images/zrx_ecosystem.svg
new file mode 100644
index 000000000..f8aed4637
--- /dev/null
+++ b/packages/website/public/images/zrx_ecosystem.svg
@@ -0,0 +1,253 @@
+<svg width="352" height="162" viewBox="0 0 352 162" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g filter="url(#filter0_d)">
+<rect width="96.165" height="52.7562" rx="4" transform="translate(4 101)" fill="#545454"/>
+<rect width="29.5892" height="52.7562" rx="4" transform="translate(4 101)" fill="#808080"/>
+<g opacity="0.4">
+<path d="M0 3.28518V14.7525C0 14.8229 0.0570457 14.88 0.127415 14.88H12.5223C12.6631 14.88 12.7772 14.7659 12.7772 14.6251V14.532C12.7772 14.4427 12.7048 14.3703 12.6154 14.3703H12.5811C12.5107 14.3703 12.4537 14.3132 12.4537 14.2429V14.1963C12.4537 14.1517 12.4175 14.1155 12.3728 14.1155C12.3282 14.1155 12.292 14.0793 12.292 14.0346V13.6401C12.292 13.5508 12.2196 13.4784 12.1302 13.4784C12.0409 13.4784 11.9685 13.406 11.9685 13.3166V13.177C11.9685 13.1323 11.9323 13.0961 11.8876 13.0961C11.843 13.0961 11.8068 13.0599 11.8068 13.0153V12.8756C11.8068 12.7863 11.7343 12.7139 11.645 12.7139C11.5557 12.7139 11.4833 12.6415 11.4833 12.5522V11.9837C11.4833 11.8944 11.4109 11.822 11.3215 11.822C11.2322 11.822 11.1598 11.7496 11.1598 11.6603V11.2658C11.1598 11.2211 11.1236 11.1849 11.0789 11.1849C11.0343 11.1849 10.9981 11.1487 10.9981 11.104V10.837C10.9981 10.7477 10.9257 10.6753 10.8363 10.6753C10.747 10.6753 10.6746 10.6028 10.6746 10.5135V10.0137C10.6746 9.74576 10.4574 9.52852 10.1894 9.52852H10.1501C9.90384 9.52852 9.70418 9.32886 9.70418 9.08257V8.96009C9.70418 8.78144 9.55936 8.63661 9.38071 8.63661C9.20206 8.63661 9.05724 8.49179 9.05724 8.31314V8.25437C9.05724 8.04326 8.8861 7.87213 8.67499 7.87213H8.65289C8.42958 7.87213 8.24855 7.6911 8.24855 7.46778V7.17134C8.24855 6.78431 7.9348 6.47056 7.54777 6.47056H7.43987C6.99325 6.47056 6.63119 6.1085 6.63119 5.66188V4.1252C6.63119 3.66127 6.2551 3.28518 5.79117 3.28518H5.62752C5.25397 3.28518 4.95115 2.98237 4.95115 2.60882C4.95115 2.23528 4.64834 1.93246 4.27479 1.93246H3.99287C3.46362 1.93246 3.03458 1.49947 3.03458 0.970218C3.03458 0.436584 2.60198 0 2.06835 0H1.59715C0.715067 0 0 0.715067 0 1.59715V3.28518Z" transform="translate(60.4883 136.168)" fill="#7EBD91" stroke="#CCFFBF" stroke-width="0.381182"/>
+<path d="M0 1.72904V7.76449C0 7.80153 0.030024 7.83155 0.0670605 7.83155H12.6431C12.7171 7.83155 12.7772 7.77151 12.7772 7.69743C12.7772 7.62336 12.7171 7.56331 12.6431 7.56331H12.5208C12.4837 7.56331 12.4537 7.53329 12.4537 7.49625C12.4537 7.45921 12.4237 7.42919 12.3866 7.42919H12.3728C12.3282 7.42919 12.292 7.39298 12.292 7.34832V7.25562C12.292 7.1663 12.2196 7.09389 12.1302 7.09389H12.0691C12.0135 7.09389 11.9685 7.04885 11.9685 6.9933V6.97357C11.9685 6.92891 11.9323 6.89271 11.8876 6.89271C11.843 6.89271 11.8068 6.8565 11.8068 6.81184V6.79212C11.8068 6.73656 11.7617 6.69152 11.7062 6.69152H11.645C11.5557 6.69152 11.4833 6.61911 11.4833 6.52979V6.38384C11.4833 6.29451 11.4109 6.2221 11.3215 6.2221C11.2322 6.2221 11.1598 6.14969 11.1598 6.06036V5.96767C11.1598 5.923 11.1236 5.8868 11.0789 5.8868C11.0343 5.8868 10.9981 5.85059 10.9981 5.80593V5.75268C10.9981 5.6786 10.938 5.61856 10.8639 5.61856H10.8363C10.747 5.61856 10.6746 5.54614 10.6746 5.45682V5.31678C10.6746 5.15012 10.5395 5.01501 10.3728 5.01501H9.93889C9.80927 5.01501 9.70418 4.90993 9.70418 4.7803C9.70418 4.65067 9.5991 4.54559 9.46947 4.54559H9.25842C9.14731 4.54559 9.05724 4.45551 9.05724 4.34441C9.05724 4.2333 8.96716 4.14322 8.85605 4.14322H8.61739C8.41369 4.14322 8.24855 3.97809 8.24855 3.77439C8.24855 3.57069 8.08342 3.40556 7.87972 3.40556H7.43987C6.99325 3.40556 6.63119 3.0435 6.63119 2.59688V2.5673C6.63119 2.10434 6.25589 1.72904 5.79293 1.72904H5.30713C5.11053 1.72904 4.95115 1.56967 4.95115 1.37306C4.95115 1.17646 4.79178 1.01708 4.59517 1.01708H3.54312C3.26226 1.01708 3.03458 0.789403 3.03458 0.508542C3.03458 0.227682 2.8069 0 2.52604 0H1.59715C0.715067 0 0 0.715067 0 1.59715V1.72904Z" transform="translate(86.043 143.219) scale(-1 1)" fill="#C99957" stroke="#F0D165" stroke-width="0.381182"/>
+</g>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 107.762)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 111.148)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(35.6055 114.527)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 117.91)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(35.6055 121.289)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(35.6055 124.672)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 128.055)" fill="#636363"/>
+<rect width="6.72483" height="2.02908" rx="1.01454" transform="translate(35.6055 131.438)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 134.816)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 138.199)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(35.6055 141.582)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 144.965)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 148.348)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 151.727)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 107.762)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(35.6055 104.383)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 104.383)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 111.148)" fill="#636363"/>
+<rect width="12.1047" height="2.02908" rx="1.01454" transform="translate(46.3672 114.527)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 117.91)" fill="#636363"/>
+<rect width="10.3754" height="2.02908" rx="1.01454" transform="translate(46.3672 121.289)" fill="#636363"/>
+<rect width="12.1047" height="2.02908" rx="1.01454" transform="translate(46.3672 124.672)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 128.055)" fill="#636363"/>
+<rect width="8.64621" height="2.02908" rx="1.01454" transform="translate(46.3672 131.438)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 134.816)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 138.199)" fill="#636363"/>
+<rect width="10.3754" height="2.02908" rx="1.01454" transform="translate(46.3672 141.582)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 144.965)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 148.348)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(46.3672 151.727)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 107.762)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 104.383)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 111.148)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(89.4062 114.527)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 117.91)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(89.4062 121.289)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(89.4062 124.672)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 128.055)" fill="#636363"/>
+<rect width="6.72483" height="2.02908" rx="1.01454" transform="translate(89.4062 131.438)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 134.816)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 138.199)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(89.4062 141.582)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 144.965)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 148.348)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(89.4062 151.727)" fill="#636363"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(63.8516 114.527)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(64.5234 113.176)" fill="#5F7866"/>
+<rect width="0.672483" height="1.35272" rx="0.336241" transform="translate(65.8672 113.176)" fill="#5F7866"/>
+<rect width="0.672483" height="1.35272" rx="0.336241" transform="translate(67.2148 112.496)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(68.5586 113.176)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(69.9023 114.527)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(71.25 114.527)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(72.5938 113.848)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(73.9414 113.848)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(75.2812 113.176)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(76.6289 112.496)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(77.9727 113.176)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.70545" rx="0.336241" transform="translate(79.3203 113.848)" fill="#7D6A4F"/>
+</g>
+<g style="mix-blend-mode:luminosity" filter="url(#filter1_d)">
+<g style="mix-blend-mode:difference" filter="url(#filter2_dd)">
+<rect width="96.165" height="52.7562" rx="4" transform="translate(347.164 101) scale(-1 1)" fill="#545454"/>
+<path d="M0 4C0 1.79086 1.79086 0 4 0H29.5892V52.7562H4C1.79086 52.7562 0 50.9653 0 48.7562V4Z" transform="translate(347.164 101) scale(-1 1)" fill="#808080"/>
+<g opacity="0.4">
+<path d="M0 3.28518V14.7525C0 14.8229 0.0570457 14.88 0.127415 14.88H12.5223C12.6631 14.88 12.7772 14.7659 12.7772 14.6251V14.532C12.7772 14.4427 12.7048 14.3703 12.6154 14.3703H12.5811C12.5107 14.3703 12.4537 14.3132 12.4537 14.2429V14.1963C12.4537 14.1517 12.4175 14.1155 12.3728 14.1155C12.3282 14.1155 12.292 14.0793 12.292 14.0346V13.6401C12.292 13.5508 12.2196 13.4784 12.1302 13.4784C12.0409 13.4784 11.9685 13.406 11.9685 13.3166V13.177C11.9685 13.1323 11.9323 13.0961 11.8876 13.0961C11.843 13.0961 11.8068 13.0599 11.8068 13.0153V12.8756C11.8068 12.7863 11.7343 12.7139 11.645 12.7139C11.5557 12.7139 11.4833 12.6415 11.4833 12.5522V11.9837C11.4833 11.8944 11.4109 11.822 11.3215 11.822C11.2322 11.822 11.1598 11.7496 11.1598 11.6603V11.2658C11.1598 11.2211 11.1236 11.1849 11.0789 11.1849C11.0343 11.1849 10.9981 11.1487 10.9981 11.104V10.837C10.9981 10.7477 10.9257 10.6753 10.8363 10.6753C10.747 10.6753 10.6746 10.6028 10.6746 10.5135V10.0137C10.6746 9.74576 10.4574 9.52852 10.1894 9.52852H10.1501C9.90384 9.52852 9.70418 9.32886 9.70418 9.08257V8.96009C9.70418 8.78144 9.55936 8.63661 9.38071 8.63661C9.20206 8.63661 9.05724 8.49179 9.05724 8.31314V8.25437C9.05724 8.04326 8.8861 7.87213 8.67499 7.87213H8.65289C8.42958 7.87213 8.24855 7.6911 8.24855 7.46778V7.17134C8.24855 6.78431 7.9348 6.47056 7.54777 6.47056H7.43987C6.99325 6.47056 6.63119 6.1085 6.63119 5.66188V4.1252C6.63119 3.66127 6.2551 3.28518 5.79117 3.28518H5.62752C5.25397 3.28518 4.95115 2.98237 4.95115 2.60882C4.95115 2.23528 4.64834 1.93246 4.27479 1.93246H3.99287C3.46362 1.93246 3.03458 1.49947 3.03458 0.970218C3.03458 0.436584 2.60198 0 2.06835 0H1.59715C0.715067 0 0 0.715067 0 1.59715V3.28518Z" transform="translate(290.676 136.168) scale(-1 1)" fill="#7EBD91" stroke="#CCFFBF" stroke-width="0.381182"/>
+<path d="M0 1.72904V7.76449C0 7.80153 0.030024 7.83155 0.0670605 7.83155H12.6431C12.7171 7.83155 12.7772 7.77151 12.7772 7.69743C12.7772 7.62336 12.7171 7.56331 12.6431 7.56331H12.5208C12.4837 7.56331 12.4537 7.53329 12.4537 7.49625C12.4537 7.45921 12.4237 7.42919 12.3866 7.42919H12.3728C12.3282 7.42919 12.292 7.39298 12.292 7.34832V7.25562C12.292 7.1663 12.2196 7.09389 12.1302 7.09389H12.0691C12.0135 7.09389 11.9685 7.04885 11.9685 6.9933V6.97357C11.9685 6.92891 11.9323 6.89271 11.8876 6.89271C11.843 6.89271 11.8068 6.8565 11.8068 6.81184V6.79212C11.8068 6.73656 11.7617 6.69152 11.7062 6.69152H11.645C11.5557 6.69152 11.4833 6.61911 11.4833 6.52979V6.38384C11.4833 6.29451 11.4109 6.2221 11.3215 6.2221C11.2322 6.2221 11.1598 6.14969 11.1598 6.06036V5.96767C11.1598 5.923 11.1236 5.8868 11.0789 5.8868C11.0343 5.8868 10.9981 5.85059 10.9981 5.80593V5.75268C10.9981 5.6786 10.938 5.61856 10.8639 5.61856H10.8363C10.747 5.61856 10.6746 5.54614 10.6746 5.45682V5.31678C10.6746 5.15012 10.5395 5.01501 10.3728 5.01501H9.93889C9.80927 5.01501 9.70418 4.90993 9.70418 4.7803C9.70418 4.65067 9.5991 4.54559 9.46947 4.54559H9.25842C9.14731 4.54559 9.05724 4.45551 9.05724 4.34441C9.05724 4.2333 8.96716 4.14322 8.85605 4.14322H8.61739C8.41369 4.14322 8.24855 3.97809 8.24855 3.77439C8.24855 3.57069 8.08342 3.40556 7.87972 3.40556H7.43987C6.99325 3.40556 6.63119 3.0435 6.63119 2.59688V2.5673C6.63119 2.10434 6.25589 1.72904 5.79293 1.72904H5.30713C5.11053 1.72904 4.95115 1.56967 4.95115 1.37306C4.95115 1.17646 4.79178 1.01708 4.59517 1.01708H3.54312C3.26226 1.01708 3.03458 0.789403 3.03458 0.508542C3.03458 0.227682 2.8069 0 2.52604 0H1.59715C0.715067 0 0 0.715067 0 1.59715V1.72904Z" transform="translate(265.121 143.219)" fill="#C99957" stroke="#F0D165" stroke-width="0.381182"/>
+</g>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 107.762) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 111.148) scale(-1 1)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(315.559 114.527) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 117.91) scale(-1 1)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(315.559 121.289) scale(-1 1)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(315.559 124.672) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 128.055) scale(-1 1)" fill="#636363"/>
+<rect width="6.72483" height="2.02908" rx="1.01454" transform="translate(315.559 131.438) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 134.816) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 138.199) scale(-1 1)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(315.559 141.582) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 144.965) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 148.348) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 151.727) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 107.762) scale(-1 1)" fill="#636363"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(315.559 104.383) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 104.383) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 111.148) scale(-1 1)" fill="#636363"/>
+<rect width="12.1047" height="2.02908" rx="1.01454" transform="translate(304.797 114.527) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 117.91) scale(-1 1)" fill="#636363"/>
+<rect width="10.3754" height="2.02908" rx="1.01454" transform="translate(304.797 121.289) scale(-1 1)" fill="#636363"/>
+<rect width="12.1047" height="2.02908" rx="1.01454" transform="translate(304.797 124.672) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 128.055) scale(-1 1)" fill="#636363"/>
+<rect width="8.64621" height="2.02908" rx="1.01454" transform="translate(304.797 131.438) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 134.816) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 138.199) scale(-1 1)" fill="#636363"/>
+<rect width="10.3754" height="2.02908" rx="1.01454" transform="translate(304.797 141.582) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 144.965) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 148.348) scale(-1 1)" fill="#636363"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(304.797 151.727) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 107.762) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 104.383) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 111.148) scale(-1 1)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(261.758 114.527) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 117.91) scale(-1 1)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(261.758 121.289) scale(-1 1)" fill="#636363"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(261.758 124.672) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 128.055) scale(-1 1)" fill="#636363"/>
+<rect width="6.72483" height="2.02908" rx="1.01454" transform="translate(261.758 131.438) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 134.816) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 138.199) scale(-1 1)" fill="#636363"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(261.758 141.582) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 144.965) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 148.348) scale(-1 1)" fill="#636363"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(261.758 151.727) scale(-1 1)" fill="#636363"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(287.312 114.527) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(286.641 113.176) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="1.35272" rx="0.336241" transform="translate(285.297 113.176) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="1.35272" rx="0.336241" transform="translate(283.949 112.496) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(282.605 113.176) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(281.262 114.527) scale(-1 1)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(279.914 114.527) scale(-1 1)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(278.57 113.848) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(277.223 113.848) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(275.883 113.176) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(274.535 112.496) scale(-1 1)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(273.191 113.176) scale(-1 1)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.70545" rx="0.336241" transform="translate(271.844 113.848) scale(-1 1)" fill="#7D6A4F"/>
+</g>
+</g>
+<g style="mix-blend-mode:hard-light" filter="url(#filter3_d)">
+<rect width="96.165" height="52.7562" rx="4" transform="translate(129 100.246)" fill="#15095E"/>
+<rect width="29.5892" height="52.7562" rx="4" transform="translate(129 100.246)" fill="#010036"/>
+<g opacity="0.4">
+<path d="M0 3.28518V14.7525C0 14.8229 0.0570457 14.88 0.127415 14.88H12.5223C12.6631 14.88 12.7772 14.7659 12.7772 14.6251V14.532C12.7772 14.4427 12.7048 14.3703 12.6154 14.3703H12.5811C12.5107 14.3703 12.4537 14.3132 12.4537 14.2429V14.1963C12.4537 14.1517 12.4175 14.1155 12.3728 14.1155C12.3282 14.1155 12.292 14.0793 12.292 14.0346V13.6401C12.292 13.5508 12.2196 13.4784 12.1302 13.4784C12.0409 13.4784 11.9685 13.406 11.9685 13.3166V13.177C11.9685 13.1323 11.9323 13.0961 11.8876 13.0961C11.843 13.0961 11.8068 13.0599 11.8068 13.0153V12.8756C11.8068 12.7863 11.7343 12.7139 11.645 12.7139C11.5557 12.7139 11.4833 12.6415 11.4833 12.5522V11.9837C11.4833 11.8944 11.4109 11.822 11.3215 11.822C11.2322 11.822 11.1598 11.7496 11.1598 11.6603V11.2658C11.1598 11.2211 11.1236 11.1849 11.0789 11.1849C11.0343 11.1849 10.9981 11.1487 10.9981 11.104V10.837C10.9981 10.7477 10.9257 10.6753 10.8363 10.6753C10.747 10.6753 10.6746 10.6028 10.6746 10.5135V10.0137C10.6746 9.74576 10.4574 9.52852 10.1894 9.52852H10.1501C9.90384 9.52852 9.70418 9.32886 9.70418 9.08257V8.96009C9.70418 8.78144 9.55936 8.63661 9.38071 8.63661C9.20206 8.63661 9.05724 8.49179 9.05724 8.31314V8.25437C9.05724 8.04326 8.8861 7.87213 8.67499 7.87213H8.65289C8.42958 7.87213 8.24855 7.6911 8.24855 7.46778V7.17134C8.24855 6.78431 7.9348 6.47056 7.54777 6.47056H7.43987C6.99325 6.47056 6.63119 6.1085 6.63119 5.66188V4.1252C6.63119 3.66127 6.2551 3.28518 5.79117 3.28518H5.62752C5.25397 3.28518 4.95115 2.98237 4.95115 2.60882C4.95115 2.23528 4.64834 1.93246 4.27479 1.93246H3.99287C3.46362 1.93246 3.03458 1.49947 3.03458 0.970218C3.03458 0.436584 2.60198 0 2.06835 0H1.59715C0.715067 0 0 0.715067 0 1.59715V3.28518Z" transform="translate(185.488 135.418)" fill="#7EBD91" stroke="#CCFFBF" stroke-width="0.381182"/>
+<path d="M0 1.72904V7.76449C0 7.80153 0.030024 7.83155 0.0670605 7.83155H12.6431C12.7171 7.83155 12.7772 7.77151 12.7772 7.69743C12.7772 7.62336 12.7171 7.56331 12.6431 7.56331H12.5208C12.4837 7.56331 12.4537 7.53329 12.4537 7.49625C12.4537 7.45921 12.4237 7.42919 12.3866 7.42919H12.3728C12.3282 7.42919 12.292 7.39298 12.292 7.34832V7.25562C12.292 7.1663 12.2196 7.09389 12.1302 7.09389H12.0691C12.0135 7.09389 11.9685 7.04885 11.9685 6.9933V6.97357C11.9685 6.92891 11.9323 6.89271 11.8876 6.89271C11.843 6.89271 11.8068 6.8565 11.8068 6.81184V6.79212C11.8068 6.73656 11.7617 6.69152 11.7062 6.69152H11.645C11.5557 6.69152 11.4833 6.61911 11.4833 6.52979V6.38384C11.4833 6.29451 11.4109 6.2221 11.3215 6.2221C11.2322 6.2221 11.1598 6.14969 11.1598 6.06036V5.96767C11.1598 5.923 11.1236 5.8868 11.0789 5.8868C11.0343 5.8868 10.9981 5.85059 10.9981 5.80593V5.75268C10.9981 5.6786 10.938 5.61856 10.8639 5.61856H10.8363C10.747 5.61856 10.6746 5.54614 10.6746 5.45682V5.31678C10.6746 5.15012 10.5395 5.01501 10.3728 5.01501H9.93889C9.80927 5.01501 9.70418 4.90993 9.70418 4.7803C9.70418 4.65067 9.5991 4.54559 9.46947 4.54559H9.25842C9.14731 4.54559 9.05724 4.45551 9.05724 4.34441C9.05724 4.2333 8.96716 4.14322 8.85605 4.14322H8.61739C8.41369 4.14322 8.24855 3.97809 8.24855 3.77439C8.24855 3.57069 8.08342 3.40556 7.87972 3.40556H7.43987C6.99325 3.40556 6.63119 3.0435 6.63119 2.59688V2.5673C6.63119 2.10434 6.25589 1.72904 5.79293 1.72904H5.30713C5.11053 1.72904 4.95115 1.56967 4.95115 1.37306C4.95115 1.17646 4.79178 1.01708 4.59517 1.01708H3.54312C3.26226 1.01708 3.03458 0.789403 3.03458 0.508542C3.03458 0.227682 2.8069 0 2.52604 0H1.59715C0.715067 0 0 0.715067 0 1.59715V1.72904Z" transform="translate(211.043 142.469) scale(-1 1)" fill="#C95E57" stroke="#942C39" stroke-width="0.381182"/>
+</g>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 107.008)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 110.395)" fill="#010036"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(160.605 113.773)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 117.156)" fill="#010036"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(160.605 120.535)" fill="#010036"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(160.605 123.918)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 127.301)" fill="#010036"/>
+<rect width="6.72483" height="2.02908" rx="1.01454" transform="translate(160.605 130.684)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 134.062)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 137.445)" fill="#010036"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(160.605 140.828)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 144.211)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 147.594)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 150.973)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 107.008)" fill="#010036"/>
+<rect width="8.74228" height="2.02908" rx="1.01454" transform="translate(160.605 103.629)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 103.629)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 110.395)" fill="#010036"/>
+<rect width="12.1047" height="2.02908" rx="1.01454" transform="translate(171.367 113.773)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 117.156)" fill="#010036"/>
+<rect width="10.3754" height="2.02908" rx="1.01454" transform="translate(171.367 120.535)" fill="#010036"/>
+<rect width="12.1047" height="2.02908" rx="1.01454" transform="translate(171.367 123.918)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 127.301)" fill="#010036"/>
+<rect width="8.64621" height="2.02908" rx="1.01454" transform="translate(171.367 130.684)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 134.062)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 137.445)" fill="#010036"/>
+<rect width="10.3754" height="2.02908" rx="1.01454" transform="translate(171.367 140.828)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 144.211)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 147.594)" fill="#010036"/>
+<rect width="11.2401" height="2.02908" rx="1.01454" transform="translate(171.367 150.973)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 107.008)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 103.629)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 110.395)" fill="#010036"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(214.406 113.773)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 117.156)" fill="#010036"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(214.406 120.535)" fill="#010036"/>
+<rect width="9.41476" height="2.02908" rx="1.01454" transform="translate(214.406 123.918)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 127.301)" fill="#010036"/>
+<rect width="6.72483" height="2.02908" rx="1.01454" transform="translate(214.406 130.684)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 134.062)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 137.445)" fill="#010036"/>
+<rect width="8.06979" height="2.02908" rx="1.01454" transform="translate(214.406 140.828)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 144.211)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 147.594)" fill="#010036"/>
+<rect width="8.74227" height="2.02908" rx="1.01454" transform="translate(214.406 150.973)" fill="#010036"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(188.852 115.773)" fill="#5F7866"/>
+<path d="M0 0.336241C0 0.15054 0.15054 0 0.336241 0C0.521942 0 0.672483 0.15054 0.672483 0.336241V1.69284C0.672483 1.87854 0.521942 2.02908 0.336241 2.02908C0.15054 2.02908 0 1.87854 0 1.69284V0.336241Z" transform="translate(189.523 114.422)" fill="#5F7866"/>
+<rect width="0.672483" height="1.35272" rx="0.336241" transform="translate(190.867 113.422)" fill="#5F7866"/>
+<rect width="0.672483" height="1.35272" rx="0.336241" transform="translate(192.215 113.742)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(193.559 112.422)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(194.902 113.773)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(196.25 113.773)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(197.594 113.094)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(198.938 111.094)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(200.281 109.422)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(201.629 107.742)" fill="#5F7866"/>
+<rect width="0.672483" height="2.02908" rx="0.336241" transform="translate(202.973 108.422)" fill="#7D6A4F"/>
+<rect width="0.672483" height="2.70545" rx="0.336241" transform="translate(204.32 109.094)" fill="#7D6A4F"/>
+</g>
+<rect width="80" height="48" transform="translate(137)" fill="url(#pattern0)"/>
+<line x1="1" y1="-1" x2="32" y2="-1" transform="translate(176 58) rotate(90)" stroke="#3289F1" stroke-width="2" stroke-linecap="round"/>
+<path d="M30 0H6V118.5H0" transform="translate(302.5 58.5) rotate(90)" stroke="#3289F1" stroke-width="2" stroke-linecap="round"/>
+<path d="M30 117.5H6V0H0" transform="translate(170.5 58.5) rotate(90)" stroke="#3289F1" stroke-width="2" stroke-linecap="round"/>
+<defs>
+<filter id="filter0_d" x="0" y="101" width="104.165" height="60.7562" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="4"/>
+<feGaussianBlur stdDeviation="2"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
+</filter>
+<filter id="filter1_d" x="247" y="101" width="104.165" height="60.7562" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="4"/>
+<feGaussianBlur stdDeviation="2"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
+</filter>
+<filter id="filter2_dd" x="247" y="101" width="104.165" height="60.7562" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="4"/>
+<feGaussianBlur stdDeviation="2"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="4"/>
+<feGaussianBlur stdDeviation="2"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
+</filter>
+<filter id="filter3_d" x="125" y="100.246" width="104.165" height="60.7562" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0"/>
+<feOffset dy="4"/>
+<feGaussianBlur stdDeviation="2"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
+</filter>
+<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
+<use xlink:href="#image0" transform="scale(0.00142857 0.00235294)"/>
+</pattern>
+<image id="image0" width="700" height="425" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAArwAAAGpCAYAAABvSeX2AAAAAXNSR0IArs4c6QAAQABJREFUeAHsvQeUZVd5pv2deEPFjurcCigBikhCASRA2IyNsQk2wTbBGLANxmHs4f8nrX/NWvYaMx7HZQ94AJtshBEWFtEWmIyFhEAGCYSy1Gp1tzpUd4UbTvrf99y63aVSVXVV1831bun2PfekvfezT937nu98+/vMVERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABPqIgNNHbVVTRWBgCfzXK7f2VN+yLDNvZ2AbpgKbxrdExTwrpZkdyio2FqGpQ445fsWKqWv1bIP5TmzTcWZuLbVCmFjmB5amkQ3VapaE45ZkOMSt25FKZknBNX80tfVHYtsf4mRh0ab3+haV6nbmusCOzThWcBKbqdat5rk2UiqZoe5jaEchcMyroo60fs5U6n6gHHp/GJVnPu1vji2LuvN1NlFP7bJNBXvV00fNsNzzBWNhgVkEXgce8AG1bqEbWD1ObajoWR3s42MVc5wxCwrg6qcW41WqRnZgyLehKLPiMbOZsdCco1XzRzA+lcTSiczi8cBG4ymrhqNW9SrmzuC62eFYdCSy5FjJSmN1y7zQ4nrNbDIzf9izxK+b7xXQjAmbrhctKZVxvdSslBQsK8yYW0pw/Ki5ad3qUcHCIZw3COwwrg3vQNXGikWbHKvZ+rpnbuzZJK47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Y9ybBOi/5C3/jd+bFDTqLSTAyWv07/I/2A8edLzgCd/xznizF38orVa7kdudmpyYmH/onkfmD99z38Lx21859dj5x+cbswsNr1JqhiZoRN1W0wSmw3lwcZclhBmFzb7EvIdUxQfM7oAXyLBAwwOjw7b1bBB0+7Kt7Qu2i+lOBERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABERABLaMwP8PiHLGLtI5pqYAAAAASUVORK5CYII="/>
+</defs>
+</svg>
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 6e4d03e27..3ebdd1dee 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -132,7 +132,7 @@ export class Blockchain {
return provider;
}
- constructor(dispatcher: Dispatcher, isSalePage: boolean = false) {
+ constructor(dispatcher: Dispatcher) {
this._dispatcher = dispatcher;
const defaultGasPrice = GWEI_IN_WEI * 30;
this._defaultGasPrice = new BigNumber(defaultGasPrice);
@@ -577,13 +577,13 @@ export class Blockchain {
trackedTokensByAddress[token.address] = token;
});
if (!_.isUndefined(this._userAddressIfExists)) {
- _.each(trackedTokensByAddress, (token: Token, address: string) => {
+ _.each(trackedTokensByAddress, (token: Token) => {
trackedTokenStorage.addTrackedTokenToUser(this._userAddressIfExists, this.networkId, token);
});
}
} else {
// Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array
- _.each(trackedTokensByAddress, (trackedToken: Token, address: string) => {
+ _.each(trackedTokensByAddress, (_trackedToken: Token, address: string) => {
if (!_.isUndefined(tokenRegistryTokensByAddress[address])) {
tokenRegistryTokensByAddress[address].isTracked = true;
}
@@ -625,6 +625,7 @@ export class Blockchain {
);
const provider = this._contractWrappers.getProvider();
const web3Wrapper = new Web3Wrapper(provider);
+ web3Wrapper.abiDecoder.addABI(this._contractWrappers.exchange.abi);
const receipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
return receipt;
}
@@ -754,7 +755,7 @@ export class Blockchain {
const tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync();
const tokenByAddress: TokenByAddress = {};
- _.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => {
+ _.each(tokenRegistryTokens, (t: ZeroExToken) => {
// HACK: For now we have a hard-coded list of iconUrls for the dummyTokens
// TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry
const iconUrl = configs.ICON_URL_BY_SYMBOL[t.symbol];
diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
index 196414407..c9727b553 100644
--- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
+++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
@@ -250,7 +250,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
});
return true;
}
- private _onDerivationPathChanged(e: any, derivationPath: string): void {
+ private _onDerivationPathChanged(_event: any, derivationPath: string): void {
let derivationErrMsg = '';
if (!_.startsWith(derivationPath, VALID_ETHEREUM_DERIVATION_PATH_PREFIX)) {
derivationErrMsg = 'Must be valid Ethereum path.';
@@ -295,7 +295,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
return userAddresses;
}
- private _onSelectedNetworkUpdated(e: any, index: number, networkId: number): void {
+ private _onSelectedNetworkUpdated(_event: any, _index: number, networkId: number): void {
this.setState({
preferredNetworkId: networkId,
});
diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index ca8634693..20b446155 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -221,9 +221,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</TableHeaderColumn>
</TableRow>
</TableHeader>
- <TableBody displayRowCheckbox={false}>
- {this._renderOutdatedWeths(etherToken, this.state.ethTokenState)}
- </TableBody>
+ <TableBody displayRowCheckbox={false}>{this._renderOutdatedWeths(etherToken)}</TableBody>
</Table>
</div>
</div>
@@ -249,7 +247,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</div>
);
}
- private _renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState): React.ReactNode {
+ private _renderOutdatedWeths(etherToken: Token): React.ReactNode {
const rows = _.map(
configs.OUTDATED_WRAPPED_ETHERS,
(outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => {
diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx
index b6b52993e..f3ea44286 100644
--- a/packages/website/ts/components/fill_order.tsx
+++ b/packages/website/ts/components/fill_order.tsx
@@ -351,7 +351,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
this._onFillOrderClickFireAndForgetAsync();
}
}
- private _onFillAmountChange(isValid: boolean, amount?: BigNumber): void {
+ private _onFillAmountChange(_isValid: boolean, amount?: BigNumber): void {
this.props.dispatcher.updateOrderFillAmount(amount);
}
private _onFillOrderJSONChanged(event: any): void {
diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx
index c44e41084..9fb332a98 100644
--- a/packages/website/ts/components/footer.tsx
+++ b/packages/website/ts/components/footer.tsx
@@ -235,7 +235,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div>
);
}
- private _updateLanguage(e: any, index: number, value: Language): void {
+ private _updateLanguage(_event: any, _index: number, value: Language): void {
this.setState({
selectedLanguage: value,
});
diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx
index 52e3b73cd..d26b5c3fa 100644
--- a/packages/website/ts/components/generate_order/generate_order_form.tsx
+++ b/packages/website/ts/components/generate_order/generate_order_form.tsx
@@ -226,7 +226,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
</div>
);
}
- private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber): void {
+ private _onTokenAmountChange(token: Token, side: Side, _isValid: boolean, amount?: BigNumber): void {
this.props.dispatcher.updateChosenAssetToken(side, {
address: token.address,
amount,
diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx
index a9b8e9589..176a0807b 100644
--- a/packages/website/ts/components/generate_order/new_token_form.tsx
+++ b/packages/website/ts/components/generate_order/new_token_form.tsx
@@ -152,7 +152,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
};
this.props.onNewTokenSubmitted(newToken);
}
- private _onTokenNameChanged(e: any, name: string): void {
+ private _onTokenNameChanged(_event: any, name: string): void {
let nameErrText = '';
const maxLength = 30;
const tokens = _.values(this.props.tokenByAddress);
@@ -173,7 +173,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
nameErrText,
});
}
- private _onTokenSymbolChanged(e: any, symbol: string): void {
+ private _onTokenSymbolChanged(_event: any, symbol: string): void {
let symbolErrText = '';
const maxLength = 5;
const tokens = _.values(this.props.tokenByAddress);
@@ -193,7 +193,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
symbolErrText,
});
}
- private _onTokenDecimalsChanged(e: any, decimals: string): void {
+ private _onTokenDecimalsChanged(_event: any, decimals: string): void {
let decimalsErrText = '';
const maxLength = 2;
if (decimals === '') {
diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx
index 09791f125..0dd2a5aa5 100644
--- a/packages/website/ts/components/inputs/allowance_toggle.tsx
+++ b/packages/website/ts/components/inputs/allowance_toggle.tsx
@@ -1,5 +1,6 @@
import { constants as sharedConstants, Styles } from '@0xproject/react-shared';
import { BigNumber, logUtils } from '@0xproject/utils';
+import * as _ from 'lodash';
import Toggle from 'material-ui/Toggle';
import * as React from 'react';
import { Blockchain } from 'ts/blockchain';
@@ -16,11 +17,11 @@ interface AllowanceToggleProps {
networkId: number;
blockchain: Blockchain;
dispatcher: Dispatcher;
- onErrorOccurred: (errType: BalanceErrs) => void;
token: Token;
tokenState: TokenState;
userAddress: string;
- isDisabled: boolean;
+ isDisabled?: boolean;
+ onErrorOccurred?: (errType: BalanceErrs) => void;
refetchTokenStateAsync: () => Promise<void>;
}
@@ -55,6 +56,10 @@ const styles: Styles = {
};
export class AllowanceToggle extends React.Component<AllowanceToggleProps, AllowanceToggleState> {
+ public static defaultProps = {
+ onErrorOccurred: _.noop,
+ isDisabled: false,
+ };
constructor(props: AllowanceToggleProps) {
super(props);
this.state = {
diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx
index e5b502b25..968609030 100644
--- a/packages/website/ts/components/inputs/balance_bounded_input.tsx
+++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx
@@ -104,7 +104,7 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp
/>
);
}
- private _onValueChange(e: any, amountString: string): void {
+ private _onValueChange(_event: any, amountString: string): void {
this._setAmountState(amountString, this.props.balance, () => {
const isValid = _.isUndefined(this._validate(amountString, this.props.balance));
const isPositiveNumber = utils.isNumeric(amountString) && !_.includes(amountString, '-');
diff --git a/packages/website/ts/components/inputs/expiration_input.tsx b/packages/website/ts/components/inputs/expiration_input.tsx
index 5c68080fe..79dd2f568 100644
--- a/packages/website/ts/components/inputs/expiration_input.tsx
+++ b/packages/website/ts/components/inputs/expiration_input.tsx
@@ -80,7 +80,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const defaultDateTime = utils.initialOrderExpiryUnixTimestampSec();
this.props.updateOrderExpiry(defaultDateTime);
}
- private _onDateChanged(e: any, date: Date): void {
+ private _onDateChanged(_event: any, date: Date): void {
const dateMoment = moment(date);
this.setState({
dateMoment,
@@ -88,7 +88,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const timestamp = utils.convertToUnixTimestampSeconds(dateMoment, this.state.timeMoment);
this.props.updateOrderExpiry(timestamp);
}
- private _onTimeChanged(e: any, time: Date): void {
+ private _onTimeChanged(_event: any, time: Date): void {
const timeMoment = moment(time);
this.setState({
timeMoment,
diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx
index 35e917eec..b4a174a03 100644
--- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx
+++ b/packages/website/ts/components/legacy_portal/legacy_portal.tsx
@@ -310,7 +310,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
/>
);
}
- private _renderFillOrder(match: any, location: Location, history: History): React.ReactNode {
+ private _renderFillOrder(_match: any, _location: Location, _history: History): React.ReactNode {
const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache)
? this.props.userSuppliedOrderCache
: this._sharedOrderIfExists;
@@ -329,7 +329,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
/>
);
}
- private _renderGenerateOrderForm(match: any, location: Location, history: History): React.ReactNode {
+ private _renderGenerateOrderForm(_match: any, _location: Location, _history: History): React.ReactNode {
return (
<GenerateOrderForm
blockchain={this._blockchain}
diff --git a/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx b/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx
new file mode 100644
index 000000000..31ce99d31
--- /dev/null
+++ b/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+
+export interface AddEthOnboardingStepProps {}
+
+export const AddEthOnboardingStep: React.StatelessComponent<AddEthOnboardingStepProps> = () => (
+ <div className="flex items-center flex-column">
+ <Text> Before you begin you will need to send some ETH to your metamask wallet.</Text>
+ <Container marginTop="15px" marginBottom="15px">
+ <img src="/images/ether_alt.svg" height="50px" width="50px" />
+ </Container>
+ <Text>
+ Click on the <img src="/images/metamask_icon.png" height="20px" width="20px" /> metamask extension in your
+ browser and click either <b>BUY</b> or <b>DEPOSIT</b>.
+ </Text>
+ </div>
+);
diff --git a/packages/website/ts/components/onboarding/congrats_onboarding_step.tsx b/packages/website/ts/components/onboarding/congrats_onboarding_step.tsx
new file mode 100644
index 000000000..3a8db8c36
--- /dev/null
+++ b/packages/website/ts/components/onboarding/congrats_onboarding_step.tsx
@@ -0,0 +1,15 @@
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+
+export interface CongratsOnboardingStepProps {}
+
+export const CongratsOnboardingStep: React.StatelessComponent<CongratsOnboardingStepProps> = () => (
+ <div className="flex items-center flex-column">
+ <Text>Your wallet is now set up for trading. Use it on any relayer in the 0x ecosystem.</Text>
+ <Container marginTop="25px" marginBottom="15px" className="flex justify-center">
+ <img src="/images/zrx_ecosystem.svg" height="150px" />
+ </Container>
+ <Text>No need to log in. Each relayer automatically detects and connects to your metamask wallet.</Text>
+ </div>
+);
diff --git a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
new file mode 100644
index 000000000..a54496186
--- /dev/null
+++ b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
@@ -0,0 +1,18 @@
+import { colors } from '@0xproject/react-shared';
+import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+
+export interface InstallWalletOnboardingStepProps {}
+
+export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWalletOnboardingStepProps> = () => (
+ <div className="flex items-center flex-column">
+ <Container marginTop="15px" marginBottom="15px">
+ <ActionAccountBalanceWallet style={{ width: '30px', height: '30px' }} color={colors.orange} />
+ </Container>
+ <Text>
+ Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps.
+ </Text>
+ </div>
+);
diff --git a/packages/website/ts/components/onboarding/intro_onboarding_step.tsx b/packages/website/ts/components/onboarding/intro_onboarding_step.tsx
new file mode 100644
index 000000000..548839218
--- /dev/null
+++ b/packages/website/ts/components/onboarding/intro_onboarding_step.tsx
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+
+export interface IntroOnboardingStepProps {}
+
+export const IntroOnboardingStep: React.StatelessComponent<IntroOnboardingStepProps> = () => (
+ <div className="flex items-center flex-column">
+ <Text>
+ In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps.
+ </Text>
+ <Container width="100%" marginTop="25px" marginBottom="15px" className="flex justify-around">
+ <div className="flex flex-column items-center">
+ <img src="/images/eth_token.svg" height="50px" width="50x" />
+ <Text> Wrap ETH </Text>
+ </div>
+ <div className="flex flex-column items-center">
+ <img src="/images/fake_toggle.svg" height="50px" width="50px" />
+ <Text> Unlock tokens </Text>
+ </div>
+ </Container>
+ </div>
+);
diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx
index 9879cd387..34aeace82 100644
--- a/packages/website/ts/components/onboarding/onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx
@@ -10,9 +10,10 @@ export interface Step {
title?: string;
content: React.ReactNode;
placement?: Placement;
- hideBackButton?: boolean;
- hideNextButton?: boolean;
+ shouldHideBackButton?: boolean;
+ shouldHideNextButton?: boolean;
continueButtonDisplay?: ContinueButtonDisplay;
+ continueButtonText?: string;
}
export interface OnboardingFlowProps {
@@ -54,17 +55,18 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
const step = steps[stepIndex];
const isLastStep = steps.length - 1 === stepIndex;
return (
- <Container marginLeft="15px">
+ <Container marginLeft="30px">
<OnboardingTooltip
title={step.title}
content={step.content}
isLastStep={isLastStep}
- hideBackButton={step.hideBackButton}
- hideNextButton={step.hideNextButton}
+ shouldHideBackButton={step.shouldHideBackButton}
+ shouldHideNextButton={step.shouldHideNextButton}
onClose={this.props.onClose}
onClickNext={this._goToNextStep.bind(this)}
onClickBack={this._goToPrevStep.bind(this)}
continueButtonDisplay={step.continueButtonDisplay}
+ continueButtonText={step.continueButtonText}
/>
</Container>
);
diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
index 155c70c5f..45851b4de 100644
--- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
@@ -1,7 +1,12 @@
+import { colors } from '@0xproject/react-shared';
import * as React from 'react';
+import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
+import { IconButton } from 'ts/components/ui/icon_button';
import { Island } from 'ts/components/ui/island';
+import { Pointer, PointerDirection } from 'ts/components/ui/pointer';
+import { Text, Title } from 'ts/components/ui/text';
export type ContinueButtonDisplay = 'enabled' | 'disabled';
@@ -13,43 +18,73 @@ export interface OnboardingTooltipProps {
onClickNext: () => void;
onClickBack: () => void;
continueButtonDisplay?: ContinueButtonDisplay;
- hideBackButton?: boolean;
- hideNextButton?: boolean;
+ shouldHideBackButton?: boolean;
+ shouldHideNextButton?: boolean;
+ pointerDirection?: PointerDirection;
+ continueButtonText?: string;
+ className?: string;
}
-// TODO: Make this more general button.
-export interface ContinueButtonProps {
- display: ContinueButtonDisplay;
- children?: string;
- onClick: () => void;
-}
+export const OnboardingTooltip: React.StatelessComponent<OnboardingTooltipProps> = ({
+ title,
+ content,
+ continueButtonDisplay,
+ continueButtonText,
+ onClickNext,
+ onClickBack,
+ onClose,
+ shouldHideBackButton,
+ shouldHideNextButton,
+ pointerDirection,
+ className,
+}) => (
+ <Pointer className={className} direction={pointerDirection}>
+ <Island>
+ <Container paddingRight="30px" paddingLeft="30px" maxWidth={350} paddingTop="15px" paddingBottom="15px">
+ <div className="flex flex-column">
+ <div className="flex justify-between">
+ <Title>{title}</Title>
+ <Container position="relative" bottom="20px" left="15px">
+ <IconButton color={colors.grey} iconName="zmdi-close" onClick={onClose}>
+ Close
+ </IconButton>
+ </Container>
+ </div>
+ <Container marginBottom="15px">
+ <Text>{content}</Text>
+ </Container>
+ {continueButtonDisplay && (
+ <Button
+ isDisabled={continueButtonDisplay === 'disabled'}
+ onClick={onClickNext}
+ fontColor={colors.white}
+ fontSize="15px"
+ backgroundColor={colors.mediumBlue}
+ >
+ {continueButtonText}
+ </Button>
+ )}
+ <Container className="flex justify-between" marginTop="15px">
+ {!shouldHideBackButton && (
+ <Text fontColor={colors.grey} onClick={onClickBack}>
+ Back
+ </Text>
+ )}
+ {!shouldHideNextButton && (
+ <Text fontColor={colors.grey} onClick={onClickNext}>
+ Skip
+ </Text>
+ )}
+ </Container>
+ </div>
+ </Container>
+ </Island>
+ </Pointer>
+);
-export const ContinueButton: React.StatelessComponent<ContinueButtonProps> = (props: ContinueButtonProps) => {
- const isDisabled = props.display === 'disabled';
- return (
- <button disabled={isDisabled} onClick={isDisabled ? undefined : props.onClick}>
- {props.children}
- </button>
- );
+OnboardingTooltip.defaultProps = {
+ pointerDirection: 'left',
+ continueButtonText: 'Continue',
};
-export const OnboardingTooltip: React.StatelessComponent<OnboardingTooltipProps> = (props: OnboardingTooltipProps) => (
- <Island>
- <Container paddingRight="30px" paddingLeft="30px" maxWidth={350} paddingTop="15px" paddingBottom="15px">
- <div className="flex flex-column">
- {props.title}
- {props.content}
- {props.continueButtonDisplay && (
- <ContinueButton onClick={props.onClickNext} display={props.continueButtonDisplay}>
- Continue
- </ContinueButton>
- )}
- {!props.hideBackButton && <button onClick={props.onClickBack}>Back</button>}
- {!props.hideNextButton && <button onClick={props.onClickNext}>Skip</button>}
- <button onClick={props.onClose}>Close</button>
- </div>
- </Container>
- </Island>
-);
-
OnboardingTooltip.displayName = 'OnboardingTooltip';
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
index bf52684d7..4283022e2 100644
--- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -2,11 +2,21 @@ import * as _ from 'lodash';
import * as React from 'react';
import { BigNumber } from '@0xproject/utils';
+import { Blockchain } from 'ts/blockchain';
+import { AddEthOnboardingStep } from 'ts/components/onboarding/add_eth_onboarding_step';
+import { CongratsOnboardingStep } from 'ts/components/onboarding/congrats_onboarding_step';
+import { InstallWalletOnboardingStep } from 'ts/components/onboarding/install_wallet_onboarding_step';
+import { IntroOnboardingStep } from 'ts/components/onboarding/intro_onboarding_step';
import { OnboardingFlow, Step } from 'ts/components/onboarding/onboarding_flow';
-import { ProviderType, TokenByAddress, TokenStateByAddress } from 'ts/types';
+import { SetAllowancesOnboardingStep } from 'ts/components/onboarding/set_allowances_onboarding_step';
+import { UnlockWalletOnboardingStep } from 'ts/components/onboarding/unlock_wallet_onboarding_step';
+import { WrapEthOnboardingStep } from 'ts/components/onboarding/wrap_eth_onboarding_step';
+import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
+import { ProviderType, Token, TokenByAddress, TokenStateByAddress } from 'ts/types';
import { utils } from 'ts/utils/utils';
export interface PortalOnboardingFlowProps {
+ blockchain: Blockchain;
stepIndex: number;
isRunning: boolean;
userAddress: string;
@@ -19,6 +29,7 @@ export interface PortalOnboardingFlowProps {
trackedTokenStateByAddress: TokenStateByAddress;
updateIsRunning: (isRunning: boolean) => void;
updateOnboardingStep: (stepIndex: number) => void;
+ refetchTokenStateAsync: (tokenAddress: string) => Promise<void>;
}
export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowProps> {
@@ -39,73 +50,117 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr
/>
);
}
-
private _getSteps(): Step[] {
const steps: Step[] = [
{
target: '.wallet',
- content:
- 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps',
+ title: '0x Ecosystem Setup',
+ content: <InstallWalletOnboardingStep />,
placement: 'right',
- hideBackButton: true,
- hideNextButton: true,
+ shouldHideBackButton: true,
+ shouldHideNextButton: true,
},
{
target: '.wallet',
- content: 'Unlock your metamask extension to begin',
+ title: '0x Ecosystem Setup',
+ content: <UnlockWalletOnboardingStep />,
placement: 'right',
- hideBackButton: true,
- hideNextButton: true,
+ shouldHideBackButton: true,
+ shouldHideNextButton: true,
},
{
target: '.wallet',
- content:
- 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps',
+ title: '0x Ecosystem Account Setup',
+ content: <IntroOnboardingStep />,
placement: 'right',
- hideBackButton: true,
+ shouldHideBackButton: true,
continueButtonDisplay: 'enabled',
},
{
target: '.eth-row',
- content: 'Before you begin you will need to send some ETH to your metamask wallet',
+ title: 'Add ETH',
+ content: <AddEthOnboardingStep />,
placement: 'right',
continueButtonDisplay: this._userHasVisibleEth() ? 'enabled' : 'disabled',
},
{
target: '.weth-row',
- content: 'You need to convert some of your ETH into tradeable Wrapped ETH (WETH)',
+ title: 'Step 1/2',
+ content: (
+ <WrapEthOnboardingStep
+ formattedEthBalanceIfExists={
+ this._userHasVisibleWeth() ? this._getFormattedWethBalance() : undefined
+ }
+ />
+ ),
+ placement: 'right',
+ continueButtonDisplay: this._userHasVisibleWeth() ? 'enabled' : undefined,
+ },
+ {
+ target: '.weth-row',
+ title: 'Step 2/2',
+ content: (
+ <SetAllowancesOnboardingStep
+ zrxAllowanceToggle={this._renderZrxAllowanceToggle()}
+ ethAllowanceToggle={this._renderEthAllowanceToggle()}
+ />
+ ),
+ placement: 'right',
+ continueButtonDisplay: this._userHasAllowancesForWethAndZrx() ? 'enabled' : 'disabled',
+ },
+ {
+ target: '.wallet',
+ title: '🎉 Congrats! The ecosystem awaits.',
+ content: <CongratsOnboardingStep />,
placement: 'right',
- continueButtonDisplay: this._userHasVisibleWeth() ? 'enabled' : 'disabled',
+ continueButtonDisplay: 'enabled',
+ shouldHideNextButton: true,
+ continueButtonText: 'Enter the 0x Ecosystem',
},
];
return steps;
}
-
private _isAddressAvailable(): boolean {
return !_.isEmpty(this.props.userAddress);
}
-
private _userHasVisibleEth(): boolean {
return this.props.userEtherBalanceInWei > new BigNumber(0);
}
-
- private _userHasVisibleWeth(): boolean {
+ private _getWethBalance(): BigNumber {
const ethToken = utils.getEthToken(this.props.tokenByAddress);
if (!ethToken) {
- return false;
+ return new BigNumber(0);
}
- const wethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
- return wethTokenState.balance > new BigNumber(0);
+ const ethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
+ return ethTokenState.balance;
+ }
+ private _getFormattedWethBalance(): string {
+ const ethToken = utils.getEthToken(this.props.tokenByAddress);
+ const ethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
+ return utils.getFormattedAmountFromToken(ethToken, ethTokenState);
+ }
+ private _userHasVisibleWeth(): boolean {
+ return this._getWethBalance() > new BigNumber(0);
+ }
+ private _userHasAllowancesForWethAndZrx(): boolean {
+ const ethToken = utils.getEthToken(this.props.tokenByAddress);
+ const zrxToken = utils.getZrxToken(this.props.tokenByAddress);
+ if (ethToken && zrxToken) {
+ const ethTokenAllowance = this.props.trackedTokenStateByAddress[ethToken.address].allowance;
+ const zrxTokenAllowance = this.props.trackedTokenStateByAddress[zrxToken.address].allowance;
+ return ethTokenAllowance > new BigNumber(0) && zrxTokenAllowance > new BigNumber(0);
+ }
+ return false;
}
-
private _overrideOnboardingStateIfShould(): void {
this._autoStartOnboardingIfShould();
this._adjustStepIfShould();
}
private _adjustStepIfShould(): void {
+ const stepIndex = this.props.stepIndex;
if (this._isAddressAvailable()) {
- if (this.props.stepIndex < 2) {
+ if (stepIndex < 2) {
this.props.updateOnboardingStep(2);
}
return;
@@ -115,14 +170,42 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr
this.props.injectedProviderName,
);
if (isExternallyInjected) {
- this.props.updateOnboardingStep(1);
+ if (stepIndex !== 1) {
+ this.props.updateOnboardingStep(1);
+ }
return;
}
- this.props.updateOnboardingStep(0);
+ if (stepIndex !== 0) {
+ this.props.updateOnboardingStep(0);
+ }
}
private _autoStartOnboardingIfShould(): void {
if (!this.props.isRunning && !this.props.hasBeenSeen && this.props.blockchainIsLoaded) {
this.props.updateIsRunning(true);
}
}
+ private _renderZrxAllowanceToggle(): React.ReactNode {
+ const zrxToken = utils.getZrxToken(this.props.tokenByAddress);
+ return this._renderAllowanceToggle(zrxToken);
+ }
+ private _renderEthAllowanceToggle(): React.ReactNode {
+ const ethToken = utils.getEthToken(this.props.tokenByAddress);
+ return this._renderAllowanceToggle(ethToken);
+ }
+ private _renderAllowanceToggle(token: Token): React.ReactNode {
+ if (!token) {
+ return null;
+ }
+ const tokenState = this.props.trackedTokenStateByAddress[token.address];
+ return (
+ <AllowanceToggle
+ token={token}
+ tokenState={tokenState}
+ isDisabled={!tokenState.isLoaded}
+ blockchain={this.props.blockchain}
+ // tslint:disable-next-line:jsx-no-lambda
+ refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(token.address)}
+ />
+ );
+ }
}
diff --git a/packages/website/ts/components/onboarding/set_allowances_onboarding_step.tsx b/packages/website/ts/components/onboarding/set_allowances_onboarding_step.tsx
new file mode 100644
index 000000000..1ff248c40
--- /dev/null
+++ b/packages/website/ts/components/onboarding/set_allowances_onboarding_step.tsx
@@ -0,0 +1,27 @@
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+
+export interface SetAllowancesOnboardingStepProps {
+ zrxAllowanceToggle: React.ReactNode;
+ ethAllowanceToggle: React.ReactNode;
+}
+
+export const SetAllowancesOnboardingStep: React.StatelessComponent<SetAllowancesOnboardingStepProps> = ({
+ ethAllowanceToggle,
+ zrxAllowanceToggle,
+}) => (
+ <div className="flex items-center flex-column">
+ <Text>Unlock your tokens for trading. You only need to do this once for each token.</Text>
+ <Container width="100%" marginTop="25px" marginBottom="15px" className="flex justify-around">
+ <div className="flex flex-column items-center">
+ <Text fontWeight={700}> Enable WETH </Text>
+ <Container marginTop="10px">{ethAllowanceToggle}</Container>
+ </div>
+ <div className="flex flex-column items-center">
+ <Text fontWeight={700}> Enable ZRX </Text>
+ <Container marginTop="10px">{zrxAllowanceToggle}</Container>
+ </div>
+ </Container>
+ </div>
+);
diff --git a/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx
new file mode 100644
index 000000000..6e6a74a06
--- /dev/null
+++ b/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx
@@ -0,0 +1,16 @@
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+
+export interface UnlockWalletOnboardingStepProps {}
+
+export const UnlockWalletOnboardingStep: React.StatelessComponent<UnlockWalletOnboardingStepProps> = () => (
+ <div className="flex items-center flex-column">
+ <div className="flex items-center flex-column">
+ <Container marginTop="15px" marginBottom="15px">
+ <img src="/images/metamask_icon.png" height="50px" width="50px" />
+ </Container>
+ <Text>Unlock your metamask extension to begin.</Text>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx b/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx
new file mode 100644
index 000000000..b21b39341
--- /dev/null
+++ b/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx
@@ -0,0 +1,73 @@
+import { colors } from '@0xproject/react-shared';
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { IconButton } from 'ts/components/ui/icon_button';
+import { Text } from 'ts/components/ui/text';
+
+export interface WrapEthOnboardingStepProps {
+ formattedEthBalanceIfExists?: string;
+}
+
+export const WrapEthOnboardingStep: React.StatelessComponent<WrapEthOnboardingStepProps> = ({
+ formattedEthBalanceIfExists,
+}) => {
+ if (formattedEthBalanceIfExists) {
+ return (
+ <div className="flex items-center flex-column">
+ <Text>Congrats you now have {formattedEthBalanceIfExists} in your wallet.</Text>
+ <Container width="100%" marginTop="25px" marginBottom="15px" className="flex justify-center">
+ <div className="flex flex-column items-center">
+ <Text fontWeight={700}> 1 ETH </Text>
+ <img src="/images/eth_dollar.svg" height="75px" width="75x" />
+ </div>
+ <Container marginRight="25px" marginLeft="25px" position="relative" top="20px">
+ <Text fontSize="25px">
+ <i className="zmdi zmdi-long-arrow-right" />
+ </Text>
+ </Container>
+ <div className="flex flex-column items-center">
+ <Text fontWeight={700}> 1 WETH </Text>
+ <img src="/images/eth_token_erc20.svg" height="75px" width="75px" />
+ </div>
+ </Container>
+ </div>
+ );
+ } else {
+ return (
+ <div className="flex items-center flex-column">
+ <Text>
+ You need to convert some of your ETH into tradeable <b>Wrapped ETH (WETH)</b>.
+ </Text>
+ <Container width="100%" marginTop="25px" marginBottom="15px" className="flex justify-center">
+ <div className="flex flex-column items-center">
+ <Text fontWeight={700}> 1 ETH </Text>
+ <img src="/images/eth_dollar.svg" height="75px" width="75x" />
+ </div>
+ <Container marginRight="25px" marginLeft="25px" position="relative" top="20px">
+ <Text fontSize="36px">=</Text>
+ </Container>
+ <div className="flex flex-column items-center">
+ <Text fontWeight={700}> 1 WETH </Text>
+ <img src="/images/eth_token_erc20.svg" height="75px" width="75px" />
+ </div>
+ </Container>
+ <Text>
+ Think of it like the coin version of a paper note. It has the same value, but some machines only
+ take coins.
+ </Text>
+ <Text>
+ Click
+ <Container display="inline-block" marginLeft="10px" marginRight="10px">
+ <IconButton
+ iconName="zmdi-long-arrow-down"
+ color={colors.mediumBlue}
+ labelText="wrap"
+ display="inline-flex"
+ />
+ </Container>
+ to wrap your ETH.
+ </Text>
+ </div>
+ );
+ }
+};
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index fb40a9580..28a303793 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -1,6 +1,7 @@
import { colors, Styles } from '@0xproject/react-shared';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
+import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
@@ -24,6 +25,7 @@ import { TradeHistory } from 'ts/components/trade_history/trade_history';
import { Container } from 'ts/components/ui/container';
import { FlashMessage } from 'ts/components/ui/flash_message';
import { Island } from 'ts/components/ui/island';
+import { Text } from 'ts/components/ui/text';
import { Wallet } from 'ts/components/wallet/wallet';
import { GenerateOrderForm } from 'ts/containers/generate_order_form';
import { PortalOnboardingFlow } from 'ts/containers/portal_onboarding_flow';
@@ -100,6 +102,7 @@ const THROTTLE_TIMEOUT = 100;
const TOP_BAR_HEIGHT = TopBar.heightForDisplayType(TopBarDisplayType.Expanded);
const LEFT_COLUMN_WIDTH = 346;
const MENU_PADDING_LEFT = 185;
+const LARGE_LAYOUT_MAX_WIDTH = 1200;
const styles: Styles = {
root: {
@@ -235,7 +238,11 @@ export class Portal extends React.Component<PortalProps, PortalState> {
: TokenVisibility.TRACKED;
return (
<div style={styles.root}>
- <PortalOnboardingFlow trackedTokenStateByAddress={this.state.trackedTokenStateByAddress} />
+ <PortalOnboardingFlow
+ blockchain={this._blockchain}
+ trackedTokenStateByAddress={this.state.trackedTokenStateByAddress}
+ refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)}
+ />
<DocumentTitle title="0x Portal DApp" />
<TopBar
userAddress={this.props.userAddress}
@@ -250,6 +257,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
translate={this.props.translate}
displayType={TopBarDisplayType.Expanded}
style={{ backgroundColor: colors.lightestGrey }}
+ maxWidth={LARGE_LAYOUT_MAX_WIDTH}
/>
<div id="portal" style={styles.body}>
<Switch>
@@ -349,8 +357,26 @@ export class Portal extends React.Component<PortalProps, PortalState> {
/>
<Container marginTop="15px">
<Island>
- {/** TODO: Implement real styles. */}
- <p onClick={this._startOnboarding.bind(this)}>Start onboarding flow.</p>
+ <Container
+ marginTop="30px"
+ marginBottom="30px"
+ marginLeft="30px"
+ marginRight="30px"
+ className="flex justify-around items-center"
+ >
+ <ActionAccountBalanceWallet
+ style={{ width: '30px', height: '30px' }}
+ color={colors.orange}
+ />
+ <Text
+ fontColor={colors.grey}
+ fontSize="16px"
+ center={true}
+ onClick={this._startOnboarding.bind(this)}
+ >
+ Learn how to set up your account
+ </Text>
+ </Container>
</Island>
</Container>
</div>
@@ -634,7 +660,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
const tokenSymbols = _.keys(tokenAddressBySymbol);
try {
const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols);
- const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol));
+ const priceByAddress = _.mapKeys(priceBySymbol, (_value, symbol) => _.get(tokenAddressBySymbol, symbol));
const result = _.mapValues(priceByAddress, price => {
const priceBigNumber = new BigNumber(price);
return priceBigNumber;
@@ -656,11 +682,11 @@ interface LargeLayoutProps {
}
const LargeLayout = (props: LargeLayoutProps) => {
return (
- <div className="sm-flex flex-center">
- <div className="flex-last px3">
+ <div className="mx-auto flex flex-center" style={{ maxWidth: LARGE_LAYOUT_MAX_WIDTH }}>
+ <div className="flex-last px2">
<div style={styles.leftColumn}>{props.left}</div>
</div>
- <div className="flex-auto px3" style={styles.scrollContainer}>
+ <div className="flex-auto px2" style={styles.scrollContainer}>
{props.right}
</div>
</div>
@@ -672,7 +698,7 @@ interface SmallLayoutProps {
}
const SmallLayout = (props: SmallLayoutProps) => {
return (
- <div className="sm-flex flex-center">
+ <div className="flex flex-center">
<div className="flex-auto px3" style={styles.scrollContainer}>
{props.content}
</div>
diff --git a/packages/website/ts/components/redirecter.tsx b/packages/website/ts/components/redirector.tsx
index 07432a926..a02693003 100644
--- a/packages/website/ts/components/redirecter.tsx
+++ b/packages/website/ts/components/redirector.tsx
@@ -1,9 +1,9 @@
import { constants } from 'ts/utils/constants';
-interface RedirecterProps {
+interface RedirectorProps {
location: string;
}
-export function Redirecter(props: RedirecterProps): void {
+export function Redirector(_props: RedirectorProps): void {
window.location.href = constants.URL_ANGELLIST;
}
diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
index fbb634164..98d6dc0b3 100644
--- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
@@ -5,6 +5,7 @@ import * as React from 'react';
import { TopTokens } from 'ts/components/relayer_index/relayer_top_tokens';
import { Container } from 'ts/components/ui/container';
+import { Image } from 'ts/components/ui/image';
import { Island } from 'ts/components/ui/island';
import { colors } from 'ts/style/colors';
import { WebsiteBackendRelayerInfo } from 'ts/types';
@@ -26,7 +27,6 @@ const styles: Styles = {
header: {
height: '50%',
width: '100%',
- objectFit: 'cover',
borderBottomRightRadius: 4,
borderBottomLeftRadius: 4,
borderTopRightRadius: 4,
@@ -58,21 +58,34 @@ const styles: Styles = {
};
const FALLBACK_IMG_SRC = '/images/landing/hero_chip_image.png';
+const FALLBACK_PRIMARY_COLOR = colors.grey200;
const NO_CONTENT_MESSAGE = '--';
+const RELAYER_ICON_HEIGHT = '110px';
export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (props: RelayerGridTileProps) => {
const link = props.relayerInfo.appUrl || props.relayerInfo.url;
const topTokens = props.relayerInfo.topTokens;
const weeklyTxnVolume = props.relayerInfo.weeklyTxnVolume;
+ const headerImageUrl = props.relayerInfo.logoImgUrl;
+ const headerBackgroundColor =
+ !_.isUndefined(headerImageUrl) && !_.isUndefined(props.relayerInfo.primaryColor)
+ ? props.relayerInfo.primaryColor
+ : FALLBACK_PRIMARY_COLOR;
return (
<Island style={styles.root} Component={GridTile}>
<div style={styles.innerDiv}>
<a href={link} target="_blank" style={{ textDecoration: 'none' }}>
- <ImgWithFallback
- src={props.relayerInfo.headerImgUrl}
- fallbackSrc={FALLBACK_IMG_SRC}
- style={styles.header}
- />
+ <div
+ className="flex items-center"
+ style={{ ...styles.header, backgroundColor: headerBackgroundColor }}
+ >
+ <Image
+ className="mx-auto"
+ src={props.relayerInfo.logoImgUrl}
+ fallbackSrc={FALLBACK_IMG_SRC}
+ height={RELAYER_ICON_HEIGHT}
+ />
+ </div>
</a>
<div style={styles.body}>
<div className="py1" style={styles.relayerNameLabel}>
@@ -108,32 +121,3 @@ const Section = (props: SectionProps) => {
};
const NoContent = () => <div style={styles.subLabel}>{NO_CONTENT_MESSAGE}</div>;
-
-interface ImgWithFallbackProps {
- src?: string;
- fallbackSrc: string;
- style: React.CSSProperties;
-}
-interface ImgWithFallbackState {
- imageLoadFailed: boolean;
-}
-class ImgWithFallback extends React.Component<ImgWithFallbackProps, ImgWithFallbackState> {
- constructor(props: ImgWithFallbackProps) {
- super(props);
- this.state = {
- imageLoadFailed: false,
- };
- }
- public render(): React.ReactNode {
- if (this.state.imageLoadFailed || _.isUndefined(this.props.src)) {
- return <img src={this.props.fallbackSrc} style={this.props.style} />;
- } else {
- return <img src={this.props.src} onError={this._onError.bind(this)} style={this.props.style} />;
- }
- }
- private _onError(): void {
- this.setState({
- imageLoadFailed: true,
- });
- }
-}
diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx
index 683f7084b..d565eb608 100644
--- a/packages/website/ts/components/relayer_index/relayer_index.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_index.tsx
@@ -1,11 +1,11 @@
import { Styles } from '@0xproject/react-shared';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
-import FlatButton from 'material-ui/FlatButton';
import { GridList } from 'material-ui/GridList';
import * as React from 'react';
import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile';
+import { Retry } from 'ts/components/ui/retry';
import { colors } from 'ts/style/colors';
import { ScreenWidths, WebsiteBackendRelayerInfo } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
@@ -37,9 +37,9 @@ const styles: Styles = {
};
const CELL_HEIGHT = 290;
-const NUMBER_OF_COLUMNS_LARGE = 4;
-const NUMBER_OF_COLUMNS_MEDIUM = 3;
-const NUMBER_OF_COLUMNS_SMALL = 1;
+const NUMBER_OF_COLUMNS_LARGE = 3;
+const NUMBER_OF_COLUMNS_MEDIUM = 2;
+const NUMBER_OF_COLUMNS_SMALL = 2;
const GRID_PADDING = 20;
export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerIndexState> {
@@ -63,7 +63,8 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde
const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos);
if (!isReadyToRender) {
return (
- // TODO: consolidate this loading component with the one in portal
+ // TODO: consolidate this loading component with the one in portal and OpenPositions
+ // TODO: possibly refactor into a generic loading container with spinner and retry UI
<div className="center">
{_.isUndefined(this.state.error) ? (
<CircularProgress size={40} thickness={5} />
@@ -124,31 +125,3 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde
}
}
}
-
-interface RetryProps {
- onRetry: () => void;
-}
-const Retry = (props: RetryProps) => (
- <div className="clearfix center" style={{ color: colors.black }}>
- <div className="mx-auto inline-block align-middle" style={{ lineHeight: '44px', textAlign: 'center' }}>
- <div className="h2" style={{ fontFamily: 'Roboto Mono' }}>
- Something went wrong.
- </div>
- <div className="py3">
- <FlatButton
- label={'reload'}
- backgroundColor={colors.black}
- labelStyle={{
- fontSize: 18,
- fontFamily: 'Roboto Mono',
- fontWeight: 'lighter',
- color: colors.white,
- textTransform: 'lowercase',
- }}
- style={{ width: 280, height: 62, borderRadius: 5 }}
- onClick={props.onRetry}
- />
- </div>
- </div>
- </div>
-);
diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx
index 555a59830..7af80745c 100644
--- a/packages/website/ts/components/token_balances.tsx
+++ b/packages/website/ts/components/token_balances.tsx
@@ -20,11 +20,11 @@ import ReactTooltip = require('react-tooltip');
import firstBy = require('thenby');
import { Blockchain } from 'ts/blockchain';
import { AssetPicker } from 'ts/components/generate_order/asset_picker';
-import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle';
import { SendButton } from 'ts/components/send_button';
import { HelpTooltip } from 'ts/components/ui/help_tooltip';
import { LifeCycleRaisedButton } from 'ts/components/ui/lifecycle_raised_button';
import { TokenIcon } from 'ts/components/ui/token_icon';
+import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
import { Dispatcher } from 'ts/redux/dispatcher';
import {
@@ -362,13 +362,10 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</TableRowColumn>
<TableRowColumn>
<AllowanceToggle
- networkId={this.props.networkId}
blockchain={this.props.blockchain}
- dispatcher={this.props.dispatcher}
token={token}
tokenState={tokenState}
onErrorOccurred={this._onErrorOccurred.bind(this)}
- userAddress={this.props.userAddress}
isDisabled={!tokenState.isLoaded}
refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this, token.address)}
/>
@@ -581,7 +578,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
}
return true;
}
- private _onErrorDialogToggle(isOpen: boolean): void {
+ private _onErrorDialogToggle(_isOpen: boolean): void {
this.setState({
errorType: undefined,
});
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index 05cc6e3ad..1a69827a4 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -45,6 +45,7 @@ export interface TopBarProps {
isNightVersion?: boolean;
onVersionSelected?: (semver: string) => void;
sidebarHeader?: React.ReactNode;
+ maxWidth?: number;
}
interface TopBarState {
@@ -213,7 +214,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
const shouldShowPortalV2Drawer = this._isViewingPortal() && utils.shouldShowPortalV2();
return (
<div style={{ ...styles.topBar, ...bottomBorderStyle, ...this.props.style, ...{ height } }} className="pb1">
- <div className={parentClassNames}>
+ <div className={parentClassNames} style={{ maxWidth: this.props.maxWidth }}>
<div className="col col-2 sm-pl1 md-pl2 lg-pl0" style={{ paddingTop: 15 }}>
<Link to={`${WebsitePaths.Home}`} className="text-decoration-none">
<img src={logoUrl} height="30" />
diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx
index 4c7d59839..cb542a386 100644
--- a/packages/website/ts/components/ui/button.tsx
+++ b/packages/website/ts/components/ui/button.tsx
@@ -1,5 +1,5 @@
import { colors } from '@0xproject/react-shared';
-import { darken } from 'polished';
+import { darken, grayscale } from 'polished';
import * as React from 'react';
import { styled } from 'ts/style/theme';
@@ -7,36 +7,39 @@ export interface ButtonProps {
className?: string;
fontSize?: string;
fontColor?: string;
+ fontFamily?: string;
backgroundColor?: string;
borderColor?: string;
width?: string;
type?: string;
+ isDisabled?: boolean;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
}
-const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, onClick, type, className }) => (
- <button type={type} className={className} onClick={onClick}>
+const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
+ <button type={type} className={className} onClick={isDisabled ? undefined : onClick}>
{children}
</button>
);
export const Button = styled(PlainButton)`
- cursor: pointer;
+ cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
font-size: ${props => props.fontSize};
color: ${props => props.fontColor};
+ transition: background-color 0.5s ease;
padding: 0.8em 2.2em;
border-radius: 6px;
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25);
font-weight: 500;
- font-family: 'Roboto';
+ font-family: ${props => props.fontFamily};
width: ${props => props.width};
- background-color: ${props => props.backgroundColor};
+ background-color: ${props => (props.isDisabled ? grayscale(props.backgroundColor) : props.backgroundColor)};
border: ${props => (props.borderColor ? `1px solid ${props.borderColor}` : 'none')};
&:hover {
- background-color: ${props => darken(0.1, props.backgroundColor)};
+ background-color: ${props => (!props.isDisabled ? darken(0.1, props.backgroundColor) : '')};
}
&:active {
- background-color: ${props => darken(0.2, props.backgroundColor)};
+ background-color: ${props => (!props.isDisabled ? darken(0.2, props.backgroundColor) : '')};
}
`;
@@ -44,6 +47,8 @@ Button.defaultProps = {
fontSize: '12px',
backgroundColor: colors.white,
width: 'auto',
+ fontFamily: 'Roboto',
+ isDisabled: false,
};
Button.displayName = 'Button';
diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx
index c6a78e181..1776345da 100644
--- a/packages/website/ts/components/ui/container.tsx
+++ b/packages/website/ts/components/ui/container.tsx
@@ -14,8 +14,15 @@ export interface ContainerProps {
backgroundColor?: string;
borderRadius?: StringOrNum;
maxWidth?: StringOrNum;
+ width?: StringOrNum;
isHidden?: boolean;
className?: string;
+ position?: 'absolute' | 'fixed' | 'relative' | 'unset';
+ display?: 'inline-block' | 'block' | 'inline-flex' | 'inline';
+ top?: string;
+ left?: string;
+ right?: string;
+ bottom?: string;
}
export const Container: React.StatelessComponent<ContainerProps> = ({ children, className, isHidden, ...style }) => {
diff --git a/packages/website/ts/components/ui/drop_down.tsx b/packages/website/ts/components/ui/drop_down.tsx
index db79ca1df..22cb942f8 100644
--- a/packages/website/ts/components/ui/drop_down.tsx
+++ b/packages/website/ts/components/ui/drop_down.tsx
@@ -42,7 +42,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
public componentWillUnmount(): void {
window.clearInterval(this._popoverCloseCheckIntervalId);
}
- public componentWillReceiveProps(nextProps: DropDownProps): void {
+ public componentWillReceiveProps(_nextProps: DropDownProps): void {
// HACK: If the popoverContent is updated to a different dimension and the users
// mouse is no longer above it, the dropdown can enter an inconsistent state where
// it believes the user is still hovering over it. In order to remedy this, we
diff --git a/packages/website/ts/components/ui/filled_image.tsx b/packages/website/ts/components/ui/filled_image.tsx
new file mode 100644
index 000000000..7f58ee5b9
--- /dev/null
+++ b/packages/website/ts/components/ui/filled_image.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react';
+
+export interface FilledImageProps {
+ src: string;
+}
+export const FilledImage = (props: FilledImageProps) => (
+ <div
+ style={{
+ width: '100%',
+ height: '100%',
+ objectFit: 'cover',
+ backgroundImage: `url(${props.src})`,
+ backgroundRepeat: 'no-repeat',
+ backgroundPosition: 'center',
+ backgroundSize: 'cover',
+ }}
+ />
+);
diff --git a/packages/website/ts/components/ui/icon_button.tsx b/packages/website/ts/components/ui/icon_button.tsx
index 2f5172f05..13cd239da 100644
--- a/packages/website/ts/components/ui/icon_button.tsx
+++ b/packages/website/ts/components/ui/icon_button.tsx
@@ -5,15 +5,15 @@ import * as React from 'react';
export interface IconButtonProps {
iconName: string;
labelText?: string;
- onClick: () => void;
+ onClick?: () => void;
color?: string;
+ display?: string;
}
interface IconButtonState {
isHovering: boolean;
}
export class IconButton extends React.Component<IconButtonProps, IconButtonState> {
public static defaultProps: Partial<IconButtonProps> = {
- onClick: _.noop,
labelText: '',
color: colors.mediumBlue,
};
@@ -26,8 +26,9 @@ export class IconButton extends React.Component<IconButtonProps, IconButtonState
public render(): React.ReactNode {
const styles: Styles = {
root: {
- cursor: 'pointer',
- opacity: this.state.isHovering ? 0.5 : 1,
+ cursor: this.props.onClick ? 'pointer' : 'undefined',
+ opacity: this.state.isHovering && this.props.onClick ? 0.5 : 1,
+ display: this.props.display,
},
icon: {
color: this.props.color,
diff --git a/packages/website/ts/components/ui/image.tsx b/packages/website/ts/components/ui/image.tsx
new file mode 100644
index 000000000..0958d2e5e
--- /dev/null
+++ b/packages/website/ts/components/ui/image.tsx
@@ -0,0 +1,37 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+export interface ImageProps {
+ className?: string;
+ src?: string;
+ fallbackSrc?: string;
+ height?: string;
+}
+interface ImageState {
+ imageLoadFailed: boolean;
+}
+export class Image extends React.Component<ImageProps, ImageState> {
+ constructor(props: ImageProps) {
+ super(props);
+ this.state = {
+ imageLoadFailed: false,
+ };
+ }
+ public render(): React.ReactNode {
+ const src =
+ this.state.imageLoadFailed || _.isUndefined(this.props.src) ? this.props.fallbackSrc : this.props.src;
+ return (
+ <img
+ className={this.props.className}
+ onError={this._onError.bind(this)}
+ src={src}
+ height={this.props.height}
+ />
+ );
+ }
+ private _onError(): void {
+ this.setState({
+ imageLoadFailed: true,
+ });
+ }
+}
diff --git a/packages/website/ts/components/ui/pointer.tsx b/packages/website/ts/components/ui/pointer.tsx
new file mode 100644
index 000000000..448786bb4
--- /dev/null
+++ b/packages/website/ts/components/ui/pointer.tsx
@@ -0,0 +1,67 @@
+import { colors } from '@0xproject/react-shared';
+import * as React from 'react';
+import { styled } from 'ts/style/theme';
+
+export type PointerDirection = 'top' | 'right' | 'bottom' | 'left';
+
+export interface PointerProps {
+ className?: string;
+ color?: string;
+ size?: number;
+ direction: PointerDirection;
+}
+
+const PlainPointer: React.StatelessComponent<PointerProps> = props => <div {...props} />;
+
+const positionToCss = (props: PointerProps) => {
+ const position = {
+ top: `bottom: 100%; left: 50%;`,
+ right: `left: 100%; top: 50%;`,
+ bottom: `top: 100%; left: 50%;`,
+ left: `right: 100%; top: 50%;`,
+ }[props.direction];
+
+ const borderColorSide = {
+ top: 'border-bottom-color',
+ right: 'border-left-color',
+ bottom: 'border-top-color',
+ left: 'border-right-color',
+ }[props.direction];
+ const border = `${borderColorSide}: ${props.color};`;
+ const marginSide = {
+ top: 'margin-left',
+ right: 'margin-top',
+ bottom: 'margin-left',
+ left: 'margin-top',
+ }[props.direction];
+ const margin = `${marginSide}: -${props.size}px`;
+ return {
+ position,
+ border,
+ margin,
+ };
+};
+
+export const Pointer = styled(PlainPointer)`
+ position: relative;
+ &:after {
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+ border-color: rgba(136, 183, 213, 0);
+ border-width: ${props => `${props.size}px`};
+ ${props => positionToCss(props).position}
+ ${props => positionToCss(props).border}
+ ${props => positionToCss(props).margin}
+ }
+`;
+
+Pointer.defaultProps = {
+ color: colors.white,
+ size: 16,
+};
+
+Pointer.displayName = 'Pointer';
diff --git a/packages/website/ts/components/ui/retry.tsx b/packages/website/ts/components/ui/retry.tsx
new file mode 100644
index 000000000..543b7df4b
--- /dev/null
+++ b/packages/website/ts/components/ui/retry.tsx
@@ -0,0 +1,32 @@
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+import { colors } from 'ts/style/colors';
+
+const BUTTON_TEXT = 'reload';
+
+export interface RetryProps {
+ onRetry: () => void;
+}
+export const Retry = (props: RetryProps) => (
+ <div className="clearfix center" style={{ color: colors.black }}>
+ <div className="mx-auto inline-block align-middle" style={{ lineHeight: '44px', textAlign: 'center' }}>
+ <div className="h2" style={{ fontFamily: 'Roboto Mono' }}>
+ Something went wrong.
+ </div>
+ <div className="py3">
+ <Button
+ type="button"
+ backgroundColor={colors.black}
+ width="290px"
+ fontColor={colors.white}
+ fontSize="18px"
+ fontFamily="Roboto Mono"
+ onClick={props.onRetry}
+ >
+ {BUTTON_TEXT}
+ </Button>
+ </div>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx
index e90c1707d..1e2a123b7 100644
--- a/packages/website/ts/components/ui/text.tsx
+++ b/packages/website/ts/components/ui/text.tsx
@@ -1,8 +1,9 @@
import { colors } from '@0xproject/react-shared';
+import { darken } from 'polished';
import * as React from 'react';
import { styled } from 'ts/style/theme';
-export type TextTag = 'p' | 'div' | 'span' | 'label';
+export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4';
export interface TextProps {
className?: string;
@@ -11,12 +12,16 @@ export interface TextProps {
fontFamily?: string;
fontColor?: string;
lineHeight?: string;
+ minHeight?: string;
center?: boolean;
- fontWeight?: number;
+ fontWeight?: number | string;
+ onClick?: () => void;
}
-const PlainText: React.StatelessComponent<TextProps> = ({ children, className, Tag }) => (
- <Tag className={className}>{children}</Tag>
+const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick, Tag }) => (
+ <Tag className={className} onClick={onClick}>
+ {children}
+ </Tag>
);
export const Text = styled(PlainText)`
@@ -26,14 +31,32 @@ export const Text = styled(PlainText)`
${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
${props => (props.center ? 'text-align: center' : '')};
color: ${props => props.fontColor};
+ ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')};
+ ${props => (props.onClick ? 'cursor: pointer' : '')};
+ transition: color 0.5s ease;
+ &:hover {
+ ${props => (props.onClick ? `color: ${darken(0.1, props.fontColor)}` : '')};
+ }
`;
Text.defaultProps = {
fontFamily: 'Roboto',
fontWeight: 400,
- fontColor: colors.white,
- fontSize: '14px',
+ fontColor: colors.black,
+ fontSize: '15px',
+ lineHeight: '1.5em',
Tag: 'div',
};
Text.displayName = 'Text';
+
+export const Title: React.StatelessComponent<TextProps> = props => <Text {...props} />;
+
+Title.defaultProps = {
+ Tag: 'h2',
+ fontSize: '20px',
+ fontWeight: 600,
+ fontColor: colors.black,
+};
+
+Title.displayName = 'Title';
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index bc2ee227d..3a6d9942d 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -13,7 +13,6 @@ import { Link } from 'react-router-dom';
import firstBy = require('thenby');
import { Blockchain } from 'ts/blockchain';
-import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle';
import { Container } from 'ts/components/ui/container';
import { IconButton } from 'ts/components/ui/icon_button';
import { Identicon } from 'ts/components/ui/identicon';
@@ -21,6 +20,7 @@ import { Island } from 'ts/components/ui/island';
import { TokenIcon } from 'ts/components/ui/token_icon';
import { WalletDisconnectedItem } from 'ts/components/wallet/wallet_disconnected_item';
import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item';
+import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { zIndex } from 'ts/style/z_index';
@@ -124,7 +124,6 @@ const styles: Styles = {
const ETHER_ICON_PATH = '/images/ether.png';
const ICON_DIMENSION = 28;
-const TOKEN_AMOUNT_DISPLAY_PRECISION = 5;
const BODY_ITEM_KEY = 'BODY';
const HEADER_ITEM_KEY = 'HEADER';
const FOOTER_ITEM_KEY = 'FOOTER';
@@ -222,7 +221,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
</div>
);
}
- private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void {
+ private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
this.setState({
isHoveringSidebar: true,
});
@@ -314,7 +313,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
);
return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this));
}
- private _renderTokenRow(token: Token, index: number): React.ReactNode {
+ private _renderTokenRow(token: Token, _index: number): React.ReactNode {
const tokenState = this.props.trackedTokenStateByAddress[token.address];
const tokenLink = sharedUtils.getEtherScanLinkIfExists(
token.address,
@@ -414,15 +413,12 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
);
}
private _renderAllowanceToggle(config: AllowanceToggleConfig): React.ReactNode {
+ // TODO: Error handling
return (
<AllowanceToggle
- networkId={this.props.networkId}
blockchain={this.props.blockchain}
- dispatcher={this.props.dispatcher}
token={config.token}
tokenState={config.tokenState}
- onErrorOccurred={_.noop} // TODO: Error handling
- userAddress={this.props.userAddress}
isDisabled={!config.tokenState.isLoaded}
refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(config.token.address)}
/>
@@ -441,10 +437,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
</PlaceHolder>
);
} else {
- const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
- const precision = Math.min(TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces());
- const formattedAmount = unitAmount.toFixed(precision);
- const result = `${formattedAmount} ${symbol}`;
+ const result = utils.getFormattedAmount(amount, decimals, symbol);
return <div style={styles.amountLabel}>{result}</div>;
}
}
diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx
index a5052735b..f65257142 100644
--- a/packages/website/ts/components/wallet/wrap_ether_item.tsx
+++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx
@@ -145,7 +145,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
</div>
);
}
- private _onValueChange(isValid: boolean, amount?: BigNumber): void {
+ private _onValueChange(_isValid: boolean, amount?: BigNumber): void {
this.setState({
currentInputAmount: amount,
});
diff --git a/packages/website/ts/containers/about.ts b/packages/website/ts/containers/about.ts
index 3dbdcd16b..3b1c99d79 100644
--- a/packages/website/ts/containers/about.ts
+++ b/packages/website/ts/containers/about.ts
@@ -14,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: AboutProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: AboutProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts
index 2ecd8107a..f939ef0df 100644
--- a/packages/website/ts/containers/connect_documentation.ts
+++ b/packages/website/ts/containers/connect_documentation.ts
@@ -89,7 +89,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/ethereum_types_documentation.ts b/packages/website/ts/containers/ethereum_types_documentation.ts
index f6d614779..285438835 100644
--- a/packages/website/ts/containers/ethereum_types_documentation.ts
+++ b/packages/website/ts/containers/ethereum_types_documentation.ts
@@ -106,7 +106,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/faq.ts b/packages/website/ts/containers/faq.ts
index b91c47889..a2b5735f6 100644
--- a/packages/website/ts/containers/faq.ts
+++ b/packages/website/ts/containers/faq.ts
@@ -14,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: FAQProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: FAQProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/generate_order_form.ts b/packages/website/ts/containers/generate_order_form.ts
index 44979b104..92296dbab 100644
--- a/packages/website/ts/containers/generate_order_form.ts
+++ b/packages/website/ts/containers/generate_order_form.ts
@@ -30,7 +30,7 @@ interface ConnectedState {
lastForceTokenStateRefetch: number;
}
-const mapStateToProps = (state: State, ownProps: GenerateOrderFormProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: GenerateOrderFormProps): ConnectedState => ({
blockchainErr: state.blockchainErr,
blockchainIsLoaded: state.blockchainIsLoaded,
orderExpiryTimestamp: state.orderExpiryTimestamp,
diff --git a/packages/website/ts/containers/inputs/allowance_toggle.ts b/packages/website/ts/containers/inputs/allowance_toggle.ts
new file mode 100644
index 000000000..545708f92
--- /dev/null
+++ b/packages/website/ts/containers/inputs/allowance_toggle.ts
@@ -0,0 +1,41 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { Blockchain } from 'ts/blockchain';
+import { State } from 'ts/redux/reducer';
+import { BalanceErrs, Token, TokenState } from 'ts/types';
+
+import { AllowanceToggle as AllowanceToggleComponent } from 'ts/components/inputs/allowance_toggle';
+import { Dispatcher } from 'ts/redux/dispatcher';
+
+interface AllowanceToggleProps {
+ blockchain: Blockchain;
+ onErrorOccurred?: (errType: BalanceErrs) => void;
+ token: Token;
+ tokenState: TokenState;
+ isDisabled?: boolean;
+ refetchTokenStateAsync: () => Promise<void>;
+}
+
+interface ConnectedState {
+ networkId: number;
+ userAddress: string;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: AllowanceToggleProps): ConnectedState => ({
+ networkId: state.networkId,
+ userAddress: state.userAddress,
+});
+
+const mapDispatchTopProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const AllowanceToggle: React.ComponentClass<AllowanceToggleProps> = connect(
+ mapStateToProps,
+ mapDispatchTopProps,
+)(AllowanceToggleComponent);
diff --git a/packages/website/ts/containers/jobs.ts b/packages/website/ts/containers/jobs.ts
new file mode 100644
index 000000000..b18485882
--- /dev/null
+++ b/packages/website/ts/containers/jobs.ts
@@ -0,0 +1,28 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { Jobs as JobsComponent, JobsProps } from 'ts/pages/jobs/jobs';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+
+interface ConnectedState {
+ translate: Translate;
+ screenWidth: ScreenWidths;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: JobsProps): ConnectedState => ({
+ translate: state.translate,
+ screenWidth: state.screenWidth,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const Jobs: React.ComponentClass<JobsProps> = connect(mapStateToProps, mapDispatchToProps)(JobsComponent);
diff --git a/packages/website/ts/containers/json_schemas_documentation.ts b/packages/website/ts/containers/json_schemas_documentation.ts
index 4df7ddecb..67740d4c6 100644
--- a/packages/website/ts/containers/json_schemas_documentation.ts
+++ b/packages/website/ts/containers/json_schemas_documentation.ts
@@ -70,7 +70,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/landing.ts b/packages/website/ts/containers/landing.ts
index a9fc1d9d1..972ed4c23 100644
--- a/packages/website/ts/containers/landing.ts
+++ b/packages/website/ts/containers/landing.ts
@@ -14,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: LandingProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: LandingProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/legacy_portal.ts b/packages/website/ts/containers/legacy_portal.ts
index eae450c21..e99f47fb7 100644
--- a/packages/website/ts/containers/legacy_portal.ts
+++ b/packages/website/ts/containers/legacy_portal.ts
@@ -37,7 +37,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: LegacyPortalComponentProps): ConnectedState => {
+const mapStateToProps = (state: State, _ownProps: LegacyPortalComponentProps): ConnectedState => {
const receiveAssetToken = state.sideToAssetToken[Side.Receive];
const depositAssetToken = state.sideToAssetToken[Side.Deposit];
const receiveAddress = !_.isUndefined(receiveAssetToken.address)
diff --git a/packages/website/ts/containers/not_found.ts b/packages/website/ts/containers/not_found.ts
index 4fdc325ea..f384dab89 100644
--- a/packages/website/ts/containers/not_found.ts
+++ b/packages/website/ts/containers/not_found.ts
@@ -14,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: NotFoundProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: NotFoundProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/order_utils_documentation.ts b/packages/website/ts/containers/order_utils_documentation.ts
index cdf97e5c8..37b7f2273 100644
--- a/packages/website/ts/containers/order_utils_documentation.ts
+++ b/packages/website/ts/containers/order_utils_documentation.ts
@@ -81,7 +81,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/portal.ts b/packages/website/ts/containers/portal.ts
index b8c8fb999..5876e65f5 100644
--- a/packages/website/ts/containers/portal.ts
+++ b/packages/website/ts/containers/portal.ts
@@ -34,7 +34,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: PortalComponentProps): ConnectedState => {
+const mapStateToProps = (state: State, _ownProps: PortalComponentProps): ConnectedState => {
const receiveAssetToken = state.sideToAssetToken[Side.Receive];
const depositAssetToken = state.sideToAssetToken[Side.Deposit];
const receiveAddress = !_.isUndefined(receiveAssetToken.address)
diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts
index 0ad9aef13..746adf0ba 100644
--- a/packages/website/ts/containers/portal_onboarding_flow.ts
+++ b/packages/website/ts/containers/portal_onboarding_flow.ts
@@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
+import { Blockchain } from 'ts/blockchain';
import { ActionTypes, ProviderType, TokenByAddress, TokenStateByAddress } from 'ts/types';
import { PortalOnboardingFlow as PortalOnboardingFlowComponent } from 'ts/components/onboarding/portal_onboarding_flow';
@@ -9,6 +10,8 @@ import { State } from 'ts/redux/reducer';
interface PortalOnboardingFlowProps {
trackedTokenStateByAddress: TokenStateByAddress;
+ blockchain: Blockchain;
+ refetchTokenStateAsync: (tokenAddress: string) => Promise<void>;
}
interface ConnectedState {
@@ -28,7 +31,7 @@ interface ConnectedDispatch {
updateOnboardingStep: (stepIndex: number) => void;
}
-const mapStateToProps = (state: State, ownProps: PortalOnboardingFlowProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: PortalOnboardingFlowProps): ConnectedState => ({
stepIndex: state.portalOnboardingStep,
isRunning: state.isPortalOnboardingShowing,
userAddress: state.userAddress,
diff --git a/packages/website/ts/containers/smart_contracts_documentation.ts b/packages/website/ts/containers/smart_contracts_documentation.ts
index 27328909c..c88c3b365 100644
--- a/packages/website/ts/containers/smart_contracts_documentation.ts
+++ b/packages/website/ts/containers/smart_contracts_documentation.ts
@@ -75,7 +75,7 @@ interface ConnectedDispatch {
docsInfo: DocsInfo;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/sol_compiler_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts
index 4ccc1850f..8720e2c1d 100644
--- a/packages/website/ts/containers/sol_compiler_documentation.ts
+++ b/packages/website/ts/containers/sol_compiler_documentation.ts
@@ -67,7 +67,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts
index 73cc99a8c..a8009071f 100644
--- a/packages/website/ts/containers/sol_cov_documentation.ts
+++ b/packages/website/ts/containers/sol_cov_documentation.ts
@@ -96,7 +96,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts
index 0c7e73f38..6d4230e53 100644
--- a/packages/website/ts/containers/subproviders_documentation.ts
+++ b/packages/website/ts/containers/subproviders_documentation.ts
@@ -128,7 +128,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts
index 34633f14d..b04a83ac4 100644
--- a/packages/website/ts/containers/web3_wrapper_documentation.ts
+++ b/packages/website/ts/containers/web3_wrapper_documentation.ts
@@ -105,7 +105,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/wiki.ts b/packages/website/ts/containers/wiki.ts
index af7228dbe..357f8bbf4 100644
--- a/packages/website/ts/containers/wiki.ts
+++ b/packages/website/ts/containers/wiki.ts
@@ -14,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: WikiProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: WikiProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts
index 9c3f447fb..bd0d1732a 100644
--- a/packages/website/ts/containers/zero_ex_js_documentation.ts
+++ b/packages/website/ts/containers/zero_ex_js_documentation.ts
@@ -173,6 +173,7 @@ const docsInfoConfig: DocsInfoConfig = {
'OrderStateInvalid',
'OrderState',
'OrderStateWatcherConfig',
+ 'OrderWatcherConfig',
'FilterObject',
'OrderRelevantState',
'JSONRPCRequestPayload',
@@ -209,7 +210,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
docsInfo,
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index 719604c02..249b4fdc9 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -4,9 +4,10 @@ import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
import * as injectTapEventPlugin from 'react-tap-event-plugin';
-import { Redirecter } from 'ts/components/redirecter';
+import { Redirector } from 'ts/components/redirector';
import { About } from 'ts/containers/about';
import { FAQ } from 'ts/containers/faq';
+import { Jobs } from 'ts/containers/jobs';
import { Landing } from 'ts/containers/landing';
import { NotFound } from 'ts/containers/not_found';
import { Wiki } from 'ts/containers/wiki';
@@ -86,8 +87,12 @@ render(
<Switch>
<Route exact={true} path="/" component={Landing as any} />
<Redirect from="/otc" to={`${WebsitePaths.Portal}`} />
-
- <Route path={WebsitePaths.Jobs} component={Redirecter as any} />
+ {/* TODO: Remove this once we ship the jobs page*/}
+ {utils.shouldShowJobsPage() ? (
+ <Route path={WebsitePaths.Jobs} component={Jobs as any} />
+ ) : (
+ <Route path={WebsitePaths.Jobs} component={Redirector as any} />
+ )}
<Route path={WebsitePaths.Portal} component={LazyPortal} />
<Route path={WebsitePaths.FAQ} component={FAQ as any} />
<Route path={WebsitePaths.About} component={About as any} />
diff --git a/packages/website/ts/local_storage/trade_history_storage.tsx b/packages/website/ts/local_storage/trade_history_storage.tsx
index cc764d98e..2e2f4e64e 100644
--- a/packages/website/ts/local_storage/trade_history_storage.tsx
+++ b/packages/website/ts/local_storage/trade_history_storage.tsx
@@ -57,7 +57,7 @@ export const tradeHistoryStorage = {
return {};
}
const userFillsByHash = JSON.parse(userFillsJSONString);
- _.each(userFillsByHash, (fill, hash) => {
+ _.each(userFillsByHash, fill => {
fill.paidMakerFee = new BigNumber(fill.paidMakerFee);
fill.paidTakerFee = new BigNumber(fill.paidTakerFee);
fill.filledTakerTokenAmount = new BigNumber(fill.filledTakerTokenAmount);
diff --git a/packages/website/ts/pages/jobs/benefits.tsx b/packages/website/ts/pages/jobs/benefits.tsx
new file mode 100644
index 000000000..006facc83
--- /dev/null
+++ b/packages/website/ts/pages/jobs/benefits.tsx
@@ -0,0 +1,109 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { FilledImage } from 'ts/components/ui/filled_image';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+const IMAGE_PATHS = ['/images/jobs/location1.png', '/images/jobs/location2.png', '/images/jobs/location3.png'];
+const BENEFIT_ITEM_PROPS_LIST: BenefitItemProps[] = [
+ {
+ bulletColor: '#6FCF97',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#56CCF2',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#EB5757',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#6FCF97',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#56CCF2',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+];
+const LARGE_LAYOUT_HEIGHT = 937;
+const LARGE_LAYOUT_BENEFITS_LIST_PADDING_LEFT = 205;
+const HEADER_TEXT = 'Benefits';
+const BENEFIT_ITEM_MIN_HEIGHT = 150;
+
+export interface BenefitsProps {
+ screenWidth: ScreenWidths;
+}
+
+export const Benefits = (props: BenefitsProps) => (
+ <div style={{ backgroundColor: colors.jobsPageBackground }}>
+ {props.screenWidth === ScreenWidths.Sm ? <SmallLayout /> : <LargeLayout />}
+ </div>
+);
+
+const LargeLayout = () => (
+ <div className="flex" style={{ height: LARGE_LAYOUT_HEIGHT }}>
+ <div style={{ width: '43%', height: '100%' }}>
+ <ImageGrid />
+ </div>
+ <div
+ className="pr4"
+ style={{ paddingLeft: LARGE_LAYOUT_BENEFITS_LIST_PADDING_LEFT, width: '57%', height: '100%' }}
+ >
+ <BenefitsList />
+ </div>
+ </div>
+);
+
+const SmallLayout = () => (
+ <div>
+ <FilledImage src={_.head(IMAGE_PATHS)} />
+ <BenefitsList />
+ </div>
+);
+
+export const BenefitsList = () => {
+ return (
+ <div>
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(BENEFIT_ITEM_PROPS_LIST, valueItemProps => <BenefitItem {...valueItemProps} />)}
+ </div>
+ );
+};
+interface BenefitItemProps {
+ bulletColor: string;
+ description: string;
+}
+
+const BenefitItem: React.StatelessComponent<BenefitItemProps> = ({ bulletColor, description }) => (
+ <div style={{ minHeight: BENEFIT_ITEM_MIN_HEIGHT }}>
+ <ListItem bulletColor={bulletColor}>
+ <div style={{ fontSize: 16, lineHeight: 1.5 }}>{description}</div>
+ </ListItem>
+ </div>
+);
+
+const ImageGrid = () => (
+ <div style={{ width: '100%', height: '100%' }}>
+ <div className="flex" style={{ height: '67%' }}>
+ <FilledImage src={IMAGE_PATHS[0]} />
+ </div>
+ <div className="clearfix" style={{ height: '33%' }}>
+ <div className="col lg-col-6 md-col-6 col-12" style={{ height: '100%' }}>
+ <FilledImage src={IMAGE_PATHS[1]} />
+ </div>
+ <div className="col lg-col-6 md-col-6 col-12" style={{ height: '100%' }}>
+ <FilledImage src={IMAGE_PATHS[2]} />
+ </div>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/pages/jobs/jobs.tsx b/packages/website/ts/pages/jobs/jobs.tsx
new file mode 100644
index 000000000..314669ee9
--- /dev/null
+++ b/packages/website/ts/pages/jobs/jobs.tsx
@@ -0,0 +1,81 @@
+import { colors, utils as sharedUtils } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import * as DocumentTitle from 'react-document-title';
+
+import { Footer } from 'ts/components/footer';
+import { TopBar } from 'ts/components/top_bar/top_bar';
+import { FilledImage } from 'ts/components/ui/filled_image';
+import { Benefits } from 'ts/pages/jobs/benefits';
+import { Join0x } from 'ts/pages/jobs/join_0x';
+import { Mission } from 'ts/pages/jobs/mission';
+import { OpenPositions } from 'ts/pages/jobs/open_positions';
+import { PhotoRail } from 'ts/pages/jobs/photo_rail';
+import { Teams } from 'ts/pages/jobs/teams';
+import { Values } from 'ts/pages/jobs/values';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+import { utils } from 'ts/utils/utils';
+
+const OPEN_POSITIONS_HASH = 'positions';
+const THROTTLE_TIMEOUT = 100;
+const PHOTO_RAIL_IMAGES = ['/images/jobs/office1.png', '/images/jobs/office2.png', '/images/jobs/office3.png'];
+
+export interface JobsProps {
+ location: Location;
+ translate: Translate;
+ dispatcher: Dispatcher;
+ screenWidth: ScreenWidths;
+}
+
+export interface JobsState {}
+
+export class Jobs extends React.Component<JobsProps, JobsState> {
+ // TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well)
+ private _throttledScreenWidthUpdate: () => void;
+ public constructor(props: JobsProps) {
+ super(props);
+ this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+ }
+ public componentDidMount(): void {
+ window.addEventListener('resize', this._throttledScreenWidthUpdate);
+ window.scrollTo(0, 0);
+ }
+ public render(): React.ReactNode {
+ return (
+ <div>
+ <DocumentTitle title="Jobs" />
+ <TopBar
+ blockchainIsLoaded={false}
+ location={this.props.location}
+ style={{ backgroundColor: colors.white, position: 'relative' }}
+ translate={this.props.translate}
+ />
+ <Join0x onCallToActionClick={this._onJoin0xCallToActionClick.bind(this)} />
+ <Mission screenWidth={this.props.screenWidth} />
+ {this._isSmallScreen() ? (
+ <FilledImage src={_.head(PHOTO_RAIL_IMAGES)} />
+ ) : (
+ <PhotoRail images={PHOTO_RAIL_IMAGES} />
+ )}
+ <Values />
+ <Benefits screenWidth={this.props.screenWidth} />
+ <Teams screenWidth={this.props.screenWidth} />
+ <OpenPositions hash={OPEN_POSITIONS_HASH} screenWidth={this.props.screenWidth} />
+ <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
+ </div>
+ );
+ }
+ private _onJoin0xCallToActionClick(): void {
+ sharedUtils.setUrlHash(OPEN_POSITIONS_HASH);
+ }
+ private _updateScreenWidth(): void {
+ const newScreenWidth = utils.getScreenWidth();
+ this.props.dispatcher.updateScreenWidth(newScreenWidth);
+ }
+ private _isSmallScreen(): boolean {
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ return isSmallScreen;
+ }
+}
diff --git a/packages/website/ts/pages/jobs/join_0x.tsx b/packages/website/ts/pages/jobs/join_0x.tsx
new file mode 100644
index 000000000..72cce3b89
--- /dev/null
+++ b/packages/website/ts/pages/jobs/join_0x.tsx
@@ -0,0 +1,41 @@
+import { colors } from '@0xproject/react-shared';
+
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+
+const BUTTON_TEXT = 'view open positions';
+
+export interface Join0xProps {
+ onCallToActionClick: () => void;
+}
+
+export const Join0x = (props: Join0xProps) => (
+ <div className="clearfix center lg-py4 md-py4" style={{ backgroundColor: colors.white, color: colors.black }}>
+ <div className="mx-auto inline-block align-middle py4" style={{ lineHeight: '44px', textAlign: 'center' }}>
+ <div className="h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
+ Join 0x
+ </div>
+ <div
+ className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 h4 sm-center"
+ style={{ fontFamily: 'Roboto', lineHeight: 2, maxWidth: 537 }}
+ >
+ 0x is transforming the way that value is exchanged on a global scale. Come join us in San Francisco or
+ work remotely anywhere in the world to help create the infrastructure of a new tokenized economy.
+ </div>
+ <div className="py3">
+ <Button
+ type="button"
+ backgroundColor={colors.black}
+ width="290px"
+ fontColor={colors.white}
+ fontSize="18px"
+ fontFamily="Roboto Mono"
+ onClick={props.onCallToActionClick}
+ >
+ {BUTTON_TEXT}
+ </Button>
+ </div>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/pages/jobs/list/header_item.tsx b/packages/website/ts/pages/jobs/list/header_item.tsx
new file mode 100644
index 000000000..ac214904c
--- /dev/null
+++ b/packages/website/ts/pages/jobs/list/header_item.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+
+import { Text } from 'ts/components/ui/text';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+
+export interface HeaderItemProps {
+ headerText?: string;
+}
+export const HeaderItem: React.StatelessComponent<HeaderItemProps> = ({ headerText }) => {
+ return (
+ <div className="h2 lg-py4 md-py4 sm-py3">
+ <ListItem>
+ <Text
+ fontFamily="Roboto Mono"
+ fontSize="24px"
+ lineHeight="1.25"
+ minHeight="1.25em"
+ fontColor={colors.black}
+ >
+ {headerText}
+ </Text>
+ </ListItem>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/list/list_item.tsx b/packages/website/ts/pages/jobs/list/list_item.tsx
new file mode 100644
index 000000000..d7838bc01
--- /dev/null
+++ b/packages/website/ts/pages/jobs/list/list_item.tsx
@@ -0,0 +1,15 @@
+import * as React from 'react';
+
+export interface ListItemProps {
+ bulletColor?: string;
+}
+export const ListItem: React.StatelessComponent<ListItemProps> = ({ bulletColor, children }) => {
+ return (
+ <div className="flex items-center">
+ <svg className="flex-none lg-px2 md-px2 sm-pl2" height="26" width="26">
+ <circle cx="13" cy="13" r="13" fill={bulletColor || 'transparent'} />
+ </svg>
+ <div className="flex-auto px2">{children}</div>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/mission.tsx b/packages/website/ts/pages/jobs/mission.tsx
new file mode 100644
index 000000000..f7f874e04
--- /dev/null
+++ b/packages/website/ts/pages/jobs/mission.tsx
@@ -0,0 +1,56 @@
+import * as React from 'react';
+
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+export interface MissionProps {
+ screenWidth: ScreenWidths;
+}
+export const Mission = (props: MissionProps) => {
+ const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
+ const image = (
+ <div className="col lg-col-6 md-col-6 col-12 sm-py2 px2 center">
+ <img src="/images/jobs/map.png" style={{ width: '100%' }} />
+ </div>
+ );
+ const missionStatementStyle = !isSmallScreen ? { height: 364, lineHeight: '364px' } : undefined;
+ const missionStatement = (
+ <div className="col lg-col-6 md-col-6 col-12 center" style={missionStatementStyle}>
+ <div
+ className="mx-auto inline-block align-middle"
+ style={{ maxWidth: 385, lineHeight: '44px', textAlign: 'center' }}
+ >
+ <div className="h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
+ Our Mission
+ </div>
+ <div
+ className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 h4 sm-center"
+ style={{ fontFamily: 'Roboto', lineHeight: 2, maxWidth: 537 }}
+ >
+ We believe a system can exist in which all world value is accessible to anyone, anywhere, regardless
+ of where you happen to be born.
+ </div>
+ </div>
+ </div>
+ );
+ return (
+ <div
+ className="container lg-py4 md-py4"
+ style={{ backgroundColor: colors.jobsPageBackground, color: colors.black }}
+ >
+ <div className="mx-auto clearfix sm-py4">
+ {isSmallScreen ? (
+ <div>
+ {missionStatement}
+ {image}
+ </div>
+ ) : (
+ <div>
+ {image}
+ {missionStatement}
+ </div>
+ )}
+ </div>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/open_positions.tsx b/packages/website/ts/pages/jobs/open_positions.tsx
new file mode 100644
index 000000000..f3d980315
--- /dev/null
+++ b/packages/website/ts/pages/jobs/open_positions.tsx
@@ -0,0 +1,192 @@
+import * as _ from 'lodash';
+import CircularProgress from 'material-ui/CircularProgress';
+import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
+import * as React from 'react';
+
+import { Retry } from 'ts/components/ui/retry';
+import { Text } from 'ts/components/ui/text';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+import { styled } from 'ts/style/theme';
+import { ScreenWidths, WebsiteBackendJobInfo } from 'ts/types';
+import { backendClient } from 'ts/utils/backend_client';
+
+const labelStyle = { fontFamily: 'Roboto Mono', fontSize: 18 };
+const HEADER_TEXT = 'Open Positions';
+const TABLE_ROW_MIN_HEIGHT = 100;
+
+export interface OpenPositionsProps {
+ hash: string;
+ screenWidth: ScreenWidths;
+}
+export interface OpenPositionsState {
+ jobInfos?: WebsiteBackendJobInfo[];
+ error?: Error;
+}
+
+export class OpenPositions extends React.Component<OpenPositionsProps, OpenPositionsState> {
+ private _isUnmounted: boolean;
+ constructor(props: OpenPositionsProps) {
+ super(props);
+ this._isUnmounted = false;
+ this.state = {
+ jobInfos: undefined,
+ error: undefined,
+ };
+ }
+ public componentWillMount(): void {
+ // tslint:disable-next-line:no-floating-promises
+ this._fetchJobInfosAsync();
+ }
+ public componentWillUnmount(): void {
+ this._isUnmounted = true;
+ }
+ public render(): React.ReactNode {
+ const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.jobInfos);
+ return (
+ <div id={this.props.hash} className="mx-auto max-width-4">
+ {isReadyToRender ? this._renderBody() : this._renderLoading()}
+ </div>
+ );
+ }
+ private _renderBody(): React.ReactNode {
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ return isSmallScreen ? this._renderList() : this._renderTable();
+ }
+ private _renderLoading(): React.ReactNode {
+ return (
+ // TODO: consolidate this loading component with the one in portal and RelayerIndex
+ // TODO: possibly refactor into a generic loading container with spinner and retry UI
+ <div className="center">
+ {_.isUndefined(this.state.error) ? (
+ <CircularProgress size={40} thickness={5} />
+ ) : (
+ <Retry onRetry={this._fetchJobInfosAsync.bind(this)} />
+ )}
+ </div>
+ );
+ }
+ private _renderList(): React.ReactNode {
+ return (
+ <div style={{ backgroundColor: colors.jobsPageBackground }}>
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(this.state.jobInfos, jobInfo => (
+ <JobInfoListItem
+ key={jobInfo.id}
+ title={jobInfo.title}
+ description={jobInfo.department}
+ onClick={this._openJobInfoUrl.bind(this, jobInfo)}
+ />
+ ))}
+ </div>
+ );
+ }
+ private _renderTable(): React.ReactNode {
+ return (
+ <div>
+ <HeaderItem headerText={HEADER_TEXT} />
+ <Table selectable={false} onCellClick={this._onCellClick.bind(this)}>
+ <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
+ <TableRow>
+ <TableHeaderColumn colSpan={5} style={labelStyle}>
+ Position
+ </TableHeaderColumn>
+ <TableHeaderColumn colSpan={3} style={labelStyle}>
+ Department
+ </TableHeaderColumn>
+ <TableHeaderColumn colSpan={4} style={labelStyle}>
+ Office
+ </TableHeaderColumn>
+ </TableRow>
+ </TableHeader>
+ <TableBody displayRowCheckbox={false} showRowHover={true}>
+ {_.map(this.state.jobInfos, jobInfo => {
+ return this._renderJobInfoTableRow(jobInfo);
+ })}
+ </TableBody>
+ </Table>
+ </div>
+ );
+ }
+ private _renderJobInfoTableRow(jobInfo: WebsiteBackendJobInfo): React.ReactNode {
+ return (
+ <TableRow
+ key={jobInfo.id}
+ hoverable={true}
+ displayBorder={false}
+ style={{ height: TABLE_ROW_MIN_HEIGHT, border: 2 }}
+ >
+ <TableRowColumn colSpan={5} style={labelStyle}>
+ {jobInfo.title}
+ </TableRowColumn>
+ <TableRowColumn colSpan={3} style={labelStyle}>
+ {jobInfo.department}
+ </TableRowColumn>
+ <TableRowColumn colSpan={4} style={labelStyle}>
+ {jobInfo.office}
+ </TableRowColumn>
+ </TableRow>
+ );
+ }
+ private async _fetchJobInfosAsync(): Promise<void> {
+ try {
+ if (!this._isUnmounted) {
+ this.setState({
+ jobInfos: undefined,
+ error: undefined,
+ });
+ }
+ const jobInfos = await backendClient.getJobInfosAsync();
+ if (!this._isUnmounted) {
+ this.setState({
+ jobInfos,
+ });
+ }
+ } catch (error) {
+ if (!this._isUnmounted) {
+ this.setState({
+ error,
+ });
+ }
+ }
+ }
+ private _onCellClick(rowNumber: number): void {
+ if (_.isUndefined(this.state.jobInfos)) {
+ return;
+ }
+ const jobInfo = this.state.jobInfos[rowNumber];
+ this._openJobInfoUrl(jobInfo);
+ }
+
+ private _openJobInfoUrl(jobInfo: WebsiteBackendJobInfo): void {
+ const url = jobInfo.url;
+ window.open(url, '_blank');
+ }
+}
+
+export interface JobInfoListItemProps {
+ title?: string;
+ description?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+}
+
+const PlainJobInfoListItem: React.StatelessComponent<JobInfoListItemProps> = ({ title, description, onClick }) => (
+ <div className="mb3" onClick={onClick}>
+ <ListItem>
+ <Text fontWeight="bold" fontSize="16px" fontColor={colors.mediumBlue}>
+ {title + ' ›'}
+ </Text>
+ <Text className="pt1" fontSize="16px" fontColor={colors.darkGrey}>
+ {description}
+ </Text>
+ </ListItem>
+ </div>
+);
+
+export const JobInfoListItem = styled(PlainJobInfoListItem)`
+ cursor: pointer;
+ &:hover {
+ opacity: 0.5;
+ }
+`;
diff --git a/packages/website/ts/pages/jobs/photo_rail.tsx b/packages/website/ts/pages/jobs/photo_rail.tsx
new file mode 100644
index 000000000..acc9dcb91
--- /dev/null
+++ b/packages/website/ts/pages/jobs/photo_rail.tsx
@@ -0,0 +1,22 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { FilledImage } from 'ts/components/ui/filled_image';
+
+export interface PhotoRailProps {
+ images: string[];
+}
+
+export const PhotoRail = (props: PhotoRailProps) => {
+ return (
+ <div className="clearfix" style={{ height: 490 }}>
+ {_.map(props.images, (image: string) => {
+ return (
+ <div key={image} className="col lg-col-4 md-col-4 col-12 center" style={{ height: '100%' }}>
+ <FilledImage src={image} />
+ </div>
+ );
+ })}
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/teams.tsx b/packages/website/ts/pages/jobs/teams.tsx
new file mode 100644
index 000000000..80b036396
--- /dev/null
+++ b/packages/website/ts/pages/jobs/teams.tsx
@@ -0,0 +1,90 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Text } from 'ts/components/ui/text';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+const TEAM_ITEM_PROPS_COLUMN1: TeamItemProps[] = [
+ {
+ bulletColor: '#EB5757',
+ title: 'User Growth',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#EB5757',
+ title: 'Governance',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+];
+const TEAM_ITEM_PROPS_COLUMN2: TeamItemProps[] = [
+ {
+ bulletColor: '#EB5757',
+ title: 'Developer Tools',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#EB5757',
+ title: 'Marketing',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+];
+const HEADER_TEXT = 'Our Teams';
+const MINIMUM_ITEM_HEIGHT = 240;
+
+export interface TeamsProps {
+ screenWidth: ScreenWidths;
+}
+
+export const Teams = (props: TeamsProps) => (props.screenWidth === ScreenWidths.Sm ? <SmallLayout /> : <LargeLayout />);
+
+const LargeLayout = () => (
+ <div className="mx-auto max-width-4 clearfix pb4">
+ <div className="col lg-col-6 md-col-6 col-12">
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(TEAM_ITEM_PROPS_COLUMN1, teamItemProps => <TeamItem {...teamItemProps} />)}
+ </div>
+ <div className="col lg-col-6 md-col-6 col-12">
+ <HeaderItem headerText=" " />
+ {_.map(TEAM_ITEM_PROPS_COLUMN2, teamItemProps => <TeamItem {...teamItemProps} />)}
+ </div>
+ </div>
+);
+
+const SmallLayout = () => (
+ <div>
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(_.concat(TEAM_ITEM_PROPS_COLUMN1, TEAM_ITEM_PROPS_COLUMN2), teamItemProps => (
+ <TeamItem {...teamItemProps} />
+ ))}
+ </div>
+);
+
+interface TeamItemProps {
+ bulletColor: string;
+ title: string;
+ description: string;
+}
+
+export const TeamItem: React.StatelessComponent<TeamItemProps> = ({ bulletColor, title, description }) => {
+ return (
+ <div style={{ minHeight: MINIMUM_ITEM_HEIGHT }}>
+ <ListItem bulletColor={bulletColor}>
+ <Text fontWeight="bold" fontSize="16px" fontColor={colors.black}>
+ {title}
+ </Text>
+ </ListItem>
+ <ListItem>
+ <Text className="pt1" fontSize="16px" lineHeight="2em" fontColor={colors.black}>
+ {description}
+ </Text>
+ </ListItem>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/values.tsx b/packages/website/ts/pages/jobs/values.tsx
new file mode 100644
index 000000000..c7c4d5726
--- /dev/null
+++ b/packages/website/ts/pages/jobs/values.tsx
@@ -0,0 +1,60 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Text } from 'ts/components/ui/text';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+
+const VALUE_ITEM_PROPS_LIST: ValueItemProps[] = [
+ {
+ bulletColor: '#6FCF97',
+ title: 'Ethics/Doing the right thing',
+ description: 'orem ipsum dolor sit amet, consectetur adipiscing elit.',
+ },
+ {
+ bulletColor: '#56CCF2',
+ title: 'Consistently ship',
+ description: 'orem ipsum dolor sit amet, consectetur adipiscing elit.',
+ },
+ {
+ bulletColor: '#EB5757',
+ title: 'Focus on long term impact',
+ description: 'orem ipsum dolor sit amet, consectetur adipiscing elit.',
+ },
+];
+
+const HEADER_TEXT = 'Our Values';
+const VALUE_ITEM_MIN_HEIGHT = 150;
+
+export const Values = () => {
+ return (
+ <div className="mx-auto max-width-4">
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(VALUE_ITEM_PROPS_LIST, valueItemProps => <ValueItem {...valueItemProps} />)}
+ </div>
+ );
+};
+
+interface ValueItemProps {
+ bulletColor: string;
+ title: string;
+ description: string;
+}
+
+export const ValueItem: React.StatelessComponent<ValueItemProps> = ({ bulletColor, title, description }) => {
+ return (
+ <div style={{ minHeight: VALUE_ITEM_MIN_HEIGHT }}>
+ <ListItem bulletColor={bulletColor}>
+ <Text fontWeight="bold" fontSize="16x" fontColor={colors.black}>
+ {title}
+ </Text>
+ </ListItem>
+ <ListItem>
+ <Text className="pt1" fontSize="16x" lineHeight="2em" fontColor={colors.black}>
+ {description}
+ </Text>
+ </ListItem>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/not_found.tsx b/packages/website/ts/pages/not_found.tsx
index a94ba5863..2fe3b1f45 100644
--- a/packages/website/ts/pages/not_found.tsx
+++ b/packages/website/ts/pages/not_found.tsx
@@ -11,7 +11,7 @@ export interface NotFoundProps {
dispatcher: Dispatcher;
}
-export const NotFound = (props: NotFoundProps) => {
+export const NotFound = (_props: NotFoundProps) => {
return (
<div>
<TopBar blockchainIsLoaded={false} location={this.props.location} translate={this.props.translate} />
diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx
index bdefe0fda..9659900be 100644
--- a/packages/website/ts/pages/wiki/wiki.tsx
+++ b/packages/website/ts/pages/wiki/wiki.tsx
@@ -233,7 +233,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
}
return menuSubsectionsBySection;
}
- private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void {
+ private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
this.setState({
isHoveringSidebar: true,
});
@@ -243,7 +243,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
isHoveringSidebar: false,
});
}
- private _onHashChanged(event: any): void {
+ private _onHashChanged(_event: any): void {
const hash = window.location.hash.slice(1);
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
}
diff --git a/packages/website/ts/style/colors.ts b/packages/website/ts/style/colors.ts
index 5ffdd6ba7..b15000d7a 100644
--- a/packages/website/ts/style/colors.ts
+++ b/packages/website/ts/style/colors.ts
@@ -11,6 +11,8 @@ const appColors = {
wrapEtherConfirmationButton: sharedColors.mediumBlue,
drawerMenuBackground: '#4a4a4a',
menuItemDefaultSelectedBackground: '#424242',
+ jobsPageBackground: sharedColors.grey50,
+ jobsPageOpenPositionRow: sharedColors.grey100,
};
export const colors = {
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index 15444e517..d00154652 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -519,6 +519,8 @@ export interface WebsiteBackendRelayerInfo {
url: string;
appUrl?: string;
headerImgUrl?: string;
+ logoImgUrl?: string;
+ primaryColor?: string;
topTokens: WebsiteBackendTokenInfo[];
}
@@ -536,4 +538,12 @@ export interface WebsiteBackendTokenInfo {
export interface WebsiteBackendGasInfo {
average: number;
}
+
+export interface WebsiteBackendJobInfo {
+ id: number;
+ title: string;
+ department: string;
+ office: string;
+ url: string;
+}
// tslint:disable:max-file-line-count
diff --git a/packages/website/ts/utils/backend_client.ts b/packages/website/ts/utils/backend_client.ts
index 6b16aea6b..835a6ef4d 100644
--- a/packages/website/ts/utils/backend_client.ts
+++ b/packages/website/ts/utils/backend_client.ts
@@ -1,10 +1,17 @@
import * as _ from 'lodash';
-import { ArticlesBySection, WebsiteBackendGasInfo, WebsiteBackendPriceInfo, WebsiteBackendRelayerInfo } from 'ts/types';
+import {
+ ArticlesBySection,
+ WebsiteBackendGasInfo,
+ WebsiteBackendJobInfo,
+ WebsiteBackendPriceInfo,
+ WebsiteBackendRelayerInfo,
+} from 'ts/types';
import { fetchUtils } from 'ts/utils/fetch_utils';
import { utils } from 'ts/utils/utils';
const ETH_GAS_STATION_ENDPOINT = '/eth_gas_station';
+const JOBS_ENDPOINT = '/jobs';
const PRICES_ENDPOINT = '/prices';
const RELAYERS_ENDPOINT = '/relayers';
const WIKI_ENDPOINT = '/wiki';
@@ -15,6 +22,10 @@ export const backendClient = {
const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), ETH_GAS_STATION_ENDPOINT);
return result;
},
+ async getJobInfosAsync(): Promise<WebsiteBackendJobInfo[]> {
+ const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), JOBS_ENDPOINT);
+ return result;
+ },
async getPriceInfoAsync(tokenSymbols: string[]): Promise<WebsiteBackendPriceInfo> {
if (_.isEmpty(tokenSymbols)) {
return {};
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index d281c5738..25670ef27 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -6,6 +6,7 @@ export const constants = {
ETHER_TOKEN_SYMBOL: 'WETH',
ZRX_TOKEN_SYMBOL: 'ZRX',
ETHER_SYMBOL: 'ETH',
+ TOKEN_AMOUNT_DISPLAY_PRECISION: 5,
GENESIS_ORDER_BLOCK_BY_NETWORK_ID: {
1: 4145578,
42: 3117574,
diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts
index 548d4d41d..f875141fe 100644
--- a/packages/website/ts/utils/error_reporter.ts
+++ b/packages/website/ts/utils/error_reporter.ts
@@ -37,7 +37,7 @@ export const errorReporter = {
return; // Let's not log development errors to rollbar
}
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, _reject) => {
rollbar.error(err, (rollbarErr: Error) => {
if (rollbarErr) {
logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`);
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index 6961784c6..414361c1b 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -3,6 +3,7 @@ import { OrderError } from '@0xproject/order-utils';
import { constants as sharedConstants, Networks } from '@0xproject/react-shared';
import { ECSignature, Provider } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
import deepEqual = require('deep-equal');
import * as _ from 'lodash';
import * as moment from 'moment';
@@ -17,6 +18,7 @@ import {
SideToAssetToken,
Token,
TokenByAddress,
+ TokenState,
} from 'ts/types';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
@@ -152,7 +154,7 @@ export const utils = {
const intervalId = setTimeout(() => {
resolve(false);
}, getApiVersionTimeoutMs);
- u2f.getApiVersion((version: number) => {
+ u2f.getApiVersion((_version: number) => {
clearTimeout(intervalId);
resolve(true);
});
@@ -279,7 +281,7 @@ export const utils = {
if (document.readyState === 'complete') {
return; // Already loaded
}
- return new Promise<void>((resolve, reject) => {
+ return new Promise<void>((resolve, _reject) => {
window.onload = () => resolve();
});
},
@@ -318,9 +320,27 @@ export const utils = {
shouldShowPortalV2(): boolean {
return this.isDevelopment() || this.isStaging() || this.isDogfood();
},
+ shouldShowJobsPage(): boolean {
+ return this.isDevelopment() || this.isStaging() || this.isDogfood();
+ },
getEthToken(tokenByAddress: TokenByAddress): Token {
+ return utils.getTokenBySymbol(constants.ETHER_TOKEN_SYMBOL, tokenByAddress);
+ },
+ getZrxToken(tokenByAddress: TokenByAddress): Token {
+ return utils.getTokenBySymbol(constants.ZRX_TOKEN_SYMBOL, tokenByAddress);
+ },
+ getTokenBySymbol(symbol: string, tokenByAddress: TokenByAddress): Token {
const tokens = _.values(tokenByAddress);
- const etherToken = _.find(tokens, { symbol: constants.ETHER_TOKEN_SYMBOL });
- return etherToken;
+ const token = _.find(tokens, { symbol });
+ return token;
+ },
+ getFormattedAmountFromToken(token: Token, tokenState: TokenState): string {
+ return utils.getFormattedAmount(tokenState.balance, token.decimals, token.symbol);
+ },
+ getFormattedAmount(amount: BigNumber, decimals: number, symbol: string): string {
+ const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
+ const precision = Math.min(constants.TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces());
+ const formattedAmount = unitAmount.toFixed(precision);
+ return `${formattedAmount} ${symbol}`;
},
};