diff options
-rw-r--r-- | packages/instant/.dogfood.discharge.json | 2 | ||||
-rw-r--r-- | packages/instant/.production.discharge.json | 13 | ||||
-rw-r--r-- | packages/instant/.staging.discharge.json | 2 | ||||
-rw-r--r-- | packages/instant/README.md | 50 | ||||
-rw-r--r-- | packages/instant/package.json | 13 | ||||
-rw-r--r-- | packages/instant/src/components/instant_heading.tsx | 11 | ||||
-rw-r--r-- | packages/instant/src/components/payment_method.tsx | 5 | ||||
-rw-r--r-- | packages/instant/src/components/ui/container.tsx | 2 | ||||
-rw-r--r-- | packages/instant/src/containers/latest_error.tsx | 8 | ||||
-rw-r--r-- | packages/instant/src/index.umd.ts | 4 | ||||
-rw-r--r-- | packages/instant/tsconfig.json | 8 | ||||
-rw-r--r-- | packages/instant/webpack.config.js | 3 | ||||
-rw-r--r-- | python-packages/order_utils/src/zero_ex/json_schemas/__init__.py | 81 | ||||
-rw-r--r-- | python-packages/order_utils/stubs/jsonschema/__init__.pyi | 10 | ||||
-rw-r--r-- | python-packages/order_utils/test/test_doctest.py | 5 | ||||
-rw-r--r-- | python-packages/order_utils/test/test_json_schemas.py | 23 | ||||
-rw-r--r-- | tsconfig.json | 4 |
17 files changed, 148 insertions, 96 deletions
diff --git a/packages/instant/.dogfood.discharge.json b/packages/instant/.dogfood.discharge.json index ca36b3861..85a48044b 100644 --- a/packages/instant/.dogfood.discharge.json +++ b/packages/instant/.dogfood.discharge.json @@ -1,6 +1,6 @@ { "domain": "0x-instant-dogfood", - "build_command": "WEBPACK_OUTPUT_PATH=public yarn build:umd:prod", + "build_command": "WEBPACK_OUTPUT_PATH=public yarn build", "upload_directory": "public", "index_key": "index.html", "error_key": "index.html", diff --git a/packages/instant/.production.discharge.json b/packages/instant/.production.discharge.json new file mode 100644 index 000000000..447fa1756 --- /dev/null +++ b/packages/instant/.production.discharge.json @@ -0,0 +1,13 @@ +{ + "domain": "instant.0xproject.com", + "build_command": "yarn build", + "upload_directory": "umd", + "index_key": "instant.js", + "error_key": "404.html", + "trailing_slashes": true, + "cache": 3600, + "aws_profile": "default", + "aws_region": "us-east-1", + "cdn": true, + "dns_configured": true +} diff --git a/packages/instant/.staging.discharge.json b/packages/instant/.staging.discharge.json index c917a650b..93fd94f40 100644 --- a/packages/instant/.staging.discharge.json +++ b/packages/instant/.staging.discharge.json @@ -1,6 +1,6 @@ { "domain": "0x-instant-staging", - "build_command": "WEBPACK_OUTPUT_PATH=public yarn build:umd:prod", + "build_command": "WEBPACK_OUTPUT_PATH=public yarn build", "upload_directory": "public", "index_key": "index.html", "error_key": "index.html", diff --git a/packages/instant/README.md b/packages/instant/README.md index b83a10508..45a871124 100644 --- a/packages/instant/README.md +++ b/packages/instant/README.md @@ -2,39 +2,11 @@ ## Installation -```bash -yarn add @0x/instant -``` - -**Import** - -**CommonJS module** - -```typescript -import { ZeroExInstant } from '@0x/instant'; -``` - -or - -```javascript -var ZeroExInstant = require('@0x/instant').ZeroExInstant; -``` - -If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: - -```json -"compilerOptions": { - "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"], -} -``` - -**UMD Module** - -The package is also available as a UMD module named `zeroExInstant`. +The package is available as a UMD module named `zeroExInstant` at https://instant.0xproject.com/instant.js. ```html <head> - <script type="text/javascript" src="[zeroExInstantUMDPath]" charset="utf-8"></script> + <script type="text/javascript" src="https://instant.0xproject.com/instant.js" charset="utf-8"></script> </head> <body> <div id="zeroExInstantContainer"></div> @@ -48,23 +20,31 @@ The package is also available as a UMD module named `zeroExInstant`. ## Deploying -You can deploy a work-in-progress version of 0x Instant at http://0x-instant-dogfood.s3-website-us-east-1.amazonaws.com for easy sharing. +You can deploy a work-in-progress version of 0x Instant at http://0x-instant-dogfood.s3-website-us-east-1.amazonaws.com/instant.js for easy sharing. -To build and deploy the site run +To build and deploy the bundle run ``` yarn deploy_dogfood ``` -We also have a staging bucket that is to be updated less frequently can be used to share instant externally: http://0x-instant-staging.s3-website-us-east-1.amazonaws.com/ +We also have a staging bucket that is to be updated less frequently can be used to share a beta version of instant externally: http://0x-instant-staging.s3-website-us-east-1.amazonaws.com/instant.js -To build and deploy to this bucket, run +To build and deploy to this bundle, run ``` yarn deploy_staging ``` -**NOTE: On deploying the site, it will say the site is available at a non-existent URL. Please ignore and use the (now updated) URL above.** +Finally, we have our live production bundle that is only meant to be updated with stable, polished releases: https://instant.0xproject.com/instant.js + +To build and deploy to this bundle, run + +``` +yarn deploy_production +``` + +**NOTE: On deploying the site to staging and dogfood, it will say the site is available at a non-existent URL. Please ignore and use the (now updated) URL above.** ## Contributing diff --git a/packages/instant/package.json b/packages/instant/package.json index c75e2408d..4f6e6d5a4 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -6,15 +6,11 @@ }, "private": true, "description": "0x Instant React Component", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "umd/instant.js", + "private": true, "scripts": { - "build": "yarn build:all", - "build:all": "run-p build:umd:prod build:commonjs", - "build:umd:prod": "webpack --mode production", - "build:commonjs": "tsc -b", + "build": "webpack --mode production", "build:ci": "yarn build", - "watch_without_deps": "tsc -w", "dev": "webpack-dev-server --mode development", "lint": "tslint --format stylish --project .", "test": "jest", @@ -24,6 +20,7 @@ "clean": "shx rm -rf lib coverage scripts", "deploy_dogfood": "discharge deploy -c .dogfood.discharge.json", "deploy_staging": "discharge deploy -c .staging.discharge.json", + "deploy_production": "discharge deploy -c .production.discharge.json", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "config": { @@ -99,6 +96,6 @@ "webpack-dev-server": "^3.1.9" }, "publishConfig": { - "access": "public" + "access": "private" } } diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx index ace577824..808c6dc7f 100644 --- a/packages/instant/src/components/instant_heading.tsx +++ b/packages/instant/src/components/instant_heading.tsx @@ -107,7 +107,14 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private readonly _renderEthAmount = (): React.ReactNode => { return ( - <Text fontSize="16px" textAlign="right" width="100%" fontColor={ColorOption.white} fontWeight={500}> + <Text + fontSize="16px" + textAlign="right" + width="100%" + fontColor={ColorOption.white} + fontWeight={500} + noWrap={true} + > {format.ethBaseUnitAmount( this.props.totalEthBaseUnitAmount, 4, @@ -119,7 +126,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private readonly _renderDollarAmount = (): React.ReactNode => { return ( - <Text fontSize="16px" textAlign="right" width="100%" fontColor={ColorOption.white}> + <Text fontSize="16px" textAlign="right" width="100%" fontColor={ColorOption.white} noWrap={true}> {format.ethBaseUnitAmountInUsd( this.props.totalEthBaseUnitAmount, this.props.ethUsdPrice, diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx index ebcd62f35..c23b43267 100644 --- a/packages/instant/src/components/payment_method.tsx +++ b/packages/instant/src/components/payment_method.tsx @@ -26,7 +26,7 @@ export interface PaymentMethodProps { export class PaymentMethod extends React.Component<PaymentMethodProps> { public render(): React.ReactNode { return ( - <Container padding="20px" width="100%"> + <Container padding="20px" width="100%" height="133px"> <Container marginBottom="12px"> <Flex justify="space-between"> <Text @@ -83,8 +83,7 @@ export class PaymentMethod extends React.Component<PaymentMethodProps> { const colors = { primaryColor, secondaryColor }; switch (account.state) { case AccountState.Loading: - // Just take up the same amount of space as the other states. - return <Container height="52px" />; + return null; case AccountState.Locked: return ( <WalletPrompt diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx index a015ab5bc..e7d909d92 100644 --- a/packages/instant/src/components/ui/container.tsx +++ b/packages/instant/src/components/ui/container.tsx @@ -29,6 +29,7 @@ export interface ContainerProps { backgroundColor?: ColorOption; rawBackgroundColor?: string; hasBoxShadow?: boolean; + isHidden?: boolean; zIndex?: number; whiteSpace?: string; opacity?: number; @@ -81,6 +82,7 @@ export const Container = ${props => props.width && stylesForMedia<string>('width', props.width)} ${props => props.height && stylesForMedia<string>('height', props.height)} ${props => props.borderRadius && stylesForMedia<string>('border-radius', props.borderRadius)} + ${props => (props.isHidden ? 'visibility: hidden;' : '')} background-color: ${props => getBackgroundColor(props.theme, props.backgroundColor, props.rawBackgroundColor)}; border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')}; &:hover { diff --git a/packages/instant/src/containers/latest_error.tsx b/packages/instant/src/containers/latest_error.tsx index b7cfdb504..0d4349124 100644 --- a/packages/instant/src/containers/latest_error.tsx +++ b/packages/instant/src/containers/latest_error.tsx @@ -4,6 +4,7 @@ import { connect } from 'react-redux'; import { Dispatch } from 'redux'; import { SlidingError } from '../components/sliding_error'; +import { Container } from '../components/ui/container'; import { Overlay } from '../components/ui/overlay'; import { Action } from '../redux/actions'; import { State } from '../redux/reducer'; @@ -23,7 +24,12 @@ export interface LatestErrorComponentProps { export const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => { if (!props.latestErrorMessage) { - return <div />; + // Render a hidden SlidingError such that instant does not move when a real error is rendered. + return ( + <Container isHidden={true}> + <SlidingError animationState="slidIn" icon="😢" message="" /> + </Container> + ); } return ( <React.Fragment> diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 667daf441..449453b56 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -112,3 +112,7 @@ export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_Z }; window.onpopstate = onPopStateHandler; }; + +// Write version info to the exported object for debugging +export const GIT_SHA = process.env.GIT_SHA; +export const NPM_VERSION = process.env.NPM_PACKAGE_VERSION; diff --git a/packages/instant/tsconfig.json b/packages/instant/tsconfig.json index 14b0ad8f7..2b3c11c9f 100644 --- a/packages/instant/tsconfig.json +++ b/packages/instant/tsconfig.json @@ -5,8 +5,10 @@ "rootDir": "src", "jsx": "react", "noImplicitAny": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "declaration": false, + "declarationMap": false, + "composite": false }, - "include": ["./src/**/*"], - "exclude": ["./src/index.umd.ts"] + "include": ["./src/**/*"] } diff --git a/packages/instant/webpack.config.js b/packages/instant/webpack.config.js index 41276809c..2a517bb59 100644 --- a/packages/instant/webpack.config.js +++ b/packages/instant/webpack.config.js @@ -3,9 +3,6 @@ const ip = require('ip'); const path = require('path'); const webpack = require('webpack'); -// The common js bundle (not this one) is built using tsc. -// The umd bundle (this one) has a different entrypoint. - const GIT_SHA = childProcess .execSync('git rev-parse HEAD') .toString() diff --git a/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py b/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py index 2a1728b8a..a76a2fa3b 100644 --- a/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py +++ b/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py @@ -8,6 +8,51 @@ from pkg_resources import resource_string import jsonschema +class _LocalRefResolver(jsonschema.RefResolver): + """Resolve package-local JSON schema id's.""" + + def __init__(self): + """Initialize a new instance.""" + self.ref_to_file = { + "/addressSchema": "address_schema.json", + "/hexSchema": "hex_schema.json", + "/orderSchema": "order_schema.json", + "/wholeNumberSchema": "whole_number_schema.json", + "/ECSignature": "ec_signature_schema.json", + "/signedOrderSchema": "signed_order_schema.json", + "/ecSignatureParameterSchema": ( + "ec_signature_parameter_schema.json" + "" + ), + } + jsonschema.RefResolver.__init__(self, "", "") + + def resolve_from_url(self, url: str) -> str: + """Resolve the given URL. + + :param url: a string representing the URL of the JSON schema to fetch. + :returns: a string representing the deserialized JSON schema + :raises jsonschema.ValidationError: when the resource associated with + `url` does not exist. + """ + ref = url.replace("file://", "") + if ref in self.ref_to_file: + return json.loads( + resource_string( + "zero_ex.json_schemas", f"schemas/{self.ref_to_file[ref]}" + ) + ) + raise jsonschema.ValidationError( + f"Unknown ref '{ref}'. " + + f"Known refs: {list(self.ref_to_file.keys())}." + ) + + +# Instantiate the `_LocalRefResolver()` only once so that `assert_valid()` can +# perform multiple schema validations without reading from disk the schema +# every time. +_LOCAL_RESOLVER = _LocalRefResolver() + + def assert_valid(data: Mapping, schema_id: str) -> None: """Validate the given `data` against the specified `schema`. @@ -24,38 +69,6 @@ def assert_valid(data: Mapping, schema_id: str) -> None: ... ) """ # noqa - class LocalRefResolver(jsonschema.RefResolver): - """Resolve package-local JSON schema id's.""" - - def __init__(self): - self.ref_to_file = { - "/addressSchema": "address_schema.json", - "/hexSchema": "hex_schema.json", - "/orderSchema": "order_schema.json", - "/wholeNumberSchema": "whole_number_schema.json", - "/ECSignature": "ec_signature_schema.json", - "/ecSignatureParameterSchema": ( - "ec_signature_parameter_schema.json" + "" - ), - } - jsonschema.RefResolver.__init__(self, "", "") - - def resolve_from_url(self, url): - """Resolve the given URL.""" - ref = url.replace("file://", "") - if ref in self.ref_to_file: - return json.loads( - resource_string( - "zero_ex.json_schemas", - f"schemas/{self.ref_to_file[ref]}", - ) - ) - raise jsonschema.ValidationError( - f"Unknown ref '{ref}'. " - + f"Known refs: {list(self.ref_to_file.keys())}." - ) - resolver = LocalRefResolver() - jsonschema.validate( - data, resolver.resolve_from_url(schema_id), resolver=resolver - ) + _, schema = _LOCAL_RESOLVER.resolve(schema_id) + jsonschema.validate(data, schema, resolver=_LOCAL_RESOLVER) diff --git a/python-packages/order_utils/stubs/jsonschema/__init__.pyi b/python-packages/order_utils/stubs/jsonschema/__init__.pyi index 762b58b22..442e2f65e 100644 --- a/python-packages/order_utils/stubs/jsonschema/__init__.pyi +++ b/python-packages/order_utils/stubs/jsonschema/__init__.pyi @@ -1,5 +1,11 @@ -from typing import Any, Dict +from typing import Any, Dict, Tuple -class RefResolver: pass + +class RefResolver: + def resolve(self, url: str) -> Tuple[str, Dict]: + ... + + +class ValidationError(Exception): pass def validate(instance: Any, schema: Dict, cls=None, *args, **kwargs) -> None: pass diff --git a/python-packages/order_utils/test/test_doctest.py b/python-packages/order_utils/test/test_doctest.py index f692b3b6c..297f75e75 100644 --- a/python-packages/order_utils/test/test_doctest.py +++ b/python-packages/order_utils/test/test_doctest.py @@ -2,16 +2,17 @@ from doctest import testmod import pkgutil +import importlib import zero_ex def test_all_doctests(): """Gather zero_ex.* modules and doctest them.""" - for (importer, modname, _) in pkgutil.walk_packages( + for (_, modname, _) in pkgutil.walk_packages( path=zero_ex.__path__, prefix="zero_ex." ): - module = importer.find_module(modname).load_module(modname) + module = importlib.import_module(modname) print(module) (failure_count, _) = testmod(module) assert failure_count == 0 diff --git a/python-packages/order_utils/test/test_json_schemas.py b/python-packages/order_utils/test/test_json_schemas.py new file mode 100644 index 000000000..51cecbd4f --- /dev/null +++ b/python-packages/order_utils/test/test_json_schemas.py @@ -0,0 +1,23 @@ +"""Tests of zero_ex.json_schemas""" + + +from zero_ex.order_utils import make_empty_order +from zero_ex.json_schemas import _LOCAL_RESOLVER, assert_valid + + +def test_assert_valid_caches_resources(): + """Test that the JSON ref resolver in `assert_valid()` caches resources + + In order to test the cache we much access the private class of + `json_schemas` and reset the LRU cache on `_LocalRefResolver`. + For this to happen, we need to disable errror `W0212` + on _LOCAL_RESOLVER + """ + _LOCAL_RESOLVER._remote_cache.cache_clear() # pylint: disable=W0212 + + assert_valid(make_empty_order(), "/orderSchema") + cache_info = ( + _LOCAL_RESOLVER._remote_cache.cache_info() # pylint: disable=W0212 + ) + assert cache_info.currsize == 4 + assert cache_info.hits == 10 diff --git a/tsconfig.json b/tsconfig.json index eaaca8e4e..0e2fefbac 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -34,7 +34,6 @@ { "path": "./packages/dev-utils" }, { "path": "./packages/ethereum-types" }, { "path": "./packages/fill-scenarios" }, - { "path": "./packages/instant" }, { "path": "./packages/json-schemas" }, { "path": "./packages/metacoin" }, { "path": "./packages/migrations" }, @@ -57,5 +56,8 @@ // Skipping website because it requires allowJs: false and this is // incompatible with project references. // { "path": "./packages/website" } + // Skipping instant because it only produces a UMD bundle + // which it uses webpack to create + // { "path": "./packages/instant" }, ] } |