aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/0x.js/CHANGELOG.json18
-rw-r--r--packages/0x.js/CHANGELOG.md8
-rw-r--r--packages/0x.js/package.json32
-rw-r--r--packages/abi-gen-wrappers/CHANGELOG.json18
-rw-r--r--packages/abi-gen-wrappers/CHANGELOG.md8
-rw-r--r--packages/abi-gen-wrappers/package.json16
-rw-r--r--packages/abi-gen/CHANGELOG.json18
-rw-r--r--packages/abi-gen/CHANGELOG.md8
-rw-r--r--packages/abi-gen/package.json10
-rw-r--r--packages/assert/CHANGELOG.json18
-rw-r--r--packages/assert/CHANGELOG.md8
-rw-r--r--packages/assert/package.json10
-rw-r--r--packages/asset-buyer/CHANGELOG.json12
-rw-r--r--packages/asset-buyer/CHANGELOG.md8
-rw-r--r--packages/asset-buyer/package.json26
-rw-r--r--packages/base-contract/CHANGELOG.json18
-rw-r--r--packages/base-contract/CHANGELOG.md8
-rw-r--r--packages/base-contract/package.json12
-rw-r--r--packages/connect/CHANGELOG.json18
-rw-r--r--packages/connect/CHANGELOG.md8
-rw-r--r--packages/connect/package.json16
-rw-r--r--packages/contract-wrappers/CHANGELOG.json18
-rw-r--r--packages/contract-wrappers/CHANGELOG.md8
-rw-r--r--packages/contract-wrappers/package.json30
-rw-r--r--packages/dev-tools-pages/package.json4
-rw-r--r--packages/dev-utils/CHANGELOG.json18
-rw-r--r--packages/dev-utils/CHANGELOG.md8
-rw-r--r--packages/dev-utils/package.json16
-rw-r--r--packages/ethereum-types/CHANGELOG.json18
-rw-r--r--packages/ethereum-types/CHANGELOG.md8
-rw-r--r--packages/ethereum-types/package.json4
-rw-r--r--packages/fill-scenarios/CHANGELOG.json18
-rw-r--r--packages/fill-scenarios/CHANGELOG.md8
-rw-r--r--packages/fill-scenarios/package.json20
-rw-r--r--packages/instant/README.md6
-rw-r--r--packages/instant/package.json29
-rw-r--r--packages/instant/src/components/erc20_token_selector.tsx13
-rw-r--r--packages/instant/src/components/instant_heading.tsx34
-rw-r--r--packages/instant/src/components/order_details.tsx265
-rw-r--r--packages/instant/src/components/payment_method.tsx11
-rw-r--r--packages/instant/src/components/scaling_amount_input.tsx1
-rw-r--r--packages/instant/src/components/scaling_input.tsx93
-rw-r--r--packages/instant/src/components/section_header.tsx20
-rw-r--r--packages/instant/src/components/ui/input.tsx6
-rw-r--r--packages/instant/src/components/zero_ex_instant_provider.tsx2
-rw-r--r--packages/instant/src/constants.ts1
-rw-r--r--packages/instant/src/containers/connected_account_payment_method.ts2
-rw-r--r--packages/instant/src/containers/latest_buy_quote_order_details.ts33
-rw-r--r--packages/instant/src/redux/actions.ts4
-rw-r--r--packages/instant/src/redux/analytics_middleware.ts3
-rw-r--r--packages/instant/src/redux/async_data.ts5
-rw-r--r--packages/instant/src/redux/reducer.ts8
-rw-r--r--packages/instant/src/types.ts6
-rw-r--r--packages/instant/src/util/analytics.ts11
-rw-r--r--packages/instant/src/util/asset.ts3
-rw-r--r--packages/instant/src/util/env.ts7
-rw-r--r--packages/instant/src/util/format.ts30
-rw-r--r--packages/instant/src/util/provider_state_factory.ts33
-rw-r--r--packages/instant/test/util/format.test.ts18
-rw-r--r--packages/json-schemas/CHANGELOG.json18
-rw-r--r--packages/json-schemas/CHANGELOG.md8
-rw-r--r--packages/json-schemas/package.json8
-rw-r--r--packages/metacoin/package.json26
-rw-r--r--packages/migrations/CHANGELOG.json18
-rw-r--r--packages/migrations/CHANGELOG.md8
-rw-r--r--packages/migrations/package.json26
-rw-r--r--packages/monorepo-scripts/package.json2
-rw-r--r--packages/monorepo-scripts/src/test_installation.ts2
-rw-r--r--packages/order-utils/CHANGELOG.json28
-rw-r--r--packages/order-utils/CHANGELOG.md12
-rw-r--r--packages/order-utils/package.json24
-rw-r--r--packages/order-utils/src/signature_utils.ts2
-rw-r--r--packages/order-utils/test/order_hash_test.ts2
-rw-r--r--packages/order-watcher/CHANGELOG.json18
-rw-r--r--packages/order-watcher/CHANGELOG.md8
-rw-r--r--packages/order-watcher/package.json32
-rw-r--r--packages/pipeline/migrations/1544131464368-CreateERC20ApprovalEvents.ts26
-rw-r--r--packages/pipeline/migrations/1544131658904-TokenOrderbookSnapshotAddOrderType.ts33
-rw-r--r--packages/pipeline/package.json21
-rw-r--r--packages/pipeline/src/data_sources/bloxy/index.ts2
-rw-r--r--packages/pipeline/src/data_sources/contract-wrappers/erc20_events.ts45
-rw-r--r--packages/pipeline/src/data_sources/contract-wrappers/exchange_events.ts76
-rw-r--r--packages/pipeline/src/data_sources/contract-wrappers/utils.ts67
-rw-r--r--packages/pipeline/src/data_sources/idex/index.ts82
-rw-r--r--packages/pipeline/src/data_sources/oasis/index.ts103
-rw-r--r--packages/pipeline/src/data_sources/ohlcv_external/crypto_compare.ts32
-rw-r--r--packages/pipeline/src/data_sources/paradex/index.ts6
-rw-r--r--packages/pipeline/src/entities/erc20_approval_event.ts26
-rw-r--r--packages/pipeline/src/entities/index.ts1
-rw-r--r--packages/pipeline/src/entities/token_order.ts10
-rw-r--r--packages/pipeline/src/ormconfig.ts2
-rw-r--r--packages/pipeline/src/parsers/ddex_orders/index.ts32
-rw-r--r--packages/pipeline/src/parsers/events/erc20_events.ts34
-rw-r--r--packages/pipeline/src/parsers/events/exchange_events.ts133
-rw-r--r--packages/pipeline/src/parsers/events/index.ts135
-rw-r--r--packages/pipeline/src/parsers/idex_orders/index.ts77
-rw-r--r--packages/pipeline/src/parsers/oasis_orders/index.ts71
-rw-r--r--packages/pipeline/src/parsers/paradex_orders/index.ts4
-rw-r--r--packages/pipeline/src/parsers/token_metadata/index.ts7
-rw-r--r--packages/pipeline/src/parsers/utils.ts28
-rw-r--r--packages/pipeline/src/scripts/pull_competing_dex_trades.ts4
-rw-r--r--packages/pipeline/src/scripts/pull_ddex_orderbook_snapshots.ts4
-rw-r--r--packages/pipeline/src/scripts/pull_erc20_events.ts96
-rw-r--r--packages/pipeline/src/scripts/pull_exchange_events.ts (renamed from packages/pipeline/src/scripts/pull_missing_events.ts)28
-rw-r--r--packages/pipeline/src/scripts/pull_idex_orderbook_snapshots.ts63
-rw-r--r--packages/pipeline/src/scripts/pull_missing_blocks.ts37
-rw-r--r--packages/pipeline/src/scripts/pull_oasis_orderbook_snapshots.ts58
-rw-r--r--packages/pipeline/src/scripts/pull_ohlcv_cryptocompare.ts6
-rw-r--r--packages/pipeline/src/scripts/pull_paradex_orderbook_snapshots.ts4
-rw-r--r--packages/pipeline/src/scripts/pull_trusted_tokens.ts8
-rw-r--r--packages/pipeline/src/scripts/update_relayer_info.ts4
-rw-r--r--packages/pipeline/src/utils/get_ohlcv_trading_pairs.ts44
-rw-r--r--packages/pipeline/src/utils/index.ts15
-rw-r--r--packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts109
-rw-r--r--packages/pipeline/test/data_sources/ohlcv_external/crypto_compare_test.ts4
-rw-r--r--packages/pipeline/test/entities/erc20_approval_events_test.ts29
-rw-r--r--packages/pipeline/test/parsers/bloxy/index_test.ts1
-rw-r--r--packages/pipeline/test/parsers/ddex_orders/index_test.ts29
-rw-r--r--packages/pipeline/test/parsers/events/erc20_events_test.ts54
-rw-r--r--packages/pipeline/test/parsers/events/exchange_events_test.ts (renamed from packages/pipeline/test/parsers/events/index_test.ts)2
-rw-r--r--packages/pipeline/test/parsers/idex_orders/index_test.ts87
-rw-r--r--packages/pipeline/test/parsers/oasis_orders/index_test.ts49
-rw-r--r--packages/pipeline/test/parsers/paradex_orders/index_test.ts4
-rw-r--r--packages/pipeline/test/parsers/utils/index_test.ts30
-rw-r--r--packages/react-docs/CHANGELOG.json18
-rw-r--r--packages/react-docs/CHANGELOG.md8
-rw-r--r--packages/react-docs/package.json12
-rw-r--r--packages/react-shared/CHANGELOG.json18
-rw-r--r--packages/react-shared/CHANGELOG.md8
-rw-r--r--packages/react-shared/package.json8
-rw-r--r--packages/sol-compiler/CHANGELOG.json12
-rw-r--r--packages/sol-compiler/CHANGELOG.md8
-rw-r--r--packages/sol-compiler/package.json22
-rw-r--r--packages/sol-compiler/src/compiler.ts2
-rw-r--r--packages/sol-cov/CHANGELOG.json18
-rw-r--r--packages/sol-cov/CHANGELOG.md8
-rw-r--r--packages/sol-cov/package.json18
-rw-r--r--packages/sol-doc/CHANGELOG.json18
-rw-r--r--packages/sol-doc/CHANGELOG.md8
-rw-r--r--packages/sol-doc/package.json12
-rw-r--r--packages/sol-resolver/CHANGELOG.json12
-rw-r--r--packages/sol-resolver/CHANGELOG.md8
-rw-r--r--packages/sol-resolver/package.json8
-rw-r--r--packages/sra-spec/CHANGELOG.json18
-rw-r--r--packages/sra-spec/CHANGELOG.md8
-rw-r--r--packages/sra-spec/package.json6
-rw-r--r--packages/subproviders/CHANGELOG.json18
-rw-r--r--packages/subproviders/CHANGELOG.md8
-rw-r--r--packages/subproviders/package.json16
-rw-r--r--packages/testnet-faucets/package.json16
-rw-r--r--packages/tslint-config/CHANGELOG.json10
-rw-r--r--packages/tslint-config/CHANGELOG.md4
-rw-r--r--packages/tslint-config/package.json2
-rw-r--r--packages/tslint-config/rules/walkers/async_suffix.ts39
-rw-r--r--packages/tslint-config/tslint.json1
-rw-r--r--packages/types/CHANGELOG.json12
-rw-r--r--packages/types/CHANGELOG.md9
-rw-r--r--packages/types/package.json6
-rw-r--r--packages/typescript-typings/CHANGELOG.json18
-rw-r--r--packages/typescript-typings/CHANGELOG.md8
-rw-r--r--packages/typescript-typings/package.json4
-rw-r--r--packages/utils/CHANGELOG.json13
-rw-r--r--packages/utils/CHANGELOG.md8
-rw-r--r--packages/utils/package.json12
-rw-r--r--packages/utils/src/abi_utils.ts4
-rw-r--r--packages/utils/test/abi_encoder/evm_data_types_test.ts4
-rw-r--r--packages/web3-wrapper/CHANGELOG.json12
-rw-r--r--packages/web3-wrapper/CHANGELOG.md8
-rw-r--r--packages/web3-wrapper/package.json14
-rw-r--r--packages/website/package.json26
-rw-r--r--packages/website/public/images/developers/tutorials/integrate_0x_instant.svg3
-rw-r--r--packages/website/translations/english.json3
-rw-r--r--packages/website/ts/components/documentation/sidebar_header.tsx16
-rw-r--r--packages/website/ts/containers/order_watcher_documentation.ts2
-rw-r--r--packages/website/ts/pages/documentation/docs_home.tsx8
-rw-r--r--packages/website/ts/types.ts2
176 files changed, 2943 insertions, 805 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json
index 4ee1e92be..32351ad82 100644
--- a/packages/0x.js/CHANGELOG.json
+++ b/packages/0x.js/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.0.8",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.0.7",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "2.0.6",
"changes": [
diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md
index 463ff923d..2923fdf03 100644
--- a/packages/0x.js/CHANGELOG.md
+++ b/packages/0x.js/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.0.8 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.0.7 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.0.6 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json
index aa038c302..2960c9e4b 100644
--- a/packages/0x.js/package.json
+++ b/packages/0x.js/package.json
@@ -1,6 +1,6 @@
{
"name": "0x.js",
- "version": "2.0.6",
+ "version": "2.0.8",
"engines": {
"node": ">=6.12"
},
@@ -42,11 +42,11 @@
},
"license": "Apache-2.0",
"devDependencies": {
- "@0x/abi-gen-wrappers": "^2.0.0",
+ "@0x/abi-gen-wrappers": "^2.0.2",
"@0x/contract-addresses": "^2.0.0",
- "@0x/dev-utils": "^1.0.19",
- "@0x/migrations": "^2.2.0",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/migrations": "^2.2.2",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "*",
@@ -72,18 +72,18 @@
"webpack": "^4.20.2"
},
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/base-contract": "^3.0.8",
- "@0x/contract-wrappers": "^4.1.1",
- "@0x/order-utils": "^3.0.4",
- "@0x/order-watcher": "^2.2.6",
- "@0x/subproviders": "^2.1.6",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/assert": "^1.0.20",
+ "@0x/base-contract": "^3.0.10",
+ "@0x/contract-wrappers": "^4.1.3",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/order-watcher": "^2.2.8",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/web3-provider-engine": "^14.0.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethers": "~4.0.4",
"lodash": "^4.17.5",
"web3-provider-engine": "14.0.6"
diff --git a/packages/abi-gen-wrappers/CHANGELOG.json b/packages/abi-gen-wrappers/CHANGELOG.json
index 6905a7537..d46e828f4 100644
--- a/packages/abi-gen-wrappers/CHANGELOG.json
+++ b/packages/abi-gen-wrappers/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.0.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.0.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"version": "2.0.0",
"changes": [
{
diff --git a/packages/abi-gen-wrappers/CHANGELOG.md b/packages/abi-gen-wrappers/CHANGELOG.md
index 30a10d6bd..c13c7a60f 100644
--- a/packages/abi-gen-wrappers/CHANGELOG.md
+++ b/packages/abi-gen-wrappers/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.0.2 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.0.1 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.0.0 - _November 28, 2018_
* Update Exchange artifact to receive ZRX asset data as a constructor argument (#1309)
diff --git a/packages/abi-gen-wrappers/package.json b/packages/abi-gen-wrappers/package.json
index e4f103cf7..25ba3a6e0 100644
--- a/packages/abi-gen-wrappers/package.json
+++ b/packages/abi-gen-wrappers/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/abi-gen-wrappers",
- "version": "2.0.0",
+ "version": "2.0.2",
"engines": {
"node": ">=6.12"
},
@@ -30,19 +30,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md",
"devDependencies": {
- "@0x/abi-gen": "^1.0.17",
+ "@0x/abi-gen": "^1.0.19",
"@0x/abi-gen-templates": "^1.0.1",
- "@0x/tslint-config": "^1.0.10",
- "@0x/types": "^1.3.0",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
- "ethereum-types": "^1.1.2",
+ "@0x/tslint-config": "^2.0.0",
+ "@0x/types": "^1.4.1",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
+ "ethereum-types": "^1.1.4",
"ethers": "~4.0.4",
"lodash": "^4.17.5",
"shx": "^0.2.2"
},
"dependencies": {
- "@0x/base-contract": "^3.0.8"
+ "@0x/base-contract": "^3.0.10"
},
"publishConfig": {
"access": "public"
diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json
index 2b4455bed..253fb124d 100644
--- a/packages/abi-gen/CHANGELOG.json
+++ b/packages/abi-gen/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.19",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.18",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1542821676,
"version": "1.0.17",
"changes": [
diff --git a/packages/abi-gen/CHANGELOG.md b/packages/abi-gen/CHANGELOG.md
index f939199fd..4ca19ad7e 100644
--- a/packages/abi-gen/CHANGELOG.md
+++ b/packages/abi-gen/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.19 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.18 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.17 - _November 21, 2018_
* Dependencies updated
diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json
index 485e72730..b122c742d 100644
--- a/packages/abi-gen/package.json
+++ b/packages/abi-gen/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/abi-gen",
- "version": "1.0.17",
+ "version": "1.0.19",
"engines": {
"node": ">=6.12"
},
@@ -31,10 +31,10 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
"chalk": "^2.3.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.5",
@@ -45,7 +45,7 @@
"yargs": "^10.0.3"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/glob": "5.0.35",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
diff --git a/packages/assert/CHANGELOG.json b/packages/assert/CHANGELOG.json
index 2b3fc68a4..3805a044f 100644
--- a/packages/assert/CHANGELOG.json
+++ b/packages/assert/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.20",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.19",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1542821676,
"version": "1.0.18",
"changes": [
diff --git a/packages/assert/CHANGELOG.md b/packages/assert/CHANGELOG.md
index 017b1c6ef..ef84c48d4 100644
--- a/packages/assert/CHANGELOG.md
+++ b/packages/assert/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.20 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.19 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.18 - _November 21, 2018_
* Dependencies updated
diff --git a/packages/assert/package.json b/packages/assert/package.json
index 90b07ae76..cec1748cd 100644
--- a/packages/assert/package.json
+++ b/packages/assert/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/assert",
- "version": "1.0.18",
+ "version": "1.0.20",
"engines": {
"node": ">=6.12"
},
@@ -29,7 +29,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
@@ -44,9 +44,9 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/json-schemas": "^2.1.2",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
"lodash": "^4.17.5",
"valid-url": "^1.0.9"
},
diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json
index 4ff83018e..470d9b03b 100644
--- a/packages/asset-buyer/CHANGELOG.json
+++ b/packages/asset-buyer/CHANGELOG.json
@@ -1,11 +1,21 @@
[
{
+ "version": "3.0.4",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "3.0.3",
"changes": [
{
"note": "Update SRA order provider to include Dai"
}
- ]
+ ],
+ "timestamp": 1544570656
},
{
"timestamp": 1543401373,
diff --git a/packages/asset-buyer/CHANGELOG.md b/packages/asset-buyer/CHANGELOG.md
index be3ef67d1..cadb1acf8 100644
--- a/packages/asset-buyer/CHANGELOG.md
+++ b/packages/asset-buyer/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v3.0.4 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v3.0.3 - _December 11, 2018_
+
+ * Update SRA order provider to include Dai
+
## v3.0.2 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/asset-buyer/package.json b/packages/asset-buyer/package.json
index 780b2e3e2..401aec120 100644
--- a/packages/asset-buyer/package.json
+++ b/packages/asset-buyer/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/asset-buyer",
- "version": "3.0.2",
+ "version": "3.0.4",
"engines": {
"node": ">=6.12"
},
@@ -36,21 +36,21 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/connect": "^3.0.8",
- "@0x/contract-wrappers": "^4.1.1",
- "@0x/json-schemas": "^2.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/subproviders": "^2.1.6",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
- "ethereum-types": "^1.1.2",
+ "@0x/assert": "^1.0.20",
+ "@0x/connect": "^3.0.10",
+ "@0x/contract-wrappers": "^4.1.3",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
+ "ethereum-types": "^1.1.4",
"lodash": "^4.17.5"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "^4.14.116",
"@types/mocha": "^2.2.42",
"@types/node": "*",
diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json
index e4dff5530..a4cd17d42 100644
--- a/packages/base-contract/CHANGELOG.json
+++ b/packages/base-contract/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "3.0.10",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "3.0.9",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "3.0.8",
"changes": [
diff --git a/packages/base-contract/CHANGELOG.md b/packages/base-contract/CHANGELOG.md
index f61b6c6ce..a8ce346d7 100644
--- a/packages/base-contract/CHANGELOG.md
+++ b/packages/base-contract/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v3.0.10 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v3.0.9 - _December 11, 2018_
+
+ * Dependencies updated
+
## v3.0.8 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json
index 2a331b3cb..87d70dd5f 100644
--- a/packages/base-contract/package.json
+++ b/packages/base-contract/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/base-contract",
- "version": "3.0.8",
+ "version": "3.0.10",
"engines": {
"node": ">=6.12"
},
@@ -29,7 +29,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
"make-promises-safe": "^1.1.0",
@@ -40,10 +40,10 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
- "ethereum-types": "^1.1.2",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
+ "ethereum-types": "^1.1.4",
"ethers": "~4.0.4",
"lodash": "^4.17.5"
},
diff --git a/packages/connect/CHANGELOG.json b/packages/connect/CHANGELOG.json
index 3abb895a7..e5bde40ae 100644
--- a/packages/connect/CHANGELOG.json
+++ b/packages/connect/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "3.0.10",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "3.0.9",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "3.0.8",
"changes": [
diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md
index 1dfc2672d..a5f95b988 100644
--- a/packages/connect/CHANGELOG.md
+++ b/packages/connect/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v3.0.10 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v3.0.9 - _December 11, 2018_
+
+ * Dependencies updated
+
## v3.0.8 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/connect/package.json b/packages/connect/package.json
index 2f3d30d84..4985d0410 100644
--- a/packages/connect/package.json
+++ b/packages/connect/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/connect",
- "version": "3.0.8",
+ "version": "3.0.10",
"engines": {
"node": ">=6.12"
},
@@ -44,12 +44,12 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/json-schemas": "^2.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
+ "@0x/assert": "^1.0.20",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
"lodash": "^4.17.5",
"query-string": "^5.0.1",
"sinon": "^4.0.0",
@@ -57,7 +57,7 @@
"websocket": "^1.0.25"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/fetch-mock": "^6.0.3",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json
index 006a0904d..9475e5a88 100644
--- a/packages/contract-wrappers/CHANGELOG.json
+++ b/packages/contract-wrappers/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "4.1.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "4.1.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "4.1.1",
"changes": [
diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md
index ebdcc9638..595fbcc31 100644
--- a/packages/contract-wrappers/CHANGELOG.md
+++ b/packages/contract-wrappers/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v4.1.3 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v4.1.2 - _December 11, 2018_
+
+ * Dependencies updated
+
## v4.1.1 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json
index e11d1a63e..f3f7301fd 100644
--- a/packages/contract-wrappers/package.json
+++ b/packages/contract-wrappers/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/contract-wrappers",
- "version": "4.1.1",
+ "version": "4.1.3",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -37,10 +37,10 @@
"node": ">=6.0.0"
},
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/migrations": "^2.2.0",
- "@0x/subproviders": "^2.1.6",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/migrations": "^2.2.2",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "*",
@@ -65,18 +65,18 @@
"web3-provider-engine": "14.0.6"
},
"dependencies": {
- "@0x/abi-gen-wrappers": "^2.0.0",
- "@0x/assert": "^1.0.18",
+ "@0x/abi-gen-wrappers": "^2.0.2",
+ "@0x/assert": "^1.0.20",
"@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.2",
- "@0x/fill-scenarios": "^1.0.14",
- "@0x/json-schemas": "^2.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
- "ethereum-types": "^1.1.2",
+ "@0x/fill-scenarios": "^1.0.16",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
+ "ethereum-types": "^1.1.4",
"ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1",
"ethers": "~4.0.4",
diff --git a/packages/dev-tools-pages/package.json b/packages/dev-tools-pages/package.json
index 4b13beb01..754db3208 100644
--- a/packages/dev-tools-pages/package.json
+++ b/packages/dev-tools-pages/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/dev-tools-pages",
- "version": "0.0.8",
+ "version": "0.0.10",
"engines": {
"node": ">=6.12"
},
@@ -16,7 +16,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@0x/react-shared": "^1.0.23",
+ "@0x/react-shared": "^1.0.25",
"basscss": "^8.0.3",
"bowser": "^1.9.3",
"less": "^2.7.2",
diff --git a/packages/dev-utils/CHANGELOG.json b/packages/dev-utils/CHANGELOG.json
index 417a3c65e..b6cc74ce7 100644
--- a/packages/dev-utils/CHANGELOG.json
+++ b/packages/dev-utils/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.21",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.20",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "1.0.19",
"changes": [
diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md
index 1842c6824..9a55e4e58 100644
--- a/packages/dev-utils/CHANGELOG.md
+++ b/packages/dev-utils/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.21 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.20 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.19 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json
index a3b5c9090..a3eb4651a 100644
--- a/packages/dev-utils/package.json
+++ b/packages/dev-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/dev-utils",
- "version": "1.0.19",
+ "version": "1.0.21",
"engines": {
"node": ">=6.12"
},
@@ -29,7 +29,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/dev-utils/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"make-promises-safe": "^1.1.0",
@@ -41,14 +41,14 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/subproviders": "^2.1.6",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/web3-provider-engine": "^14.0.0",
"chai": "^4.0.1",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/ethereum-types/CHANGELOG.json b/packages/ethereum-types/CHANGELOG.json
index 9db75ae9f..9a0f2ad49 100644
--- a/packages/ethereum-types/CHANGELOG.json
+++ b/packages/ethereum-types/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.1.4",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.1.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"version": "1.1.2",
"changes": [
{
diff --git a/packages/ethereum-types/CHANGELOG.md b/packages/ethereum-types/CHANGELOG.md
index 6ad7b4cc6..1d27757f3 100644
--- a/packages/ethereum-types/CHANGELOG.md
+++ b/packages/ethereum-types/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.1.4 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.1.3 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.1.2 - _November 9, 2018_
* Dependencies updated
diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json
index 1630344db..69ae64c2b 100644
--- a/packages/ethereum-types/package.json
+++ b/packages/ethereum-types/package.json
@@ -1,6 +1,6 @@
{
"name": "ethereum-types",
- "version": "1.1.2",
+ "version": "1.1.4",
"engines": {
"node": ">=6.12"
},
@@ -29,7 +29,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/ethereum-types/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.11.0",
diff --git a/packages/fill-scenarios/CHANGELOG.json b/packages/fill-scenarios/CHANGELOG.json
index 58ba49509..ca256399a 100644
--- a/packages/fill-scenarios/CHANGELOG.json
+++ b/packages/fill-scenarios/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.16",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.15",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "1.0.14",
"changes": [
diff --git a/packages/fill-scenarios/CHANGELOG.md b/packages/fill-scenarios/CHANGELOG.md
index aa7df302e..e9b88547d 100644
--- a/packages/fill-scenarios/CHANGELOG.md
+++ b/packages/fill-scenarios/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.16 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.15 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.14 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json
index b29eb674c..7a9d21e0a 100644
--- a/packages/fill-scenarios/package.json
+++ b/packages/fill-scenarios/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/fill-scenarios",
- "version": "1.0.14",
+ "version": "1.0.16",
"description": "0x order fill scenario generator",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -20,7 +20,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/fill-scenarios/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/lodash": "4.14.104",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
@@ -28,15 +28,15 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/abi-gen-wrappers": "^2.0.0",
- "@0x/base-contract": "^3.0.8",
+ "@0x/abi-gen-wrappers": "^2.0.2",
+ "@0x/base-contract": "^3.0.10",
"@0x/contract-artifacts": "^1.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
- "ethereum-types": "^1.1.2",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
+ "ethereum-types": "^1.1.4",
"ethers": "~4.0.4",
"lodash": "^4.17.5"
},
diff --git a/packages/instant/README.md b/packages/instant/README.md
index 2092b45d9..32abf76e0 100644
--- a/packages/instant/README.md
+++ b/packages/instant/README.md
@@ -1,5 +1,11 @@
## @0x/instant
+## Integration
+
+Looking to integrate 0x Instant into your web application or site? Check out the dedicated [instant documentation](https://0xproject.com/wiki#Get-Started-With-Instant) to get started. The documentation covers instant and related topics in depth. For a more "drag and drop" experience, check out our [configurator tool](https://0xproject.com/instant#configure). For on demand developer support, join our [Discord](https://discordapp.com/invite/d3FTX3M).
+
+Check out a live sample integration [here](https://www.rexrelay.com/instant).
+
## Installation
The package is available as a UMD module named `zeroExInstant` at https://instant.0xproject.com/instant.js.
diff --git a/packages/instant/package.json b/packages/instant/package.json
index 9303276b4..0a5e152ca 100644
--- a/packages/instant/package.json
+++ b/packages/instant/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/instant",
- "version": "1.0.2",
+ "version": "1.0.4",
"engines": {
"node": ">=6.12"
},
@@ -24,7 +24,10 @@
},
"config": {
"postpublish": {
- "assets": ["packages/instant/umd/instant.js", "packages/instant/umd/instant.js.map"]
+ "assets": [
+ "packages/instant/umd/instant.js",
+ "packages/instant/umd/instant.js.map"
+ ]
}
},
"repository": {
@@ -38,18 +41,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/asset-buyer": "^3.0.2",
- "@0x/json-schemas": "^2.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/subproviders": "^2.1.6",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/assert": "^1.0.20",
+ "@0x/asset-buyer": "^3.0.4",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"bowser": "^1.9.4",
"copy-to-clipboard": "^3.0.8",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"lodash": "^4.17.5",
"polished": "^2.2.0",
"react": "^16.5.2",
@@ -62,7 +65,7 @@
"ts-optchain": "^0.1.1"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@static/discharge": "https://github.com/0xProject/discharge.git",
"@types/enzyme": "^3.1.14",
"@types/enzyme-adapter-react-16": "^1.0.3",
diff --git a/packages/instant/src/components/erc20_token_selector.tsx b/packages/instant/src/components/erc20_token_selector.tsx
index f7d5a4fe4..cb8a8c797 100644
--- a/packages/instant/src/components/erc20_token_selector.tsx
+++ b/packages/instant/src/components/erc20_token_selector.tsx
@@ -7,7 +7,6 @@ import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
import { SearchInput } from './search_input';
-
import { Circle } from './ui/circle';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
@@ -123,10 +122,20 @@ interface TokenSelectorRowIconProps {
token: ERC20Asset;
}
+const getTokenIcon = (symbol: string): React.StatelessComponent | undefined => {
+ try {
+ return require(`../assets/icons/${symbol}.svg`) as React.StatelessComponent;
+ } catch (e) {
+ // Can't find icon
+ return undefined;
+ }
+};
+
const TokenSelectorRowIcon: React.StatelessComponent<TokenSelectorRowIconProps> = props => {
const { token } = props;
const iconUrlIfExists = token.metaData.iconUrl;
- const TokenIcon = require(`../assets/icons/${token.metaData.symbol}.svg`);
+
+ const TokenIcon = getTokenIcon(token.metaData.symbol);
const displaySymbol = assetUtils.bestNameForAsset(token);
if (!_.isUndefined(iconUrlIfExists)) {
return <img src={iconUrlIfExists} />;
diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx
index 117f9dd5f..5b1f9592d 100644
--- a/packages/instant/src/components/instant_heading.tsx
+++ b/packages/instant/src/components/instant_heading.tsx
@@ -61,12 +61,19 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
}
private _renderAmountsSection(): React.ReactNode {
- return (
- <Container>
- <Container marginBottom="5px">{this._renderPlaceholderOrAmount(this._renderEthAmount)}</Container>
- <Container opacity={0.7}>{this._renderPlaceholderOrAmount(this._renderDollarAmount)}</Container>
- </Container>
- );
+ if (
+ _.isUndefined(this.props.totalEthBaseUnitAmount) &&
+ this.props.quoteRequestState !== AsyncProcessState.Pending
+ ) {
+ return null;
+ } else {
+ return (
+ <Container>
+ <Container marginBottom="5px">{this._renderPlaceholderOrAmount(this._renderEthAmount)}</Container>
+ <Container opacity={0.7}>{this._renderPlaceholderOrAmount(this._renderDollarAmount)}</Container>
+ </Container>
+ );
+ }
}
private _renderIcon(): React.ReactNode {
@@ -106,20 +113,23 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
}
private readonly _renderEthAmount = (): React.ReactNode => {
+ const ethAmount = format.ethBaseUnitAmount(
+ this.props.totalEthBaseUnitAmount,
+ 4,
+ <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
+ );
+
+ const fontSize = _.isString(ethAmount) && ethAmount.length >= 13 ? '14px' : '16px';
return (
<Text
- fontSize="16px"
+ fontSize={fontSize}
textAlign="right"
width="100%"
fontColor={ColorOption.white}
fontWeight={500}
noWrap={true}
>
- {format.ethBaseUnitAmount(
- this.props.totalEthBaseUnitAmount,
- 4,
- <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
- )}
+ {ethAmount}
</Text>
);
};
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx
index a8e0e2513..9c10ef9e6 100644
--- a/packages/instant/src/components/order_details.tsx
+++ b/packages/instant/src/components/order_details.tsx
@@ -4,124 +4,227 @@ import * as _ from 'lodash';
import * as React from 'react';
import { oc } from 'ts-optchain';
-import { BIG_NUMBER_ZERO } from '../constants';
+import { BIG_NUMBER_ZERO, DEFAULT_UNKOWN_ASSET_NAME } from '../constants';
import { ColorOption } from '../style/theme';
+import { BaseCurrency } from '../types';
import { format } from '../util/format';
import { AmountPlaceholder } from './amount_placeholder';
+import { SectionHeader } from './section_header';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
-import { Text } from './ui/text';
+import { Text, TextProps } from './ui/text';
export interface OrderDetailsProps {
buyQuoteInfo?: BuyQuoteInfo;
selectedAssetUnitAmount?: BigNumber;
ethUsdPrice?: BigNumber;
isLoading: boolean;
+ assetName?: string;
+ baseCurrency: BaseCurrency;
+ onBaseCurrencySwitchEth: () => void;
+ onBaseCurrencySwitchUsd: () => void;
}
export class OrderDetails extends React.Component<OrderDetailsProps> {
public render(): React.ReactNode {
- const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props;
- const buyQuoteAccessor = oc(buyQuoteInfo);
- const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount();
- const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount();
- const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount();
- const pricePerTokenEth =
- !_.isUndefined(assetEthBaseUnitAmount) &&
- !_.isUndefined(selectedAssetUnitAmount) &&
- !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
- ? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil()
- : undefined;
+ const shouldShowUsdError = this.props.baseCurrency === BaseCurrency.USD && this._hadErrorFetchingUsdPrice();
return (
<Container width="100%" flexGrow={1} padding="20px 20px 0px 20px">
- <Container marginBottom="10px">
- <Text
- letterSpacing="1px"
- fontColor={ColorOption.primaryColor}
- fontWeight={600}
- textTransform="uppercase"
- fontSize="14px"
- >
- Order Details
- </Text>
- </Container>
- <EthAmountRow
- rowLabel="Token Price"
- ethAmount={pricePerTokenEth}
- ethUsdPrice={ethUsdPrice}
- isLoading={this.props.isLoading}
+ <Container marginBottom="10px">{this._renderHeader()}</Container>
+ {shouldShowUsdError ? this._renderErrorFetchingUsdPrice() : this._renderRows()}
+ </Container>
+ );
+ }
+
+ private _renderRows(): React.ReactNode {
+ const { buyQuoteInfo } = this.props;
+ return (
+ <React.Fragment>
+ <OrderDetailsRow
+ labelText={this._assetAmountLabel()}
+ primaryValue={this._displayAmountOrPlaceholder(buyQuoteInfo && buyQuoteInfo.assetEthAmount)}
/>
- <EthAmountRow
- rowLabel="Fee"
- ethAmount={feeEthBaseUnitAmount}
- ethUsdPrice={ethUsdPrice}
- isLoading={this.props.isLoading}
+ <OrderDetailsRow
+ labelText="Fee"
+ primaryValue={this._displayAmountOrPlaceholder(buyQuoteInfo && buyQuoteInfo.feeEthAmount)}
/>
- <EthAmountRow
- rowLabel="Total Cost"
- ethAmount={totalEthBaseUnitAmount}
- ethUsdPrice={ethUsdPrice}
- shouldEmphasize={true}
- isLoading={this.props.isLoading}
+ <OrderDetailsRow
+ labelText="Total Cost"
+ isLabelBold={true}
+ primaryValue={this._displayAmountOrPlaceholder(buyQuoteInfo && buyQuoteInfo.totalEthAmount)}
+ isPrimaryValueBold={true}
+ secondaryValue={this._totalCostSecondaryValue()}
/>
- </Container>
+ </React.Fragment>
);
}
-}
-export interface EthAmountRowProps {
- rowLabel: string;
- ethAmount?: BigNumber;
- isEthAmountInBaseUnits?: boolean;
- ethUsdPrice?: BigNumber;
- shouldEmphasize?: boolean;
- isLoading: boolean;
+ private _renderErrorFetchingUsdPrice(): React.ReactNode {
+ return (
+ <Text>
+ There was an error fetching the USD price.
+ <Text
+ onClick={this.props.onBaseCurrencySwitchEth}
+ fontWeight={700}
+ fontColor={ColorOption.primaryColor}
+ >
+ Click here
+ </Text>
+ {' to view ETH prices'}
+ </Text>
+ );
+ }
+
+ private _hadErrorFetchingUsdPrice(): boolean {
+ return this.props.ethUsdPrice ? this.props.ethUsdPrice.equals(BIG_NUMBER_ZERO) : false;
+ }
+
+ private _totalCostSecondaryValue(): React.ReactNode {
+ const secondaryCurrency = this.props.baseCurrency === BaseCurrency.USD ? BaseCurrency.ETH : BaseCurrency.USD;
+
+ const canDisplayCurrency =
+ secondaryCurrency === BaseCurrency.ETH ||
+ (secondaryCurrency === BaseCurrency.USD && this.props.ethUsdPrice && !this._hadErrorFetchingUsdPrice());
+
+ if (this.props.buyQuoteInfo && canDisplayCurrency) {
+ return this._displayAmount(secondaryCurrency, this.props.buyQuoteInfo.totalEthAmount);
+ } else {
+ return undefined;
+ }
+ }
+
+ private _displayAmountOrPlaceholder(weiAmount?: BigNumber): React.ReactNode {
+ const { baseCurrency, isLoading } = this.props;
+
+ if (_.isUndefined(weiAmount)) {
+ return (
+ <Container opacity={0.5}>
+ <AmountPlaceholder color={ColorOption.lightGrey} isPulsating={isLoading} />
+ </Container>
+ );
+ }
+
+ return this._displayAmount(baseCurrency, weiAmount);
+ }
+
+ private _displayAmount(currency: BaseCurrency, weiAmount: BigNumber): React.ReactNode {
+ switch (currency) {
+ case BaseCurrency.USD:
+ return format.ethBaseUnitAmountInUsd(weiAmount, this.props.ethUsdPrice, 2, '');
+ case BaseCurrency.ETH:
+ return format.ethBaseUnitAmount(weiAmount, 4, '');
+ }
+ }
+
+ private _assetAmountLabel(): React.ReactNode {
+ const { assetName, baseCurrency } = this.props;
+ const numTokens = this.props.selectedAssetUnitAmount;
+
+ // Display as 0 if we have a selected asset
+ const displayNumTokens =
+ assetName && assetName !== DEFAULT_UNKOWN_ASSET_NAME && _.isUndefined(numTokens)
+ ? new BigNumber(0)
+ : numTokens;
+ if (!_.isUndefined(displayNumTokens)) {
+ let numTokensWithSymbol: React.ReactNode = displayNumTokens.toString();
+ if (assetName) {
+ numTokensWithSymbol += ` ${assetName}`;
+ }
+ const pricePerTokenWei = this._pricePerTokenWei();
+ if (pricePerTokenWei) {
+ const atPriceDisplay = (
+ <Text fontColor={ColorOption.lightGrey}>
+ @ {this._displayAmount(baseCurrency, pricePerTokenWei)}
+ </Text>
+ );
+ numTokensWithSymbol = (
+ <React.Fragment>
+ {numTokensWithSymbol} {atPriceDisplay}
+ </React.Fragment>
+ );
+ }
+ return numTokensWithSymbol;
+ }
+ return 'Token Amount';
+ }
+
+ private _pricePerTokenWei(): BigNumber | undefined {
+ const buyQuoteAccessor = oc(this.props.buyQuoteInfo);
+ const assetTotalInWei = buyQuoteAccessor.assetEthAmount();
+ const selectedAssetUnitAmount = this.props.selectedAssetUnitAmount;
+ return !_.isUndefined(assetTotalInWei) &&
+ !_.isUndefined(selectedAssetUnitAmount) &&
+ !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
+ ? assetTotalInWei.div(selectedAssetUnitAmount).ceil()
+ : undefined;
+ }
+
+ private _baseCurrencyChoice(choice: BaseCurrency): React.ReactNode {
+ const onClick =
+ choice === BaseCurrency.ETH ? this.props.onBaseCurrencySwitchEth : this.props.onBaseCurrencySwitchUsd;
+ const isSelected = this.props.baseCurrency === choice;
+
+ const textStyle: TextProps = { onClick, fontSize: '12px' };
+ if (isSelected) {
+ textStyle.fontColor = ColorOption.primaryColor;
+ textStyle.fontWeight = 700;
+ } else {
+ textStyle.fontColor = ColorOption.lightGrey;
+ }
+ return <Text {...textStyle}>{choice}</Text>;
+ }
+
+ private _renderHeader(): React.ReactNode {
+ return (
+ <Flex justify="space-between">
+ <SectionHeader>Order Details</SectionHeader>
+ <Container>
+ {this._baseCurrencyChoice(BaseCurrency.ETH)}
+ <Container marginLeft="5px" marginRight="5px" display="inline">
+ <Text fontSize="12px" fontColor={ColorOption.feintGrey}>
+ /
+ </Text>
+ </Container>
+ {this._baseCurrencyChoice(BaseCurrency.USD)}
+ </Container>
+ </Flex>
+ );
+ }
}
-export class EthAmountRow extends React.Component<EthAmountRowProps> {
- public static defaultProps = {
- shouldEmphasize: false,
- isEthAmountInBaseUnits: true,
- };
+export interface OrderDetailsRowProps {
+ labelText: React.ReactNode;
+ isLabelBold?: boolean;
+ isPrimaryValueBold?: boolean;
+ primaryValue: React.ReactNode;
+ secondaryValue?: React.ReactNode;
+}
+export class OrderDetailsRow extends React.Component<OrderDetailsRowProps, {}> {
public render(): React.ReactNode {
- const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
-
- const fontWeight = shouldEmphasize ? 700 : 400;
- const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseUnitAmount : format.ethUnitAmount;
return (
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
<Flex justify="space-between">
- <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
- {rowLabel}
+ <Text fontWeight={this.props.isLabelBold ? 700 : 400} fontColor={ColorOption.grey}>
+ {this.props.labelText}
</Text>
- <Container>
- {this._renderUsdSection()}
- <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
- {ethFormatter(
- ethAmount,
- 4,
- <Container opacity={0.5}>
- <AmountPlaceholder color={ColorOption.lightGrey} isPulsating={isLoading} />
- </Container>,
- )}
- </Text>
- </Container>
+ <Container>{this._renderValues()}</Container>
</Flex>
</Container>
);
}
- private _renderUsdSection(): React.ReactNode {
- const usdFormatter = this.props.isEthAmountInBaseUnits
- ? format.ethBaseUnitAmountInUsd
- : format.ethUnitAmountInUsd;
- const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount);
- return shouldHideUsdPriceSection ? null : (
+
+ private _renderValues(): React.ReactNode {
+ const secondaryValueNode: React.ReactNode = this.props.secondaryValue && (
<Container marginRight="3px" display="inline-block">
- <Text fontColor={ColorOption.lightGrey}>
- ({usdFormatter(this.props.ethAmount, this.props.ethUsdPrice)})
- </Text>
+ <Text fontColor={ColorOption.lightGrey}>({this.props.secondaryValue})</Text>
</Container>
);
+ return (
+ <React.Fragment>
+ {secondaryValueNode}
+ <Text fontWeight={this.props.isPrimaryValueBold ? 700 : 400}>{this.props.primaryValue}</Text>
+ </React.Fragment>
+ );
}
}
diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx
index 7c93f1d1c..abadf4bd6 100644
--- a/packages/instant/src/components/payment_method.tsx
+++ b/packages/instant/src/components/payment_method.tsx
@@ -8,6 +8,7 @@ import { envUtil } from '../util/env';
import { CoinbaseWalletLogo } from './coinbase_wallet_logo';
import { MetaMaskLogo } from './meta_mask_logo';
import { PaymentMethodDropdown } from './payment_method_dropdown';
+import { SectionHeader } from './section_header';
import { Circle } from './ui/circle';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
@@ -29,15 +30,7 @@ export class PaymentMethod extends React.Component<PaymentMethodProps> {
<Container width="100%" height="120px" padding="20px 20px 0px 20px">
<Container marginBottom="12px">
<Flex justify="space-between">
- <Text
- letterSpacing="1px"
- fontColor={ColorOption.primaryColor}
- fontWeight={600}
- textTransform="uppercase"
- fontSize="14px"
- >
- {this._renderTitleText()}
- </Text>
+ <SectionHeader>{this._renderTitleText()}</SectionHeader>
{this._renderTitleLabel()}
</Flex>
</Container>
diff --git a/packages/instant/src/components/scaling_amount_input.tsx b/packages/instant/src/components/scaling_amount_input.tsx
index 86aca5a65..4feb0502d 100644
--- a/packages/instant/src/components/scaling_amount_input.tsx
+++ b/packages/instant/src/components/scaling_amount_input.tsx
@@ -58,6 +58,7 @@ export class ScalingAmountInput extends React.Component<ScalingAmountInputProps,
const { textLengthThreshold, fontColor, maxFontSizePx, onFontSizeChange } = this.props;
return (
<ScalingInput
+ type="number"
maxFontSizePx={maxFontSizePx}
textLengthThreshold={textLengthThreshold}
onFontSizeChange={onFontSizeChange}
diff --git a/packages/instant/src/components/scaling_input.tsx b/packages/instant/src/components/scaling_input.tsx
index 791692257..00aea37da 100644
--- a/packages/instant/src/components/scaling_input.tsx
+++ b/packages/instant/src/components/scaling_input.tsx
@@ -1,3 +1,4 @@
+import { ObjectMap } from '@0x/types';
import * as _ from 'lodash';
import * as React from 'react';
@@ -13,10 +14,15 @@ export enum ScalingInputPhase {
export interface ScalingSettings {
percentageToReduceFontSizePerCharacter: number;
- constantPxToIncreaseWidthPerCharacter: number;
+ // 1ch = the width of the 0 chararacter.
+ // Allow to customize 'char' length for different characters.
+ characterWidthOverrides: ObjectMap<number>;
+ // How much room to leave to the right of the scaling input.
+ additionalInputSpaceInCh: number;
}
export interface ScalingInputProps {
+ type?: string;
textLengthThreshold: number;
maxFontSizePx: number;
value: string;
@@ -31,32 +37,29 @@ export interface ScalingInputProps {
hasAutofocus: boolean;
}
-export interface ScalingInputState {
- inputWidthPxAtPhaseChange?: number;
-}
-
export interface ScalingInputSnapshot {
inputWidthPx: number;
}
// These are magic numbers that were determined experimentally.
const defaultScalingSettings: ScalingSettings = {
- percentageToReduceFontSizePerCharacter: 0.125,
- constantPxToIncreaseWidthPerCharacter: 4,
+ percentageToReduceFontSizePerCharacter: 0.1,
+ characterWidthOverrides: {
+ '1': 0.7,
+ '.': 0.4,
+ },
+ additionalInputSpaceInCh: 0.4,
};
-export class ScalingInput extends React.Component<ScalingInputProps, ScalingInputState> {
+export class ScalingInput extends React.Component<ScalingInputProps> {
public static defaultProps = {
onChange: util.boundNoop,
onFontSizeChange: util.boundNoop,
- maxLength: 7,
+ maxLength: 9,
scalingSettings: defaultScalingSettings,
isDisabled: false,
hasAutofocus: false,
};
- public state: ScalingInputState = {
- inputWidthPxAtPhaseChange: undefined,
- };
private readonly _inputRef = React.createRef<HTMLInputElement>();
public static getPhase(textLengthThreshold: number, value: string): ScalingInputPhase {
if (value.length <= textLengthThreshold) {
@@ -93,36 +96,15 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
scalingSettings.percentageToReduceFontSizePerCharacter,
);
}
- public getSnapshotBeforeUpdate(): ScalingInputSnapshot {
- return {
- inputWidthPx: this._getInputWidthInPx(),
- };
- }
public componentDidMount(): void {
// Trigger an initial notification of the calculated fontSize.
const currentPhase = ScalingInput.getPhaseFromProps(this.props);
const currentFontSize = ScalingInput.calculateFontSizeFromProps(this.props, currentPhase);
this.props.onFontSizeChange(currentFontSize);
}
- public componentDidUpdate(
- prevProps: ScalingInputProps,
- prevState: ScalingInputState,
- snapshot: ScalingInputSnapshot,
- ): void {
+ public componentDidUpdate(prevProps: ScalingInputProps): void {
const prevPhase = ScalingInput.getPhaseFromProps(prevProps);
const curPhase = ScalingInput.getPhaseFromProps(this.props);
- // if we went from fixed to scaling, save the width from the transition
- if (prevPhase !== ScalingInputPhase.ScalingFontSize && curPhase === ScalingInputPhase.ScalingFontSize) {
- this.setState({
- inputWidthPxAtPhaseChange: snapshot.inputWidthPx,
- });
- }
- // if we went from scaling to fixed, revert back to scaling using `ch`
- if (prevPhase === ScalingInputPhase.ScalingFontSize && curPhase !== ScalingInputPhase.ScalingFontSize) {
- this.setState({
- inputWidthPxAtPhaseChange: undefined,
- });
- }
const prevFontSize = ScalingInput.calculateFontSizeFromProps(prevProps, prevPhase);
const curFontSize = ScalingInput.calculateFontSizeFromProps(this.props, curPhase);
// If font size has changed, notify.
@@ -131,13 +113,14 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
}
}
public render(): React.ReactNode {
- const { hasAutofocus, isDisabled, fontColor, onChange, placeholder, value, maxLength } = this.props;
+ const { type, hasAutofocus, isDisabled, fontColor, placeholder, value, maxLength } = this.props;
const phase = ScalingInput.getPhaseFromProps(this.props);
return (
<Input
+ type={type}
ref={this._inputRef as any}
fontColor={fontColor}
- onChange={onChange}
+ onChange={this._handleChange}
value={value}
placeholder={placeholder}
fontSize={`${this._calculateFontSize(phase)}px`}
@@ -149,32 +132,34 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
);
}
private readonly _calculateWidth = (phase: ScalingInputPhase): string => {
- const { value, textLengthThreshold, scalingSettings } = this.props;
+ const { value, scalingSettings } = this.props;
if (_.isEmpty(value)) {
return `${this.props.emptyInputWidthCh}ch`;
}
- switch (phase) {
- case ScalingInputPhase.FixedFontSize:
- return `${value.length}ch`;
- case ScalingInputPhase.ScalingFontSize:
- const { inputWidthPxAtPhaseChange } = this.state;
- if (!_.isUndefined(inputWidthPxAtPhaseChange)) {
- const charactersOverMax = value.length - textLengthThreshold;
- const scalingAmount = scalingSettings.constantPxToIncreaseWidthPerCharacter * charactersOverMax;
- const width = inputWidthPxAtPhaseChange + scalingAmount;
- return `${width}px`;
+ const lengthInCh = _.reduce(
+ value.split(''),
+ (sum, char) => {
+ const widthOverride = scalingSettings.characterWidthOverrides[char];
+ if (!_.isUndefined(widthOverride)) {
+ // tslint is confused
+ // tslint:disable-next-line:restrict-plus-operands
+ return sum + widthOverride;
}
- return `${textLengthThreshold}ch`;
- }
+ return sum + 1;
+ },
+ scalingSettings.additionalInputSpaceInCh,
+ );
+ return `${lengthInCh}ch`;
};
private readonly _calculateFontSize = (phase: ScalingInputPhase): number => {
return ScalingInput.calculateFontSizeFromProps(this.props, phase);
};
- private readonly _getInputWidthInPx = (): number => {
- const ref = this._inputRef.current;
- if (!ref) {
- return 0;
+ private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
+ const value = event.target.value;
+ const { maxLength } = this.props;
+ if (!_.isUndefined(value) && !_.isUndefined(maxLength) && value.length > maxLength) {
+ return;
}
- return ref.getBoundingClientRect().width;
+ this.props.onChange(event);
};
}
diff --git a/packages/instant/src/components/section_header.tsx b/packages/instant/src/components/section_header.tsx
new file mode 100644
index 000000000..d0974ebdc
--- /dev/null
+++ b/packages/instant/src/components/section_header.tsx
@@ -0,0 +1,20 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Text } from './ui/text';
+
+export interface SectionHeaderProps {}
+export const SectionHeader: React.StatelessComponent<SectionHeaderProps> = props => {
+ return (
+ <Text
+ letterSpacing="1px"
+ fontColor={ColorOption.primaryColor}
+ fontWeight={600}
+ textTransform="uppercase"
+ fontSize="12px"
+ >
+ {props.children}
+ </Text>
+ );
+};
diff --git a/packages/instant/src/components/ui/input.tsx b/packages/instant/src/components/ui/input.tsx
index 62c70f9e1..53c43ea0b 100644
--- a/packages/instant/src/components/ui/input.tsx
+++ b/packages/instant/src/components/ui/input.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { ColorOption, styled } from '../../style/theme';
-export interface InputProps {
+export interface InputProps extends React.HTMLAttributes<HTMLInputElement> {
tabIndex?: number;
className?: string;
value?: string;
@@ -32,6 +32,10 @@ export const Input =
color: ${props => props.theme[props.fontColor || 'white']} !important;
opacity: 0.5 !important;
}
+ &::-webkit-outer-spin-button, &::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
}
`;
diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx
index 7ae27de23..2de327cd7 100644
--- a/packages/instant/src/components/zero_ex_instant_provider.tsx
+++ b/packages/instant/src/components/zero_ex_instant_provider.tsx
@@ -38,6 +38,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
props.orderSource,
networkId,
props.provider,
+ props.walletDisplayName,
);
// merge the additional additionalAssetMetaDataMap with our default map
const completeAssetMetaDataMap = {
@@ -121,6 +122,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
window,
state.selectedAsset,
this.props.affiliateInfo,
+ state.baseCurrency,
),
);
analytics.trackInstantOpened();
diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts
index f83eb4ac7..975dfcbea 100644
--- a/packages/instant/src/constants.ts
+++ b/packages/instant/src/constants.ts
@@ -17,6 +17,7 @@ export const ONE_MINUTE_MS = ONE_SECOND_MS * 60;
export const GIT_SHA = process.env.GIT_SHA;
export const NODE_ENV = process.env.NODE_ENV;
export const NPM_PACKAGE_VERSION = process.env.NPM_PACKAGE_VERSION;
+export const DEFAULT_UNKOWN_ASSET_NAME = '???';
export const ACCOUNT_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 5;
export const BUY_QUOTE_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 15;
export const DEFAULT_GAS_PRICE = GWEI_IN_WEI.mul(6);
diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts
index bb68fdd57..f648f0b54 100644
--- a/packages/instant/src/containers/connected_account_payment_method.ts
+++ b/packages/instant/src/containers/connected_account_payment_method.ts
@@ -58,7 +58,7 @@ const mergeProps = (
...ownProps,
network: connectedState.network,
account: connectedState.providerState.account,
- walletDisplayName: connectedState.walletDisplayName || connectedState.providerState.name,
+ walletDisplayName: connectedState.providerState.displayName,
onUnlockWalletClick: () => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState),
onInstallWalletClick: () => {
const isMobile = envUtil.isMobileOperatingSystem();
diff --git a/packages/instant/src/containers/latest_buy_quote_order_details.ts b/packages/instant/src/containers/latest_buy_quote_order_details.ts
index 5dfe535e7..148735c47 100644
--- a/packages/instant/src/containers/latest_buy_quote_order_details.ts
+++ b/packages/instant/src/containers/latest_buy_quote_order_details.ts
@@ -1,32 +1,41 @@
-import { BuyQuoteInfo } from '@0x/asset-buyer';
-import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
import { oc } from 'ts-optchain';
+import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer';
-import { OrderDetails } from '../components/order_details';
-import { AsyncProcessState } from '../types';
+import { OrderDetails, OrderDetailsProps } from '../components/order_details';
+import { AsyncProcessState, BaseCurrency, Omit } from '../types';
+import { assetUtils } from '../util/asset';
-export interface LatestBuyQuoteOrderDetailsProps {}
-
-interface ConnectedState {
- buyQuoteInfo?: BuyQuoteInfo;
- selectedAssetUnitAmount?: BigNumber;
- ethUsdPrice?: BigNumber;
- isLoading: boolean;
-}
+type DispatchProperties = 'onBaseCurrencySwitchEth' | 'onBaseCurrencySwitchUsd';
+interface ConnectedState extends Omit<OrderDetailsProps, DispatchProperties> {}
const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({
// use the worst case quote info
buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(),
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
ethUsdPrice: state.ethUsdPrice,
isLoading: state.quoteRequestState === AsyncProcessState.Pending,
+ assetName: assetUtils.bestNameForAsset(state.selectedAsset),
+ baseCurrency: state.baseCurrency,
});
+interface ConnectedDispatch extends Pick<OrderDetailsProps, DispatchProperties> {}
+const mapDispatchToProps = (dispatch: Dispatch<Action>): ConnectedDispatch => ({
+ onBaseCurrencySwitchEth: () => {
+ dispatch(actions.updateBaseCurrency(BaseCurrency.ETH));
+ },
+ onBaseCurrencySwitchUsd: () => {
+ dispatch(actions.updateBaseCurrency(BaseCurrency.USD));
+ },
+});
+
+export interface LatestBuyQuoteOrderDetailsProps {}
export const LatestBuyQuoteOrderDetails: React.ComponentClass<LatestBuyQuoteOrderDetailsProps> = connect(
mapStateToProps,
+ mapDispatchToProps,
)(OrderDetails);
diff --git a/packages/instant/src/redux/actions.ts b/packages/instant/src/redux/actions.ts
index 77e3dec12..9d7a61fc7 100644
--- a/packages/instant/src/redux/actions.ts
+++ b/packages/instant/src/redux/actions.ts
@@ -2,7 +2,7 @@ import { BuyQuote } from '@0x/asset-buyer';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
-import { ActionsUnion, AddressAndEthBalanceInWei, Asset, StandardSlidingPanelContent } from '../types';
+import { ActionsUnion, AddressAndEthBalanceInWei, Asset, BaseCurrency, StandardSlidingPanelContent } from '../types';
export interface PlainAction<T extends string> {
type: T;
@@ -43,6 +43,7 @@ export enum ActionTypes {
RESET_AMOUNT = 'RESET_AMOUNT',
OPEN_STANDARD_SLIDING_PANEL = 'OPEN_STANDARD_SLIDING_PANEL',
CLOSE_STANDARD_SLIDING_PANEL = 'CLOSE_STANDARD_SLIDING_PANEL',
+ UPDATE_BASE_CURRENCY = 'UPDATE_BASE_CURRENCY',
}
export const actions = {
@@ -72,4 +73,5 @@ export const actions = {
openStandardSlidingPanel: (content: StandardSlidingPanelContent) =>
createAction(ActionTypes.OPEN_STANDARD_SLIDING_PANEL, content),
closeStandardSlidingPanel: () => createAction(ActionTypes.CLOSE_STANDARD_SLIDING_PANEL),
+ updateBaseCurrency: (baseCurrency: BaseCurrency) => createAction(ActionTypes.UPDATE_BASE_CURRENCY, baseCurrency),
};
diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts
index 3f7a51707..a86a16b1a 100644
--- a/packages/instant/src/redux/analytics_middleware.ts
+++ b/packages/instant/src/redux/analytics_middleware.ts
@@ -99,6 +99,9 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction
analytics.trackInstallWalletModalClosed();
}
break;
+ case ActionTypes.UPDATE_BASE_CURRENCY:
+ analytics.trackBaseCurrencyChanged(curState.baseCurrency);
+ analytics.addEventProperties({ baseCurrency: curState.baseCurrency });
}
return nextAction;
diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts
index c67b222d1..884ab103d 100644
--- a/packages/instant/src/redux/async_data.ts
+++ b/packages/instant/src/redux/async_data.ts
@@ -4,7 +4,7 @@ import * as _ from 'lodash';
import { Dispatch } from 'redux';
import { BIG_NUMBER_ZERO } from '../constants';
-import { AccountState, ERC20Asset, OrderProcessState, ProviderState, QuoteFetchOrigin } from '../types';
+import { AccountState, BaseCurrency, ERC20Asset, OrderProcessState, ProviderState, QuoteFetchOrigin } from '../types';
import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
import { buyQuoteUpdater } from '../util/buy_quote_updater';
@@ -24,7 +24,9 @@ export const asyncData = {
const errorMessage = 'Error fetching ETH/USD price';
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
+ dispatch(actions.updateBaseCurrency(BaseCurrency.ETH));
errorReporter.report(e);
+ analytics.trackUsdPriceFailed();
}
},
fetchAvailableAssetDatasAndDispatchToStore: async (state: State, dispatch: Dispatch) => {
@@ -97,6 +99,7 @@ export const asyncData = {
if (
!_.isUndefined(selectedAssetUnitAmount) &&
!_.isUndefined(selectedAsset) &&
+ selectedAssetUnitAmount.greaterThan(BIG_NUMBER_ZERO) &&
buyOrderState.processState === OrderProcessState.None &&
selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20
) {
diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts
index a9a407b7d..8c13c9c72 100644
--- a/packages/instant/src/redux/reducer.ts
+++ b/packages/instant/src/redux/reducer.ts
@@ -14,6 +14,7 @@ import {
Asset,
AssetMetaData,
AsyncProcessState,
+ BaseCurrency,
DisplayStatus,
Network,
OrderProcessState,
@@ -33,6 +34,7 @@ export interface DefaultState {
latestErrorDisplayStatus: DisplayStatus;
quoteRequestState: AsyncProcessState;
standardSlidingPanelSettings: StandardSlidingPanelSettings;
+ baseCurrency: BaseCurrency;
}
// State that is required but needs to be derived from the props
@@ -64,6 +66,7 @@ export const DEFAULT_STATE: DefaultState = {
animationState: 'none',
content: StandardSlidingPanelContent.None,
},
+ baseCurrency: BaseCurrency.USD,
};
export const createReducer = (initialState: State) => {
@@ -243,6 +246,11 @@ export const createReducer = (initialState: State) => {
animationState: 'slidOut',
},
};
+ case ActionTypes.UPDATE_BASE_CURRENCY:
+ return {
+ ...state,
+ baseCurrency: action.data,
+ };
default:
return state;
}
diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts
index e65961e95..e7c920f36 100644
--- a/packages/instant/src/types.ts
+++ b/packages/instant/src/types.ts
@@ -26,6 +26,11 @@ export enum QuoteFetchOrigin {
Heartbeat = 'Heartbeat',
}
+export enum BaseCurrency {
+ USD = 'USD',
+ ETH = 'ETH',
+}
+
export interface SimulatedProgress {
startTimeUnix: number;
expectedEndTimeUnix: number;
@@ -102,6 +107,7 @@ export interface AffiliateInfo {
export interface ProviderState {
name: string;
+ displayName: string;
provider: Provider;
assetBuyer: AssetBuyer;
web3Wrapper: Web3Wrapper;
diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts
index 6da52db16..6c63907dc 100644
--- a/packages/instant/src/util/analytics.ts
+++ b/packages/instant/src/util/analytics.ts
@@ -6,6 +6,7 @@ import { GIT_SHA, HEAP_ENABLED, INSTANT_DISCHARGE_TARGET, NODE_ENV, NPM_PACKAGE_
import {
AffiliateInfo,
Asset,
+ BaseCurrency,
Network,
OrderProcessState,
OrderSource,
@@ -37,6 +38,7 @@ enum EventNames {
ACCOUNT_UNLOCK_REQUESTED = 'Account - Unlock Requested',
ACCOUNT_UNLOCK_DENIED = 'Account - Unlock Denied',
ACCOUNT_ADDRESS_CHANGED = 'Account - Address Changed',
+ BASE_CURRENCY_CHANGED = 'Base Currency - Changed',
PAYMENT_METHOD_DROPDOWN_OPENED = 'Payment Method - Dropdown Opened',
PAYMENT_METHOD_OPENED_ETHERSCAN = 'Payment Method - Opened Etherscan',
PAYMENT_METHOD_COPIED_ADDRESS = 'Payment Method - Copied Address',
@@ -47,6 +49,7 @@ enum EventNames {
BUY_TX_SUBMITTED = 'Buy - Tx Submitted',
BUY_TX_SUCCEEDED = 'Buy - Tx Succeeded',
BUY_TX_FAILED = 'Buy - Tx Failed',
+ USD_PRICE_FETCH_FAILED = 'USD Price - Fetch Failed',
INSTALL_WALLET_CLICKED = 'Install Wallet - Clicked',
INSTALL_WALLET_MODAL_OPENED = 'Install Wallet - Modal - Opened',
INSTALL_WALLET_MODAL_CLICKED_EXPLANATION = 'Install Wallet - Modal - Clicked Explanation',
@@ -106,6 +109,7 @@ export interface AnalyticsEventOptions {
ethAddress?: string;
networkId?: number;
providerName?: string;
+ providerDisplayName?: string;
gitSha?: string;
npmVersion?: string;
instantEnvironment?: string;
@@ -117,6 +121,7 @@ export interface AnalyticsEventOptions {
selectedAssetSymbol?: string;
selectedAssetData?: string;
selectedAssetDecimals?: number;
+ baseCurrency?: string;
}
export enum TokenSelectorClosedVia {
ClickedX = 'Clicked X',
@@ -140,6 +145,7 @@ export const analytics = {
window: Window,
selectedAsset?: Asset,
affiliateInfo?: AffiliateInfo,
+ baseCurrency?: BaseCurrency,
): AnalyticsEventOptions => {
const affiliateAddress = affiliateInfo ? affiliateInfo.feeRecipient : 'none';
const affiliateFeePercent = affiliateInfo ? parseFloat(affiliateInfo.feePercentage.toFixed(4)) : 0;
@@ -149,6 +155,7 @@ export const analytics = {
embeddedUrl: window.location.href,
networkId: network,
providerName: providerState.name,
+ providerDisplayName: providerState.displayName,
gitSha: GIT_SHA,
npmVersion: NPM_PACKAGE_VERSION,
orderSource: orderSourceName,
@@ -157,6 +164,7 @@ export const analytics = {
selectedAssetName: selectedAsset ? selectedAsset.metaData.name : 'none',
selectedAssetData: selectedAsset ? selectedAsset.assetData : 'none',
instantEnvironment: INSTANT_DISCHARGE_TARGET || `Local ${NODE_ENV}`,
+ baseCurrency,
};
return eventOptions;
},
@@ -168,6 +176,8 @@ export const analytics = {
trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.ACCOUNT_UNLOCK_DENIED),
trackAccountAddressChanged: (address: string) =>
trackingEventFnWithPayload(EventNames.ACCOUNT_ADDRESS_CHANGED)({ address }),
+ trackBaseCurrencyChanged: (currencyChangedTo: BaseCurrency) =>
+ trackingEventFnWithPayload(EventNames.BASE_CURRENCY_CHANGED)({ currencyChangedTo }),
trackPaymentMethodDropdownOpened: trackingEventFnWithoutPayload(EventNames.PAYMENT_METHOD_DROPDOWN_OPENED),
trackPaymentMethodOpenedEtherscan: trackingEventFnWithoutPayload(EventNames.PAYMENT_METHOD_OPENED_ETHERSCAN),
trackPaymentMethodCopiedAddress: trackingEventFnWithoutPayload(EventNames.PAYMENT_METHOD_COPIED_ADDRESS),
@@ -228,4 +238,5 @@ export const analytics = {
fetchOrigin,
});
},
+ trackUsdPriceFailed: trackingEventFnWithoutPayload(EventNames.USD_PRICE_FETCH_FAILED),
};
diff --git a/packages/instant/src/util/asset.ts b/packages/instant/src/util/asset.ts
index 13f84ef74..faaeb7c22 100644
--- a/packages/instant/src/util/asset.ts
+++ b/packages/instant/src/util/asset.ts
@@ -2,6 +2,7 @@ import { AssetBuyerError } from '@0x/asset-buyer';
import { AssetProxyId, ObjectMap } from '@0x/types';
import * as _ from 'lodash';
+import { DEFAULT_UNKOWN_ASSET_NAME } from '../constants';
import { assetDataNetworkMapping } from '../data/asset_data_network_mapping';
import { Asset, AssetMetaData, ERC20Asset, Network, ZeroExInstantError } from '../types';
@@ -71,7 +72,7 @@ export const assetUtils = {
}
return metaData;
},
- bestNameForAsset: (asset?: Asset, defaultName: string = '???'): string => {
+ bestNameForAsset: (asset?: Asset, defaultName: string = DEFAULT_UNKOWN_ASSET_NAME): string => {
if (_.isUndefined(asset)) {
return defaultName;
}
diff --git a/packages/instant/src/util/env.ts b/packages/instant/src/util/env.ts
index 4a32f9cb1..0fda0cc0e 100644
--- a/packages/instant/src/util/env.ts
+++ b/packages/instant/src/util/env.ts
@@ -62,4 +62,11 @@ export const envUtil = {
}
return PROVIDER_TYPE_TO_NAME[providerTypeIfExists];
},
+ getProviderDisplayName(provider: Provider): string {
+ const providerTypeIfExists = envUtil.getProviderType(provider);
+ if (_.isUndefined(providerTypeIfExists)) {
+ return 'Wallet';
+ }
+ return PROVIDER_TYPE_TO_NAME[providerTypeIfExists];
+ },
};
diff --git a/packages/instant/src/util/format.ts b/packages/instant/src/util/format.ts
index e9c432b2f..4adb63e21 100644
--- a/packages/instant/src/util/format.ts
+++ b/packages/instant/src/util/format.ts
@@ -2,7 +2,7 @@ import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash';
-import { ETH_DECIMALS } from '../constants';
+import { BIG_NUMBER_ZERO, ETH_DECIMALS } from '../constants';
export const format = {
ethBaseUnitAmount: (
@@ -20,24 +20,38 @@ export const format = {
ethUnitAmount?: BigNumber,
decimalPlaces: number = 4,
defaultText: React.ReactNode = '0 ETH',
+ minUnitAmountToDisplay: BigNumber = new BigNumber('0.00001'),
): React.ReactNode => {
if (_.isUndefined(ethUnitAmount)) {
return defaultText;
}
- const roundedAmount = ethUnitAmount.round(decimalPlaces).toDigits(decimalPlaces);
- return `${roundedAmount} ETH`;
+ let roundedAmount = ethUnitAmount.round(decimalPlaces).toDigits(decimalPlaces);
+
+ if (roundedAmount.eq(BIG_NUMBER_ZERO) && ethUnitAmount.greaterThan(BIG_NUMBER_ZERO)) {
+ // Sometimes for small ETH amounts (i.e. 0.000045) the amount rounded to 4 decimalPlaces is 0
+ // If that is the case, show to 1 significant digit
+ roundedAmount = new BigNumber(ethUnitAmount.toPrecision(1));
+ }
+
+ const displayAmount =
+ roundedAmount.greaterThan(BIG_NUMBER_ZERO) && roundedAmount.lessThan(minUnitAmountToDisplay)
+ ? `< ${minUnitAmountToDisplay.toString()}`
+ : roundedAmount.toString();
+
+ return `${displayAmount} ETH`;
},
ethBaseUnitAmountInUsd: (
ethBaseUnitAmount?: BigNumber,
ethUsdPrice?: BigNumber,
decimalPlaces: number = 2,
defaultText: React.ReactNode = '$0.00',
+ minUnitAmountToDisplay: BigNumber = new BigNumber('0.00001'),
): React.ReactNode => {
if (_.isUndefined(ethBaseUnitAmount) || _.isUndefined(ethUsdPrice)) {
return defaultText;
}
const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS);
- return format.ethUnitAmountInUsd(ethUnitAmount, ethUsdPrice, decimalPlaces);
+ return format.ethUnitAmountInUsd(ethUnitAmount, ethUsdPrice, decimalPlaces, minUnitAmountToDisplay);
},
ethUnitAmountInUsd: (
ethUnitAmount?: BigNumber,
@@ -48,7 +62,13 @@ export const format = {
if (_.isUndefined(ethUnitAmount) || _.isUndefined(ethUsdPrice)) {
return defaultText;
}
- return `$${ethUnitAmount.mul(ethUsdPrice).toFixed(decimalPlaces)}`;
+ const rawUsdPrice = ethUnitAmount.mul(ethUsdPrice);
+ const roundedUsdPrice = rawUsdPrice.toFixed(decimalPlaces);
+ if (roundedUsdPrice === '0.00' && rawUsdPrice.gt(BIG_NUMBER_ZERO)) {
+ return '<$0.01';
+ } else {
+ return `$${roundedUsdPrice}`;
+ }
},
ethAddress: (address: string): string => {
return `0x${address.slice(2, 7)}…${address.slice(-5)}`;
diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts
index 7c788dff2..bd2d6dad5 100644
--- a/packages/instant/src/util/provider_state_factory.ts
+++ b/packages/instant/src/util/provider_state_factory.ts
@@ -10,27 +10,40 @@ import { assetBuyerFactory } from './asset_buyer_factory';
import { providerFactory } from './provider_factory';
export const providerStateFactory = {
- getInitialProviderState: (orderSource: OrderSource, network: Network, provider?: Provider): ProviderState => {
+ getInitialProviderState: (
+ orderSource: OrderSource,
+ network: Network,
+ provider?: Provider,
+ walletDisplayName?: string,
+ ): ProviderState => {
if (!_.isUndefined(provider)) {
- return providerStateFactory.getInitialProviderStateFromProvider(orderSource, network, provider);
+ return providerStateFactory.getInitialProviderStateFromProvider(
+ orderSource,
+ network,
+ provider,
+ walletDisplayName,
+ );
}
const providerStateFromWindowIfExits = providerStateFactory.getInitialProviderStateFromWindowIfExists(
orderSource,
network,
+ walletDisplayName,
);
if (providerStateFromWindowIfExits) {
return providerStateFromWindowIfExits;
} else {
- return providerStateFactory.getInitialProviderStateFallback(orderSource, network);
+ return providerStateFactory.getInitialProviderStateFallback(orderSource, network, walletDisplayName);
}
},
getInitialProviderStateFromProvider: (
orderSource: OrderSource,
network: Network,
provider: Provider,
+ walletDisplayName?: string,
): ProviderState => {
const providerState: ProviderState = {
name: envUtil.getProviderName(provider),
+ displayName: walletDisplayName || envUtil.getProviderDisplayName(provider),
provider,
web3Wrapper: new Web3Wrapper(provider),
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),
@@ -38,11 +51,16 @@ export const providerStateFactory = {
};
return providerState;
},
- getInitialProviderStateFromWindowIfExists: (orderSource: OrderSource, network: Network): Maybe<ProviderState> => {
+ getInitialProviderStateFromWindowIfExists: (
+ orderSource: OrderSource,
+ network: Network,
+ walletDisplayName?: string,
+ ): Maybe<ProviderState> => {
const injectedProviderIfExists = providerFactory.getInjectedProviderIfExists();
if (!_.isUndefined(injectedProviderIfExists)) {
const providerState: ProviderState = {
name: envUtil.getProviderName(injectedProviderIfExists),
+ displayName: walletDisplayName || envUtil.getProviderDisplayName(injectedProviderIfExists),
provider: injectedProviderIfExists,
web3Wrapper: new Web3Wrapper(injectedProviderIfExists),
assetBuyer: assetBuyerFactory.getAssetBuyer(injectedProviderIfExists, orderSource, network),
@@ -53,10 +71,15 @@ export const providerStateFactory = {
return undefined;
}
},
- getInitialProviderStateFallback: (orderSource: OrderSource, network: Network): ProviderState => {
+ getInitialProviderStateFallback: (
+ orderSource: OrderSource,
+ network: Network,
+ walletDisplayName?: string,
+ ): ProviderState => {
const provider = providerFactory.getFallbackNoSigningProvider(network);
const providerState: ProviderState = {
name: 'Fallback',
+ displayName: walletDisplayName || envUtil.getProviderDisplayName(provider),
provider,
web3Wrapper: new Web3Wrapper(provider),
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),
diff --git a/packages/instant/test/util/format.test.ts b/packages/instant/test/util/format.test.ts
index fe0a63e6e..38bf356ec 100644
--- a/packages/instant/test/util/format.test.ts
+++ b/packages/instant/test/util/format.test.ts
@@ -41,6 +41,18 @@ describe('format', () => {
it('converts BigNumber(5.3014059295032) to the string `5.301 ETH`', () => {
expect(format.ethUnitAmount(BIG_NUMBER_IRRATIONAL)).toBe('5.301 ETH');
});
+ it('shows 1 significant digit when rounded amount would be 0', () => {
+ expect(format.ethUnitAmount(new BigNumber(0.00003))).toBe('0.00003 ETH');
+ expect(format.ethUnitAmount(new BigNumber(0.000034))).toBe('0.00003 ETH');
+ expect(format.ethUnitAmount(new BigNumber(0.000035))).toBe('0.00004 ETH');
+ });
+ it('shows < 0.00001 when hits threshold', () => {
+ expect(format.ethUnitAmount(new BigNumber(0.000011))).toBe('0.00001 ETH');
+ expect(format.ethUnitAmount(new BigNumber(0.00001))).toBe('0.00001 ETH');
+ expect(format.ethUnitAmount(new BigNumber(0.000009))).toBe('< 0.00001 ETH');
+ expect(format.ethUnitAmount(new BigNumber(0.0000000009))).toBe('< 0.00001 ETH');
+ expect(format.ethUnitAmount(new BigNumber(0))).toBe('0 ETH');
+ });
it('returns defaultText param when ethUnitAmount is not defined', () => {
const defaultText = 'defaultText';
expect(format.ethUnitAmount(undefined, 4, defaultText)).toBe(defaultText);
@@ -86,6 +98,12 @@ describe('format', () => {
it('correctly formats 5.3014059295032 ETH to usd according to some price', () => {
expect(format.ethUnitAmountInUsd(BIG_NUMBER_IRRATIONAL, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$13.43');
});
+ it('correctly formats amount that is less than 1 cent', () => {
+ expect(format.ethUnitAmountInUsd(new BigNumber(0.000001), BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('<$0.01');
+ });
+ it('correctly formats exactly 1 cent', () => {
+ expect(format.ethUnitAmountInUsd(new BigNumber(0.0039), BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$0.01');
+ });
it('returns defaultText param when ethUnitAmountInUsd or ethUsdPrice is not defined', () => {
const defaultText = 'defaultText';
expect(format.ethUnitAmountInUsd(undefined, undefined, 2, defaultText)).toBe(defaultText);
diff --git a/packages/json-schemas/CHANGELOG.json b/packages/json-schemas/CHANGELOG.json
index 17cabc473..201190145 100644
--- a/packages/json-schemas/CHANGELOG.json
+++ b/packages/json-schemas/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.1.4",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.1.3",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1542821676,
"version": "2.1.2",
"changes": [
diff --git a/packages/json-schemas/CHANGELOG.md b/packages/json-schemas/CHANGELOG.md
index 2f39c9596..7e407bdda 100644
--- a/packages/json-schemas/CHANGELOG.md
+++ b/packages/json-schemas/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.1.4 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.1.3 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.1.2 - _November 21, 2018_
* Dependencies updated
diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json
index da3231b57..57dd9dc00 100644
--- a/packages/json-schemas/package.json
+++ b/packages/json-schemas/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/json-schemas",
- "version": "2.1.2",
+ "version": "2.1.4",
"engines": {
"node": ">=6.12"
},
@@ -39,14 +39,14 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/json-schemas/README.md",
"dependencies": {
- "@0x/typescript-typings": "^3.0.4",
+ "@0x/typescript-typings": "^3.0.6",
"@types/node": "*",
"jsonschema": "^1.2.0",
"lodash.values": "^4.3.0"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
- "@0x/utils": "^2.0.6",
+ "@0x/tslint-config": "^2.0.0",
+ "@0x/utils": "^2.0.8",
"@types/lodash.foreach": "^4.5.3",
"@types/lodash.values": "^4.3.3",
"@types/mocha": "^2.2.42",
diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json
index 7622fa5d4..0e9fa4920 100644
--- a/packages/metacoin/package.json
+++ b/packages/metacoin/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/metacoin",
- "version": "0.0.30",
+ "version": "0.0.32",
"engines": {
"node": ">=6.12"
},
@@ -29,26 +29,26 @@
"author": "",
"license": "Apache-2.0",
"dependencies": {
- "@0x/abi-gen": "^1.0.17",
+ "@0x/abi-gen": "^1.0.19",
"@0x/abi-gen-templates": "^1.0.1",
- "@0x/base-contract": "^3.0.8",
- "@0x/sol-cov": "^2.1.14",
- "@0x/subproviders": "^2.1.6",
- "@0x/tslint-config": "^1.0.10",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/base-contract": "^3.0.10",
+ "@0x/sol-cov": "^2.1.16",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/tslint-config": "^2.0.0",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/mocha": "^5.2.2",
"copyfiles": "^2.0.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethers": "~4.0.4",
"lodash": "^4.17.5",
"run-s": "^0.0.0"
},
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/sol-compiler": "^1.1.14",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/sol-compiler": "^1.1.16",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
diff --git a/packages/migrations/CHANGELOG.json b/packages/migrations/CHANGELOG.json
index 56705fc1a..e7b18f12b 100644
--- a/packages/migrations/CHANGELOG.json
+++ b/packages/migrations/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.2.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.2.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"version": "2.2.0",
"changes": [
{
diff --git a/packages/migrations/CHANGELOG.md b/packages/migrations/CHANGELOG.md
index 3808b2d3d..0b7b9a364 100644
--- a/packages/migrations/CHANGELOG.md
+++ b/packages/migrations/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.2.2 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.2.1 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.2.0 - _November 28, 2018_
* Add CLI `0x-migrate` for running the 0x migrations in a language-agnostic way (#1324)
diff --git a/packages/migrations/package.json b/packages/migrations/package.json
index f4dd1f9f9..72ffe67b2 100644
--- a/packages/migrations/package.json
+++ b/packages/migrations/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/migrations",
- "version": "2.2.0",
+ "version": "2.2.2",
"engines": {
"node": ">=6.12"
},
@@ -26,9 +26,9 @@
},
"license": "Apache-2.0",
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/tslint-config": "^1.0.10",
- "@0x/types": "^1.3.0",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/tslint-config": "^2.0.0",
+ "@0x/types": "^1.4.1",
"@types/yargs": "^10.0.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
@@ -39,18 +39,18 @@
"yargs": "^10.0.3"
},
"dependencies": {
- "@0x/abi-gen-wrappers": "^2.0.0",
- "@0x/base-contract": "^3.0.8",
+ "@0x/abi-gen-wrappers": "^2.0.2",
+ "@0x/base-contract": "^3.0.10",
"@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/sol-compiler": "^1.1.14",
- "@0x/subproviders": "^2.1.6",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/sol-compiler": "^1.1.16",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@ledgerhq/hw-app-eth": "^4.3.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethers": "~4.0.4",
"lodash": "^4.17.5"
},
diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json
index 9af18a6b7..0483e87c8 100644
--- a/packages/monorepo-scripts/package.json
+++ b/packages/monorepo-scripts/package.json
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@0x/monorepo-scripts",
- "version": "1.0.14",
+ "version": "1.0.15",
"engines": {
"node": ">=6.12"
},
diff --git a/packages/monorepo-scripts/src/test_installation.ts b/packages/monorepo-scripts/src/test_installation.ts
index 96875d0f9..5ae13b198 100644
--- a/packages/monorepo-scripts/src/test_installation.ts
+++ b/packages/monorepo-scripts/src/test_installation.ts
@@ -98,7 +98,7 @@ async function testInstallPackageAsync(
const lastChangelogVersion = JSON.parse(fs.readFileSync(changelogPath).toString())[0].version;
const packageName = installablePackage.packageJson.name;
utils.log(`Testing ${packageName}@${lastChangelogVersion}`);
- const packageDirName = path.join(...(packageName + '-test').split('/'));
+ const packageDirName = path.join(...`${packageName}-test`.split('/'));
// NOTE(fabio): The `testDirectory` needs to be somewhere **outside** the monorepo root directory.
// Otherwise, it will have access to the hoisted `node_modules` directory and the Typescript missing
// type errors will not be caught.
diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json
index 6c8fd6239..11889b92e 100644
--- a/packages/order-utils/CHANGELOG.json
+++ b/packages/order-utils/CHANGELOG.json
@@ -1,5 +1,33 @@
[
{
+ "version": "3.0.7",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "3.0.6",
+ "changes": [
+ {
+ "note": "Fix bug in wallet signature type verification",
+ "pr": 1414
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
+ "timestamp": 1544482891,
+ "version": "3.0.5",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
"timestamp": 1543401373,
"version": "3.0.4",
"changes": [
diff --git a/packages/order-utils/CHANGELOG.md b/packages/order-utils/CHANGELOG.md
index 5eae590b5..bc8b48767 100644
--- a/packages/order-utils/CHANGELOG.md
+++ b/packages/order-utils/CHANGELOG.md
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v3.0.7 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v3.0.6 - _December 11, 2018_
+
+ * Fix bug in wallet signature type verification (#1414)
+
+## v3.0.5 - _December 10, 2018_
+
+ * Dependencies updated
+
## v3.0.4 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json
index 50229dafb..400c9b66f 100644
--- a/packages/order-utils/package.json
+++ b/packages/order-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/order-utils",
- "version": "3.0.4",
+ "version": "3.0.7",
"engines": {
"node": ">=6.12"
},
@@ -35,8 +35,8 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md",
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/tslint-config": "^2.0.0",
"@types/bn.js": "^4.11.0",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
@@ -53,18 +53,18 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/abi-gen-wrappers": "^2.0.0",
- "@0x/assert": "^1.0.18",
- "@0x/base-contract": "^3.0.8",
+ "@0x/abi-gen-wrappers": "^2.0.2",
+ "@0x/assert": "^1.0.20",
+ "@0x/base-contract": "^3.0.10",
"@0x/contract-artifacts": "^1.1.2",
- "@0x/json-schemas": "^2.1.2",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/node": "*",
"bn.js": "^4.11.8",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
"ethers": "~4.0.4",
diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts
index 96d90e21a..131144d48 100644
--- a/packages/order-utils/src/signature_utils.ts
+++ b/packages/order-utils/src/signature_utils.ts
@@ -115,7 +115,7 @@ export const signatureUtils = {
assert.isHexString('signature', signature);
assert.isETHAddressHex('signerAddress', signerAddress);
// tslint:disable-next-line:custom-no-magic-numbers
- const signatureWithoutType = signature.slice(-2);
+ const signatureWithoutType = signature.slice(0, -2);
const walletContract = new IWalletContract(artifacts.IWallet.compilerOutput.abi, signerAddress, provider);
const isValid = await walletContract.isValidSignature.callAsync(data, signatureWithoutType);
return isValid;
diff --git a/packages/order-utils/test/order_hash_test.ts b/packages/order-utils/test/order_hash_test.ts
index a85d4c81a..30fb15a37 100644
--- a/packages/order-utils/test/order_hash_test.ts
+++ b/packages/order-utils/test/order_hash_test.ts
@@ -70,7 +70,7 @@ describe('Order hashing', () => {
});
it('returns true if order hash is correct', () => {
const orderHashLength = 65;
- const isValid = orderHashUtils.isValidOrderHash('0x' + Array(orderHashLength).join('0'));
+ const isValid = orderHashUtils.isValidOrderHash(`0x${Array(orderHashLength).join('0')}`);
expect(isValid).to.be.true();
});
});
diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json
index 4e56dc400..c1fd8d4a9 100644
--- a/packages/order-watcher/CHANGELOG.json
+++ b/packages/order-watcher/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.2.8",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.2.7",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "2.2.6",
"changes": [
diff --git a/packages/order-watcher/CHANGELOG.md b/packages/order-watcher/CHANGELOG.md
index 37b4a7438..4e49b4637 100644
--- a/packages/order-watcher/CHANGELOG.md
+++ b/packages/order-watcher/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.2.8 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.2.7 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.2.6 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json
index cfaf5d724..16a46294e 100644
--- a/packages/order-watcher/package.json
+++ b/packages/order-watcher/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/order-watcher",
- "version": "2.2.6",
+ "version": "2.2.8",
"description": "An order watcher daemon that watches for order validity",
"keywords": [
"0x",
@@ -33,9 +33,9 @@
"node": ">=6.0.0"
},
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/migrations": "^2.2.0",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/migrations": "^2.2.2",
+ "@0x/tslint-config": "^2.0.0",
"@types/bintrees": "^1.0.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
@@ -57,21 +57,21 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/abi-gen-wrappers": "^2.0.0",
- "@0x/assert": "^1.0.18",
- "@0x/base-contract": "^3.0.8",
+ "@0x/abi-gen-wrappers": "^2.0.2",
+ "@0x/assert": "^1.0.20",
+ "@0x/base-contract": "^3.0.10",
"@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.2",
- "@0x/contract-wrappers": "^4.1.1",
- "@0x/fill-scenarios": "^1.0.14",
- "@0x/json-schemas": "^2.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/contract-wrappers": "^4.1.3",
+ "@0x/fill-scenarios": "^1.0.16",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"bintrees": "^1.0.2",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-blockstream": "6.0.0",
"ethers": "~4.0.4",
"lodash": "^4.17.5",
diff --git a/packages/pipeline/migrations/1544131464368-CreateERC20ApprovalEvents.ts b/packages/pipeline/migrations/1544131464368-CreateERC20ApprovalEvents.ts
new file mode 100644
index 000000000..2e84e0ec8
--- /dev/null
+++ b/packages/pipeline/migrations/1544131464368-CreateERC20ApprovalEvents.ts
@@ -0,0 +1,26 @@
+import { MigrationInterface, QueryRunner, Table } from 'typeorm';
+
+const erc20ApprovalEvents = new Table({
+ name: 'raw.erc20_approval_events',
+ columns: [
+ { name: 'token_address', type: 'varchar(42)', isPrimary: true },
+ { name: 'log_index', type: 'integer', isPrimary: true },
+ { name: 'block_number', type: 'bigint', isPrimary: true },
+
+ { name: 'raw_data', type: 'varchar' },
+ { name: 'transaction_hash', type: 'varchar' },
+ { name: 'owner_address', type: 'varchar(42)' },
+ { name: 'spender_address', type: 'varchar(42)' },
+ { name: 'amount', type: 'numeric' },
+ ],
+});
+
+export class CreateERC20TokenApprovalEvents1544131464368 implements MigrationInterface {
+ public async up(queryRunner: QueryRunner): Promise<any> {
+ await queryRunner.createTable(erc20ApprovalEvents);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<any> {
+ await queryRunner.dropTable(erc20ApprovalEvents);
+ }
+}
diff --git a/packages/pipeline/migrations/1544131658904-TokenOrderbookSnapshotAddOrderType.ts b/packages/pipeline/migrations/1544131658904-TokenOrderbookSnapshotAddOrderType.ts
new file mode 100644
index 000000000..a501ec6d8
--- /dev/null
+++ b/packages/pipeline/migrations/1544131658904-TokenOrderbookSnapshotAddOrderType.ts
@@ -0,0 +1,33 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class TokenOrderbookSnapshotAddOrderType1544131658904 implements MigrationInterface {
+ public async up(queryRunner: QueryRunner): Promise<any> {
+ await queryRunner.query(
+ `ALTER TABLE raw.token_orderbook_snapshots
+ DROP CONSTRAINT "PK_8a16487e7cb6862ec5a84ed3495",
+ ADD PRIMARY KEY (observed_timestamp, source, order_type, price, base_asset_symbol, quote_asset_symbol);
+ `,
+ );
+ await queryRunner.query(
+ `ALTER TABLE raw.token_orderbook_snapshots
+ ALTER COLUMN quote_asset_address DROP NOT NULL,
+ ALTER COLUMN base_asset_address DROP NOT NULL;
+ `,
+ );
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<any> {
+ await queryRunner.query(
+ `ALTER TABLE raw.token_orderbook_snapshots
+ ALTER COLUMN quote_asset_address SET NOT NULL,
+ ALTER COLUMN base_asset_address SET NOT NULL;
+ `,
+ );
+ await queryRunner.query(
+ `ALTER TABLE raw.token_orderbook_snapshots
+ DROP CONSTRAINT token_orderbook_snapshots_pkey,
+ ADD CONSTRAINT "PK_8a16487e7cb6862ec5a84ed3495" PRIMARY KEY (observed_timestamp, source, price, base_asset_symbol, quote_asset_symbol);
+ `,
+ );
+ }
+}
diff --git a/packages/pipeline/package.json b/packages/pipeline/package.json
index 0539618d4..a40f3d21c 100644
--- a/packages/pipeline/package.json
+++ b/packages/pipeline/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/pipeline",
- "version": "1.0.0",
+ "version": "1.0.2",
"private": true,
"description": "Data pipeline for offline analysis",
"scripts": {
@@ -27,7 +27,7 @@
},
"license": "Apache-2.0",
"devDependencies": {
- "@0x/tslint-config": "^1.0.9",
+ "@0x/tslint-config": "^2.0.0",
"@types/axios": "^0.14.0",
"@types/ramda": "^0.25.38",
"chai": "^4.1.2",
@@ -39,22 +39,23 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/connect": "^3.0.2",
+ "@0x/connect": "^3.0.10",
+ "@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.0.1",
"@0x/contract-wrappers": "^3.0.0",
- "@0x/dev-utils": "^1.0.13",
+ "@0x/dev-utils": "^1.0.21",
"@0x/order-utils": "^2.0.0",
- "@0x/subproviders": "^2.1.0",
- "@0x/types": "^1.2.0",
- "@0x/utils": "^2.0.3",
- "@0x/web3-wrapper": "^3.1.0",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/types": "^1.4.1",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/dockerode": "^2.5.9",
"@types/p-limit": "^2.0.0",
"async-parallel": "^1.2.3",
"axios": "^0.18.0",
+ "bottleneck": "^2.13.2",
"dockerode": "^2.5.7",
- "ethereum-types": "^1.0.6",
- "p-limit": "^2.0.0",
+ "ethereum-types": "^1.1.4",
"pg": "^7.5.0",
"prettier": "^1.15.3",
"ramda": "^0.25.0",
diff --git a/packages/pipeline/src/data_sources/bloxy/index.ts b/packages/pipeline/src/data_sources/bloxy/index.ts
index 31cd5bfd6..94468d25a 100644
--- a/packages/pipeline/src/data_sources/bloxy/index.ts
+++ b/packages/pipeline/src/data_sources/bloxy/index.ts
@@ -116,7 +116,7 @@ export class BloxySource {
},
});
if (isError(resp.data)) {
- throw new Error('Error in Bloxy API response: ' + resp.data.error);
+ throw new Error(`Error in Bloxy API response: ${resp.data.error}`);
}
return resp.data;
}
diff --git a/packages/pipeline/src/data_sources/contract-wrappers/erc20_events.ts b/packages/pipeline/src/data_sources/contract-wrappers/erc20_events.ts
new file mode 100644
index 000000000..e0098122f
--- /dev/null
+++ b/packages/pipeline/src/data_sources/contract-wrappers/erc20_events.ts
@@ -0,0 +1,45 @@
+import {
+ ContractWrappers,
+ ERC20TokenApprovalEventArgs,
+ ERC20TokenEvents,
+ ERC20TokenWrapper,
+} from '@0x/contract-wrappers';
+import { Web3ProviderEngine } from '@0x/subproviders';
+import { LogWithDecodedArgs } from 'ethereum-types';
+
+import { GetEventsFunc, getEventsWithPaginationAsync } from './utils';
+
+export class ERC20EventsSource {
+ private readonly _erc20Wrapper: ERC20TokenWrapper;
+ private readonly _tokenAddress: string;
+ constructor(provider: Web3ProviderEngine, networkId: number, tokenAddress: string) {
+ const contractWrappers = new ContractWrappers(provider, { networkId });
+ this._erc20Wrapper = contractWrappers.erc20Token;
+ this._tokenAddress = tokenAddress;
+ }
+
+ public async getApprovalEventsAsync(
+ startBlock: number,
+ endBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<ERC20TokenApprovalEventArgs>>> {
+ return getEventsWithPaginationAsync(
+ this._getApprovalEventsForRangeAsync.bind(this) as GetEventsFunc<ERC20TokenApprovalEventArgs>,
+ startBlock,
+ endBlock,
+ );
+ }
+
+ // Gets all approval events of for a specific sub-range. This getter
+ // function will be called during each step of pagination.
+ private async _getApprovalEventsForRangeAsync(
+ fromBlock: number,
+ toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<ERC20TokenApprovalEventArgs>>> {
+ return this._erc20Wrapper.getLogsAsync<ERC20TokenApprovalEventArgs>(
+ this._tokenAddress,
+ ERC20TokenEvents.Approval,
+ { fromBlock, toBlock },
+ {},
+ );
+ }
+}
diff --git a/packages/pipeline/src/data_sources/contract-wrappers/exchange_events.ts b/packages/pipeline/src/data_sources/contract-wrappers/exchange_events.ts
index 1717eb8b3..58691e2ab 100644
--- a/packages/pipeline/src/data_sources/contract-wrappers/exchange_events.ts
+++ b/packages/pipeline/src/data_sources/contract-wrappers/exchange_events.ts
@@ -8,78 +8,52 @@ import {
ExchangeWrapper,
} from '@0x/contract-wrappers';
import { Web3ProviderEngine } from '@0x/subproviders';
-import { Web3Wrapper } from '@0x/web3-wrapper';
import { LogWithDecodedArgs } from 'ethereum-types';
-import { EXCHANGE_START_BLOCK } from '../../utils';
-
-const BLOCK_FINALITY_THRESHOLD = 10; // When to consider blocks as final. Used to compute default toBlock.
-const NUM_BLOCKS_PER_QUERY = 20000; // Number of blocks to query for events at a time.
+import { GetEventsFunc, getEventsWithPaginationAsync } from './utils';
export class ExchangeEventsSource {
private readonly _exchangeWrapper: ExchangeWrapper;
- private readonly _web3Wrapper: Web3Wrapper;
constructor(provider: Web3ProviderEngine, networkId: number) {
- this._web3Wrapper = new Web3Wrapper(provider);
const contractWrappers = new ContractWrappers(provider, { networkId });
this._exchangeWrapper = contractWrappers.exchange;
}
public async getFillEventsAsync(
- fromBlock?: number,
- toBlock?: number,
+ startBlock: number,
+ endBlock: number,
): Promise<Array<LogWithDecodedArgs<ExchangeFillEventArgs>>> {
- return this._getEventsAsync<ExchangeFillEventArgs>(ExchangeEvents.Fill, fromBlock, toBlock);
+ const getFillEventsForRangeAsync = this._makeGetterFuncForEventType<ExchangeFillEventArgs>(ExchangeEvents.Fill);
+ return getEventsWithPaginationAsync(getFillEventsForRangeAsync, startBlock, endBlock);
}
public async getCancelEventsAsync(
- fromBlock?: number,
- toBlock?: number,
+ startBlock: number,
+ endBlock: number,
): Promise<Array<LogWithDecodedArgs<ExchangeCancelEventArgs>>> {
- return this._getEventsAsync<ExchangeCancelEventArgs>(ExchangeEvents.Cancel, fromBlock, toBlock);
+ const getCancelEventsForRangeAsync = this._makeGetterFuncForEventType<ExchangeCancelEventArgs>(
+ ExchangeEvents.Cancel,
+ );
+ return getEventsWithPaginationAsync(getCancelEventsForRangeAsync, startBlock, endBlock);
}
public async getCancelUpToEventsAsync(
- fromBlock?: number,
- toBlock?: number,
+ startBlock: number,
+ endBlock: number,
): Promise<Array<LogWithDecodedArgs<ExchangeCancelUpToEventArgs>>> {
- return this._getEventsAsync<ExchangeCancelUpToEventArgs>(ExchangeEvents.CancelUpTo, fromBlock, toBlock);
- }
-
- private async _getEventsAsync<ArgsType extends ExchangeEventArgs>(
- eventName: ExchangeEvents,
- fromBlock: number = EXCHANGE_START_BLOCK,
- toBlock?: number,
- ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- const calculatedToBlock =
- toBlock === undefined
- ? (await this._web3Wrapper.getBlockNumberAsync()) - BLOCK_FINALITY_THRESHOLD
- : toBlock;
- let events: Array<LogWithDecodedArgs<ArgsType>> = [];
- for (let currFromBlock = fromBlock; currFromBlock <= calculatedToBlock; currFromBlock += NUM_BLOCKS_PER_QUERY) {
- events = events.concat(
- await this._getEventsForRangeAsync<ArgsType>(
- eventName,
- currFromBlock,
- Math.min(currFromBlock + NUM_BLOCKS_PER_QUERY - 1, calculatedToBlock),
- ),
- );
- }
- return events;
+ const getCancelUpToEventsForRangeAsync = this._makeGetterFuncForEventType<ExchangeCancelUpToEventArgs>(
+ ExchangeEvents.CancelUpTo,
+ );
+ return getEventsWithPaginationAsync(getCancelUpToEventsForRangeAsync, startBlock, endBlock);
}
- private async _getEventsForRangeAsync<ArgsType extends ExchangeEventArgs>(
- eventName: ExchangeEvents,
- fromBlock: number,
- toBlock: number,
- ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
- return this._exchangeWrapper.getLogsAsync<ArgsType>(
- eventName,
- {
- fromBlock,
- toBlock,
- },
- {},
- );
+ // Returns a getter function which gets all events of a specific type for a
+ // specific sub-range. This getter function will be called during each step
+ // of pagination.
+ private _makeGetterFuncForEventType<ArgsType extends ExchangeEventArgs>(
+ eventType: ExchangeEvents,
+ ): GetEventsFunc<ArgsType> {
+ return async (fromBlock: number, toBlock: number) =>
+ this._exchangeWrapper.getLogsAsync<ArgsType>(eventType, { fromBlock, toBlock }, {});
}
}
diff --git a/packages/pipeline/src/data_sources/contract-wrappers/utils.ts b/packages/pipeline/src/data_sources/contract-wrappers/utils.ts
new file mode 100644
index 000000000..67660a37e
--- /dev/null
+++ b/packages/pipeline/src/data_sources/contract-wrappers/utils.ts
@@ -0,0 +1,67 @@
+import { DecodedLogArgs, LogWithDecodedArgs } from 'ethereum-types';
+
+const NUM_BLOCKS_PER_QUERY = 10000; // Number of blocks to query for events at a time.
+const NUM_RETRIES = 3; // Number of retries if a request fails or times out.
+
+export type GetEventsFunc<ArgsType extends DecodedLogArgs> = (
+ fromBlock: number,
+ toBlock: number,
+) => Promise<Array<LogWithDecodedArgs<ArgsType>>>;
+
+/**
+ * Gets all events between the given startBlock and endBlock by querying for
+ * NUM_BLOCKS_PER_QUERY at a time. Accepts a getter function in order to
+ * maximize code re-use and allow for getting different types of events for
+ * different contracts. If the getter function throws with a retryable error,
+ * it will automatically be retried up to NUM_RETRIES times.
+ * @param getEventsAsync A getter function which will be called for each step during pagination.
+ * @param startBlock The start of the entire block range to get events for.
+ * @param endBlock The end of the entire block range to get events for.
+ */
+export async function getEventsWithPaginationAsync<ArgsType extends DecodedLogArgs>(
+ getEventsAsync: GetEventsFunc<ArgsType>,
+ startBlock: number,
+ endBlock: number,
+): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
+ let events: Array<LogWithDecodedArgs<ArgsType>> = [];
+ for (let fromBlock = startBlock; fromBlock <= endBlock; fromBlock += NUM_BLOCKS_PER_QUERY) {
+ const toBlock = Math.min(fromBlock + NUM_BLOCKS_PER_QUERY - 1, endBlock);
+ const eventsInRange = await _getEventsWithRetriesAsync(getEventsAsync, NUM_RETRIES, fromBlock, toBlock);
+ events = events.concat(eventsInRange);
+ }
+ return events;
+}
+
+/**
+ * Calls the getEventsAsync function and retries up to numRetries times if it
+ * throws with an error that is considered retryable.
+ * @param getEventsAsync a function that will be called on each iteration.
+ * @param numRetries the maximum number times to retry getEventsAsync if it fails with a retryable error.
+ * @param fromBlock the start of the sub-range of blocks we are getting events for.
+ * @param toBlock the end of the sub-range of blocks we are getting events for.
+ */
+export async function _getEventsWithRetriesAsync<ArgsType extends DecodedLogArgs>(
+ getEventsAsync: GetEventsFunc<ArgsType>,
+ numRetries: number,
+ fromBlock: number,
+ toBlock: number,
+): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
+ let eventsInRange: Array<LogWithDecodedArgs<ArgsType>> = [];
+ for (let i = 0; i <= numRetries; i++) {
+ try {
+ eventsInRange = await getEventsAsync(fromBlock, toBlock);
+ } catch (err) {
+ if (isErrorRetryable(err) && i < numRetries) {
+ continue;
+ } else {
+ throw err;
+ }
+ }
+ break;
+ }
+ return eventsInRange;
+}
+
+function isErrorRetryable(err: Error): boolean {
+ return err.message.includes('network timeout');
+}
diff --git a/packages/pipeline/src/data_sources/idex/index.ts b/packages/pipeline/src/data_sources/idex/index.ts
new file mode 100644
index 000000000..c1e53c08d
--- /dev/null
+++ b/packages/pipeline/src/data_sources/idex/index.ts
@@ -0,0 +1,82 @@
+import { fetchAsync } from '@0x/utils';
+
+const IDEX_BASE_URL = 'https://api.idex.market';
+const MARKETS_URL = `${IDEX_BASE_URL}/returnTicker`;
+const ORDERBOOK_URL = `${IDEX_BASE_URL}/returnOrderBook`;
+const MAX_ORDER_COUNT = 100; // Maximum based on https://github.com/AuroraDAO/idex-api-docs#returnorderbook
+export const IDEX_SOURCE = 'idex';
+
+export interface IdexMarketsResponse {
+ [marketName: string]: IdexMarket;
+}
+
+export interface IdexMarket {
+ last: string;
+ high: string;
+ low: string;
+ lowestAsk: string;
+ highestBid: string;
+ percentChange: string;
+ baseVolume: string;
+ quoteVolume: string;
+}
+
+export interface IdexOrderbook {
+ asks: IdexOrder[];
+ bids: IdexOrder[];
+}
+
+export interface IdexOrder {
+ price: string;
+ amount: string;
+ total: string;
+ orderHash: string;
+ params: IdexOrderParam;
+}
+
+export interface IdexOrderParam {
+ tokenBuy: string;
+ buySymbol: string;
+ buyPrecision: number;
+ amountBuy: string;
+ tokenSell: string;
+ sellSymbol: string;
+ sellPrecision: number;
+ amountSell: string;
+ expires: number;
+ nonce: number;
+ user: string;
+}
+
+// tslint:disable:prefer-function-over-method
+// ^ Keep consistency with other sources and help logical organization
+export class IdexSource {
+ /**
+ * Call Idex API to find out which markets they are maintaining orderbooks for.
+ */
+ public async getMarketsAsync(): Promise<string[]> {
+ const params = { method: 'POST' };
+ const resp = await fetchAsync(MARKETS_URL, params);
+ const respJson: IdexMarketsResponse = await resp.json();
+ const markets: string[] = Object.keys(respJson);
+ return markets;
+ }
+
+ /**
+ * Retrieve orderbook from Idex API for a given market.
+ * @param marketId String identifying the market we want data for. Eg. 'REP_AUG'
+ */
+ public async getMarketOrderbookAsync(marketId: string): Promise<IdexOrderbook> {
+ const params = {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ market: marketId,
+ count: MAX_ORDER_COUNT,
+ }),
+ };
+ const resp = await fetchAsync(ORDERBOOK_URL, params);
+ const respJson: IdexOrderbook = await resp.json();
+ return respJson;
+ }
+}
diff --git a/packages/pipeline/src/data_sources/oasis/index.ts b/packages/pipeline/src/data_sources/oasis/index.ts
new file mode 100644
index 000000000..3b30e9dfd
--- /dev/null
+++ b/packages/pipeline/src/data_sources/oasis/index.ts
@@ -0,0 +1,103 @@
+import { fetchAsync } from '@0x/utils';
+
+const OASIS_BASE_URL = 'https://data.makerdao.com/v1';
+const OASIS_MARKET_QUERY = `query {
+ oasisMarkets(period: "1 week") {
+ nodes {
+ id
+ base
+ quote
+ buyVol
+ sellVol
+ price
+ high
+ low
+ }
+ }
+}`;
+const OASIS_ORDERBOOK_QUERY = `query ($market: String!) {
+ allOasisOrders(condition: { market: $market }) {
+ totalCount
+ nodes {
+ market
+ offerId
+ price
+ amount
+ act
+ }
+ }
+}`;
+export const OASIS_SOURCE = 'oasis';
+
+export interface OasisMarket {
+ id: string; // market symbol e.g MKRDAI
+ base: string; // base symbol e.g MKR
+ quote: string; // quote symbol e.g DAI
+ buyVol: number; // total buy volume (base)
+ sellVol: number; // total sell volume (base)
+ price: number; // volume weighted price (quote)
+ high: number; // max sell price
+ low: number; // min buy price
+}
+
+export interface OasisMarketResponse {
+ data: {
+ oasisMarkets: {
+ nodes: OasisMarket[];
+ };
+ };
+}
+
+export interface OasisOrder {
+ offerId: number; // Offer Id
+ market: string; // Market symbol (base/quote)
+ price: string; // Offer price (quote)
+ amount: string; // Offer amount (base)
+ act: string; // Action (ask|bid)
+}
+
+export interface OasisOrderbookResponse {
+ data: {
+ allOasisOrders: {
+ totalCount: number;
+ nodes: OasisOrder[];
+ };
+ };
+}
+
+// tslint:disable:prefer-function-over-method
+// ^ Keep consistency with other sources and help logical organization
+export class OasisSource {
+ /**
+ * Call Ddex API to find out which markets they are maintaining orderbooks for.
+ */
+ public async getActiveMarketsAsync(): Promise<OasisMarket[]> {
+ const params = {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ query: OASIS_MARKET_QUERY }),
+ };
+ const resp = await fetchAsync(OASIS_BASE_URL, params);
+ const respJson: OasisMarketResponse = await resp.json();
+ const markets = respJson.data.oasisMarkets.nodes;
+ return markets;
+ }
+
+ /**
+ * Retrieve orderbook from Oasis API for a given market.
+ * @param marketId String identifying the market we want data for. Eg. 'REPAUG'.
+ */
+ public async getMarketOrderbookAsync(marketId: string): Promise<OasisOrder[]> {
+ const input = {
+ market: marketId,
+ };
+ const params = {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ query: OASIS_ORDERBOOK_QUERY, variables: input }),
+ };
+ const resp = await fetchAsync(OASIS_BASE_URL, params);
+ const respJson: OasisOrderbookResponse = await resp.json();
+ return respJson.data.allOasisOrders.nodes;
+ }
+}
diff --git a/packages/pipeline/src/data_sources/ohlcv_external/crypto_compare.ts b/packages/pipeline/src/data_sources/ohlcv_external/crypto_compare.ts
index 8804c34d0..85042501b 100644
--- a/packages/pipeline/src/data_sources/ohlcv_external/crypto_compare.ts
+++ b/packages/pipeline/src/data_sources/ohlcv_external/crypto_compare.ts
@@ -1,6 +1,6 @@
// tslint:disable:no-duplicate-imports
import { fetchAsync } from '@0x/utils';
-import promiseLimit = require('p-limit');
+import Bottleneck from 'bottleneck';
import { stringify } from 'querystring';
import * as R from 'ramda';
@@ -33,43 +33,41 @@ export interface CryptoCompareOHLCVParams {
toTs?: number;
}
-const ONE_WEEK = 7 * 24 * 60 * 60 * 1000; // tslint:disable-line:custom-no-magic-numbers
const ONE_HOUR = 60 * 60 * 1000; // tslint:disable-line:custom-no-magic-numbers
const ONE_SECOND = 1000;
const ONE_HOUR_AGO = new Date().getTime() - ONE_HOUR;
const HTTP_OK_STATUS = 200;
const CRYPTO_COMPARE_VALID_EMPTY_RESPONSE_TYPE = 96;
+const MAX_PAGE_SIZE = 2000;
export class CryptoCompareOHLCVSource {
- public readonly interval = ONE_WEEK; // the hourly API returns data for one week at a time
- public readonly default_exchange = 'CCCAGG';
public readonly intervalBetweenRecords = ONE_HOUR;
+ public readonly defaultExchange = 'CCCAGG';
+ public readonly interval = this.intervalBetweenRecords * MAX_PAGE_SIZE; // the hourly API returns data for one interval at a time
private readonly _url: string = 'https://min-api.cryptocompare.com/data/histohour?';
// rate-limit for all API calls through this class instance
- private readonly _promiseLimit: (fetchFn: () => Promise<Response>) => Promise<Response>;
- constructor(maxConcurrentRequests: number = 50) {
- this._promiseLimit = promiseLimit(maxConcurrentRequests);
+ private readonly _limiter: Bottleneck;
+ constructor(maxReqsPerSecond: number) {
+ this._limiter = new Bottleneck({
+ minTime: ONE_SECOND / maxReqsPerSecond,
+ reservoir: 30,
+ reservoirRefreshAmount: 30,
+ reservoirRefreshInterval: ONE_SECOND,
+ });
}
// gets OHLCV records starting from pair.latest
public async getHourlyOHLCVAsync(pair: TradingPair): Promise<CryptoCompareOHLCVRecord[]> {
const params = {
- e: this.default_exchange,
+ e: this.defaultExchange,
fsym: pair.fromSymbol,
tsym: pair.toSymbol,
+ limit: MAX_PAGE_SIZE,
toTs: Math.floor((pair.latestSavedTime + this.interval) / ONE_SECOND), // CryptoCompare uses timestamp in seconds. not ms
};
const url = this._url + stringify(params);
-
- // go through the instance-wide rate-limit
- const fetchPromise: Promise<Response> = this._promiseLimit(() => {
- // tslint:disable-next-line:no-console
- console.log(`Scraping Crypto Compare at ${url}`);
- return fetchAsync(url);
- });
-
- const response = await Promise.resolve(fetchPromise);
+ const response = await this._limiter.schedule(() => fetchAsync(url));
if (response.status !== HTTP_OK_STATUS) {
throw new Error(`HTTP error while scraping Crypto Compare: [${response}]`);
}
diff --git a/packages/pipeline/src/data_sources/paradex/index.ts b/packages/pipeline/src/data_sources/paradex/index.ts
index 69a03d553..46d448f4b 100644
--- a/packages/pipeline/src/data_sources/paradex/index.ts
+++ b/packages/pipeline/src/data_sources/paradex/index.ts
@@ -1,9 +1,9 @@
import { fetchAsync, logUtils } from '@0x/utils';
const PARADEX_BASE_URL = 'https://api.paradex.io/consumer/v0';
-const ACTIVE_MARKETS_URL = PARADEX_BASE_URL + '/markets';
-const ORDERBOOK_ENDPOINT = PARADEX_BASE_URL + '/orderbook';
-const TOKEN_INFO_ENDPOINT = PARADEX_BASE_URL + '/tokens';
+const ACTIVE_MARKETS_URL = `${PARADEX_BASE_URL}/markets`;
+const ORDERBOOK_ENDPOINT = `${PARADEX_BASE_URL}/orderbook`;
+const TOKEN_INFO_ENDPOINT = `${PARADEX_BASE_URL}/tokens`;
export const PARADEX_SOURCE = 'paradex';
export type ParadexActiveMarketsResponse = ParadexMarket[];
diff --git a/packages/pipeline/src/entities/erc20_approval_event.ts b/packages/pipeline/src/entities/erc20_approval_event.ts
new file mode 100644
index 000000000..69cdfcb0b
--- /dev/null
+++ b/packages/pipeline/src/entities/erc20_approval_event.ts
@@ -0,0 +1,26 @@
+import { BigNumber } from '@0x/utils';
+import { Column, Entity, PrimaryColumn } from 'typeorm';
+
+import { bigNumberTransformer, numberToBigIntTransformer } from '../utils';
+
+@Entity({ name: 'erc20_approval_events', schema: 'raw' })
+export class ERC20ApprovalEvent {
+ @PrimaryColumn({ name: 'token_address' })
+ public tokenAddress!: string;
+ @PrimaryColumn({ name: 'log_index' })
+ public logIndex!: number;
+ @PrimaryColumn({ name: 'block_number', transformer: numberToBigIntTransformer })
+ public blockNumber!: number;
+
+ @Column({ name: 'raw_data' })
+ public rawData!: string;
+
+ @Column({ name: 'transaction_hash' })
+ public transactionHash!: string;
+ @Column({ name: 'owner_address' })
+ public ownerAddress!: string;
+ @Column({ name: 'spender_address' })
+ public spenderAddress!: string;
+ @Column({ name: 'amount', type: 'numeric', transformer: bigNumberTransformer })
+ public amount!: BigNumber;
+}
diff --git a/packages/pipeline/src/entities/index.ts b/packages/pipeline/src/entities/index.ts
index db0814e38..cc3de78bb 100644
--- a/packages/pipeline/src/entities/index.ts
+++ b/packages/pipeline/src/entities/index.ts
@@ -14,5 +14,6 @@ export { SraOrdersObservedTimeStamp, createObservedTimestampForOrder } from './s
export { TokenMetadata } from './token_metadata';
export { TokenOrderbookSnapshot } from './token_order';
export { Transaction } from './transaction';
+export { ERC20ApprovalEvent } from './erc20_approval_event';
export type ExchangeEvent = ExchangeFillEvent | ExchangeCancelEvent | ExchangeCancelUpToEvent;
diff --git a/packages/pipeline/src/entities/token_order.ts b/packages/pipeline/src/entities/token_order.ts
index 557705767..4b8f0abc3 100644
--- a/packages/pipeline/src/entities/token_order.ts
+++ b/packages/pipeline/src/entities/token_order.ts
@@ -10,20 +10,20 @@ export class TokenOrderbookSnapshot {
public observedTimestamp!: number;
@PrimaryColumn({ name: 'source' })
public source!: string;
- @Column({ name: 'order_type' })
+ @PrimaryColumn({ name: 'order_type' })
public orderType!: OrderType;
@PrimaryColumn({ name: 'price', type: 'numeric', transformer: bigNumberTransformer })
public price!: BigNumber;
@PrimaryColumn({ name: 'base_asset_symbol' })
public baseAssetSymbol!: string;
- @Column({ name: 'base_asset_address' })
- public baseAssetAddress!: string;
+ @Column({ nullable: true, type: String, name: 'base_asset_address' })
+ public baseAssetAddress!: string | null;
@Column({ name: 'base_volume', type: 'numeric', transformer: bigNumberTransformer })
public baseVolume!: BigNumber;
@PrimaryColumn({ name: 'quote_asset_symbol' })
public quoteAssetSymbol!: string;
- @Column({ name: 'quote_asset_address' })
- public quoteAssetAddress!: string;
+ @Column({ nullable: true, type: String, name: 'quote_asset_address' })
+ public quoteAssetAddress!: string | null;
@Column({ name: 'quote_volume', type: 'numeric', transformer: bigNumberTransformer })
public quoteVolume!: BigNumber;
}
diff --git a/packages/pipeline/src/ormconfig.ts b/packages/pipeline/src/ormconfig.ts
index 9f7815b4e..fe11d81d5 100644
--- a/packages/pipeline/src/ormconfig.ts
+++ b/packages/pipeline/src/ormconfig.ts
@@ -3,6 +3,7 @@ import { ConnectionOptions } from 'typeorm';
import {
Block,
DexTrade,
+ ERC20ApprovalEvent,
ExchangeCancelEvent,
ExchangeCancelUpToEvent,
ExchangeFillEvent,
@@ -21,6 +22,7 @@ const entities = [
ExchangeCancelEvent,
ExchangeCancelUpToEvent,
ExchangeFillEvent,
+ ERC20ApprovalEvent,
OHLCVExternal,
Relayer,
SraOrder,
diff --git a/packages/pipeline/src/parsers/ddex_orders/index.ts b/packages/pipeline/src/parsers/ddex_orders/index.ts
index 81132e8f0..d7b97efbe 100644
--- a/packages/pipeline/src/parsers/ddex_orders/index.ts
+++ b/packages/pipeline/src/parsers/ddex_orders/index.ts
@@ -1,7 +1,8 @@
import { BigNumber } from '@0x/utils';
-import * as R from 'ramda';
-import { DdexMarket, DdexOrder, DdexOrderbook } from '../../data_sources/ddex';
+import { aggregateOrders } from '../utils';
+
+import { DdexMarket, DdexOrderbook } from '../../data_sources/ddex';
import { TokenOrderbookSnapshot as TokenOrder } from '../../entities';
import { OrderType } from '../../types';
@@ -28,19 +29,6 @@ export function parseDdexOrders(
}
/**
- * Aggregates orders by price point for consistency with other exchanges.
- * Querying the Ddex API at level 3 setting returns a breakdown of
- * individual orders at each price point. Other exchanges only give total amount
- * at each price point. Returns an array of <price, amount> tuples.
- * @param ddexOrders A list of Ddex orders awaiting aggregation.
- */
-export function aggregateOrders(ddexOrders: DdexOrder[]): Array<[string, BigNumber]> {
- const sumAmount = (acc: BigNumber, order: DdexOrder): BigNumber => acc.plus(order.amount);
- const aggregatedPricePoints = R.reduceBy(sumAmount, new BigNumber(0), R.prop('price'), ddexOrders);
- return Object.entries(aggregatedPricePoints);
-}
-
-/**
* Parse a single aggregated Ddex order in order to form a tokenOrder entity
* which can be saved into the database.
* @param ddexMarket An object containing information about the market where these
@@ -66,12 +54,14 @@ export function parseDdexOrder(
tokenOrder.orderType = orderType;
tokenOrder.price = price;
- tokenOrder.baseAssetSymbol = ddexMarket.baseToken;
- tokenOrder.baseAssetAddress = ddexMarket.baseTokenAddress;
- tokenOrder.baseVolume = price.times(amount);
+ // ddex currently confuses quote and base assets.
+ // We switch them here to maintain our internal consistency.
+ tokenOrder.baseAssetSymbol = ddexMarket.quoteToken;
+ tokenOrder.baseAssetAddress = ddexMarket.quoteTokenAddress;
+ tokenOrder.baseVolume = amount;
- tokenOrder.quoteAssetSymbol = ddexMarket.quoteToken;
- tokenOrder.quoteAssetAddress = ddexMarket.quoteTokenAddress;
- tokenOrder.quoteVolume = amount;
+ tokenOrder.quoteAssetSymbol = ddexMarket.baseToken;
+ tokenOrder.quoteAssetAddress = ddexMarket.baseTokenAddress;
+ tokenOrder.quoteVolume = price.times(amount);
return tokenOrder;
}
diff --git a/packages/pipeline/src/parsers/events/erc20_events.ts b/packages/pipeline/src/parsers/events/erc20_events.ts
new file mode 100644
index 000000000..caf9984d0
--- /dev/null
+++ b/packages/pipeline/src/parsers/events/erc20_events.ts
@@ -0,0 +1,34 @@
+import { ERC20TokenApprovalEventArgs } from '@0x/contract-wrappers';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import * as R from 'ramda';
+
+import { ERC20ApprovalEvent } from '../../entities';
+
+/**
+ * Parses raw event logs for an ERC20 approval event and returns an array of
+ * ERC20ApprovalEvent entities.
+ * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
+ */
+export const parseERC20ApprovalEvents: (
+ eventLogs: Array<LogWithDecodedArgs<ERC20TokenApprovalEventArgs>>,
+) => ERC20ApprovalEvent[] = R.map(_convertToERC20ApprovalEvent);
+
+/**
+ * Converts a raw event log for an ERC20 approval event into an
+ * ERC20ApprovalEvent entity.
+ * @param eventLog Raw event log (e.g. returned from contract-wrappers).
+ */
+export function _convertToERC20ApprovalEvent(
+ eventLog: LogWithDecodedArgs<ERC20TokenApprovalEventArgs>,
+): ERC20ApprovalEvent {
+ const erc20ApprovalEvent = new ERC20ApprovalEvent();
+ erc20ApprovalEvent.tokenAddress = eventLog.address as string;
+ erc20ApprovalEvent.blockNumber = eventLog.blockNumber as number;
+ erc20ApprovalEvent.logIndex = eventLog.logIndex as number;
+ erc20ApprovalEvent.rawData = eventLog.data as string;
+ erc20ApprovalEvent.transactionHash = eventLog.transactionHash;
+ erc20ApprovalEvent.ownerAddress = eventLog.args._owner;
+ erc20ApprovalEvent.spenderAddress = eventLog.args._spender;
+ erc20ApprovalEvent.amount = eventLog.args._value;
+ return erc20ApprovalEvent;
+}
diff --git a/packages/pipeline/src/parsers/events/exchange_events.ts b/packages/pipeline/src/parsers/events/exchange_events.ts
new file mode 100644
index 000000000..e18106c75
--- /dev/null
+++ b/packages/pipeline/src/parsers/events/exchange_events.ts
@@ -0,0 +1,133 @@
+import { ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, ExchangeFillEventArgs } from '@0x/contract-wrappers';
+import { assetDataUtils } from '@0x/order-utils';
+import { AssetProxyId, ERC721AssetData } from '@0x/types';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import * as R from 'ramda';
+
+import { ExchangeCancelEvent, ExchangeCancelUpToEvent, ExchangeFillEvent } from '../../entities';
+import { bigNumbertoStringOrNull } from '../../utils';
+
+/**
+ * Parses raw event logs for a fill event and returns an array of
+ * ExchangeFillEvent entities.
+ * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
+ */
+export const parseExchangeFillEvents: (
+ eventLogs: Array<LogWithDecodedArgs<ExchangeFillEventArgs>>,
+) => ExchangeFillEvent[] = R.map(_convertToExchangeFillEvent);
+
+/**
+ * Parses raw event logs for a cancel event and returns an array of
+ * ExchangeCancelEvent entities.
+ * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
+ */
+export const parseExchangeCancelEvents: (
+ eventLogs: Array<LogWithDecodedArgs<ExchangeCancelEventArgs>>,
+) => ExchangeCancelEvent[] = R.map(_convertToExchangeCancelEvent);
+
+/**
+ * Parses raw event logs for a CancelUpTo event and returns an array of
+ * ExchangeCancelUpToEvent entities.
+ * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
+ */
+export const parseExchangeCancelUpToEvents: (
+ eventLogs: Array<LogWithDecodedArgs<ExchangeCancelUpToEventArgs>>,
+) => ExchangeCancelUpToEvent[] = R.map(_convertToExchangeCancelUpToEvent);
+
+/**
+ * Converts a raw event log for a fill event into an ExchangeFillEvent entity.
+ * @param eventLog Raw event log (e.g. returned from contract-wrappers).
+ */
+export function _convertToExchangeFillEvent(eventLog: LogWithDecodedArgs<ExchangeFillEventArgs>): ExchangeFillEvent {
+ const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.makerAssetData);
+ const makerAssetType = makerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
+ const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.takerAssetData);
+ const takerAssetType = takerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
+ const exchangeFillEvent = new ExchangeFillEvent();
+ exchangeFillEvent.contractAddress = eventLog.address as string;
+ exchangeFillEvent.blockNumber = eventLog.blockNumber as number;
+ exchangeFillEvent.logIndex = eventLog.logIndex as number;
+ exchangeFillEvent.rawData = eventLog.data as string;
+ exchangeFillEvent.transactionHash = eventLog.transactionHash;
+ exchangeFillEvent.makerAddress = eventLog.args.makerAddress;
+ exchangeFillEvent.takerAddress = eventLog.args.takerAddress;
+ exchangeFillEvent.feeRecipientAddress = eventLog.args.feeRecipientAddress;
+ exchangeFillEvent.senderAddress = eventLog.args.senderAddress;
+ exchangeFillEvent.makerAssetFilledAmount = eventLog.args.makerAssetFilledAmount;
+ exchangeFillEvent.takerAssetFilledAmount = eventLog.args.takerAssetFilledAmount;
+ exchangeFillEvent.makerFeePaid = eventLog.args.makerFeePaid;
+ exchangeFillEvent.takerFeePaid = eventLog.args.takerFeePaid;
+ exchangeFillEvent.orderHash = eventLog.args.orderHash;
+ exchangeFillEvent.rawMakerAssetData = eventLog.args.makerAssetData;
+ exchangeFillEvent.makerAssetType = makerAssetType;
+ exchangeFillEvent.makerAssetProxyId = makerAssetData.assetProxyId;
+ exchangeFillEvent.makerTokenAddress = makerAssetData.tokenAddress;
+ // tslint has a false positive here. Type assertion is required.
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ exchangeFillEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
+ exchangeFillEvent.rawTakerAssetData = eventLog.args.takerAssetData;
+ exchangeFillEvent.takerAssetType = takerAssetType;
+ exchangeFillEvent.takerAssetProxyId = takerAssetData.assetProxyId;
+ exchangeFillEvent.takerTokenAddress = takerAssetData.tokenAddress;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ exchangeFillEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
+ return exchangeFillEvent;
+}
+
+/**
+ * Converts a raw event log for a cancel event into an ExchangeCancelEvent
+ * entity.
+ * @param eventLog Raw event log (e.g. returned from contract-wrappers).
+ */
+export function _convertToExchangeCancelEvent(
+ eventLog: LogWithDecodedArgs<ExchangeCancelEventArgs>,
+): ExchangeCancelEvent {
+ const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.makerAssetData);
+ const makerAssetType = makerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
+ const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.takerAssetData);
+ const takerAssetType = takerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
+ const exchangeCancelEvent = new ExchangeCancelEvent();
+ exchangeCancelEvent.contractAddress = eventLog.address as string;
+ exchangeCancelEvent.blockNumber = eventLog.blockNumber as number;
+ exchangeCancelEvent.logIndex = eventLog.logIndex as number;
+ exchangeCancelEvent.rawData = eventLog.data as string;
+ exchangeCancelEvent.transactionHash = eventLog.transactionHash;
+ exchangeCancelEvent.makerAddress = eventLog.args.makerAddress;
+ exchangeCancelEvent.takerAddress = eventLog.args.takerAddress;
+ exchangeCancelEvent.feeRecipientAddress = eventLog.args.feeRecipientAddress;
+ exchangeCancelEvent.senderAddress = eventLog.args.senderAddress;
+ exchangeCancelEvent.orderHash = eventLog.args.orderHash;
+ exchangeCancelEvent.rawMakerAssetData = eventLog.args.makerAssetData;
+ exchangeCancelEvent.makerAssetType = makerAssetType;
+ exchangeCancelEvent.makerAssetProxyId = makerAssetData.assetProxyId;
+ exchangeCancelEvent.makerTokenAddress = makerAssetData.tokenAddress;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ exchangeCancelEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
+ exchangeCancelEvent.rawTakerAssetData = eventLog.args.takerAssetData;
+ exchangeCancelEvent.takerAssetType = takerAssetType;
+ exchangeCancelEvent.takerAssetProxyId = takerAssetData.assetProxyId;
+ exchangeCancelEvent.takerTokenAddress = takerAssetData.tokenAddress;
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ exchangeCancelEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
+ return exchangeCancelEvent;
+}
+
+/**
+ * Converts a raw event log for a cancelUpTo event into an
+ * ExchangeCancelUpToEvent entity.
+ * @param eventLog Raw event log (e.g. returned from contract-wrappers).
+ */
+export function _convertToExchangeCancelUpToEvent(
+ eventLog: LogWithDecodedArgs<ExchangeCancelUpToEventArgs>,
+): ExchangeCancelUpToEvent {
+ const exchangeCancelUpToEvent = new ExchangeCancelUpToEvent();
+ exchangeCancelUpToEvent.contractAddress = eventLog.address as string;
+ exchangeCancelUpToEvent.blockNumber = eventLog.blockNumber as number;
+ exchangeCancelUpToEvent.logIndex = eventLog.logIndex as number;
+ exchangeCancelUpToEvent.rawData = eventLog.data as string;
+ exchangeCancelUpToEvent.transactionHash = eventLog.transactionHash;
+ exchangeCancelUpToEvent.makerAddress = eventLog.args.makerAddress;
+ exchangeCancelUpToEvent.senderAddress = eventLog.args.senderAddress;
+ exchangeCancelUpToEvent.orderEpoch = eventLog.args.orderEpoch;
+ return exchangeCancelUpToEvent;
+}
diff --git a/packages/pipeline/src/parsers/events/index.ts b/packages/pipeline/src/parsers/events/index.ts
index e18106c75..3f9915e8b 100644
--- a/packages/pipeline/src/parsers/events/index.ts
+++ b/packages/pipeline/src/parsers/events/index.ts
@@ -1,133 +1,2 @@
-import { ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, ExchangeFillEventArgs } from '@0x/contract-wrappers';
-import { assetDataUtils } from '@0x/order-utils';
-import { AssetProxyId, ERC721AssetData } from '@0x/types';
-import { LogWithDecodedArgs } from 'ethereum-types';
-import * as R from 'ramda';
-
-import { ExchangeCancelEvent, ExchangeCancelUpToEvent, ExchangeFillEvent } from '../../entities';
-import { bigNumbertoStringOrNull } from '../../utils';
-
-/**
- * Parses raw event logs for a fill event and returns an array of
- * ExchangeFillEvent entities.
- * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
- */
-export const parseExchangeFillEvents: (
- eventLogs: Array<LogWithDecodedArgs<ExchangeFillEventArgs>>,
-) => ExchangeFillEvent[] = R.map(_convertToExchangeFillEvent);
-
-/**
- * Parses raw event logs for a cancel event and returns an array of
- * ExchangeCancelEvent entities.
- * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
- */
-export const parseExchangeCancelEvents: (
- eventLogs: Array<LogWithDecodedArgs<ExchangeCancelEventArgs>>,
-) => ExchangeCancelEvent[] = R.map(_convertToExchangeCancelEvent);
-
-/**
- * Parses raw event logs for a CancelUpTo event and returns an array of
- * ExchangeCancelUpToEvent entities.
- * @param eventLogs Raw event logs (e.g. returned from contract-wrappers).
- */
-export const parseExchangeCancelUpToEvents: (
- eventLogs: Array<LogWithDecodedArgs<ExchangeCancelUpToEventArgs>>,
-) => ExchangeCancelUpToEvent[] = R.map(_convertToExchangeCancelUpToEvent);
-
-/**
- * Converts a raw event log for a fill event into an ExchangeFillEvent entity.
- * @param eventLog Raw event log (e.g. returned from contract-wrappers).
- */
-export function _convertToExchangeFillEvent(eventLog: LogWithDecodedArgs<ExchangeFillEventArgs>): ExchangeFillEvent {
- const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.makerAssetData);
- const makerAssetType = makerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
- const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.takerAssetData);
- const takerAssetType = takerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
- const exchangeFillEvent = new ExchangeFillEvent();
- exchangeFillEvent.contractAddress = eventLog.address as string;
- exchangeFillEvent.blockNumber = eventLog.blockNumber as number;
- exchangeFillEvent.logIndex = eventLog.logIndex as number;
- exchangeFillEvent.rawData = eventLog.data as string;
- exchangeFillEvent.transactionHash = eventLog.transactionHash;
- exchangeFillEvent.makerAddress = eventLog.args.makerAddress;
- exchangeFillEvent.takerAddress = eventLog.args.takerAddress;
- exchangeFillEvent.feeRecipientAddress = eventLog.args.feeRecipientAddress;
- exchangeFillEvent.senderAddress = eventLog.args.senderAddress;
- exchangeFillEvent.makerAssetFilledAmount = eventLog.args.makerAssetFilledAmount;
- exchangeFillEvent.takerAssetFilledAmount = eventLog.args.takerAssetFilledAmount;
- exchangeFillEvent.makerFeePaid = eventLog.args.makerFeePaid;
- exchangeFillEvent.takerFeePaid = eventLog.args.takerFeePaid;
- exchangeFillEvent.orderHash = eventLog.args.orderHash;
- exchangeFillEvent.rawMakerAssetData = eventLog.args.makerAssetData;
- exchangeFillEvent.makerAssetType = makerAssetType;
- exchangeFillEvent.makerAssetProxyId = makerAssetData.assetProxyId;
- exchangeFillEvent.makerTokenAddress = makerAssetData.tokenAddress;
- // tslint has a false positive here. Type assertion is required.
- // tslint:disable-next-line:no-unnecessary-type-assertion
- exchangeFillEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
- exchangeFillEvent.rawTakerAssetData = eventLog.args.takerAssetData;
- exchangeFillEvent.takerAssetType = takerAssetType;
- exchangeFillEvent.takerAssetProxyId = takerAssetData.assetProxyId;
- exchangeFillEvent.takerTokenAddress = takerAssetData.tokenAddress;
- // tslint:disable-next-line:no-unnecessary-type-assertion
- exchangeFillEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
- return exchangeFillEvent;
-}
-
-/**
- * Converts a raw event log for a cancel event into an ExchangeCancelEvent
- * entity.
- * @param eventLog Raw event log (e.g. returned from contract-wrappers).
- */
-export function _convertToExchangeCancelEvent(
- eventLog: LogWithDecodedArgs<ExchangeCancelEventArgs>,
-): ExchangeCancelEvent {
- const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.makerAssetData);
- const makerAssetType = makerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
- const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.takerAssetData);
- const takerAssetType = takerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
- const exchangeCancelEvent = new ExchangeCancelEvent();
- exchangeCancelEvent.contractAddress = eventLog.address as string;
- exchangeCancelEvent.blockNumber = eventLog.blockNumber as number;
- exchangeCancelEvent.logIndex = eventLog.logIndex as number;
- exchangeCancelEvent.rawData = eventLog.data as string;
- exchangeCancelEvent.transactionHash = eventLog.transactionHash;
- exchangeCancelEvent.makerAddress = eventLog.args.makerAddress;
- exchangeCancelEvent.takerAddress = eventLog.args.takerAddress;
- exchangeCancelEvent.feeRecipientAddress = eventLog.args.feeRecipientAddress;
- exchangeCancelEvent.senderAddress = eventLog.args.senderAddress;
- exchangeCancelEvent.orderHash = eventLog.args.orderHash;
- exchangeCancelEvent.rawMakerAssetData = eventLog.args.makerAssetData;
- exchangeCancelEvent.makerAssetType = makerAssetType;
- exchangeCancelEvent.makerAssetProxyId = makerAssetData.assetProxyId;
- exchangeCancelEvent.makerTokenAddress = makerAssetData.tokenAddress;
- // tslint:disable-next-line:no-unnecessary-type-assertion
- exchangeCancelEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
- exchangeCancelEvent.rawTakerAssetData = eventLog.args.takerAssetData;
- exchangeCancelEvent.takerAssetType = takerAssetType;
- exchangeCancelEvent.takerAssetProxyId = takerAssetData.assetProxyId;
- exchangeCancelEvent.takerTokenAddress = takerAssetData.tokenAddress;
- // tslint:disable-next-line:no-unnecessary-type-assertion
- exchangeCancelEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
- return exchangeCancelEvent;
-}
-
-/**
- * Converts a raw event log for a cancelUpTo event into an
- * ExchangeCancelUpToEvent entity.
- * @param eventLog Raw event log (e.g. returned from contract-wrappers).
- */
-export function _convertToExchangeCancelUpToEvent(
- eventLog: LogWithDecodedArgs<ExchangeCancelUpToEventArgs>,
-): ExchangeCancelUpToEvent {
- const exchangeCancelUpToEvent = new ExchangeCancelUpToEvent();
- exchangeCancelUpToEvent.contractAddress = eventLog.address as string;
- exchangeCancelUpToEvent.blockNumber = eventLog.blockNumber as number;
- exchangeCancelUpToEvent.logIndex = eventLog.logIndex as number;
- exchangeCancelUpToEvent.rawData = eventLog.data as string;
- exchangeCancelUpToEvent.transactionHash = eventLog.transactionHash;
- exchangeCancelUpToEvent.makerAddress = eventLog.args.makerAddress;
- exchangeCancelUpToEvent.senderAddress = eventLog.args.senderAddress;
- exchangeCancelUpToEvent.orderEpoch = eventLog.args.orderEpoch;
- return exchangeCancelUpToEvent;
-}
+export { parseExchangeCancelEvents, parseExchangeCancelUpToEvents, parseExchangeFillEvents } from './exchange_events';
+export { parseERC20ApprovalEvents } from './erc20_events';
diff --git a/packages/pipeline/src/parsers/idex_orders/index.ts b/packages/pipeline/src/parsers/idex_orders/index.ts
new file mode 100644
index 000000000..dfe27455c
--- /dev/null
+++ b/packages/pipeline/src/parsers/idex_orders/index.ts
@@ -0,0 +1,77 @@
+import { BigNumber } from '@0x/utils';
+
+import { aggregateOrders } from '../utils';
+
+import { IdexOrder, IdexOrderbook, IdexOrderParam } from '../../data_sources/idex';
+import { TokenOrderbookSnapshot as TokenOrder } from '../../entities';
+import { OrderType } from '../../types';
+
+/**
+ * Marque function of this file.
+ * 1) Takes in orders from an orderbook,
+ * 2) Aggregates them by price point,
+ * 3) Parses them into entities which are then saved into the database.
+ * @param idexOrderbook raw orderbook that we pull from the Idex API.
+ * @param observedTimestamp Time at which the orders for the market were pulled.
+ * @param source The exchange where these orders are placed. In this case 'idex'.
+ */
+export function parseIdexOrders(idexOrderbook: IdexOrderbook, observedTimestamp: number, source: string): TokenOrder[] {
+ const aggregatedBids = aggregateOrders(idexOrderbook.bids);
+ // Any of the bid orders' params will work
+ const idexBidOrder = idexOrderbook.bids[0];
+ const parsedBids =
+ aggregatedBids.length > 0
+ ? aggregatedBids.map(order => parseIdexOrder(idexBidOrder.params, observedTimestamp, 'bid', source, order))
+ : [];
+
+ const aggregatedAsks = aggregateOrders(idexOrderbook.asks);
+ // Any of the ask orders' params will work
+ const idexAskOrder = idexOrderbook.asks[0];
+ const parsedAsks =
+ aggregatedAsks.length > 0
+ ? aggregatedAsks.map(order => parseIdexOrder(idexAskOrder.params, observedTimestamp, 'ask', source, order))
+ : [];
+ return parsedBids.concat(parsedAsks);
+}
+
+/**
+ * Parse a single aggregated Idex order in order to form a tokenOrder entity
+ * which can be saved into the database.
+ * @param idexOrderParam An object containing information about the market where these
+ * trades have been placed.
+ * @param observedTimestamp The time when the API response returned back to us.
+ * @param orderType 'bid' or 'ask' enum.
+ * @param source Exchange where these orders were placed.
+ * @param idexOrder A <price, amount> tuple which we will convert to volume-basis.
+ */
+export function parseIdexOrder(
+ idexOrderParam: IdexOrderParam,
+ observedTimestamp: number,
+ orderType: OrderType,
+ source: string,
+ idexOrder: [string, BigNumber],
+): TokenOrder {
+ const tokenOrder = new TokenOrder();
+ const price = new BigNumber(idexOrder[0]);
+ const amount = idexOrder[1];
+
+ tokenOrder.source = source;
+ tokenOrder.observedTimestamp = observedTimestamp;
+ tokenOrder.orderType = orderType;
+ tokenOrder.price = price;
+ tokenOrder.baseVolume = amount;
+ tokenOrder.quoteVolume = price.times(amount);
+
+ if (orderType === 'bid') {
+ tokenOrder.baseAssetSymbol = idexOrderParam.buySymbol;
+ tokenOrder.baseAssetAddress = idexOrderParam.tokenBuy;
+ tokenOrder.quoteAssetSymbol = idexOrderParam.sellSymbol;
+ tokenOrder.quoteAssetAddress = idexOrderParam.tokenSell;
+ } else {
+ tokenOrder.baseAssetSymbol = idexOrderParam.sellSymbol;
+ tokenOrder.baseAssetAddress = idexOrderParam.tokenSell;
+ tokenOrder.quoteAssetSymbol = idexOrderParam.buySymbol;
+ tokenOrder.quoteAssetAddress = idexOrderParam.tokenBuy;
+ }
+ return tokenOrder;
+}
diff --git a/packages/pipeline/src/parsers/oasis_orders/index.ts b/packages/pipeline/src/parsers/oasis_orders/index.ts
new file mode 100644
index 000000000..13997f31b
--- /dev/null
+++ b/packages/pipeline/src/parsers/oasis_orders/index.ts
@@ -0,0 +1,71 @@
+import { BigNumber } from '@0x/utils';
+import * as R from 'ramda';
+
+import { aggregateOrders } from '../utils';
+
+import { OasisMarket, OasisOrder } from '../../data_sources/oasis';
+import { TokenOrderbookSnapshot as TokenOrder } from '../../entities';
+import { OrderType } from '../../types';
+
+/**
+ * Marque function of this file.
+ * 1) Takes in orders from an orderbook,
+ * 2) Aggregates them according to price point,
+ * 3) Builds TokenOrder entity with other information attached.
+ * @param oasisOrderbook A raw orderbook that we pull from the Oasis API.
+ * @param oasisMarket An object containing market data also directly from the API.
+ * @param observedTimestamp Time at which the orders for the market were pulled.
+ * @param source The exchange where these orders are placed. In this case 'oasis'.
+ */
+export function parseOasisOrders(
+ oasisOrderbook: OasisOrder[],
+ oasisMarket: OasisMarket,
+ observedTimestamp: number,
+ source: string,
+): TokenOrder[] {
+ const aggregatedBids = aggregateOrders(R.filter(R.propEq('act', 'bid'), oasisOrderbook));
+ const aggregatedAsks = aggregateOrders(R.filter(R.propEq('act', 'ask'), oasisOrderbook));
+ const parsedBids = aggregatedBids.map(order =>
+ parseOasisOrder(oasisMarket, observedTimestamp, 'bid', source, order),
+ );
+ const parsedAsks = aggregatedAsks.map(order =>
+ parseOasisOrder(oasisMarket, observedTimestamp, 'ask', source, order),
+ );
+ return parsedBids.concat(parsedAsks);
+}
+
+/**
+ * Parse a single aggregated Oasis order to form a tokenOrder entity
+ * which can be saved into the database.
+ * @param oasisMarket An object containing information about the market where these
+ * trades have been placed.
+ * @param observedTimestamp The time when the API response returned back to us.
+ * @param orderType 'bid' or 'ask' enum.
+ * @param source Exchange where these orders were placed.
+ * @param oasisOrder A <price, amount> tuple which we will convert to volume-basis.
+ */
+export function parseOasisOrder(
+ oasisMarket: OasisMarket,
+ observedTimestamp: number,
+ orderType: OrderType,
+ source: string,
+ oasisOrder: [string, BigNumber],
+): TokenOrder {
+ const tokenOrder = new TokenOrder();
+ const price = new BigNumber(oasisOrder[0]);
+ const amount = oasisOrder[1];
+
+ tokenOrder.source = source;
+ tokenOrder.observedTimestamp = observedTimestamp;
+ tokenOrder.orderType = orderType;
+ tokenOrder.price = price;
+
+ tokenOrder.baseAssetSymbol = oasisMarket.base;
+ tokenOrder.baseAssetAddress = null; // Oasis doesn't provide address information
+ tokenOrder.baseVolume = amount;
+
+ tokenOrder.quoteAssetSymbol = oasisMarket.quote;
+ tokenOrder.quoteAssetAddress = null; // Oasis doesn't provide address information
+ tokenOrder.quoteVolume = price.times(amount);
+ return tokenOrder;
+}
diff --git a/packages/pipeline/src/parsers/paradex_orders/index.ts b/packages/pipeline/src/parsers/paradex_orders/index.ts
index 7966658a7..5ceeb64a4 100644
--- a/packages/pipeline/src/parsers/paradex_orders/index.ts
+++ b/packages/pipeline/src/parsers/paradex_orders/index.ts
@@ -57,10 +57,10 @@ export function parseParadexOrder(
tokenOrder.baseAssetSymbol = paradexMarket.baseToken;
tokenOrder.baseAssetAddress = paradexMarket.baseTokenAddress as string;
- tokenOrder.baseVolume = price.times(amount);
+ tokenOrder.baseVolume = amount;
tokenOrder.quoteAssetSymbol = paradexMarket.quoteToken;
tokenOrder.quoteAssetAddress = paradexMarket.quoteTokenAddress as string;
- tokenOrder.quoteVolume = amount;
+ tokenOrder.quoteVolume = price.times(amount);
return tokenOrder;
}
diff --git a/packages/pipeline/src/parsers/token_metadata/index.ts b/packages/pipeline/src/parsers/token_metadata/index.ts
index 3b3e05d76..65e0aaa6e 100644
--- a/packages/pipeline/src/parsers/token_metadata/index.ts
+++ b/packages/pipeline/src/parsers/token_metadata/index.ts
@@ -1,9 +1,8 @@
-import { BigNumber } from '@0x/utils';
import * as R from 'ramda';
import { MetamaskTrustedTokenMeta, ZeroExTrustedTokenMeta } from '../../data_sources/trusted_tokens';
import { TokenMetadata } from '../../entities';
-import {} from '../../utils';
+import { toBigNumberOrNull } from '../../utils';
/**
* Parses Metamask's trusted tokens list.
@@ -26,7 +25,7 @@ function parseMetamaskTrustedToken(resp: MetamaskTrustedTokenMeta, address: stri
const trustedToken = new TokenMetadata();
trustedToken.address = address;
- trustedToken.decimals = new BigNumber(resp.decimals);
+ trustedToken.decimals = toBigNumberOrNull(resp.decimals);
trustedToken.symbol = resp.symbol;
trustedToken.name = resp.name;
trustedToken.authority = 'metamask';
@@ -38,7 +37,7 @@ function parseZeroExTrustedToken(resp: ZeroExTrustedTokenMeta): TokenMetadata {
const trustedToken = new TokenMetadata();
trustedToken.address = resp.address;
- trustedToken.decimals = new BigNumber(resp.decimals);
+ trustedToken.decimals = toBigNumberOrNull(resp.decimals);
trustedToken.symbol = resp.symbol;
trustedToken.name = resp.name;
trustedToken.authority = '0x';
diff --git a/packages/pipeline/src/parsers/utils.ts b/packages/pipeline/src/parsers/utils.ts
new file mode 100644
index 000000000..860729e9f
--- /dev/null
+++ b/packages/pipeline/src/parsers/utils.ts
@@ -0,0 +1,28 @@
+import { BigNumber } from '@0x/utils';
+
+export interface GenericRawOrder {
+ price: string;
+ amount: string;
+}
+
+/**
+ * Aggregates individual orders by price point. Filters zero amount orders.
+ * @param rawOrders An array of objects that have price and amount information.
+ */
+export function aggregateOrders(rawOrders: GenericRawOrder[]): Array<[string, BigNumber]> {
+ const aggregatedOrders = new Map<string, BigNumber>();
+ rawOrders.forEach(order => {
+ const amount = new BigNumber(order.amount);
+ if (amount.isZero()) {
+ return;
+ }
+ // Use string instead of BigNum to aggregate by value instead of variable.
+ // Convert to BigNumber first to consolidate different string
+ // representations of the same number. Eg. '0.0' and '0.00'.
+ const price = new BigNumber(order.price).toString();
+
+ const existingAmount = aggregatedOrders.get(price) || new BigNumber(0);
+ aggregatedOrders.set(price, amount.plus(existingAmount));
+ });
+ return Array.from(aggregatedOrders.entries());
+}
diff --git a/packages/pipeline/src/scripts/pull_competing_dex_trades.ts b/packages/pipeline/src/scripts/pull_competing_dex_trades.ts
index 4e4c12dd0..1478d5615 100644
--- a/packages/pipeline/src/scripts/pull_competing_dex_trades.ts
+++ b/packages/pipeline/src/scripts/pull_competing_dex_trades.ts
@@ -15,11 +15,11 @@ let connection: Connection;
(async () => {
connection = await createConnection(ormConfig as ConnectionOptions);
- await getAndSaveTrades();
+ await getAndSaveTradesAsync();
process.exit(0);
})().catch(handleError);
-async function getAndSaveTrades(): Promise<void> {
+async function getAndSaveTradesAsync(): Promise<void> {
const apiKey = process.env.BLOXY_API_KEY;
if (apiKey === undefined) {
throw new Error('Missing required env var: BLOXY_API_KEY');
diff --git a/packages/pipeline/src/scripts/pull_ddex_orderbook_snapshots.ts b/packages/pipeline/src/scripts/pull_ddex_orderbook_snapshots.ts
index 7868e9c5a..4e00f258f 100644
--- a/packages/pipeline/src/scripts/pull_ddex_orderbook_snapshots.ts
+++ b/packages/pipeline/src/scripts/pull_ddex_orderbook_snapshots.ts
@@ -25,7 +25,7 @@ let connection: Connection;
const markets = await ddexSource.getActiveMarketsAsync();
for (const marketsChunk of R.splitEvery(MARKET_ORDERBOOK_REQUEST_BATCH_SIZE, markets)) {
await Promise.all(
- marketsChunk.map(async (market: DdexMarket) => getAndSaveMarketOrderbook(ddexSource, market)),
+ marketsChunk.map(async (market: DdexMarket) => getAndSaveMarketOrderbookAsync(ddexSource, market)),
);
await new Promise<void>(resolve => setTimeout(resolve, MILLISEC_MARKET_ORDERBOOK_REQUEST_DELAY));
}
@@ -38,7 +38,7 @@ let connection: Connection;
* @param ddexSource Data source which can query Ddex API.
* @param market Object from Ddex API containing market data.
*/
-async function getAndSaveMarketOrderbook(ddexSource: DdexSource, market: DdexMarket): Promise<void> {
+async function getAndSaveMarketOrderbookAsync(ddexSource: DdexSource, market: DdexMarket): Promise<void> {
const orderBook = await ddexSource.getMarketOrderbookAsync(market.id);
const observedTimestamp = Date.now();
diff --git a/packages/pipeline/src/scripts/pull_erc20_events.ts b/packages/pipeline/src/scripts/pull_erc20_events.ts
new file mode 100644
index 000000000..bd520c610
--- /dev/null
+++ b/packages/pipeline/src/scripts/pull_erc20_events.ts
@@ -0,0 +1,96 @@
+import { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses';
+import { web3Factory } from '@0x/dev-utils';
+import { Web3ProviderEngine } from '@0x/subproviders';
+import { logUtils } from '@0x/utils';
+import { Web3Wrapper } from '@0x/web3-wrapper';
+import 'reflect-metadata';
+import { Connection, ConnectionOptions, createConnection } from 'typeorm';
+
+import { ERC20EventsSource } from '../data_sources/contract-wrappers/erc20_events';
+import { ERC20ApprovalEvent } from '../entities';
+import * as ormConfig from '../ormconfig';
+import { parseERC20ApprovalEvents } from '../parsers/events';
+import { handleError, INFURA_ROOT_URL } from '../utils';
+
+const NETWORK_ID = 1;
+const START_BLOCK_OFFSET = 100; // Number of blocks before the last known block to consider when updating fill events.
+const BATCH_SAVE_SIZE = 1000; // Number of events to save at once.
+const BLOCK_FINALITY_THRESHOLD = 10; // When to consider blocks as final. Used to compute default endBlock.
+
+let connection: Connection;
+
+interface Token {
+ // name is used for logging only.
+ name: string;
+ address: string;
+ defaultStartBlock: number;
+}
+
+const tokensToGetApprovalEvents: Token[] = [
+ {
+ name: 'WETH',
+ address: getContractAddressesForNetworkOrThrow(NETWORK_ID).etherToken,
+ defaultStartBlock: 4719568, // Block when the WETH contract was deployed.
+ },
+ {
+ name: 'ZRX',
+ address: getContractAddressesForNetworkOrThrow(NETWORK_ID).zrxToken,
+ defaultStartBlock: 4145415, // Block when the ZRX contract was deployed.
+ },
+ {
+ name: 'DAI',
+ address: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359',
+ defaultStartBlock: 4752008, // Block when the DAI contract was deployed.
+ },
+];
+
+(async () => {
+ connection = await createConnection(ormConfig as ConnectionOptions);
+ const provider = web3Factory.getRpcProvider({
+ rpcUrl: INFURA_ROOT_URL,
+ });
+ const endBlock = await calculateEndBlockAsync(provider);
+ for (const token of tokensToGetApprovalEvents) {
+ await getAndSaveApprovalEventsAsync(provider, token, endBlock);
+ }
+ process.exit(0);
+})().catch(handleError);
+
+async function getAndSaveApprovalEventsAsync(
+ provider: Web3ProviderEngine,
+ token: Token,
+ endBlock: number,
+): Promise<void> {
+ logUtils.log(`Getting approval events for ${token.name}...`);
+ logUtils.log('Checking existing approval events...');
+ const repository = connection.getRepository(ERC20ApprovalEvent);
+ const startBlock = (await getStartBlockAsync(token)) || token.defaultStartBlock;
+
+ logUtils.log(`Getting approval events starting at ${startBlock}...`);
+ const eventsSource = new ERC20EventsSource(provider, NETWORK_ID, token.address);
+ const eventLogs = await eventsSource.getApprovalEventsAsync(startBlock, endBlock);
+
+ logUtils.log(`Parsing ${eventLogs.length} approval events...`);
+ const events = parseERC20ApprovalEvents(eventLogs);
+ logUtils.log(`Retrieved and parsed ${events.length} total approval events.`);
+ await repository.save(events, { chunk: Math.ceil(events.length / BATCH_SAVE_SIZE) });
+}
+
+async function calculateEndBlockAsync(provider: Web3ProviderEngine): Promise<number> {
+ const web3Wrapper = new Web3Wrapper(provider);
+ const currentBlock = await web3Wrapper.getBlockNumberAsync();
+ return currentBlock - BLOCK_FINALITY_THRESHOLD;
+}
+
+async function getStartBlockAsync(token: Token): Promise<number | null> {
+ const queryResult = await connection.query(
+ `SELECT block_number FROM raw.erc20_approval_events WHERE token_address = $1 ORDER BY block_number DESC LIMIT 1`,
+ [token.address],
+ );
+ if (queryResult.length === 0) {
+ logUtils.log(`No existing approval events found for ${token.name}.`);
+ return null;
+ }
+ const lastKnownBlock = queryResult[0].block_number;
+ return lastKnownBlock - START_BLOCK_OFFSET;
+}
diff --git a/packages/pipeline/src/scripts/pull_missing_events.ts b/packages/pipeline/src/scripts/pull_exchange_events.ts
index 80abbb8b0..e98fc6629 100644
--- a/packages/pipeline/src/scripts/pull_missing_events.ts
+++ b/packages/pipeline/src/scripts/pull_exchange_events.ts
@@ -1,5 +1,7 @@
// tslint:disable:no-console
import { web3Factory } from '@0x/dev-utils';
+import { Web3ProviderEngine } from '@0x/subproviders';
+import { Web3Wrapper } from '@0x/web3-wrapper';
import R = require('ramda');
import 'reflect-metadata';
import { Connection, ConnectionOptions, createConnection, Repository } from 'typeorm';
@@ -12,6 +14,7 @@ import { EXCHANGE_START_BLOCK, handleError, INFURA_ROOT_URL } from '../utils';
const START_BLOCK_OFFSET = 100; // Number of blocks before the last known block to consider when updating fill events.
const BATCH_SAVE_SIZE = 1000; // Number of events to save at once.
+const BLOCK_FINALITY_THRESHOLD = 10; // When to consider blocks as final. Used to compute default endBlock.
let connection: Connection;
@@ -20,43 +23,44 @@ let connection: Connection;
const provider = web3Factory.getRpcProvider({
rpcUrl: INFURA_ROOT_URL,
});
+ const endBlock = await calculateEndBlockAsync(provider);
const eventsSource = new ExchangeEventsSource(provider, 1);
- await getFillEventsAsync(eventsSource);
- await getCancelEventsAsync(eventsSource);
- await getCancelUpToEventsAsync(eventsSource);
+ await getFillEventsAsync(eventsSource, endBlock);
+ await getCancelEventsAsync(eventsSource, endBlock);
+ await getCancelUpToEventsAsync(eventsSource, endBlock);
process.exit(0);
})().catch(handleError);
-async function getFillEventsAsync(eventsSource: ExchangeEventsSource): Promise<void> {
+async function getFillEventsAsync(eventsSource: ExchangeEventsSource, endBlock: number): Promise<void> {
console.log('Checking existing fill events...');
const repository = connection.getRepository(ExchangeFillEvent);
const startBlock = await getStartBlockAsync(repository);
console.log(`Getting fill events starting at ${startBlock}...`);
- const eventLogs = await eventsSource.getFillEventsAsync(startBlock);
+ const eventLogs = await eventsSource.getFillEventsAsync(startBlock, endBlock);
console.log('Parsing fill events...');
const events = parseExchangeFillEvents(eventLogs);
console.log(`Retrieved and parsed ${events.length} total fill events.`);
await saveEventsAsync(startBlock === EXCHANGE_START_BLOCK, repository, events);
}
-async function getCancelEventsAsync(eventsSource: ExchangeEventsSource): Promise<void> {
+async function getCancelEventsAsync(eventsSource: ExchangeEventsSource, endBlock: number): Promise<void> {
console.log('Checking existing cancel events...');
const repository = connection.getRepository(ExchangeCancelEvent);
const startBlock = await getStartBlockAsync(repository);
console.log(`Getting cancel events starting at ${startBlock}...`);
- const eventLogs = await eventsSource.getCancelEventsAsync(startBlock);
+ const eventLogs = await eventsSource.getCancelEventsAsync(startBlock, endBlock);
console.log('Parsing cancel events...');
const events = parseExchangeCancelEvents(eventLogs);
console.log(`Retrieved and parsed ${events.length} total cancel events.`);
await saveEventsAsync(startBlock === EXCHANGE_START_BLOCK, repository, events);
}
-async function getCancelUpToEventsAsync(eventsSource: ExchangeEventsSource): Promise<void> {
+async function getCancelUpToEventsAsync(eventsSource: ExchangeEventsSource, endBlock: number): Promise<void> {
console.log('Checking existing CancelUpTo events...');
const repository = connection.getRepository(ExchangeCancelUpToEvent);
const startBlock = await getStartBlockAsync(repository);
console.log(`Getting CancelUpTo events starting at ${startBlock}...`);
- const eventLogs = await eventsSource.getCancelUpToEventsAsync(startBlock);
+ const eventLogs = await eventsSource.getCancelUpToEventsAsync(startBlock, endBlock);
console.log('Parsing CancelUpTo events...');
const events = parseExchangeCancelUpToEvents(eventLogs);
console.log(`Retrieved and parsed ${events.length} total CancelUpTo events.`);
@@ -134,3 +138,9 @@ async function saveIndividuallyWithFallbackAsync<T extends ExchangeEvent>(
}
}
}
+
+async function calculateEndBlockAsync(provider: Web3ProviderEngine): Promise<number> {
+ const web3Wrapper = new Web3Wrapper(provider);
+ const currentBlock = await web3Wrapper.getBlockNumberAsync();
+ return currentBlock - BLOCK_FINALITY_THRESHOLD;
+}
diff --git a/packages/pipeline/src/scripts/pull_idex_orderbook_snapshots.ts b/packages/pipeline/src/scripts/pull_idex_orderbook_snapshots.ts
new file mode 100644
index 000000000..490b17766
--- /dev/null
+++ b/packages/pipeline/src/scripts/pull_idex_orderbook_snapshots.ts
@@ -0,0 +1,63 @@
+import { logUtils } from '@0x/utils';
+import * as R from 'ramda';
+import { Connection, ConnectionOptions, createConnection } from 'typeorm';
+
+import { IDEX_SOURCE, IdexSource } from '../data_sources/idex';
+import { TokenOrderbookSnapshot as TokenOrder } from '../entities';
+import * as ormConfig from '../ormconfig';
+import { parseIdexOrders } from '../parsers/idex_orders';
+import { handleError } from '../utils';
+
+// Number of orders to save at once.
+const BATCH_SAVE_SIZE = 1000;
+
+// Number of markets to retrieve orderbooks for at once.
+const MARKET_ORDERBOOK_REQUEST_BATCH_SIZE = 100;
+
+// Delay between market orderbook requests.
+const MILLISEC_MARKET_ORDERBOOK_REQUEST_DELAY = 2000;
+
+let connection: Connection;
+
+(async () => {
+ connection = await createConnection(ormConfig as ConnectionOptions);
+ const idexSource = new IdexSource();
+ logUtils.log('Getting all IDEX markets');
+ const markets = await idexSource.getMarketsAsync();
+ logUtils.log(`Got ${markets.length} markets.`);
+ for (const marketsChunk of R.splitEvery(MARKET_ORDERBOOK_REQUEST_BATCH_SIZE, markets)) {
+ await Promise.all(
+ marketsChunk.map(async (marketId: string) => getAndSaveMarketOrderbookAsync(idexSource, marketId)),
+ );
+ await new Promise<void>(resolve => setTimeout(resolve, MILLISEC_MARKET_ORDERBOOK_REQUEST_DELAY));
+ }
+ process.exit(0);
+})().catch(handleError);
+
+/**
+ * Retrieve orderbook from Idex API for a given market. Parse orders and insert
+ * them into our database.
+ * @param idexSource Data source which can query Idex API.
+ * @param marketId String representing market of interest, eg. 'ETH_TIC'.
+ */
+async function getAndSaveMarketOrderbookAsync(idexSource: IdexSource, marketId: string): Promise<void> {
+ logUtils.log(`${marketId}: Retrieving orderbook.`);
+ const orderBook = await idexSource.getMarketOrderbookAsync(marketId);
+ const observedTimestamp = Date.now();
+
+ if (!R.has('bids', orderBook) || !R.has('asks', orderBook)) {
+ logUtils.warn(`${marketId}: Orderbook faulty.`);
+ return;
+ }
+
+ logUtils.log(`${marketId}: Parsing orders.`);
+ const orders = parseIdexOrders(orderBook, observedTimestamp, IDEX_SOURCE);
+
+ if (orders.length > 0) {
+ logUtils.log(`${marketId}: Saving ${orders.length} orders.`);
+ const TokenOrderRepository = connection.getRepository(TokenOrder);
+ await TokenOrderRepository.save(orders, { chunk: Math.ceil(orders.length / BATCH_SAVE_SIZE) });
+ } else {
+ logUtils.log(`${marketId}: 0 orders to save.`);
+ }
+}
diff --git a/packages/pipeline/src/scripts/pull_missing_blocks.ts b/packages/pipeline/src/scripts/pull_missing_blocks.ts
index b7bd51f08..bb5385126 100644
--- a/packages/pipeline/src/scripts/pull_missing_blocks.ts
+++ b/packages/pipeline/src/scripts/pull_missing_blocks.ts
@@ -9,7 +9,7 @@ import { Web3Source } from '../data_sources/web3';
import { Block } from '../entities';
import * as ormConfig from '../ormconfig';
import { parseBlock } from '../parsers/web3';
-import { EXCHANGE_START_BLOCK, handleError, INFURA_ROOT_URL } from '../utils';
+import { handleError, INFURA_ROOT_URL } from '../utils';
// Number of blocks to save at once.
const BATCH_SAVE_SIZE = 1000;
@@ -24,10 +24,10 @@ let connection: Connection;
(async () => {
connection = await createConnection(ormConfig as ConnectionOptions);
const provider = web3Factory.getRpcProvider({
- rpcUrl: `${INFURA_ROOT_URL}/${process.env.INFURA_API_KEY}`,
+ rpcUrl: INFURA_ROOT_URL,
});
const web3Source = new Web3Source(provider);
- await getAllMissingBlocks(web3Source);
+ await getAllMissingBlocksAsync(web3Source);
process.exit(0);
})().catch(handleError);
@@ -35,35 +35,44 @@ interface MissingBlocksResponse {
block_number: string;
}
-async function getAllMissingBlocks(web3Source: Web3Source): Promise<void> {
+async function getAllMissingBlocksAsync(web3Source: Web3Source): Promise<void> {
const blocksRepository = connection.getRepository(Block);
- let fromBlock = EXCHANGE_START_BLOCK;
while (true) {
- const blockNumbers = await getMissingBlockNumbers(fromBlock);
+ const blockNumbers = await getMissingBlockNumbersAsync();
if (blockNumbers.length === 0) {
// There are no more missing blocks. We're done.
break;
}
- await getAndSaveBlocks(web3Source, blocksRepository, blockNumbers);
- fromBlock = Math.max(...blockNumbers) + 1;
+ await getAndSaveBlocksAsync(web3Source, blocksRepository, blockNumbers);
}
const totalBlocks = await blocksRepository.count();
console.log(`Done saving blocks. There are now ${totalBlocks} total blocks.`);
}
-async function getMissingBlockNumbers(fromBlock: number): Promise<number[]> {
- console.log(`Checking for missing blocks starting at ${fromBlock}...`);
+async function getMissingBlockNumbersAsync(): Promise<number[]> {
+ // Note(albrow): The easiest way to get all the blocks we need is to
+ // consider all the events tables together in a single query. If this query
+ // gets too slow, we should consider re-architecting so that we can work on
+ // getting the blocks for one type of event at a time.
const response = (await connection.query(
- 'SELECT DISTINCT(block_number) FROM raw.exchange_fill_events WHERE block_number NOT IN (SELECT number FROM raw.blocks) AND block_number >= $1 ORDER BY block_number ASC LIMIT $2',
- [fromBlock, MAX_BLOCKS_PER_QUERY],
+ `WITH all_events AS (
+ SELECT block_number FROM raw.exchange_fill_events
+ UNION SELECT block_number FROM raw.exchange_cancel_events
+ UNION SELECT block_number FROM raw.exchange_cancel_up_to_events
+ UNION SELECT block_number FROM raw.erc20_approval_events
+ )
+ SELECT DISTINCT(block_number) FROM all_events
+ WHERE block_number NOT IN (SELECT number FROM raw.blocks)
+ ORDER BY block_number ASC LIMIT $1`,
+ [MAX_BLOCKS_PER_QUERY],
)) as MissingBlocksResponse[];
const blockNumberStrings = R.pluck('block_number', response);
const blockNumbers = R.map(parseInt, blockNumberStrings);
- console.log(`Found ${blockNumbers.length} missing blocks in the given range.`);
+ console.log(`Found ${blockNumbers.length} missing blocks.`);
return blockNumbers;
}
-async function getAndSaveBlocks(
+async function getAndSaveBlocksAsync(
web3Source: Web3Source,
blocksRepository: Repository<Block>,
blockNumbers: number[],
diff --git a/packages/pipeline/src/scripts/pull_oasis_orderbook_snapshots.ts b/packages/pipeline/src/scripts/pull_oasis_orderbook_snapshots.ts
new file mode 100644
index 000000000..c4dcf6c83
--- /dev/null
+++ b/packages/pipeline/src/scripts/pull_oasis_orderbook_snapshots.ts
@@ -0,0 +1,58 @@
+import { logUtils } from '@0x/utils';
+import * as R from 'ramda';
+import { Connection, ConnectionOptions, createConnection } from 'typeorm';
+
+import { OASIS_SOURCE, OasisMarket, OasisSource } from '../data_sources/oasis';
+import { TokenOrderbookSnapshot as TokenOrder } from '../entities';
+import * as ormConfig from '../ormconfig';
+import { parseOasisOrders } from '../parsers/oasis_orders';
+import { handleError } from '../utils';
+
+// Number of orders to save at once.
+const BATCH_SAVE_SIZE = 1000;
+
+// Number of markets to retrieve orderbooks for at once.
+const MARKET_ORDERBOOK_REQUEST_BATCH_SIZE = 50;
+
+// Delay between market orderbook requests.
+const MILLISEC_MARKET_ORDERBOOK_REQUEST_DELAY = 1000;
+
+let connection: Connection;
+
+(async () => {
+ connection = await createConnection(ormConfig as ConnectionOptions);
+ const oasisSource = new OasisSource();
+ logUtils.log('Getting all active Oasis markets');
+ const markets = await oasisSource.getActiveMarketsAsync();
+ logUtils.log(`Got ${markets.length} markets.`);
+ for (const marketsChunk of R.splitEvery(MARKET_ORDERBOOK_REQUEST_BATCH_SIZE, markets)) {
+ await Promise.all(
+ marketsChunk.map(async (market: OasisMarket) => getAndSaveMarketOrderbookAsync(oasisSource, market)),
+ );
+ await new Promise<void>(resolve => setTimeout(resolve, MILLISEC_MARKET_ORDERBOOK_REQUEST_DELAY));
+ }
+ process.exit(0);
+})().catch(handleError);
+
+/**
+ * Retrieve orderbook from Oasis API for a given market. Parse orders and insert
+ * them into our database.
+ * @param oasisSource Data source which can query Oasis API.
+ * @param marketId String identifying market we want data for. eg. 'REPAUG'.
+ */
+async function getAndSaveMarketOrderbookAsync(oasisSource: OasisSource, market: OasisMarket): Promise<void> {
+ logUtils.log(`${market.id}: Retrieving orderbook.`);
+ const orderBook = await oasisSource.getMarketOrderbookAsync(market.id);
+ const observedTimestamp = Date.now();
+
+ logUtils.log(`${market.id}: Parsing orders.`);
+ const orders = parseOasisOrders(orderBook, market, observedTimestamp, OASIS_SOURCE);
+
+ if (orders.length > 0) {
+ logUtils.log(`${market.id}: Saving ${orders.length} orders.`);
+ const TokenOrderRepository = connection.getRepository(TokenOrder);
+ await TokenOrderRepository.save(orders, { chunk: Math.ceil(orders.length / BATCH_SAVE_SIZE) });
+ } else {
+ logUtils.log(`${market.id}: 0 orders to save.`);
+ }
+}
diff --git a/packages/pipeline/src/scripts/pull_ohlcv_cryptocompare.ts b/packages/pipeline/src/scripts/pull_ohlcv_cryptocompare.ts
index 7377a64d8..d44eb5cc6 100644
--- a/packages/pipeline/src/scripts/pull_ohlcv_cryptocompare.ts
+++ b/packages/pipeline/src/scripts/pull_ohlcv_cryptocompare.ts
@@ -11,7 +11,7 @@ import { fetchOHLCVTradingPairsAsync, TradingPair } from '../utils/get_ohlcv_tra
const SOURCE_NAME = 'CryptoCompare';
const TWO_HOURS_AGO = new Date().getTime() - 2 * 60 * 60 * 1000; // tslint:disable-line:custom-no-magic-numbers
-const MAX_CONCURRENT_REQUESTS = parseInt(process.env.CRYPTOCOMPARE_MAX_CONCURRENT_REQUESTS || '14', 10); // tslint:disable-line:custom-no-magic-numbers
+const MAX_REQS_PER_SECOND = parseInt(process.env.CRYPTOCOMPARE_MAX_REQS_PER_SECOND || '15', 10); // tslint:disable-line:custom-no-magic-numbers
const EARLIEST_BACKFILL_DATE = process.env.OHLCV_EARLIEST_BACKFILL_DATE || '2014-06-01';
const EARLIEST_BACKFILL_TIME = new Date(EARLIEST_BACKFILL_DATE).getTime();
@@ -20,7 +20,7 @@ let connection: Connection;
(async () => {
connection = await createConnection(ormConfig as ConnectionOptions);
const repository = connection.getRepository(OHLCVExternal);
- const source = new CryptoCompareOHLCVSource(MAX_CONCURRENT_REQUESTS);
+ const source = new CryptoCompareOHLCVSource(MAX_REQS_PER_SECOND);
const jobTime = new Date().getTime();
const tradingPairs = await fetchOHLCVTradingPairsAsync(connection, SOURCE_NAME, EARLIEST_BACKFILL_TIME);
@@ -63,7 +63,7 @@ async function fetchAndSaveAsync(
console.log(`Retrieved ${records.length} records for ${JSON.stringify(pair)}`);
if (records.length > 0) {
const metadata: OHLCVMetadata = {
- exchange: source.default_exchange,
+ exchange: source.defaultExchange,
fromSymbol: pair.fromSymbol,
toSymbol: pair.toSymbol,
source: SOURCE_NAME,
diff --git a/packages/pipeline/src/scripts/pull_paradex_orderbook_snapshots.ts b/packages/pipeline/src/scripts/pull_paradex_orderbook_snapshots.ts
index bae1fbede..34345f355 100644
--- a/packages/pipeline/src/scripts/pull_paradex_orderbook_snapshots.ts
+++ b/packages/pipeline/src/scripts/pull_paradex_orderbook_snapshots.ts
@@ -29,7 +29,7 @@ let connection: Connection;
const tokenInfoResponse = await paradexSource.getTokenInfoAsync();
const extendedMarkets = addTokenAddresses(markets, tokenInfoResponse);
await Promise.all(
- extendedMarkets.map(async (market: ParadexMarket) => getAndSaveMarketOrderbook(paradexSource, market)),
+ extendedMarkets.map(async (market: ParadexMarket) => getAndSaveMarketOrderbookAsync(paradexSource, market)),
);
process.exit(0);
})().catch(handleError);
@@ -70,7 +70,7 @@ function addTokenAddresses(
* @param paradexSource Data source which can query the Paradex API.
* @param market Object from the Paradex API with information about the market in question.
*/
-async function getAndSaveMarketOrderbook(paradexSource: ParadexSource, market: ParadexMarket): Promise<void> {
+async function getAndSaveMarketOrderbookAsync(paradexSource: ParadexSource, market: ParadexMarket): Promise<void> {
const paradexOrderbookResponse = await paradexSource.getMarketOrderbookAsync(market.symbol);
const observedTimestamp = Date.now();
diff --git a/packages/pipeline/src/scripts/pull_trusted_tokens.ts b/packages/pipeline/src/scripts/pull_trusted_tokens.ts
index 1befc4437..5906deee6 100644
--- a/packages/pipeline/src/scripts/pull_trusted_tokens.ts
+++ b/packages/pipeline/src/scripts/pull_trusted_tokens.ts
@@ -16,12 +16,12 @@ let connection: Connection;
(async () => {
connection = await createConnection(ormConfig as ConnectionOptions);
- await getMetamaskTrustedTokens();
- await getZeroExTrustedTokens();
+ await getMetamaskTrustedTokensAsync();
+ await getZeroExTrustedTokensAsync();
process.exit(0);
})().catch(handleError);
-async function getMetamaskTrustedTokens(): Promise<void> {
+async function getMetamaskTrustedTokensAsync(): Promise<void> {
// tslint:disable-next-line:no-console
console.log('Getting latest metamask trusted tokens list ...');
const trustedTokensRepository = connection.getRepository(TokenMetadata);
@@ -37,7 +37,7 @@ async function getMetamaskTrustedTokens(): Promise<void> {
console.log('Done saving metamask trusted tokens.');
}
-async function getZeroExTrustedTokens(): Promise<void> {
+async function getZeroExTrustedTokensAsync(): Promise<void> {
// tslint:disable-next-line:no-console
console.log('Getting latest 0x trusted tokens list ...');
const trustedTokensRepository = connection.getRepository(TokenMetadata);
diff --git a/packages/pipeline/src/scripts/update_relayer_info.ts b/packages/pipeline/src/scripts/update_relayer_info.ts
index f8918728d..41d29b385 100644
--- a/packages/pipeline/src/scripts/update_relayer_info.ts
+++ b/packages/pipeline/src/scripts/update_relayer_info.ts
@@ -17,11 +17,11 @@ let connection: Connection;
(async () => {
connection = await createConnection(ormConfig as ConnectionOptions);
- await getRelayers();
+ await getRelayersAsync();
process.exit(0);
})().catch(handleError);
-async function getRelayers(): Promise<void> {
+async function getRelayersAsync(): Promise<void> {
console.log('Getting latest relayer info...');
const relayerRepository = connection.getRepository(Relayer);
const relayerSource = new RelayerRegistrySource(RELAYER_REGISTRY_URL);
diff --git a/packages/pipeline/src/utils/get_ohlcv_trading_pairs.ts b/packages/pipeline/src/utils/get_ohlcv_trading_pairs.ts
index 9d3ef2fba..19f81344e 100644
--- a/packages/pipeline/src/utils/get_ohlcv_trading_pairs.ts
+++ b/packages/pipeline/src/utils/get_ohlcv_trading_pairs.ts
@@ -23,6 +23,18 @@ interface CryptoCompareCoin {
const TO_CURRENCIES = ['USD', 'EUR', 'ETH', 'USDT'];
const ETHEREUM_IDENTIFIER = '7605';
const HTTP_OK_STATUS = 200;
+
+interface StaticPair {
+ fromSymbol: string;
+ toSymbol: string;
+}
+const SPECIAL_CASES: StaticPair[] = [
+ {
+ fromSymbol: 'ETH',
+ toSymbol: 'USD',
+ },
+];
+
/**
* Get trading pairs with latest scraped time for OHLCV records
* @param conn a typeorm Connection to postgres
@@ -44,6 +56,7 @@ export async function fetchOHLCVTradingPairsAsync(
FROM raw.ohlcv_external
GROUP BY from_symbol, to_symbol;`);
+ // build addressable index: { fromsym: { tosym: time }}
const latestTradingPairsIndex: { [fromSym: string]: { [toSym: string]: number } } = {};
latestTradingPairs.forEach(pair => {
const latestIndex: { [toSym: string]: number } = latestTradingPairsIndex[pair.from_symbol] || {};
@@ -51,6 +64,13 @@ export async function fetchOHLCVTradingPairsAsync(
latestTradingPairsIndex[pair.from_symbol] = latestIndex;
});
+ // match time to special cases
+ const specialCases: TradingPair[] = SPECIAL_CASES.map(pair => {
+ const latestSavedTime =
+ R.path<number>([pair.fromSymbol, pair.toSymbol], latestTradingPairsIndex) || earliestBackfillTime;
+ return R.assoc('latestSavedTime', latestSavedTime, pair);
+ });
+
// get token symbols used by Crypto Compare
const allCoinsResp = await fetchAsync(COINLIST_API);
if (allCoinsResp.status !== HTTP_OK_STATUS) {
@@ -66,27 +86,31 @@ export async function fetchOHLCVTradingPairsAsync(
});
// fetch all tokens that are traded on 0x
- const rawTokenAddresses: Array<{ tokenaddress: string }> = await conn.query(
+ const rawEventTokenAddresses: Array<{ tokenaddress: string }> = await conn.query(
`SELECT DISTINCT(maker_token_address) as tokenaddress FROM raw.exchange_fill_events UNION
SELECT DISTINCT(taker_token_address) as tokenaddress FROM raw.exchange_fill_events`,
);
- const tokenAddresses = R.pluck('tokenaddress', rawTokenAddresses);
+
+ // tslint:disable-next-line:no-unbound-method
+ const eventTokenAddresses = R.pluck('tokenaddress', rawEventTokenAddresses).map(R.toLower);
// join token addresses with CC symbols
- const allTokenSymbols: string[] = tokenAddresses
- .map(tokenAddress => erc20CoinsIndex.get(tokenAddress.toLowerCase()) || '')
- .filter(x => x);
+ const eventTokenSymbols: string[] = eventTokenAddresses
+ .filter(tokenAddress => erc20CoinsIndex.has(tokenAddress))
+ .map(tokenAddress => erc20CoinsIndex.get(tokenAddress) as string);
- // generate list of all tokens with time of latest existing record OR default earliest time
- const allTradingPairCombinations: TradingPair[] = R.chain(sym => {
+ // join traded tokens with fiat and latest backfill time
+ const eventTradingPairs: TradingPair[] = R.chain(sym => {
return TO_CURRENCIES.map(fiat => {
- return {
+ const pair = {
fromSymbol: sym,
toSymbol: fiat,
latestSavedTime: R.path<number>([sym, fiat], latestTradingPairsIndex) || earliestBackfillTime,
};
+ return pair;
});
- }, allTokenSymbols);
+ }, eventTokenSymbols);
- return allTradingPairCombinations;
+ // join with special cases
+ return R.concat(eventTradingPairs, specialCases);
}
diff --git a/packages/pipeline/src/utils/index.ts b/packages/pipeline/src/utils/index.ts
index 2096a0a39..094c0178e 100644
--- a/packages/pipeline/src/utils/index.ts
+++ b/packages/pipeline/src/utils/index.ts
@@ -15,6 +15,21 @@ export function bigNumbertoStringOrNull(n: BigNumber): string | null {
}
/**
+ * If value is null or undefined, returns null. Otherwise converts value to a
+ * BigNumber.
+ * @param value A string or number to be converted to a BigNumber
+ */
+export function toBigNumberOrNull(value: string | number | null): BigNumber | null {
+ switch (value) {
+ case null:
+ case undefined:
+ return null;
+ default:
+ return new BigNumber(value);
+ }
+}
+
+/**
* Logs an error by intelligently checking for `message` and `stack` properties.
* Intended for use with top-level immediately invoked asynchronous functions.
* @param e the error to log.
diff --git a/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts b/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts
new file mode 100644
index 000000000..06f1a5e86
--- /dev/null
+++ b/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts
@@ -0,0 +1,109 @@
+// tslint:disable:custom-no-magic-numbers
+import * as chai from 'chai';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import 'mocha';
+
+import { _getEventsWithRetriesAsync } from '../../../src/data_sources/contract-wrappers/utils';
+import { chaiSetup } from '../../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const retryableMessage = 'network timeout: (simulated network timeout error)';
+const retryableError = new Error(retryableMessage);
+
+describe('data_sources/contract-wrappers/utils', () => {
+ describe('_getEventsWithRetriesAsync', () => {
+ it('sends a single request if it was successful', async () => {
+ // Pre-declare values for the fromBlock and toBlock arguments.
+ const expectedFromBlock = 100;
+ const expectedToBlock = 200;
+ const expectedLogs: Array<LogWithDecodedArgs<any>> = [
+ {
+ logIndex: 123,
+ transactionIndex: 456,
+ transactionHash: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd33657fe',
+ blockHash: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd33657ff',
+ blockNumber: 789,
+ address: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd3365800',
+ data: 'fake raw data',
+ topics: [],
+ event: 'TEST_EVENT',
+ args: [1, 2, 3],
+ },
+ ];
+
+ // mockGetEventsAsync checks its arguments, increments `callCount`
+ // and returns `expectedLogs`.
+ let callCount = 0;
+ const mockGetEventsAsync = async (
+ fromBlock: number,
+ toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ expect(fromBlock).equals(expectedFromBlock);
+ expect(toBlock).equals(expectedToBlock);
+ callCount += 1;
+ return expectedLogs;
+ };
+
+ // Make sure that we get what we expected and that the mock function
+ // was called exactly once.
+ const gotLogs = await _getEventsWithRetriesAsync(mockGetEventsAsync, 3, expectedFromBlock, expectedToBlock);
+ expect(gotLogs).deep.equals(expectedLogs);
+ expect(callCount).equals(
+ 1,
+ 'getEventsAsync function was called more than once even though it was successful',
+ );
+ });
+ it('retries and eventually succeeds', async () => {
+ const numRetries = 5;
+ let callCount = 0;
+ // mockGetEventsAsync throws unless callCount == numRetries + 1.
+ const mockGetEventsAsync = async (
+ _fromBlock: number,
+ _toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ callCount += 1;
+ if (callCount === numRetries + 1) {
+ return [];
+ }
+ throw retryableError;
+ };
+ await _getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300);
+ expect(callCount).equals(numRetries + 1, 'getEventsAsync function was called the wrong number of times');
+ });
+ it('throws for non-retryable errors', async () => {
+ const numRetries = 5;
+ const expectedMessage = 'Non-retryable error';
+ // mockGetEventsAsync always throws a non-retryable error.
+ const mockGetEventsAsync = async (
+ _fromBlock: number,
+ _toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ throw new Error(expectedMessage);
+ };
+ // Note(albrow): This does actually return a promise (or at least a
+ // "promise-like object" and is a false positive in TSLint.
+ // tslint:disable-next-line:await-promise
+ await expect(_getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300)).to.be.rejectedWith(
+ expectedMessage,
+ );
+ });
+ it('throws after too many retries', async () => {
+ const numRetries = 5;
+ // mockGetEventsAsync always throws a retryable error.
+ const mockGetEventsAsync = async (
+ _fromBlock: number,
+ _toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ throw retryableError;
+ };
+ // Note(albrow): This does actually return a promise (or at least a
+ // "promise-like object" and is a false positive in TSLint.
+ // tslint:disable-next-line:await-promise
+ await expect(_getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300)).to.be.rejectedWith(
+ retryableMessage,
+ );
+ });
+ });
+});
diff --git a/packages/pipeline/test/data_sources/ohlcv_external/crypto_compare_test.ts b/packages/pipeline/test/data_sources/ohlcv_external/crypto_compare_test.ts
index cb374bbb1..2efe3f5ec 100644
--- a/packages/pipeline/test/data_sources/ohlcv_external/crypto_compare_test.ts
+++ b/packages/pipeline/test/data_sources/ohlcv_external/crypto_compare_test.ts
@@ -13,7 +13,7 @@ const expect = chai.expect;
describe('ohlcv_external data source (Crypto Compare)', () => {
describe('generateBackfillIntervals', () => {
it('generates pairs with intervals to query', () => {
- const source = new CryptoCompareOHLCVSource();
+ const source = new CryptoCompareOHLCVSource(20);
const pair: TradingPair = {
fromSymbol: 'ETH',
toSymbol: 'ZRX',
@@ -31,7 +31,7 @@ describe('ohlcv_external data source (Crypto Compare)', () => {
});
it('returns single pair if no backfill is needed', () => {
- const source = new CryptoCompareOHLCVSource();
+ const source = new CryptoCompareOHLCVSource(20);
const pair: TradingPair = {
fromSymbol: 'ETH',
toSymbol: 'ZRX',
diff --git a/packages/pipeline/test/entities/erc20_approval_events_test.ts b/packages/pipeline/test/entities/erc20_approval_events_test.ts
new file mode 100644
index 000000000..1ecf41ee5
--- /dev/null
+++ b/packages/pipeline/test/entities/erc20_approval_events_test.ts
@@ -0,0 +1,29 @@
+import { BigNumber } from '@0x/utils';
+import 'mocha';
+import 'reflect-metadata';
+
+import { ERC20ApprovalEvent } from '../../src/entities';
+import { createDbConnectionOnceAsync } from '../db_setup';
+import { chaiSetup } from '../utils/chai_setup';
+
+import { testSaveAndFindEntityAsync } from './util';
+
+chaiSetup.configure();
+
+// tslint:disable:custom-no-magic-numbers
+describe('ERC20ApprovalEvent entity', () => {
+ it('save/find', async () => {
+ const connection = await createDbConnectionOnceAsync();
+ const event = new ERC20ApprovalEvent();
+ event.tokenAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
+ event.blockNumber = 6281577;
+ event.rawData = '0x000000000000000000000000000000000000000000000002b9cba5ee21ad3df9';
+ event.logIndex = 43;
+ event.transactionHash = '0xcb46b19c786376a0a0140d51e3e606a4c4f926d8ca5434e96d2f69d04d8d9c7f';
+ event.ownerAddress = '0x0b65c5f6f3a05d6be5588a72b603360773b3fe04';
+ event.spenderAddress = '0x448a5065aebb8e423f0896e6c5d525c040f59af3';
+ event.amount = new BigNumber('50281464906893835769');
+ const blocksRepository = connection.getRepository(ERC20ApprovalEvent);
+ await testSaveAndFindEntityAsync(blocksRepository, event);
+ });
+});
diff --git a/packages/pipeline/test/parsers/bloxy/index_test.ts b/packages/pipeline/test/parsers/bloxy/index_test.ts
index 2b8d68f98..6aabb091d 100644
--- a/packages/pipeline/test/parsers/bloxy/index_test.ts
+++ b/packages/pipeline/test/parsers/bloxy/index_test.ts
@@ -7,7 +7,6 @@ import * as R from 'ramda';
import { BLOXY_DEX_TRADES_URL, BloxyTrade } from '../../../src/data_sources/bloxy';
import { DexTrade } from '../../../src/entities';
import { _parseBloxyTrade } from '../../../src/parsers/bloxy';
-import { _convertToExchangeFillEvent } from '../../../src/parsers/events';
import { chaiSetup } from '../../utils/chai_setup';
chaiSetup.configure();
diff --git a/packages/pipeline/test/parsers/ddex_orders/index_test.ts b/packages/pipeline/test/parsers/ddex_orders/index_test.ts
index 213100f44..4a4a86bf8 100644
--- a/packages/pipeline/test/parsers/ddex_orders/index_test.ts
+++ b/packages/pipeline/test/parsers/ddex_orders/index_test.ts
@@ -4,7 +4,7 @@ import 'mocha';
import { DdexMarket } from '../../../src/data_sources/ddex';
import { TokenOrderbookSnapshot as TokenOrder } from '../../../src/entities';
-import { aggregateOrders, parseDdexOrder } from '../../../src/parsers/ddex_orders';
+import { parseDdexOrder } from '../../../src/parsers/ddex_orders';
import { OrderType } from '../../../src/types';
import { chaiSetup } from '../../utils/chai_setup';
@@ -13,19 +13,6 @@ const expect = chai.expect;
// tslint:disable:custom-no-magic-numbers
describe('ddex_orders', () => {
- describe('aggregateOrders', () => {
- it('aggregates orders by price point', () => {
- const input = [
- { price: '1', amount: '20', orderId: 'testtest' },
- { price: '1', amount: '30', orderId: 'testone' },
- { price: '2', amount: '100', orderId: 'testtwo' },
- ];
- const expected = [['1', new BigNumber(50)], ['2', new BigNumber(100)]];
- const actual = aggregateOrders(input);
- expect(actual).deep.equal(expected);
- });
- });
-
describe('parseDdexOrder', () => {
it('converts ddexOrder to TokenOrder entity', () => {
const ddexOrder: [string, BigNumber] = ['0.5', new BigNumber(10)];
@@ -52,12 +39,14 @@ describe('ddex_orders', () => {
expected.observedTimestamp = observedTimestamp;
expected.orderType = 'bid';
expected.price = new BigNumber(0.5);
- expected.baseAssetSymbol = 'DEF';
- expected.baseAssetAddress = '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81';
- expected.baseVolume = new BigNumber(5);
- expected.quoteAssetSymbol = 'ABC';
- expected.quoteAssetAddress = '0x0000000000000000000000000000000000000000';
- expected.quoteVolume = new BigNumber(10);
+ // ddex currently confuses base and quote assets.
+ // Switch them to maintain our internal consistency.
+ expected.baseAssetSymbol = 'ABC';
+ expected.baseAssetAddress = '0x0000000000000000000000000000000000000000';
+ expected.baseVolume = new BigNumber(10);
+ expected.quoteAssetSymbol = 'DEF';
+ expected.quoteAssetAddress = '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81';
+ expected.quoteVolume = new BigNumber(5);
const actual = parseDdexOrder(ddexMarket, observedTimestamp, orderType, source, ddexOrder);
expect(actual).deep.equal(expected);
diff --git a/packages/pipeline/test/parsers/events/erc20_events_test.ts b/packages/pipeline/test/parsers/events/erc20_events_test.ts
new file mode 100644
index 000000000..962c50f98
--- /dev/null
+++ b/packages/pipeline/test/parsers/events/erc20_events_test.ts
@@ -0,0 +1,54 @@
+import { ERC20TokenApprovalEventArgs } from '@0x/contract-wrappers';
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import 'mocha';
+
+import { ERC20ApprovalEvent } from '../../../src/entities';
+import { _convertToERC20ApprovalEvent } from '../../../src/parsers/events/erc20_events';
+import { _convertToExchangeFillEvent } from '../../../src/parsers/events/exchange_events';
+import { chaiSetup } from '../../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// tslint:disable:custom-no-magic-numbers
+describe('erc20_events', () => {
+ describe('_convertToERC20ApprovalEvent', () => {
+ it('converts LogWithDecodedArgs to ERC20ApprovalEvent entity', () => {
+ const input: LogWithDecodedArgs<ERC20TokenApprovalEventArgs> = {
+ address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
+ blockHash: '0xd2d7aafaa7102aec0bca8ef026d5a85133e87892334c46ee1e92e42912991c9b',
+ blockNumber: 6281577,
+ data: '0x000000000000000000000000000000000000000000000002b9cba5ee21ad3df9',
+ logIndex: 43,
+ topics: [
+ '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925',
+ '0x0000000000000000000000000b65c5f6f3a05d6be5588a72b603360773b3fe04',
+ '0x000000000000000000000000448a5065aebb8e423f0896e6c5d525c040f59af3',
+ ],
+ transactionHash: '0xcb46b19c786376a0a0140d51e3e606a4c4f926d8ca5434e96d2f69d04d8d9c7f',
+ transactionIndex: 103,
+ event: 'Approval',
+ args: {
+ _owner: '0x0b65c5f6f3a05d6be5588a72b603360773b3fe04',
+ _spender: '0x448a5065aebb8e423f0896e6c5d525c040f59af3',
+ _value: new BigNumber('50281464906893835769'),
+ },
+ };
+
+ const expected = new ERC20ApprovalEvent();
+ expected.tokenAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
+ expected.blockNumber = 6281577;
+ expected.rawData = '0x000000000000000000000000000000000000000000000002b9cba5ee21ad3df9';
+ expected.logIndex = 43;
+ expected.transactionHash = '0xcb46b19c786376a0a0140d51e3e606a4c4f926d8ca5434e96d2f69d04d8d9c7f';
+ expected.ownerAddress = '0x0b65c5f6f3a05d6be5588a72b603360773b3fe04';
+ expected.spenderAddress = '0x448a5065aebb8e423f0896e6c5d525c040f59af3';
+ expected.amount = new BigNumber('50281464906893835769');
+
+ const actual = _convertToERC20ApprovalEvent(input);
+ expect(actual).deep.equal(expected);
+ });
+ });
+});
diff --git a/packages/pipeline/test/parsers/events/index_test.ts b/packages/pipeline/test/parsers/events/exchange_events_test.ts
index 7e439ce39..5d4b185a5 100644
--- a/packages/pipeline/test/parsers/events/index_test.ts
+++ b/packages/pipeline/test/parsers/events/exchange_events_test.ts
@@ -5,7 +5,7 @@ import { LogWithDecodedArgs } from 'ethereum-types';
import 'mocha';
import { ExchangeFillEvent } from '../../../src/entities';
-import { _convertToExchangeFillEvent } from '../../../src/parsers/events';
+import { _convertToExchangeFillEvent } from '../../../src/parsers/events/exchange_events';
import { chaiSetup } from '../../utils/chai_setup';
chaiSetup.configure();
diff --git a/packages/pipeline/test/parsers/idex_orders/index_test.ts b/packages/pipeline/test/parsers/idex_orders/index_test.ts
new file mode 100644
index 000000000..d54ecb9a8
--- /dev/null
+++ b/packages/pipeline/test/parsers/idex_orders/index_test.ts
@@ -0,0 +1,87 @@
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { IdexOrderParam } from '../../../src/data_sources/idex';
+import { TokenOrderbookSnapshot as TokenOrder } from '../../../src/entities';
+import { parseIdexOrder } from '../../../src/parsers/idex_orders';
+import { OrderType } from '../../../src/types';
+import { chaiSetup } from '../../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// tslint:disable:custom-no-magic-numbers
+describe('idex_orders', () => {
+ describe('parseIdexOrder', () => {
+ // for market listed as 'DEF_ABC'.
+ it('correctly converts bid type idexOrder to TokenOrder entity', () => {
+ const idexOrder: [string, BigNumber] = ['0.5', new BigNumber(10)];
+ const idexOrderParam: IdexOrderParam = {
+ tokenBuy: '0x0000000000000000000000000000000000000000',
+ buySymbol: 'ABC',
+ buyPrecision: 2,
+ amountBuy: '10',
+ tokenSell: '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81',
+ sellSymbol: 'DEF',
+ sellPrecision: 2,
+ amountSell: '5',
+ expires: Date.now() + 100000,
+ nonce: 1,
+ user: '0x212345667543456435324564345643453453333',
+ };
+ const observedTimestamp: number = Date.now();
+ const orderType: OrderType = 'bid';
+ const source: string = 'idex';
+
+ const expected = new TokenOrder();
+ expected.source = 'idex';
+ expected.observedTimestamp = observedTimestamp;
+ expected.orderType = 'bid';
+ expected.price = new BigNumber(0.5);
+ expected.baseAssetSymbol = 'ABC';
+ expected.baseAssetAddress = '0x0000000000000000000000000000000000000000';
+ expected.baseVolume = new BigNumber(10);
+ expected.quoteAssetSymbol = 'DEF';
+ expected.quoteAssetAddress = '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81';
+ expected.quoteVolume = new BigNumber(5);
+
+ const actual = parseIdexOrder(idexOrderParam, observedTimestamp, orderType, source, idexOrder);
+ expect(actual).deep.equal(expected);
+ });
+ it('correctly converts ask type idexOrder to TokenOrder entity', () => {
+ const idexOrder: [string, BigNumber] = ['0.5', new BigNumber(10)];
+ const idexOrderParam: IdexOrderParam = {
+ tokenBuy: '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81',
+ buySymbol: 'DEF',
+ buyPrecision: 2,
+ amountBuy: '5',
+ tokenSell: '0x0000000000000000000000000000000000000000',
+ sellSymbol: 'ABC',
+ sellPrecision: 2,
+ amountSell: '10',
+ expires: Date.now() + 100000,
+ nonce: 1,
+ user: '0x212345667543456435324564345643453453333',
+ };
+ const observedTimestamp: number = Date.now();
+ const orderType: OrderType = 'ask';
+ const source: string = 'idex';
+
+ const expected = new TokenOrder();
+ expected.source = 'idex';
+ expected.observedTimestamp = observedTimestamp;
+ expected.orderType = 'ask';
+ expected.price = new BigNumber(0.5);
+ expected.baseAssetSymbol = 'ABC';
+ expected.baseAssetAddress = '0x0000000000000000000000000000000000000000';
+ expected.baseVolume = new BigNumber(10);
+ expected.quoteAssetSymbol = 'DEF';
+ expected.quoteAssetAddress = '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81';
+ expected.quoteVolume = new BigNumber(5);
+
+ const actual = parseIdexOrder(idexOrderParam, observedTimestamp, orderType, source, idexOrder);
+ expect(actual).deep.equal(expected);
+ });
+ });
+});
diff --git a/packages/pipeline/test/parsers/oasis_orders/index_test.ts b/packages/pipeline/test/parsers/oasis_orders/index_test.ts
new file mode 100644
index 000000000..433bfb665
--- /dev/null
+++ b/packages/pipeline/test/parsers/oasis_orders/index_test.ts
@@ -0,0 +1,49 @@
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { OasisMarket } from '../../../src/data_sources/oasis';
+import { TokenOrderbookSnapshot as TokenOrder } from '../../../src/entities';
+import { parseOasisOrder } from '../../../src/parsers/oasis_orders';
+import { OrderType } from '../../../src/types';
+import { chaiSetup } from '../../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// tslint:disable:custom-no-magic-numbers
+describe('oasis_orders', () => {
+ describe('parseOasisOrder', () => {
+ it('converts oasisOrder to TokenOrder entity', () => {
+ const oasisOrder: [string, BigNumber] = ['0.5', new BigNumber(10)];
+ const oasisMarket: OasisMarket = {
+ id: 'ABCDEF',
+ base: 'DEF',
+ quote: 'ABC',
+ buyVol: 100,
+ sellVol: 200,
+ price: 1,
+ high: 1,
+ low: 0,
+ };
+ const observedTimestamp: number = Date.now();
+ const orderType: OrderType = 'bid';
+ const source: string = 'oasis';
+
+ const expected = new TokenOrder();
+ expected.source = 'oasis';
+ expected.observedTimestamp = observedTimestamp;
+ expected.orderType = 'bid';
+ expected.price = new BigNumber(0.5);
+ expected.baseAssetSymbol = 'DEF';
+ expected.baseAssetAddress = null;
+ expected.baseVolume = new BigNumber(10);
+ expected.quoteAssetSymbol = 'ABC';
+ expected.quoteAssetAddress = null;
+ expected.quoteVolume = new BigNumber(5);
+
+ const actual = parseOasisOrder(oasisMarket, observedTimestamp, orderType, source, oasisOrder);
+ expect(actual).deep.equal(expected);
+ });
+ });
+});
diff --git a/packages/pipeline/test/parsers/paradex_orders/index_test.ts b/packages/pipeline/test/parsers/paradex_orders/index_test.ts
index 1522806bf..6b811b90d 100644
--- a/packages/pipeline/test/parsers/paradex_orders/index_test.ts
+++ b/packages/pipeline/test/parsers/paradex_orders/index_test.ts
@@ -42,10 +42,10 @@ describe('paradex_orders', () => {
expected.price = new BigNumber(0.1245);
expected.baseAssetSymbol = 'DEF';
expected.baseAssetAddress = '0xb45df06e38540a675fdb5b598abf2c0dbe9d6b81';
- expected.baseVolume = new BigNumber(412 * 0.1245);
+ expected.baseVolume = new BigNumber(412);
expected.quoteAssetSymbol = 'ABC';
expected.quoteAssetAddress = '0x0000000000000000000000000000000000000000';
- expected.quoteVolume = new BigNumber(412);
+ expected.quoteVolume = new BigNumber(412 * 0.1245);
const actual = parseParadexOrder(paradexMarket, observedTimestamp, orderType, source, paradexOrder);
expect(actual).deep.equal(expected);
diff --git a/packages/pipeline/test/parsers/utils/index_test.ts b/packages/pipeline/test/parsers/utils/index_test.ts
new file mode 100644
index 000000000..5a0d0f182
--- /dev/null
+++ b/packages/pipeline/test/parsers/utils/index_test.ts
@@ -0,0 +1,30 @@
+import { BigNumber } from '@0x/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { aggregateOrders, GenericRawOrder } from '../../../src/parsers/utils';
+import { chaiSetup } from '../../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// tslint:disable:custom-no-magic-numbers
+describe('aggregateOrders', () => {
+ it('aggregates order by price point', () => {
+ const input = [
+ { price: '1', amount: '20', orderHash: 'testtest', total: '20' },
+ { price: '1', amount: '30', orderHash: 'testone', total: '30' },
+ { price: '2', amount: '100', orderHash: 'testtwo', total: '200' },
+ ];
+ const expected = [['1', new BigNumber(50)], ['2', new BigNumber(100)]];
+ const actual = aggregateOrders(input);
+ expect(actual).deep.equal(expected);
+ });
+
+ it('handles empty orders gracefully', () => {
+ const input: GenericRawOrder[] = [];
+ const expected: Array<[string, BigNumber]> = [];
+ const actual = aggregateOrders(input);
+ expect(actual).deep.equal(expected);
+ });
+});
diff --git a/packages/react-docs/CHANGELOG.json b/packages/react-docs/CHANGELOG.json
index d456a3b53..9d8b5bc88 100644
--- a/packages/react-docs/CHANGELOG.json
+++ b/packages/react-docs/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.22",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.21",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "1.0.20",
"changes": [
diff --git a/packages/react-docs/CHANGELOG.md b/packages/react-docs/CHANGELOG.md
index e48f43fb8..5c702d562 100644
--- a/packages/react-docs/CHANGELOG.md
+++ b/packages/react-docs/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.22 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.21 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.20 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index 968ac4e34..f58a51c90 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/react-docs",
- "version": "1.0.20",
+ "version": "1.0.22",
"engines": {
"node": ">=6.12"
},
@@ -24,8 +24,8 @@
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/tslint-config": "^2.0.0",
"@types/compare-versions": "^3.0.0",
"@types/styled-components": "^4.0.0",
"make-promises-safe": "^1.1.0",
@@ -34,9 +34,9 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/react-shared": "^1.0.23",
- "@0x/types": "^1.3.0",
- "@0x/utils": "^2.0.6",
+ "@0x/react-shared": "^1.0.25",
+ "@0x/types": "^1.4.1",
+ "@0x/utils": "^2.0.8",
"@types/lodash": "4.14.104",
"@types/material-ui": "^0.20.0",
"@types/node": "*",
diff --git a/packages/react-shared/CHANGELOG.json b/packages/react-shared/CHANGELOG.json
index a376bae29..23e0d7f7e 100644
--- a/packages/react-shared/CHANGELOG.json
+++ b/packages/react-shared/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.25",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.24",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "1.0.23",
"changes": [
diff --git a/packages/react-shared/CHANGELOG.md b/packages/react-shared/CHANGELOG.md
index a983e0af2..8afa94e04 100644
--- a/packages/react-shared/CHANGELOG.md
+++ b/packages/react-shared/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.25 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.24 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.23 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json
index b5816ad98..17defe35a 100644
--- a/packages/react-shared/package.json
+++ b/packages/react-shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/react-shared",
- "version": "1.0.23",
+ "version": "1.0.25",
"engines": {
"node": ">=6.12"
},
@@ -25,15 +25,15 @@
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/tslint-config": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "^5.9.1",
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/types": "^1.3.0",
+ "@0x/types": "^1.4.1",
"@material-ui/core": "^3.0.1",
"@types/is-mobile": "0.3.0",
"@types/lodash": "4.14.104",
diff --git a/packages/sol-compiler/CHANGELOG.json b/packages/sol-compiler/CHANGELOG.json
index fe077b6cc..0a757f519 100644
--- a/packages/sol-compiler/CHANGELOG.json
+++ b/packages/sol-compiler/CHANGELOG.json
@@ -1,12 +1,22 @@
[
{
+ "version": "1.1.16",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "1.1.15",
"changes": [
{
"note": "Fix bug where we were appending base path to absolute imports (e.g NPM imports)",
"pr": 1311
}
- ]
+ ],
+ "timestamp": 1544570656
},
{
"timestamp": 1543401373,
diff --git a/packages/sol-compiler/CHANGELOG.md b/packages/sol-compiler/CHANGELOG.md
index a1782bb3b..b2066448d 100644
--- a/packages/sol-compiler/CHANGELOG.md
+++ b/packages/sol-compiler/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.1.16 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.1.15 - _December 11, 2018_
+
+ * Fix bug where we were appending base path to absolute imports (e.g NPM imports) (#1311)
+
## v1.1.14 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json
index d27c0ee31..0ad620b1f 100644
--- a/packages/sol-compiler/package.json
+++ b/packages/sol-compiler/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/sol-compiler",
- "version": "1.1.14",
+ "version": "1.1.16",
"engines": {
"node": ">=6.12"
},
@@ -42,8 +42,8 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-compiler/README.md",
"devDependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/tslint-config": "^1.0.10",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/tslint-config": "^2.0.0",
"@types/mkdirp": "^0.5.2",
"@types/require-from-string": "^1.2.0",
"@types/semver": "^5.5.0",
@@ -65,16 +65,16 @@
"zeppelin-solidity": "1.8.0"
},
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/json-schemas": "^2.1.2",
- "@0x/sol-resolver": "^1.0.17",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/assert": "^1.0.20",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/sol-resolver": "^1.1.1",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/yargs": "^11.0.0",
"chalk": "^2.3.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-util": "^5.1.1",
"lodash": "^4.17.5",
"mkdirp": "^0.5.1",
diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts
index cba67f292..85df8209e 100644
--- a/packages/sol-compiler/src/compiler.ts
+++ b/packages/sol-compiler/src/compiler.ts
@@ -400,7 +400,7 @@ export class Compiler {
* while others are absolute ("Token.sol", "@0x/contracts/Wallet.sol")
* And we need to append the base path for relative imports.
*/
- importPath = path.resolve('/' + contractFolder, importPath).replace('/', '');
+ importPath = path.resolve(`/${contractFolder}`, importPath).replace('/', '');
}
if (_.isUndefined(sourcesToAppendTo[importPath])) {
diff --git a/packages/sol-cov/CHANGELOG.json b/packages/sol-cov/CHANGELOG.json
index bc8aa71e1..b7973c135 100644
--- a/packages/sol-cov/CHANGELOG.json
+++ b/packages/sol-cov/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.1.16",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.1.15",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "2.1.14",
"changes": [
diff --git a/packages/sol-cov/CHANGELOG.md b/packages/sol-cov/CHANGELOG.md
index 25ba93026..879ef9c95 100644
--- a/packages/sol-cov/CHANGELOG.md
+++ b/packages/sol-cov/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.1.16 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.1.15 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.1.14 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json
index 73c11980f..3ade51c80 100644
--- a/packages/sol-cov/package.json
+++ b/packages/sol-cov/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/sol-cov",
- "version": "2.1.14",
+ "version": "2.1.16",
"engines": {
"node": ">=6.12"
},
@@ -42,14 +42,14 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md",
"dependencies": {
- "@0x/dev-utils": "^1.0.19",
- "@0x/sol-compiler": "^1.1.14",
- "@0x/subproviders": "^2.1.6",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/dev-utils": "^1.0.21",
+ "@0x/sol-compiler": "^1.1.16",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@types/solidity-parser-antlr": "^0.2.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-util": "^5.1.1",
"glob": "^7.1.2",
"istanbul": "^0.4.5",
@@ -61,7 +61,7 @@
"solidity-parser-antlr": "^0.2.12"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/istanbul": "^0.4.30",
"@types/loglevel": "^1.5.3",
"@types/mkdirp": "^0.5.1",
diff --git a/packages/sol-doc/CHANGELOG.json b/packages/sol-doc/CHANGELOG.json
index 332aeb025..e8fef746e 100644
--- a/packages/sol-doc/CHANGELOG.json
+++ b/packages/sol-doc/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.11",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.10",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "1.0.9",
"changes": [
diff --git a/packages/sol-doc/CHANGELOG.md b/packages/sol-doc/CHANGELOG.md
index 5a1df59c7..1b4a938af 100644
--- a/packages/sol-doc/CHANGELOG.md
+++ b/packages/sol-doc/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.11 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.10 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.9 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/sol-doc/package.json b/packages/sol-doc/package.json
index edf1707d6..c83c122df 100644
--- a/packages/sol-doc/package.json
+++ b/packages/sol-doc/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/sol-doc",
- "version": "1.0.9",
+ "version": "1.0.11",
"description": "Solidity documentation generator",
"main": "lib/src/index.js",
"types": "lib/src/index.d.js",
@@ -25,16 +25,16 @@
"author": "F. Eugene Aumson",
"license": "Apache-2.0",
"dependencies": {
- "@0x/sol-compiler": "^1.1.14",
- "@0x/types": "^1.3.0",
- "@0x/utils": "^2.0.6",
- "ethereum-types": "^1.1.2",
+ "@0x/sol-compiler": "^1.1.16",
+ "@0x/types": "^1.4.1",
+ "@0x/utils": "^2.0.8",
+ "ethereum-types": "^1.1.4",
"ethereumjs-util": "^5.1.1",
"lodash": "^4.17.10",
"yargs": "^12.0.2"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.2",
diff --git a/packages/sol-resolver/CHANGELOG.json b/packages/sol-resolver/CHANGELOG.json
index 4c9e612d7..85398e624 100644
--- a/packages/sol-resolver/CHANGELOG.json
+++ b/packages/sol-resolver/CHANGELOG.json
@@ -1,12 +1,22 @@
[
{
+ "version": "1.1.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "1.1.0",
"changes": [
{
"note": "NPMResolver now supports scoped packages",
"pr": 1311
}
- ]
+ ],
+ "timestamp": 1544570656
},
{
"timestamp": 1542821676,
diff --git a/packages/sol-resolver/CHANGELOG.md b/packages/sol-resolver/CHANGELOG.md
index b83275e5a..98435be19 100644
--- a/packages/sol-resolver/CHANGELOG.md
+++ b/packages/sol-resolver/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.1.1 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.1.0 - _December 11, 2018_
+
+ * NPMResolver now supports scoped packages (#1311)
+
## v1.0.17 - _November 21, 2018_
* Dependencies updated
diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json
index 5c5eec2cf..0163765d9 100644
--- a/packages/sol-resolver/package.json
+++ b/packages/sol-resolver/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/sol-resolver",
- "version": "1.0.17",
+ "version": "1.1.1",
"engines": {
"node": ">=6.12"
},
@@ -23,15 +23,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/resolver/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/sra-spec/CHANGELOG.json b/packages/sra-spec/CHANGELOG.json
index 49d1f1c83..393054465 100644
--- a/packages/sra-spec/CHANGELOG.json
+++ b/packages/sra-spec/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "1.0.13",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "1.0.12",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1542821676,
"version": "1.0.11",
"changes": [
diff --git a/packages/sra-spec/CHANGELOG.md b/packages/sra-spec/CHANGELOG.md
index 77b22515f..fd673b837 100644
--- a/packages/sra-spec/CHANGELOG.md
+++ b/packages/sra-spec/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.0.13 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.0.12 - _December 11, 2018_
+
+ * Dependencies updated
+
## v1.0.11 - _November 21, 2018_
* Dependencies updated
diff --git a/packages/sra-spec/package.json b/packages/sra-spec/package.json
index 1623e2574..3a6ee96d3 100644
--- a/packages/sra-spec/package.json
+++ b/packages/sra-spec/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/sra-spec",
- "version": "1.0.11",
+ "version": "1.0.13",
"engines": {
"node": ">=6.12"
},
@@ -35,11 +35,11 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sra-spec/README.md",
"dependencies": {
- "@0x/json-schemas": "^2.1.2",
+ "@0x/json-schemas": "^2.1.4",
"@loopback/openapi-v3-types": "^0.8.2"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/mocha": "^2.2.42",
"@types/node": "^10.5.3",
"chai": "^4.0.1",
diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json
index 6da170be3..938b2a717 100644
--- a/packages/subproviders/CHANGELOG.json
+++ b/packages/subproviders/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.1.8",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "2.1.7",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"timestamp": 1543401373,
"version": "2.1.6",
"changes": [
diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md
index 01dd8d652..002c76395 100644
--- a/packages/subproviders/CHANGELOG.md
+++ b/packages/subproviders/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.1.8 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.1.7 - _December 11, 2018_
+
+ * Dependencies updated
+
## v2.1.6 - _November 28, 2018_
* Dependencies updated
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index 86f3738af..90ef6b677 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/subproviders",
- "version": "2.1.6",
+ "version": "2.1.8",
"engines": {
"node": ">=6.12"
},
@@ -29,11 +29,11 @@
}
},
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/assert": "^1.0.20",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"@ledgerhq/hw-app-eth": "^4.3.0",
"@ledgerhq/hw-transport-u2f": "4.24.0",
"@types/eth-lightwallet": "^3.0.0",
@@ -43,7 +43,7 @@
"bip39": "^2.5.0",
"bn.js": "^4.11.8",
"eth-lightwallet": "^3.0.1",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-tx": "^1.3.5",
"ethereumjs-util": "^5.1.1",
"ganache-core": "^2.2.1",
@@ -54,7 +54,7 @@
"web3-provider-engine": "14.0.6"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/bip39": "^2.4.0",
"@types/bn.js": "^4.11.0",
"@types/ethereumjs-tx": "^1.0.0",
diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json
index 8c4b942a3..70d785c74 100644
--- a/packages/testnet-faucets/package.json
+++ b/packages/testnet-faucets/package.json
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@0x/testnet-faucets",
- "version": "1.0.58",
+ "version": "1.0.60",
"engines": {
"node": ">=6.12"
},
@@ -18,13 +18,13 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
- "0x.js": "^2.0.6",
- "@0x/subproviders": "^2.1.6",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "0x.js": "^2.0.8",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"body-parser": "^1.17.1",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-tx": "^1.3.5",
"ethereumjs-util": "^5.1.1",
"express": "^4.15.2",
@@ -32,7 +32,7 @@
"rollbar": "^0.6.5"
},
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/body-parser": "^1.16.1",
"@types/express": "^4.0.35",
"@types/lodash": "4.14.104",
diff --git a/packages/tslint-config/CHANGELOG.json b/packages/tslint-config/CHANGELOG.json
index 9f504216c..0070a5b81 100644
--- a/packages/tslint-config/CHANGELOG.json
+++ b/packages/tslint-config/CHANGELOG.json
@@ -1,5 +1,15 @@
[
{
+ "version": "2.0.0",
+ "changes": [
+ {
+ "note": "Improve async-suffix rule to check functions too, not just methods",
+ "pr": 1425
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "1.0.10",
"changes": [
{
diff --git a/packages/tslint-config/CHANGELOG.md b/packages/tslint-config/CHANGELOG.md
index f5cacb5d1..3cebb1e95 100644
--- a/packages/tslint-config/CHANGELOG.md
+++ b/packages/tslint-config/CHANGELOG.md
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.0.0 - _December 13, 2018_
+
+ * Improve async-suffix rule to check functions too, not just methods (#1425)
+
## v1.0.10 - _November 9, 2018_
* Dependencies updated
diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json
index 2914f31e2..64ec1e967 100644
--- a/packages/tslint-config/package.json
+++ b/packages/tslint-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/tslint-config",
- "version": "1.0.10",
+ "version": "2.0.0",
"engines": {
"node": ">=6.12"
},
diff --git a/packages/tslint-config/rules/walkers/async_suffix.ts b/packages/tslint-config/rules/walkers/async_suffix.ts
index eaec9c5f6..4e12152e8 100644
--- a/packages/tslint-config/rules/walkers/async_suffix.ts
+++ b/packages/tslint-config/rules/walkers/async_suffix.ts
@@ -3,24 +3,33 @@ import * as Lint from 'tslint';
import * as ts from 'typescript';
export class AsyncSuffixWalker extends Lint.RuleWalker {
- public static FAILURE_STRING = 'async functions must have an Async suffix';
+ public static FAILURE_STRING = 'async functions/methods must have an Async suffix';
+ public visitFunctionDeclaration(node: ts.FunctionDeclaration): void {
+ this._visitFunctionOrMethodDeclaration(node);
+ super.visitFunctionDeclaration(node);
+ }
public visitMethodDeclaration(node: ts.MethodDeclaration): void {
- const methodNameNode = node.name;
- const methodName = methodNameNode.getText();
- if (!_.isUndefined(node.type)) {
- if (node.type.kind === ts.SyntaxKind.TypeReference) {
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const returnTypeName = (node.type as ts.TypeReferenceNode).typeName.getText();
- if (returnTypeName === 'Promise' && !methodName.endsWith('Async')) {
- const failure = this.createFailure(
- methodNameNode.getStart(),
- methodNameNode.getWidth(),
- AsyncSuffixWalker.FAILURE_STRING,
- );
- this.addFailure(failure);
+ this._visitFunctionOrMethodDeclaration(node);
+ super.visitMethodDeclaration(node);
+ }
+ private _visitFunctionOrMethodDeclaration(node: ts.MethodDeclaration | ts.FunctionDeclaration): void {
+ const nameNode = node.name;
+ if (!_.isUndefined(nameNode)) {
+ const name = nameNode.getText();
+ if (!_.isUndefined(node.type)) {
+ if (node.type.kind === ts.SyntaxKind.TypeReference) {
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ const returnTypeName = (node.type as ts.TypeReferenceNode).typeName.getText();
+ if (returnTypeName === 'Promise' && !name.endsWith('Async')) {
+ const failure = this.createFailure(
+ nameNode.getStart(),
+ nameNode.getWidth(),
+ AsyncSuffixWalker.FAILURE_STRING,
+ );
+ this.addFailure(failure);
+ }
}
}
}
- super.visitMethodDeclaration(node);
}
}
diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json
index fd1849dd0..e8de6221e 100644
--- a/packages/tslint-config/tslint.json
+++ b/packages/tslint-config/tslint.json
@@ -92,6 +92,7 @@
"prefer-function-over-method": true,
"prefer-object-spread": true,
"prefer-readonly": true,
+ "prefer-template": true,
"promise-function-async": true,
"quotemark": [true, "single", "avoid-escape", "jsx-double"],
"restrict-plus-operands": true,
diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json
index b09859101..f1cd2f18e 100644
--- a/packages/types/CHANGELOG.json
+++ b/packages/types/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "1.4.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "1.4.0",
"changes": [
{
@@ -10,7 +19,8 @@
"note": "Add RevertReasons for DutchAuction contract",
"pr": 1225
}
- ]
+ ],
+ "timestamp": 1544570656
},
{
"version": "1.3.0",
diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md
index f133c05f1..5170eb4db 100644
--- a/packages/types/CHANGELOG.md
+++ b/packages/types/CHANGELOG.md
@@ -5,6 +5,15 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v1.4.1 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v1.4.0 - _December 11, 2018_
+
+ * Add `LengthMismatch` and `LengthGreaterThan3Required` revert reasons (#1224)
+ * Add RevertReasons for DutchAuction contract (#1225)
+
## v1.3.0 - _November 21, 2018_
* Add the `SimpleContractArtifact` type, which describes the artifact format published in the `@0x/contract-artifacts` package (#1298)
diff --git a/packages/types/package.json b/packages/types/package.json
index 46e268a66..3c4bb6fe6 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/types",
- "version": "1.3.0",
+ "version": "1.4.1",
"engines": {
"node": ">=6.12"
},
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/types/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.11.0",
@@ -32,7 +32,7 @@
"dependencies": {
"@types/node": "*",
"bignumber.js": "~4.1.0",
- "ethereum-types": "^1.1.2"
+ "ethereum-types": "^1.1.4"
},
"publishConfig": {
"access": "public"
diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json
index 5653b397d..fadf5ad14 100644
--- a/packages/typescript-typings/CHANGELOG.json
+++ b/packages/typescript-typings/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "3.0.6",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
+ "version": "3.0.5",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544570656
+ },
+ {
"version": "3.0.4",
"changes": [
{
diff --git a/packages/typescript-typings/CHANGELOG.md b/packages/typescript-typings/CHANGELOG.md
index 62e6665be..1663d40af 100644
--- a/packages/typescript-typings/CHANGELOG.md
+++ b/packages/typescript-typings/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v3.0.6 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v3.0.5 - _December 11, 2018_
+
+ * Dependencies updated
+
## v3.0.4 - _November 9, 2018_
* Dependencies updated
diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json
index 9dbbe1370..c67b660c8 100644
--- a/packages/typescript-typings/package.json
+++ b/packages/typescript-typings/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/typescript-typings",
- "version": "3.0.4",
+ "version": "3.0.6",
"engines": {
"node": ">=6.12"
},
@@ -27,7 +27,7 @@
"@types/bn.js": "^4.11.0",
"@types/react": "*",
"bignumber.js": "~4.1.0",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"popper.js": "1.14.3"
},
"devDependencies": {
diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json
index 08801a891..fe66d3f31 100644
--- a/packages/utils/CHANGELOG.json
+++ b/packages/utils/CHANGELOG.json
@@ -1,13 +1,22 @@
[
{
- "timestamp": 1543448882,
+ "version": "2.0.8",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "2.0.7",
"changes": [
{
"note":
"Optimized ABI Encoder/Decoder. Generates compressed calldata to save gas. Generates human-readable calldata to aid development."
}
- ]
+ ],
+ "timestamp": 1544570656
},
{
"timestamp": 1542821676,
diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md
index c5c42161a..c0437392d 100644
--- a/packages/utils/CHANGELOG.md
+++ b/packages/utils/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.0.8 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v2.0.7 - _December 11, 2018_
+
+ * Optimized ABI Encoder/Decoder. Generates compressed calldata to save gas. Generates human-readable calldata to aid development.
+
## v2.0.6 - _November 21, 2018_
* Dependencies updated
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 1f4d85843..a25dc9cff 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/utils",
- "version": "2.0.6",
+ "version": "2.0.8",
"engines": {
"node": ">=6.12"
},
@@ -28,7 +28,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/utils/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/detect-node": "2.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
@@ -44,13 +44,13 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
"@types/node": "*",
"abortcontroller-polyfill": "^1.1.9",
"bignumber.js": "~4.1.0",
"detect-node": "2.0.3",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-util": "^5.1.1",
"ethers": "~4.0.4",
"isomorphic-fetch": "^2.2.1",
@@ -60,4 +60,4 @@
"publishConfig": {
"access": "public"
}
-} \ No newline at end of file
+}
diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts
index 598ea5fcc..3e6fc9665 100644
--- a/packages/utils/src/abi_utils.ts
+++ b/packages/utils/src/abi_utils.ts
@@ -26,7 +26,7 @@ function parseEthersParams(params: DataItem[]): { names: ParamName[]; types: str
const result = parseEthersParams(param.components);
names.push({ name: param.name || null, names: result.names });
- types.push('tuple(' + result.types.join(',') + ')' + suffix);
+ types.push(`tuple(${result.types.join(',')})${suffix}`);
} else {
names.push(param.name || null);
types.push(param.type);
@@ -120,7 +120,7 @@ function splitTupleTypes(type: string): string[] {
if (_.endsWith(type, '[]')) {
throw new Error('Internal error: array types are not supported');
} else if (!_.startsWith(type, 'tuple(')) {
- throw new Error('Internal error: expected tuple type but got non-tuple type: ' + type);
+ throw new Error(`Internal error: expected tuple type but got non-tuple type: ${type}`);
}
// Trim the outtermost tuple().
const trimmedType = type.substring('tuple('.length, type.length - 1);
diff --git a/packages/utils/test/abi_encoder/evm_data_types_test.ts b/packages/utils/test/abi_encoder/evm_data_types_test.ts
index 9ef80a560..7185851a8 100644
--- a/packages/utils/test/abi_encoder/evm_data_types_test.ts
+++ b/packages/utils/test/abi_encoder/evm_data_types_test.ts
@@ -901,7 +901,7 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
// Construct args to be encoded
// Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes.
const bytesLength = 40;
- const args = '0x' + '61'.repeat(bytesLength);
+ const args = `0x${'61'.repeat(bytesLength)}`;
// Encode Args and validate result
const encodedArgs = dataType.encode(args, encodingRules);
const expectedEncodedArgs =
@@ -993,7 +993,7 @@ describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => {
// Construct args to be encoded
// Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes.
const strLength = 40;
- const args = '0x' + 'a'.repeat(strLength);
+ const args = `0x${'a'.repeat(strLength)}`;
// Encode Args and validate result
const encodedArgs = dataType.encode(args, encodingRules);
const expectedEncodedArgs =
diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json
index ed484c8e8..6b76626a9 100644
--- a/packages/web3-wrapper/CHANGELOG.json
+++ b/packages/web3-wrapper/CHANGELOG.json
@@ -1,12 +1,22 @@
[
{
+ "version": "3.2.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1544739608
+ },
+ {
"version": "3.2.0",
"changes": [
{
"note": "Return `value` and `gasPrice` as BigNumbers to avoid loss of precision errors",
"pr": 1402
}
- ]
+ ],
+ "timestamp": 1544570656
},
{
"version": "3.1.6",
diff --git a/packages/web3-wrapper/CHANGELOG.md b/packages/web3-wrapper/CHANGELOG.md
index fffaf1d0a..76ca80e69 100644
--- a/packages/web3-wrapper/CHANGELOG.md
+++ b/packages/web3-wrapper/CHANGELOG.md
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v3.2.1 - _December 13, 2018_
+
+ * Dependencies updated
+
+## v3.2.0 - _December 11, 2018_
+
+ * Return `value` and `gasPrice` as BigNumbers to avoid loss of precision errors (#1402)
+
## v3.1.6 - _November 28, 2018_
* Unmarshall mined transaction receipts (#1308)
diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json
index 218d85bfc..e5af24965 100644
--- a/packages/web3-wrapper/package.json
+++ b/packages/web3-wrapper/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/web3-wrapper",
- "version": "3.1.6",
+ "version": "3.2.1",
"engines": {
"node": ">=6.12"
},
@@ -36,7 +36,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/web3-wrapper/README.md",
"devDependencies": {
- "@0x/tslint-config": "^1.0.10",
+ "@0x/tslint-config": "^2.0.0",
"@types/ganache-core": "^2.1.0",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
@@ -54,11 +54,11 @@
"typescript": "3.0.1"
},
"dependencies": {
- "@0x/assert": "^1.0.18",
- "@0x/json-schemas": "^2.1.2",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "ethereum-types": "^1.1.2",
+ "@0x/assert": "^1.0.20",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "ethereum-types": "^1.1.4",
"ethereumjs-util": "^5.1.1",
"ethers": "~4.0.4",
"lodash": "^4.17.5"
diff --git a/packages/website/package.json b/packages/website/package.json
index 5d2e563e9..c24a0ba6e 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -1,6 +1,6 @@
{
"name": "@0x/website",
- "version": "0.0.61",
+ "version": "0.0.63",
"engines": {
"node": ">=6.12"
},
@@ -20,24 +20,24 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
- "@0x/asset-buyer": "^3.0.2",
+ "@0x/asset-buyer": "^3.0.4",
"@0x/contract-addresses": "^2.0.0",
- "@0x/contract-wrappers": "^4.1.1",
- "@0x/json-schemas": "^2.1.2",
- "@0x/order-utils": "^3.0.4",
- "@0x/react-docs": "^1.0.20",
- "@0x/react-shared": "^1.0.23",
- "@0x/subproviders": "^2.1.6",
- "@0x/types": "^1.3.0",
- "@0x/typescript-typings": "^3.0.4",
- "@0x/utils": "^2.0.6",
- "@0x/web3-wrapper": "^3.1.6",
+ "@0x/contract-wrappers": "^4.1.3",
+ "@0x/json-schemas": "^2.1.4",
+ "@0x/order-utils": "^3.0.7",
+ "@0x/react-docs": "^1.0.22",
+ "@0x/react-shared": "^1.0.25",
+ "@0x/subproviders": "^2.1.8",
+ "@0x/types": "^1.4.1",
+ "@0x/typescript-typings": "^3.0.6",
+ "@0x/utils": "^2.0.8",
+ "@0x/web3-wrapper": "^3.2.1",
"accounting": "^0.4.1",
"basscss": "^8.0.3",
"blockies": "^0.0.2",
"bowser": "^1.9.3",
"deep-equal": "^1.0.1",
- "ethereum-types": "^1.1.2",
+ "ethereum-types": "^1.1.4",
"ethereumjs-util": "^5.1.1",
"find-versions": "^2.0.0",
"jsonschema": "^1.2.0",
diff --git a/packages/website/public/images/developers/tutorials/integrate_0x_instant.svg b/packages/website/public/images/developers/tutorials/integrate_0x_instant.svg
new file mode 100644
index 000000000..e9c9278a8
--- /dev/null
+++ b/packages/website/public/images/developers/tutorials/integrate_0x_instant.svg
@@ -0,0 +1,3 @@
+<svg width="32" height="39" viewBox="0 0 32 39" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M16 1L1 23.242H16L16.0412 38L31 15.7159H16V1Z" stroke="#3289F1" stroke-width="1.5" stroke-miterlimit="10" stroke-linejoin="round"/>
+</svg>
diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json
index 78f29d0f6..2914ffead 100644
--- a/packages/website/translations/english.json
+++ b/packages/website/translations/english.json
@@ -92,6 +92,9 @@
"ORDER_BASICS_DESCRIPTION": "Tutorial on how to create, validate and fill an order using 0x",
"USE_NETWORKED_LIQUIDITY": "use networked liquidity",
"USE_NETWORKED_LIQUIDITY_DESCRIPTION": "Learn how to tap into networked liquidity using the Standard Relayer API",
+ "INTEGRATE_0X_INSTANT": "add seamless purchasing of crypto assets to your website or app",
+ "INTEGRATE_0X_INSTANT_DESCRIPTION":
+ "learn how to use 0x Instant or AssetBuyer to give your users the power of purchasing crypto assets using 0x",
"VIEW_ALL_DOCUMENTATION": "view all documentation",
"SANDBOX": "0x.js sandbox",
"GITHUB": "github",
diff --git a/packages/website/ts/components/documentation/sidebar_header.tsx b/packages/website/ts/components/documentation/sidebar_header.tsx
index 9ced52c74..0ab24ab5e 100644
--- a/packages/website/ts/components/documentation/sidebar_header.tsx
+++ b/packages/website/ts/components/documentation/sidebar_header.tsx
@@ -24,7 +24,7 @@ export const SidebarHeader: React.StatelessComponent<SidebarHeaderProps> = ({
return (
<Container>
<Container className="flex justify-bottom">
- <Container className="left pl1" width="150px">
+ <Container className="col col-7 pl1">
<Text
fontColor={colors.lightLinkBlue}
fontSize={screenWidth === ScreenWidths.Sm ? '20px' : '22px'}
@@ -37,12 +37,14 @@ export const SidebarHeader: React.StatelessComponent<SidebarHeaderProps> = ({
{!_.isUndefined(docsVersion) &&
!_.isUndefined(availableDocVersions) &&
!_.isUndefined(onVersionSelected) && (
- <div className="right" style={{ alignSelf: 'flex-end', paddingBottom: 4 }}>
- <VersionDropDown
- selectedVersion={docsVersion}
- versions={availableDocVersions}
- onVersionSelected={onVersionSelected}
- />
+ <div className="col col-5 pl1" style={{ alignSelf: 'flex-end', paddingBottom: 4 }}>
+ <Container className="right">
+ <VersionDropDown
+ selectedVersion={docsVersion}
+ versions={availableDocVersions}
+ onVersionSelected={onVersionSelected}
+ />
+ </Container>
</div>
)}
</Container>
diff --git a/packages/website/ts/containers/order_watcher_documentation.ts b/packages/website/ts/containers/order_watcher_documentation.ts
index ac92e6a22..683e1fe9f 100644
--- a/packages/website/ts/containers/order_watcher_documentation.ts
+++ b/packages/website/ts/containers/order_watcher_documentation.ts
@@ -24,7 +24,7 @@ const docsInfoConfig: DocsInfoConfig = {
id: DocPackages.OrderWatcher,
packageName: '@0x/order-watcher',
type: SupportedDocJson.TypeDoc,
- displayName: 'OrderWatcher',
+ displayName: 'Order Watcher',
packageUrl: 'https://github.com/0xProject/0x-monorepo',
markdownMenu: {
'getting-started': [markdownSections.introduction, markdownSections.installation],
diff --git a/packages/website/ts/pages/documentation/docs_home.tsx b/packages/website/ts/pages/documentation/docs_home.tsx
index f68d2892f..9dc779e96 100644
--- a/packages/website/ts/pages/documentation/docs_home.tsx
+++ b/packages/website/ts/pages/documentation/docs_home.tsx
@@ -44,6 +44,14 @@ const TUTORIALS: TutorialInfo[] = [
to: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`,
},
},
+ {
+ iconUrl: '/images/developers/tutorials/integrate_0x_instant.svg',
+ description: Key.Integrate0xInstantDescription,
+ link: {
+ title: Key.Integrate0xInstant,
+ to: `${WebsitePaths.Wiki}#Get-Started-With-Instant`,
+ },
+ },
];
const CATEGORY_TO_PACKAGES: ObjectMap<Package[]> = {
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index b20dd7095..2967fdac5 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -474,6 +474,8 @@ export enum Key {
OrderBasicsDescription = 'ORDER_BASICS_DESCRIPTION',
UseNetworkedLiquidity = 'USE_NETWORKED_LIQUIDITY',
UseNetworkedLiquidityDescription = 'USE_NETWORKED_LIQUIDITY_DESCRIPTION',
+ Integrate0xInstant = 'INTEGRATE_0X_INSTANT',
+ Integrate0xInstantDescription = 'INTEGRATE_0X_INSTANT_DESCRIPTION',
ViewAllDocumentation = 'VIEW_ALL_DOCUMENTATION',
Sandbox = 'SANDBOX',
Github = 'GITHUB',