diff options
Diffstat (limited to 'packages')
134 files changed, 1869 insertions, 508 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json index 096b29c78..32351ad82 100644 --- a/packages/0x.js/CHANGELOG.json +++ b/packages/0x.js/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.0.8", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.0.7", "changes": [ { diff --git a/packages/0x.js/CHANGELOG.md b/packages/0x.js/CHANGELOG.md index 226b4919a..2923fdf03 100644 --- a/packages/0x.js/CHANGELOG.md +++ b/packages/0x.js/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index fa1c61131..2960c9e4b 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -1,6 +1,6 @@ { "name": "0x.js", - "version": "2.0.7", + "version": "2.0.8", "engines": { "node": ">=6.12" }, @@ -42,11 +42,11 @@ }, "license": "Apache-2.0", "devDependencies": { - "@0x/abi-gen-wrappers": "^2.0.1", + "@0x/abi-gen-wrappers": "^2.0.2", "@0x/contract-addresses": "^2.0.0", - "@0x/dev-utils": "^1.0.20", - "@0x/migrations": "^2.2.1", - "@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.19", - "@0x/base-contract": "^3.0.9", - "@0x/contract-wrappers": "^4.1.2", - "@0x/order-utils": "^3.0.6", - "@0x/order-watcher": "^2.2.7", - "@0x/subproviders": "^2.1.7", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "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 41e35b712..d46e828f4 100644 --- a/packages/abi-gen-wrappers/CHANGELOG.json +++ b/packages/abi-gen-wrappers/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.0.2", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.0.1", "changes": [ { diff --git a/packages/abi-gen-wrappers/CHANGELOG.md b/packages/abi-gen-wrappers/CHANGELOG.md index 1209a059b..c13c7a60f 100644 --- a/packages/abi-gen-wrappers/CHANGELOG.md +++ b/packages/abi-gen-wrappers/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/abi-gen-wrappers/package.json b/packages/abi-gen-wrappers/package.json index e40a19615..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.1", + "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.18", + "@0x/abi-gen": "^1.0.19", "@0x/abi-gen-templates": "^1.0.1", - "@0x/tslint-config": "^1.0.10", - "@0x/types": "^1.4.0", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", - "ethereum-types": "^1.1.3", + "@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.9" + "@0x/base-contract": "^3.0.10" }, "publishConfig": { "access": "public" diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json index 9142d86d0..253fb124d 100644 --- a/packages/abi-gen/CHANGELOG.json +++ b/packages/abi-gen/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.19", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.18", "changes": [ { diff --git a/packages/abi-gen/CHANGELOG.md b/packages/abi-gen/CHANGELOG.md index 4edc82bd3..4ca19ad7e 100644 --- a/packages/abi-gen/CHANGELOG.md +++ b/packages/abi-gen/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 8f46eaca0..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.18", + "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.5", - "@0x/utils": "^2.0.7", + "@0x/typescript-typings": "^3.0.6", + "@0x/utils": "^2.0.8", "chalk": "^2.3.0", - "ethereum-types": "^1.1.3", + "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 bedde7738..3805a044f 100644 --- a/packages/assert/CHANGELOG.json +++ b/packages/assert/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.20", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.19", "changes": [ { diff --git a/packages/assert/CHANGELOG.md b/packages/assert/CHANGELOG.md index bef49229b..ef84c48d4 100644 --- a/packages/assert/CHANGELOG.md +++ b/packages/assert/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/assert/package.json b/packages/assert/package.json index 2792c066f..cec1748cd 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -1,6 +1,6 @@ { "name": "@0x/assert", - "version": "1.0.19", + "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.3", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", + "@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 1a304f4a3..470d9b03b 100644 --- a/packages/asset-buyer/CHANGELOG.json +++ b/packages/asset-buyer/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.4", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "3.0.3", "changes": [ { diff --git a/packages/asset-buyer/CHANGELOG.md b/packages/asset-buyer/CHANGELOG.md index cc64f295b..cadb1acf8 100644 --- a/packages/asset-buyer/CHANGELOG.md +++ b/packages/asset-buyer/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/asset-buyer/package.json b/packages/asset-buyer/package.json index 54e652361..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.3", + "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.19", - "@0x/connect": "^3.0.9", - "@0x/contract-wrappers": "^4.1.2", - "@0x/json-schemas": "^2.1.3", - "@0x/order-utils": "^3.0.6", - "@0x/subproviders": "^2.1.7", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", - "ethereum-types": "^1.1.3", + "@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 fc3f065d9..a4cd17d42 100644 --- a/packages/base-contract/CHANGELOG.json +++ b/packages/base-contract/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.10", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "3.0.9", "changes": [ { diff --git a/packages/base-contract/CHANGELOG.md b/packages/base-contract/CHANGELOG.md index 65888d9ab..a8ce346d7 100644 --- a/packages/base-contract/CHANGELOG.md +++ b/packages/base-contract/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 17c2af2dd..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.9", + "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.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", - "ethereum-types": "^1.1.3", + "@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 f9d0f51cc..e5bde40ae 100644 --- a/packages/connect/CHANGELOG.json +++ b/packages/connect/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.10", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "3.0.9", "changes": [ { diff --git a/packages/connect/CHANGELOG.md b/packages/connect/CHANGELOG.md index befd0572c..a5f95b988 100644 --- a/packages/connect/CHANGELOG.md +++ b/packages/connect/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/connect/package.json b/packages/connect/package.json index 9d1218b5a..4985d0410 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -1,6 +1,6 @@ { "name": "@0x/connect", - "version": "3.0.9", + "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.19", - "@0x/json-schemas": "^2.1.3", - "@0x/order-utils": "^3.0.6", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", + "@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 e0f5c8ded..9475e5a88 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "4.1.3", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "4.1.2", "changes": [ { diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md index 3716db927..595fbcc31 100644 --- a/packages/contract-wrappers/CHANGELOG.md +++ b/packages/contract-wrappers/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index ec0dcb0cb..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.2", + "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.20", - "@0x/migrations": "^2.2.1", - "@0x/subproviders": "^2.1.7", - "@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.1", - "@0x/assert": "^1.0.19", + "@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.15", - "@0x/json-schemas": "^2.1.3", - "@0x/order-utils": "^3.0.6", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", - "ethereum-types": "^1.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", + "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 f83b57308..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.9", + "version": "0.0.10", "engines": { "node": ">=6.12" }, @@ -16,7 +16,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@0x/react-shared": "^1.0.24", + "@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 940a59ea6..b6cc74ce7 100644 --- a/packages/dev-utils/CHANGELOG.json +++ b/packages/dev-utils/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.21", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.20", "changes": [ { diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index f2484854b..9a55e4e58 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 872a285a3..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.20", + "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.7", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "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 6ce8feb1e..9a0f2ad49 100644 --- a/packages/ethereum-types/CHANGELOG.json +++ b/packages/ethereum-types/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.1.4", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.1.3", "changes": [ { diff --git a/packages/ethereum-types/CHANGELOG.md b/packages/ethereum-types/CHANGELOG.md index 07cf8e042..1d27757f3 100644 --- a/packages/ethereum-types/CHANGELOG.md +++ b/packages/ethereum-types/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json index 473f9119c..69ae64c2b 100644 --- a/packages/ethereum-types/package.json +++ b/packages/ethereum-types/package.json @@ -1,6 +1,6 @@ { "name": "ethereum-types", - "version": "1.1.3", + "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 af44a13d5..ca256399a 100644 --- a/packages/fill-scenarios/CHANGELOG.json +++ b/packages/fill-scenarios/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.16", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.15", "changes": [ { diff --git a/packages/fill-scenarios/CHANGELOG.md b/packages/fill-scenarios/CHANGELOG.md index f85f5ceed..e9b88547d 100644 --- a/packages/fill-scenarios/CHANGELOG.md +++ b/packages/fill-scenarios/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index 10f8b0495..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.15", + "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.1", - "@0x/base-contract": "^3.0.9", + "@0x/abi-gen-wrappers": "^2.0.2", + "@0x/base-contract": "^3.0.10", "@0x/contract-artifacts": "^1.1.2", - "@0x/order-utils": "^3.0.6", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", - "ethereum-types": "^1.1.3", + "@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/package.json b/packages/instant/package.json index 7a519f460..0a5e152ca 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -1,6 +1,6 @@ { "name": "@0x/instant", - "version": "1.0.3", + "version": "1.0.4", "engines": { "node": ">=6.12" }, @@ -41,18 +41,18 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md", "dependencies": { - "@0x/assert": "^1.0.19", - "@0x/asset-buyer": "^3.0.3", - "@0x/json-schemas": "^2.1.3", - "@0x/order-utils": "^3.0.6", - "@0x/subproviders": "^2.1.7", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "ethereum-types": "^1.1.4", "lodash": "^4.17.5", "polished": "^2.2.0", "react": "^16.5.2", @@ -65,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/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx index 816cc5c33..5b1f9592d 100644 --- a/packages/instant/src/components/instant_heading.tsx +++ b/packages/instant/src/components/instant_heading.tsx @@ -113,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 204115fa9..2de327cd7 100644 --- a/packages/instant/src/components/zero_ex_instant_provider.tsx +++ b/packages/instant/src/components/zero_ex_instant_provider.tsx @@ -122,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/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 1c7490e63..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; diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts index e6128f857..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', @@ -118,6 +121,7 @@ export interface AnalyticsEventOptions { selectedAssetSymbol?: string; selectedAssetData?: string; selectedAssetDecimals?: number; + baseCurrency?: string; } export enum TokenSelectorClosedVia { ClickedX = 'Clicked X', @@ -141,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; @@ -159,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; }, @@ -170,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), @@ -230,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/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/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 07649aa60..201190145 100644 --- a/packages/json-schemas/CHANGELOG.json +++ b/packages/json-schemas/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.1.4", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.1.3", "changes": [ { diff --git a/packages/json-schemas/CHANGELOG.md b/packages/json-schemas/CHANGELOG.md index cb5d315c2..7e407bdda 100644 --- a/packages/json-schemas/CHANGELOG.md +++ b/packages/json-schemas/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index 01662beed..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.3", + "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.5", + "@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.7", + "@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/json-schemas/schemas/order_watcher_web_socket_request_schema.json b/packages/json-schemas/schemas/order_watcher_web_socket_request_schema.json new file mode 100644 index 000000000..b0c419f94 --- /dev/null +++ b/packages/json-schemas/schemas/order_watcher_web_socket_request_schema.json @@ -0,0 +1,52 @@ +{ + "id": "/orderWatcherWebSocketRequestSchema", + "type": "object", + "definitions": { + "signedOrderParam": { + "type": "object", + "properties": { + "signedOrder": { "$ref": "/signedOrderSchema" } + }, + "required": ["signedOrder"] + }, + "orderHashParam": { + "type": "object", + "properties": { + "orderHash": { "$ref": "/hexSchema" } + }, + "required": ["orderHash"] + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "id": { "type": "number" }, + "jsonrpc": { "type": "string" }, + "method": { "enum": ["ADD_ORDER"] }, + "params": { "$ref": "#/definitions/signedOrderParam" } + }, + "required": ["id", "jsonrpc", "method", "params"] + }, + { + "type": "object", + "properties": { + "id": { "type": "number" }, + "jsonrpc": { "type": "string" }, + "method": { "enum": ["REMOVE_ORDER"] }, + "params": { "$ref": "#/definitions/orderHashParam" } + }, + "required": ["id", "jsonrpc", "method", "params"] + }, + { + "type": "object", + "properties": { + "id": { "type": "number" }, + "jsonrpc": { "type": "string" }, + "method": { "enum": ["GET_STATS"] }, + "params": {} + }, + "required": ["id", "jsonrpc", "method"] + } + ] +}
\ No newline at end of file diff --git a/packages/json-schemas/schemas/order_watcher_web_socket_utf8_message_schema.json b/packages/json-schemas/schemas/order_watcher_web_socket_utf8_message_schema.json new file mode 100644 index 000000000..154d6d754 --- /dev/null +++ b/packages/json-schemas/schemas/order_watcher_web_socket_utf8_message_schema.json @@ -0,0 +1,10 @@ +{ + "id": "/orderWatcherWebSocketUtf8MessageSchema", + "properties": { + "utf8Data": { "type": "string" } + }, + "required": [ + "utf8Data" + ], + "type": "object" +} diff --git a/packages/json-schemas/src/schemas.ts b/packages/json-schemas/src/schemas.ts index 21a6f424c..050f4e625 100644 --- a/packages/json-schemas/src/schemas.ts +++ b/packages/json-schemas/src/schemas.ts @@ -16,6 +16,8 @@ import * as orderFillOrKillRequestsSchema from '../schemas/order_fill_or_kill_re import * as orderFillRequestsSchema from '../schemas/order_fill_requests_schema.json'; import * as orderHashSchema from '../schemas/order_hash_schema.json'; import * as orderSchema from '../schemas/order_schema.json'; +import * as orderWatcherWebSocketRequestSchema from '../schemas/order_watcher_web_socket_request_schema.json'; +import * as orderWatcherWebSocketUtf8MessageSchema from '../schemas/order_watcher_web_socket_utf8_message_schema.json'; import * as orderBookRequestSchema from '../schemas/orderbook_request_schema.json'; import * as ordersRequestOptsSchema from '../schemas/orders_request_opts_schema.json'; import * as ordersSchema from '../schemas/orders_schema.json'; @@ -66,6 +68,8 @@ export const schemas = { jsNumber, requestOptsSchema, pagedRequestOptsSchema, + orderWatcherWebSocketRequestSchema, + orderWatcherWebSocketUtf8MessageSchema, ordersRequestOptsSchema, orderBookRequestSchema, orderConfigRequestSchema, diff --git a/packages/json-schemas/tsconfig.json b/packages/json-schemas/tsconfig.json index a79d54385..ec573290c 100644 --- a/packages/json-schemas/tsconfig.json +++ b/packages/json-schemas/tsconfig.json @@ -23,6 +23,8 @@ "./schemas/order_schema.json", "./schemas/signed_order_schema.json", "./schemas/orders_schema.json", + "./schemas/order_watcher_web_socket_request_schema.json", + "./schemas/order_watcher_web_socket_utf8_message_schema.json", "./schemas/paginated_collection_schema.json", "./schemas/relayer_api_asset_data_pairs_response_schema.json", "./schemas/relayer_api_asset_data_pairs_schema.json", diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index e51b240db..0e9fa4920 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -1,6 +1,6 @@ { "name": "@0x/metacoin", - "version": "0.0.31", + "version": "0.0.32", "engines": { "node": ">=6.12" }, @@ -29,26 +29,26 @@ "author": "", "license": "Apache-2.0", "dependencies": { - "@0x/abi-gen": "^1.0.18", + "@0x/abi-gen": "^1.0.19", "@0x/abi-gen-templates": "^1.0.1", - "@0x/base-contract": "^3.0.9", - "@0x/sol-cov": "^2.1.15", - "@0x/subproviders": "^2.1.7", - "@0x/tslint-config": "^1.0.10", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "ethereum-types": "^1.1.4", "ethers": "~4.0.4", "lodash": "^4.17.5", "run-s": "^0.0.0" }, "devDependencies": { - "@0x/dev-utils": "^1.0.20", - "@0x/sol-compiler": "^1.1.15", + "@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 8e109414d..e7b18f12b 100644 --- a/packages/migrations/CHANGELOG.json +++ b/packages/migrations/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.2.2", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.2.1", "changes": [ { diff --git a/packages/migrations/CHANGELOG.md b/packages/migrations/CHANGELOG.md index 7ea114fa1..0b7b9a364 100644 --- a/packages/migrations/CHANGELOG.md +++ b/packages/migrations/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/migrations/package.json b/packages/migrations/package.json index b2d16c0ee..72ffe67b2 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -1,6 +1,6 @@ { "name": "@0x/migrations", - "version": "2.2.1", + "version": "2.2.2", "engines": { "node": ">=6.12" }, @@ -26,9 +26,9 @@ }, "license": "Apache-2.0", "devDependencies": { - "@0x/dev-utils": "^1.0.20", - "@0x/tslint-config": "^1.0.10", - "@0x/types": "^1.4.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.1", - "@0x/base-contract": "^3.0.9", + "@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.6", - "@0x/sol-compiler": "^1.1.15", - "@0x/subproviders": "^2.1.7", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "ethereum-types": "^1.1.4", "ethers": "~4.0.4", "lodash": "^4.17.5" }, diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index d974028be..11889b92e 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.7", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "3.0.6", "changes": [ { diff --git a/packages/order-utils/CHANGELOG.md b/packages/order-utils/CHANGELOG.md index 7b7334db8..bc8b48767 100644 --- a/packages/order-utils/CHANGELOG.md +++ b/packages/order-utils/CHANGELOG.md @@ -5,6 +5,10 @@ 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) diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 55541787a..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.6", + "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.20", - "@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.1", - "@0x/assert": "^1.0.19", - "@0x/base-contract": "^3.0.9", + "@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.3", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "ethereum-types": "^1.1.4", "ethereumjs-abi": "0.6.5", "ethereumjs-util": "^5.1.1", "ethers": "~4.0.4", diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json index 9730e68b7..304dc45fd 100644 --- a/packages/order-watcher/CHANGELOG.json +++ b/packages/order-watcher/CHANGELOG.json @@ -1,5 +1,24 @@ [ { + "version": "2.3.0", + "changes": [ + { + "note": + "Added a WebSocket interface to OrderWatcher so that it can be used by a client written in any language", + "pr": 1427 + } + ] + }, + { + "version": "2.2.8", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.2.7", "changes": [ { diff --git a/packages/order-watcher/CHANGELOG.md b/packages/order-watcher/CHANGELOG.md index 30b4516cf..4e49b4637 100644 --- a/packages/order-watcher/CHANGELOG.md +++ b/packages/order-watcher/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/order-watcher/README.md b/packages/order-watcher/README.md index c0b99b272..385fe4715 100644 --- a/packages/order-watcher/README.md +++ b/packages/order-watcher/README.md @@ -4,6 +4,9 @@ An order watcher daemon that watches for order validity. #### Read the wiki [article](https://0xproject.com/wiki#0x-OrderWatcher). +OrderWatcher also comes with a WebSocket server to provide language-agnostic access +to order watching functionality. We used the [WebSocket Client and Server Implementation for Node](https://www.npmjs.com/package/websocket). The server sends and receives messages that conform to the [JSON RPC specifications](https://www.jsonrpc.org/specification). + ## Installation **Install** @@ -26,6 +29,91 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol } ``` +## Using the WebSocket Server + +**Setup** + +**Environmental Variables** +Several environmental variables can be set to configure the server: + +* `ORDER_WATCHER_HTTP_PORT` specifies the port that the http server will listen on + and accept connections from. When this is not set, we default to 8080. + +**Requests** +The server accepts three types of requests: `ADD_ORDER`, `REMOVE_ORDER` and `GET_STATS`. These mirror what the underlying OrderWatcher does. You can read more in the [wiki](https://0xproject.com/wiki#0x-OrderWatcher). Unlike the OrderWatcher, it does not expose any `subscribe` or `unsubscribe` functionality because the WebSocket server keeps a single subscription open for all clients. + +The first step for making a request is establishing a connection with the server. In Javascript: + +``` +var W3CWebSocket = require('websocket').w3cwebsocket; +wsClient = new W3CWebSocket('ws://127.0.0.1:8080'); +``` + +In Python, you could use the [websocket-client library](http://pypi.python.org/pypi/websocket-client/) and run: + +``` +from websocket import create_connection +wsClient = create_connection("ws://127.0.0.1:8080") +``` + +With the connection established, you prepare the payload for your request. The payload is a json object with a format established by the [JSON RPC specification](https://www.jsonrpc.org/specification): + +* `id`: All requests require you to specify a numerical `id`. When the server responds to the request, the response will have the same `id` as the one supplied with your request. +* `jsonrpc`: This is always the string `'2.0'`. +* `method`: This specifies the OrderWatcher method you want to call. I.e., `'ADD_ORDER'`, `'REMOVE_ORDER'` or `'GET_STATS'`. +* `params`: These contain the parameters needed by OrderWatcher to execute the method you called. For `ADD_ORDER`, provide `{ signedOrder: <your signedOrder> }`. For `REMOVE_ORDER`, provide `{ orderHash: <your orderHash> }`. For `GET_STATS`, no parameters are needed, so you may leave this empty. + +Next, convert the payload to a string and send it through the connection. +In Javascript: + +``` +const addOrderPayload = { + id: 1, + jsonrpc: '2.0', + method: 'ADD_ORDER', + params: { signedOrder: <your signedOrder> }, +}; +wsClient.send(JSON.stringify(addOrderPayload)); +``` + +In Python: + +``` +import json +remove_order_payload = { + 'id': 1, + 'jsonrpc': '2.0', + 'method': 'REMOVE_ORDER', + 'params': {'orderHash': '0x6edc16bf37fde79f5012088c33784c730e2f103d9ab1caf73060c386ad107b7e'}, +} +wsClient.send(json.dumps(remove_order_payload)); +``` + +**Response** +The server responds to all requests in a similar format. In the data field, you'll find another object containing the following fields: + +* `id`: The id corresponding to the request that the server is responding to. `UPDATE` responses are not based on any requests so the `id` field is omitted`. +* `jsonrpc`: Always `'2.0'`. +* `method`: The method the server is responding to. Eg. `ADD_ORDER`. When order states change the server may also initiate a response. In this case, method will be listed as `UPDATE`. +* `result`: This field varies based on the method. `UPDATE` responses contain the new order state. `GET_STATS` responses contain the current order count. When there are errors, this field is omitted. +* `error`: When there is an error executing a request, the [JSON RPC](https://www.jsonrpc.org/specification) error object is listed here. When the server responds successfully, this field is omitted. + +In Javascript, the responses can be parsed using the `onmessage` callback: + +``` +wsClient.onmessage = (msg) => { + const responseData = JSON.parse(msg.data); + const method = responseData.method +}; +``` + +In Python, `recv` is a lightweight way to receive a response: + +``` +result = wsClient.recv() +method = result.method +``` + ## Contributing We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index b6c519e94..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.7", + "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.20", - "@0x/migrations": "^2.2.1", - "@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,24 +57,25 @@ "typescript": "3.0.1" }, "dependencies": { - "@0x/abi-gen-wrappers": "^2.0.1", - "@0x/assert": "^1.0.19", - "@0x/base-contract": "^3.0.9", + "@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.2", - "@0x/fill-scenarios": "^1.0.15", - "@0x/json-schemas": "^2.1.3", - "@0x/order-utils": "^3.0.6", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "ethereum-types": "^1.1.4", "ethereumjs-blockstream": "6.0.0", "ethers": "~4.0.4", - "lodash": "^4.17.5" + "lodash": "^4.17.5", + "websocket": "^1.0.25" }, "publishConfig": { "access": "public" diff --git a/packages/order-watcher/src/index.ts b/packages/order-watcher/src/index.ts index 5eeba3e87..e275a0c6a 100644 --- a/packages/order-watcher/src/index.ts +++ b/packages/order-watcher/src/index.ts @@ -1,4 +1,5 @@ export { OrderWatcher } from './order_watcher/order_watcher'; +export { OrderWatcherWebSocketServer } from './order_watcher/order_watcher_web_socket_server'; export { ExpirationWatcher } from './order_watcher/expiration_watcher'; export { diff --git a/packages/order-watcher/src/order_watcher/order_watcher_web_socket_server.ts b/packages/order-watcher/src/order_watcher/order_watcher_web_socket_server.ts new file mode 100644 index 000000000..b75b07603 --- /dev/null +++ b/packages/order-watcher/src/order_watcher/order_watcher_web_socket_server.ts @@ -0,0 +1,200 @@ +import { ContractAddresses } from '@0x/contract-addresses'; +import { schemas } from '@0x/json-schemas'; +import { OrderStateInvalid, OrderStateValid, SignedOrder } from '@0x/types'; +import { BigNumber, logUtils } from '@0x/utils'; +import { Provider } from 'ethereum-types'; +import * as http from 'http'; +import * as WebSocket from 'websocket'; + +import { GetStatsResult, OrderWatcherConfig, OrderWatcherMethod, WebSocketRequest, WebSocketResponse } from '../types'; +import { assert } from '../utils/assert'; + +import { OrderWatcher } from './order_watcher'; + +const DEFAULT_HTTP_PORT = 8080; +const JSON_RPC_VERSION = '2.0'; + +// Wraps the OrderWatcher functionality in a WebSocket server. Motivations: +// 1) Users can watch orders via non-typescript programs. +// 2) Better encapsulation so that users can work +export class OrderWatcherWebSocketServer { + private readonly _orderWatcher: OrderWatcher; + private readonly _httpServer: http.Server; + private readonly _connectionStore: Set<WebSocket.connection>; + private readonly _wsServer: WebSocket.server; + private readonly _isVerbose: boolean; + /** + * Recover types lost when the payload is stringified. + */ + private static _parseSignedOrder(rawRequest: any): SignedOrder { + const bigNumberFields = [ + 'salt', + 'makerFee', + 'takerFee', + 'makerAssetAmount', + 'takerAssetAmount', + 'expirationTimeSeconds', + ]; + for (const field of bigNumberFields) { + rawRequest[field] = new BigNumber(rawRequest[field]); + } + return rawRequest; + } + + /** + * Instantiate a new WebSocket server which provides OrderWatcher functionality + * @param provider Web3 provider to use for JSON RPC calls. + * @param networkId NetworkId to watch orders on. + * @param contractAddresses Optional contract addresses. Defaults to known + * addresses based on networkId. + * @param orderWatcherConfig OrderWatcher configurations. isVerbose sets the verbosity for the WebSocket server aswell. + * @param isVerbose Whether to enable verbose logging. Defaults to true. + */ + constructor( + provider: Provider, + networkId: number, + contractAddresses?: ContractAddresses, + orderWatcherConfig?: Partial<OrderWatcherConfig>, + ) { + this._isVerbose = + orderWatcherConfig !== undefined && orderWatcherConfig.isVerbose !== undefined + ? orderWatcherConfig.isVerbose + : true; + this._orderWatcher = new OrderWatcher(provider, networkId, contractAddresses, orderWatcherConfig); + this._connectionStore = new Set(); + this._httpServer = http.createServer(); + this._wsServer = new WebSocket.server({ + httpServer: this._httpServer, + // Avoid setting autoAcceptConnections to true as it defeats all + // standard cross-origin protection facilities built into the protocol + // and the browser. + // Source: https://www.npmjs.com/package/websocket#server-example + // Also ensures that a request event is emitted by + // the server whenever a new WebSocket request is made. + autoAcceptConnections: false, + }); + + this._wsServer.on('request', async (request: any) => { + // Designed for usage pattern where client and server are run on the same + // machine by the same user. As such, no security checks are in place. + const connection: WebSocket.connection = request.accept(null, request.origin); + this._log(`${new Date()} [Server] Accepted connection from origin ${request.origin}.`); + connection.on('message', this._onMessageCallbackAsync.bind(this, connection)); + connection.on('close', this._onCloseCallback.bind(this, connection)); + this._connectionStore.add(connection); + }); + } + + /** + * Activates the WebSocket server by subscribing to the OrderWatcher and + * starting the WebSocket's HTTP server + */ + public start(): void { + // Have the WebSocket server subscribe to the OrderWatcher to receive updates. + // These updates are then broadcast to clients in the _connectionStore. + this._orderWatcher.subscribe(this._broadcastCallback.bind(this)); + + const port = process.env.ORDER_WATCHER_HTTP_PORT || DEFAULT_HTTP_PORT; + this._httpServer.listen(port, () => { + this._log(`${new Date()} [Server] Listening on port ${port}`); + }); + } + + /** + * Deactivates the WebSocket server by stopping the HTTP server from accepting + * new connections and unsubscribing from the OrderWatcher + */ + public stop(): void { + this._httpServer.close(); + this._orderWatcher.unsubscribe(); + } + + private _log(...args: any[]): void { + if (this._isVerbose) { + logUtils.log(...args); + } + } + + private async _onMessageCallbackAsync(connection: WebSocket.connection, message: any): Promise<void> { + let response: WebSocketResponse; + let id: number | null = null; + try { + assert.doesConformToSchema('message', message, schemas.orderWatcherWebSocketUtf8MessageSchema); + const request: WebSocketRequest = JSON.parse(message.utf8Data); + id = request.id; + assert.doesConformToSchema('request', request, schemas.orderWatcherWebSocketRequestSchema); + assert.isString(request.jsonrpc, JSON_RPC_VERSION); + response = { + id, + jsonrpc: JSON_RPC_VERSION, + method: request.method, + result: await this._routeRequestAsync(request), + }; + } catch (err) { + response = { + id, + jsonrpc: JSON_RPC_VERSION, + method: null, + error: err.toString(), + }; + } + this._log(`${new Date()} [Server] OrderWatcher output: ${JSON.stringify(response)}`); + connection.sendUTF(JSON.stringify(response)); + } + + private _onCloseCallback(connection: WebSocket.connection): void { + this._connectionStore.delete(connection); + this._log(`${new Date()} [Server] Client ${connection.remoteAddress} disconnected.`); + } + + private async _routeRequestAsync(request: WebSocketRequest): Promise<GetStatsResult | undefined> { + this._log(`${new Date()} [Server] Request received: ${request.method}`); + switch (request.method) { + case OrderWatcherMethod.AddOrder: { + const signedOrder: SignedOrder = OrderWatcherWebSocketServer._parseSignedOrder( + request.params.signedOrder, + ); + await this._orderWatcher.addOrderAsync(signedOrder); + break; + } + case OrderWatcherMethod.RemoveOrder: { + this._orderWatcher.removeOrder(request.params.orderHash || 'undefined'); + break; + } + case OrderWatcherMethod.GetStats: { + return this._orderWatcher.getStats(); + } + default: + // Should never reach here. Should be caught by JSON schema check. + throw new Error(`Unexpected default case hit for request.method`); + } + return undefined; + } + + /** + * Broadcasts OrderState changes to ALL connected clients. At the moment, + * we do not support clients subscribing to only a subset of orders. As such, + * Client B will be notified of changes to an order that Client A added. + */ + private _broadcastCallback(err: Error | null, orderState?: OrderStateValid | OrderStateInvalid | undefined): void { + const method = OrderWatcherMethod.Update; + const response = + err === null + ? { + jsonrpc: JSON_RPC_VERSION, + method, + result: orderState, + } + : { + jsonrpc: JSON_RPC_VERSION, + method, + error: { + code: -32000, + message: err.message, + }, + }; + this._connectionStore.forEach((connection: WebSocket.connection) => { + connection.sendUTF(JSON.stringify(response)); + }); + } +} diff --git a/packages/order-watcher/src/types.ts b/packages/order-watcher/src/types.ts index 8078dd971..2b529a939 100644 --- a/packages/order-watcher/src/types.ts +++ b/packages/order-watcher/src/types.ts @@ -1,4 +1,4 @@ -import { OrderState } from '@0x/types'; +import { OrderState, SignedOrder } from '@0x/types'; import { LogEntryEvent } from 'ethereum-types'; export enum OrderWatcherError { @@ -31,3 +31,67 @@ export enum InternalOrderWatcherError { ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY', WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY', } + +export enum OrderWatcherMethod { + // Methods initiated by the user. + GetStats = 'GET_STATS', + AddOrder = 'ADD_ORDER', + RemoveOrder = 'REMOVE_ORDER', + // These are spontaneous; they are primarily orderstate changes. + Update = 'UPDATE', + // `subscribe` and `unsubscribe` are methods of OrderWatcher, but we don't + // need to expose them to the WebSocket server user because the user implicitly + // subscribes and unsubscribes by connecting and disconnecting from the server. +} + +// Users have to create a json object of this format and attach it to +// the data field of their WebSocket message to interact with the server. +export type WebSocketRequest = AddOrderRequest | RemoveOrderRequest | GetStatsRequest; + +export interface AddOrderRequest { + id: number; + jsonrpc: string; + method: OrderWatcherMethod.AddOrder; + params: { signedOrder: SignedOrder }; +} + +export interface RemoveOrderRequest { + id: number; + jsonrpc: string; + method: OrderWatcherMethod.RemoveOrder; + params: { orderHash: string }; +} + +export interface GetStatsRequest { + id: number; + jsonrpc: string; + method: OrderWatcherMethod.GetStats; +} + +// Users should expect a json object of this format in the data field +// of the WebSocket messages that the server sends out. +export type WebSocketResponse = SuccessfulWebSocketResponse | ErrorWebSocketResponse; + +export interface SuccessfulWebSocketResponse { + id: number; + jsonrpc: string; + method: OrderWatcherMethod; + result: OrderState | GetStatsResult | undefined; // result is undefined for ADD_ORDER and REMOVE_ORDER +} + +export interface ErrorWebSocketResponse { + id: number | null; + jsonrpc: string; + method: null; + error: JSONRPCError; +} + +export interface JSONRPCError { + code: number; + message: string; + data?: string | object; +} + +export interface GetStatsResult { + orderCount: number; +} diff --git a/packages/order-watcher/test/order_watcher_web_socket_server_test.ts b/packages/order-watcher/test/order_watcher_web_socket_server_test.ts new file mode 100644 index 000000000..578e0de61 --- /dev/null +++ b/packages/order-watcher/test/order_watcher_web_socket_server_test.ts @@ -0,0 +1,308 @@ +import { ContractWrappers } from '@0x/contract-wrappers'; +import { tokenUtils } from '@0x/contract-wrappers/lib/test/utils/token_utils'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; +import { ExchangeContractErrs, OrderStateInvalid, OrderStateValid, SignedOrder } from '@0x/types'; +import { BigNumber, logUtils } from '@0x/utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import * as chai from 'chai'; +import 'mocha'; +import * as WebSocket from 'websocket'; + +import { OrderWatcherWebSocketServer } from '../src/order_watcher/order_watcher_web_socket_server'; +import { AddOrderRequest, OrderWatcherMethod, RemoveOrderRequest } from '../src/types'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +interface WsMessage { + data: string; +} + +describe.only('OrderWatcherWebSocketServer', async () => { + let contractWrappers: ContractWrappers; + let wsServer: OrderWatcherWebSocketServer; + let wsClient: WebSocket.w3cwebsocket; + let wsClientTwo: WebSocket.w3cwebsocket; + let fillScenarios: FillScenarios; + let userAddresses: string[]; + let makerAssetData: string; + let takerAssetData: string; + let makerTokenAddress: string; + let takerTokenAddress: string; + let makerAddress: string; + let takerAddress: string; + let zrxTokenAddress: string; + let signedOrder: SignedOrder; + let orderHash: string; + let addOrderPayload: AddOrderRequest; + let removeOrderPayload: RemoveOrderRequest; + const decimals = constants.ZRX_DECIMALS; + const fillableAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals); + + before(async () => { + // Set up constants + const contractAddresses = await migrateOnceAsync(); + await blockchainLifecycle.startAsync(); + const networkId = constants.TESTRPC_NETWORK_ID; + const config = { + networkId, + contractAddresses, + }; + contractWrappers = new ContractWrappers(provider, config); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + zrxTokenAddress = contractAddresses.zrxToken; + [makerAddress, takerAddress] = userAddresses; + [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + [makerAssetData, takerAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + fillScenarios = new FillScenarios( + provider, + userAddresses, + zrxTokenAddress, + contractAddresses.exchange, + contractAddresses.erc20Proxy, + contractAddresses.erc721Proxy, + ); + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableAmount, + ); + orderHash = orderHashUtils.getOrderHashHex(signedOrder); + addOrderPayload = { + id: 1, + jsonrpc: '2.0', + method: OrderWatcherMethod.AddOrder, + params: { signedOrder }, + }; + removeOrderPayload = { + id: 1, + jsonrpc: '2.0', + method: OrderWatcherMethod.RemoveOrder, + params: { orderHash }, + }; + + // Prepare OrderWatcher WebSocket server + const orderWatcherConfig = { + isVerbose: true, + }; + wsServer = new OrderWatcherWebSocketServer(provider, networkId, contractAddresses, orderWatcherConfig); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + wsServer.start(); + await blockchainLifecycle.startAsync(); + wsClient = new WebSocket.w3cwebsocket('ws://127.0.0.1:8080/'); + logUtils.log(`${new Date()} [Client] Connected.`); + }); + afterEach(async () => { + wsClient.close(); + await blockchainLifecycle.revertAsync(); + wsServer.stop(); + logUtils.log(`${new Date()} [Client] Closed.`); + }); + + it('responds to getStats requests correctly', (done: any) => { + const payload = { + id: 1, + jsonrpc: '2.0', + method: 'GET_STATS', + }; + wsClient.onopen = () => wsClient.send(JSON.stringify(payload)); + wsClient.onmessage = (msg: any) => { + const responseData = JSON.parse(msg.data); + expect(responseData.id).to.be.eq(1); + expect(responseData.jsonrpc).to.be.eq('2.0'); + expect(responseData.method).to.be.eq('GET_STATS'); + expect(responseData.result.orderCount).to.be.eq(0); + done(); + }; + }); + + it('throws an error when an invalid method is attempted', async () => { + const invalidMethodPayload = { + id: 1, + jsonrpc: '2.0', + method: 'BAD_METHOD', + }; + wsClient.onopen = () => wsClient.send(JSON.stringify(invalidMethodPayload)); + const errorMsg = await onMessageAsync(wsClient, null); + const errorData = JSON.parse(errorMsg.data); + // tslint:disable-next-line:no-unused-expression + expect(errorData.id).to.be.null; + // tslint:disable-next-line:no-unused-expression + expect(errorData.method).to.be.null; + expect(errorData.jsonrpc).to.be.eq('2.0'); + expect(errorData.error).to.match(/^Error: Expected request to conform to schema/); + }); + + it('throws an error when jsonrpc field missing from request', async () => { + const noJsonRpcPayload = { + id: 1, + method: 'GET_STATS', + }; + wsClient.onopen = () => wsClient.send(JSON.stringify(noJsonRpcPayload)); + const errorMsg = await onMessageAsync(wsClient, null); + const errorData = JSON.parse(errorMsg.data); + // tslint:disable-next-line:no-unused-expression + expect(errorData.method).to.be.null; + expect(errorData.jsonrpc).to.be.eq('2.0'); + expect(errorData.error).to.match(/^Error: Expected request to conform to schema/); + }); + + it('throws an error when we try to add an order without a signedOrder', async () => { + const noSignedOrderAddOrderPayload = { + id: 1, + jsonrpc: '2.0', + method: 'ADD_ORDER', + orderHash: '0x7337e2f2a9aa2ed6afe26edc2df7ad79c3ffa9cf9b81a964f707ea63f5272355', + }; + wsClient.onopen = () => wsClient.send(JSON.stringify(noSignedOrderAddOrderPayload)); + const errorMsg = await onMessageAsync(wsClient, null); + const errorData = JSON.parse(errorMsg.data); + // tslint:disable-next-line:no-unused-expression + expect(errorData.id).to.be.null; + // tslint:disable-next-line:no-unused-expression + expect(errorData.method).to.be.null; + expect(errorData.jsonrpc).to.be.eq('2.0'); + expect(errorData.error).to.match(/^Error: Expected request to conform to schema/); + }); + + it('throws an error when we try to add a bad signedOrder', async () => { + const invalidAddOrderPayload = { + id: 1, + jsonrpc: '2.0', + method: 'ADD_ORDER', + signedOrder: { + makerAddress: '0x0', + }, + }; + wsClient.onopen = () => wsClient.send(JSON.stringify(invalidAddOrderPayload)); + const errorMsg = await onMessageAsync(wsClient, null); + const errorData = JSON.parse(errorMsg.data); + // tslint:disable-next-line:no-unused-expression + expect(errorData.id).to.be.null; + // tslint:disable-next-line:no-unused-expression + expect(errorData.method).to.be.null; + expect(errorData.error).to.match(/^Error: Expected request to conform to schema/); + }); + + it('executes addOrder and removeOrder requests correctly', async () => { + wsClient.onopen = () => wsClient.send(JSON.stringify(addOrderPayload)); + const addOrderMsg = await onMessageAsync(wsClient, OrderWatcherMethod.AddOrder); + const addOrderData = JSON.parse(addOrderMsg.data); + expect(addOrderData.method).to.be.eq('ADD_ORDER'); + expect((wsServer as any)._orderWatcher._orderByOrderHash).to.deep.include({ + [orderHash]: signedOrder, + }); + + const clientOnMessagePromise = onMessageAsync(wsClient, OrderWatcherMethod.RemoveOrder); + wsClient.send(JSON.stringify(removeOrderPayload)); + const removeOrderMsg = await clientOnMessagePromise; + const removeOrderData = JSON.parse(removeOrderMsg.data); + expect(removeOrderData.method).to.be.eq('REMOVE_ORDER'); + expect((wsServer as any)._orderWatcher._orderByOrderHash).to.not.deep.include({ + [orderHash]: signedOrder, + }); + }); + + it('broadcasts orderStateInvalid message when makerAddress allowance set to 0 for watched order', async () => { + // Add the regular order + wsClient.onopen = () => wsClient.send(JSON.stringify(addOrderPayload)); + + // We register the onMessage callback before calling `setProxyAllowanceAsync` which we + // expect will cause a message to be emitted. We do now "await" here, since we want to + // check for messages _after_ calling `setProxyAllowanceAsync` + const clientOnMessagePromise = onMessageAsync(wsClient, OrderWatcherMethod.Update); + + // Set the allowance to 0 + await contractWrappers.erc20Token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, new BigNumber(0)); + + // We now await the `onMessage` promise to check for the message + const orderWatcherUpdateMsg = await clientOnMessagePromise; + const orderWatcherUpdateData = JSON.parse(orderWatcherUpdateMsg.data); + expect(orderWatcherUpdateData.method).to.be.eq('UPDATE'); + const invalidOrderState = orderWatcherUpdateData.result as OrderStateInvalid; + expect(invalidOrderState.isValid).to.be.false(); + expect(invalidOrderState.orderHash).to.be.eq(orderHash); + expect(invalidOrderState.error).to.be.eq(ExchangeContractErrs.InsufficientMakerAllowance); + }); + + it('broadcasts to multiple clients when an order backing ZRX allowance changes', async () => { + // Prepare order + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), decimals); + const nonZeroMakerFeeSignedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( + makerAssetData, + takerAssetData, + makerFee, + takerFee, + makerAddress, + takerAddress, + fillableAmount, + takerAddress, + ); + const nonZeroMakerFeeOrderPayload = { + id: 1, + jsonrpc: '2.0', + method: 'ADD_ORDER', + signedOrder: nonZeroMakerFeeSignedOrder, + }; + + // Set up a second client and have it add the order + wsClientTwo = new WebSocket.w3cwebsocket('ws://127.0.0.1:8080/'); + logUtils.log(`${new Date()} [Client] Connected.`); + wsClientTwo.onopen = () => wsClientTwo.send(JSON.stringify(nonZeroMakerFeeOrderPayload)); + + // Setup the onMessage callbacks, but don't await them yet + const clientOneOnMessagePromise = onMessageAsync(wsClient, OrderWatcherMethod.Update); + const clientTwoOnMessagePromise = onMessageAsync(wsClientTwo, OrderWatcherMethod.Update); + + // Change the allowance + await contractWrappers.erc20Token.setProxyAllowanceAsync(zrxTokenAddress, makerAddress, new BigNumber(0)); + + // Check that both clients receive the emitted event by awaiting the onMessageAsync promises + let updateMsg = await clientOneOnMessagePromise; + let updateData = JSON.parse(updateMsg.data); + let orderState = updateData.result as OrderStateValid; + expect(orderState.isValid).to.be.true(); + expect(orderState.orderRelevantState.makerFeeProxyAllowance).to.be.eq('0'); + + updateMsg = await clientTwoOnMessagePromise; + updateData = JSON.parse(updateMsg.data); + orderState = updateData.result as OrderStateValid; + expect(orderState.isValid).to.be.true(); + expect(orderState.orderRelevantState.makerFeeProxyAllowance).to.be.eq('0'); + + wsClientTwo.close(); + logUtils.log(`${new Date()} [Client] Closed.`); + }); +}); + +// HACK: createFillableSignedOrderAsync is Promise-based, which forces us +// to use Promises instead of the done() callbacks for tests. +// onmessage callback must thus be wrapped as a Promise. +async function onMessageAsync(client: WebSocket.w3cwebsocket, method: string | null): Promise<WsMessage> { + return new Promise<WsMessage>(resolve => { + client.onmessage = (msg: WsMessage) => { + const data = JSON.parse(msg.data); + if (data.method === method) { + resolve(msg); + } + }; + }); +} diff --git a/packages/pipeline/package.json b/packages/pipeline/package.json index f8adf9055..a40f3d21c 100644 --- a/packages/pipeline/package.json +++ b/packages/pipeline/package.json @@ -1,6 +1,6 @@ { "name": "@0x/pipeline", - "version": "1.0.1", + "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,23 +39,23 @@ "typescript": "3.0.1" }, "dependencies": { - "@0x/connect": "^3.0.9", + "@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.20", + "@0x/dev-utils": "^1.0.21", "@0x/order-utils": "^2.0.0", - "@0x/subproviders": "^2.1.7", - "@0x/types": "^1.4.0", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.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.1.3", + "ethereum-types": "^1.1.4", "pg": "^7.5.0", "prettier": "^1.15.3", "ramda": "^0.25.0", diff --git a/packages/pipeline/src/parsers/ddex_orders/index.ts b/packages/pipeline/src/parsers/ddex_orders/index.ts index 52a998f9f..d7b97efbe 100644 --- a/packages/pipeline/src/parsers/ddex_orders/index.ts +++ b/packages/pipeline/src/parsers/ddex_orders/index.ts @@ -54,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/oasis_orders/index.ts b/packages/pipeline/src/parsers/oasis_orders/index.ts index 7aafbf460..13997f31b 100644 --- a/packages/pipeline/src/parsers/oasis_orders/index.ts +++ b/packages/pipeline/src/parsers/oasis_orders/index.ts @@ -62,10 +62,10 @@ export function parseOasisOrder( tokenOrder.baseAssetSymbol = oasisMarket.base; tokenOrder.baseAssetAddress = null; // Oasis doesn't provide address information - tokenOrder.baseVolume = price.times(amount); + tokenOrder.baseVolume = amount; tokenOrder.quoteAssetSymbol = oasisMarket.quote; tokenOrder.quoteAssetAddress = null; // Oasis doesn't provide address information - tokenOrder.quoteVolume = amount; + 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/scripts/pull_erc20_events.ts b/packages/pipeline/src/scripts/pull_erc20_events.ts index 0ad12c97a..bd520c610 100644 --- a/packages/pipeline/src/scripts/pull_erc20_events.ts +++ b/packages/pipeline/src/scripts/pull_erc20_events.ts @@ -1,10 +1,10 @@ -// tslint:disable:no-console 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, Repository } from 'typeorm'; +import { Connection, ConnectionOptions, createConnection } from 'typeorm'; import { ERC20EventsSource } from '../data_sources/contract-wrappers/erc20_events'; import { ERC20ApprovalEvent } from '../entities'; @@ -16,33 +16,63 @@ 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. -const WETH_START_BLOCK = 4719568; // Block number when the WETH contract was deployed. 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); - await getAndSaveWETHApprovalEventsAsync(provider, endBlock); + for (const token of tokensToGetApprovalEvents) { + await getAndSaveApprovalEventsAsync(provider, token, endBlock); + } process.exit(0); })().catch(handleError); -async function getAndSaveWETHApprovalEventsAsync(provider: Web3ProviderEngine, endBlock: number): Promise<void> { - console.log('Checking existing approval events...'); +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(repository)) || WETH_START_BLOCK; + const startBlock = (await getStartBlockAsync(token)) || token.defaultStartBlock; - console.log(`Getting WETH approval events starting at ${startBlock}...`); - const wethTokenAddress = getContractAddressesForNetworkOrThrow(NETWORK_ID).etherToken; - const eventsSource = new ERC20EventsSource(provider, NETWORK_ID, wethTokenAddress); + logUtils.log(`Getting approval events starting at ${startBlock}...`); + const eventsSource = new ERC20EventsSource(provider, NETWORK_ID, token.address); const eventLogs = await eventsSource.getApprovalEventsAsync(startBlock, endBlock); - console.log(`Parsing ${eventLogs.length} WETH approval events...`); + logUtils.log(`Parsing ${eventLogs.length} approval events...`); const events = parseERC20ApprovalEvents(eventLogs); - console.log(`Retrieved and parsed ${events.length} total WETH approval events.`); + logUtils.log(`Retrieved and parsed ${events.length} total approval events.`); await repository.save(events, { chunk: Math.ceil(events.length / BATCH_SAVE_SIZE) }); } @@ -52,15 +82,15 @@ async function calculateEndBlockAsync(provider: Web3ProviderEngine): Promise<num return currentBlock - BLOCK_FINALITY_THRESHOLD; } -async function getStartBlockAsync(repository: Repository<ERC20ApprovalEvent>): Promise<number | null> { - const fillEventCount = await repository.count(); - if (fillEventCount === 0) { - console.log(`No existing approval events found.`); - return null; - } +async function getStartBlockAsync(token: Token): Promise<number | null> { const queryResult = await connection.query( - `SELECT block_number FROM raw.erc20_approval_events ORDER BY block_number DESC LIMIT 1`, + `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_blocks.ts b/packages/pipeline/src/scripts/pull_missing_blocks.ts index a5203824c..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; @@ -37,22 +37,19 @@ interface MissingBlocksResponse { async function getAllMissingBlocksAsync(web3Source: Web3Source): Promise<void> { const blocksRepository = connection.getRepository(Block); - let fromBlock = EXCHANGE_START_BLOCK; while (true) { - const blockNumbers = await getMissingBlockNumbersAsync(fromBlock); + const blockNumbers = await getMissingBlockNumbersAsync(); if (blockNumbers.length === 0) { // There are no more missing blocks. We're done. break; } await getAndSaveBlocksAsync(web3Source, blocksRepository, blockNumbers); - fromBlock = Math.max(...blockNumbers) + 1; } const totalBlocks = await blocksRepository.count(); console.log(`Done saving blocks. There are now ${totalBlocks} total blocks.`); } -async function getMissingBlockNumbersAsync(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 @@ -66,13 +63,12 @@ async function getMissingBlockNumbersAsync(fromBlock: number): Promise<number[]> ) SELECT DISTINCT(block_number) FROM all_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], + 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; } 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/test/parsers/ddex_orders/index_test.ts b/packages/pipeline/test/parsers/ddex_orders/index_test.ts index 9f4bfe7e3..4a4a86bf8 100644 --- a/packages/pipeline/test/parsers/ddex_orders/index_test.ts +++ b/packages/pipeline/test/parsers/ddex_orders/index_test.ts @@ -39,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/oasis_orders/index_test.ts b/packages/pipeline/test/parsers/oasis_orders/index_test.ts index 9e8ba9a40..433bfb665 100644 --- a/packages/pipeline/test/parsers/oasis_orders/index_test.ts +++ b/packages/pipeline/test/parsers/oasis_orders/index_test.ts @@ -37,10 +37,10 @@ describe('oasis_orders', () => { expected.price = new BigNumber(0.5); expected.baseAssetSymbol = 'DEF'; expected.baseAssetAddress = null; - expected.baseVolume = new BigNumber(5); + expected.baseVolume = new BigNumber(10); expected.quoteAssetSymbol = 'ABC'; expected.quoteAssetAddress = null; - expected.quoteVolume = new BigNumber(10); + 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/react-docs/CHANGELOG.json b/packages/react-docs/CHANGELOG.json index 51d3be8ec..9d8b5bc88 100644 --- a/packages/react-docs/CHANGELOG.json +++ b/packages/react-docs/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.22", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.21", "changes": [ { diff --git a/packages/react-docs/CHANGELOG.md b/packages/react-docs/CHANGELOG.md index fc8f7db1f..5c702d562 100644 --- a/packages/react-docs/CHANGELOG.md +++ b/packages/react-docs/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index b4de54a21..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.21", + "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.20", - "@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.24", - "@0x/types": "^1.4.0", - "@0x/utils": "^2.0.7", + "@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 985e56814..23e0d7f7e 100644 --- a/packages/react-shared/CHANGELOG.json +++ b/packages/react-shared/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.25", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.24", "changes": [ { diff --git a/packages/react-shared/CHANGELOG.md b/packages/react-shared/CHANGELOG.md index 456eb765a..8afa94e04 100644 --- a/packages/react-shared/CHANGELOG.md +++ b/packages/react-shared/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index 125edf374..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.24", + "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.20", - "@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.4.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 8da8726e7..0a757f519 100644 --- a/packages/sol-compiler/CHANGELOG.json +++ b/packages/sol-compiler/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.1.16", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.1.15", "changes": [ { diff --git a/packages/sol-compiler/CHANGELOG.md b/packages/sol-compiler/CHANGELOG.md index 05b48f0fc..b2066448d 100644 --- a/packages/sol-compiler/CHANGELOG.md +++ b/packages/sol-compiler/CHANGELOG.md @@ -5,6 +5,10 @@ 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) diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 35c3012f6..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.15", + "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.20", - "@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.19", - "@0x/json-schemas": "^2.1.3", - "@0x/sol-resolver": "^1.1.0", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "ethereum-types": "^1.1.4", "ethereumjs-util": "^5.1.1", "lodash": "^4.17.5", "mkdirp": "^0.5.1", diff --git a/packages/sol-cov/CHANGELOG.json b/packages/sol-cov/CHANGELOG.json index 45b57bdac..b7973c135 100644 --- a/packages/sol-cov/CHANGELOG.json +++ b/packages/sol-cov/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.1.16", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.1.15", "changes": [ { diff --git a/packages/sol-cov/CHANGELOG.md b/packages/sol-cov/CHANGELOG.md index c827b1865..879ef9c95 100644 --- a/packages/sol-cov/CHANGELOG.md +++ b/packages/sol-cov/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index aae65107a..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.15", + "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.20", - "@0x/sol-compiler": "^1.1.15", - "@0x/subproviders": "^2.1.7", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "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 9c6d724bc..e8fef746e 100644 --- a/packages/sol-doc/CHANGELOG.json +++ b/packages/sol-doc/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.11", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.10", "changes": [ { diff --git a/packages/sol-doc/CHANGELOG.md b/packages/sol-doc/CHANGELOG.md index 5a1fa1d5a..1b4a938af 100644 --- a/packages/sol-doc/CHANGELOG.md +++ b/packages/sol-doc/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/sol-doc/package.json b/packages/sol-doc/package.json index 1d2762875..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.10", + "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.15", - "@0x/types": "^1.4.0", - "@0x/utils": "^2.0.7", - "ethereum-types": "^1.1.3", + "@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 40c34d2e7..85398e624 100644 --- a/packages/sol-resolver/CHANGELOG.json +++ b/packages/sol-resolver/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.1.1", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.1.0", "changes": [ { diff --git a/packages/sol-resolver/CHANGELOG.md b/packages/sol-resolver/CHANGELOG.md index d37938a58..98435be19 100644 --- a/packages/sol-resolver/CHANGELOG.md +++ b/packages/sol-resolver/CHANGELOG.md @@ -5,6 +5,10 @@ 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) diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index f6a928356..0163765d9 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -1,6 +1,6 @@ { "name": "@0x/sol-resolver", - "version": "1.1.0", + "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.4.0", - "@0x/typescript-typings": "^3.0.5", + "@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 9897ae6a3..393054465 100644 --- a/packages/sra-spec/CHANGELOG.json +++ b/packages/sra-spec/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.13", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "1.0.12", "changes": [ { diff --git a/packages/sra-spec/CHANGELOG.md b/packages/sra-spec/CHANGELOG.md index 0f6aef476..fd673b837 100644 --- a/packages/sra-spec/CHANGELOG.md +++ b/packages/sra-spec/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/sra-spec/package.json b/packages/sra-spec/package.json index 2983ba044..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.12", + "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.3", + "@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 f0766e58b..938b2a717 100644 --- a/packages/subproviders/CHANGELOG.json +++ b/packages/subproviders/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.1.8", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.1.7", "changes": [ { diff --git a/packages/subproviders/CHANGELOG.md b/packages/subproviders/CHANGELOG.md index b0bef4b0d..002c76395 100644 --- a/packages/subproviders/CHANGELOG.md +++ b/packages/subproviders/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 8cd29b8e8..90ef6b677 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -1,6 +1,6 @@ { "name": "@0x/subproviders", - "version": "2.1.7", + "version": "2.1.8", "engines": { "node": ">=6.12" }, @@ -29,11 +29,11 @@ } }, "dependencies": { - "@0x/assert": "^1.0.19", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "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 454314c86..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.59", + "version": "1.0.60", "engines": { "node": ">=6.12" }, @@ -18,13 +18,13 @@ "author": "Fabio Berger", "license": "Apache-2.0", "dependencies": { - "0x.js": "^2.0.7", - "@0x/subproviders": "^2.1.7", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "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.3", + "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 eb2698a75..0070a5b81 100644 --- a/packages/tslint-config/CHANGELOG.json +++ b/packages/tslint-config/CHANGELOG.json @@ -6,7 +6,8 @@ "note": "Improve async-suffix rule to check functions too, not just methods", "pr": 1425 } - ] + ], + "timestamp": 1544739608 }, { "version": "1.0.10", 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/types/CHANGELOG.json b/packages/types/CHANGELOG.json index 23a317a15..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": [ { diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index ef8337d76..5170eb4db 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -5,6 +5,10 @@ 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) diff --git a/packages/types/package.json b/packages/types/package.json index 1e2bc5ae8..3c4bb6fe6 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@0x/types", - "version": "1.4.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.3" + "ethereum-types": "^1.1.4" }, "publishConfig": { "access": "public" diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 6b728af71..4470dd501 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -243,6 +243,10 @@ export enum RevertReason { AuctionNotStarted = 'AUCTION_NOT_STARTED', AuctionInvalidBeginTime = 'INVALID_BEGIN_TIME', InvalidAssetData = 'INVALID_ASSET_DATA', + // Balance Threshold Filter + InvalidOrBlockedExchangeSelector = 'INVALID_OR_BLOCKED_EXCHANGE_SELECTOR', + BalanceQueryFailed = 'BALANCE_QUERY_FAILED', + AtLeastOneAddressDoesNotMeetBalanceThreshold = 'AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD', } export enum StatusCodes { diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json index 39ef9d77c..fadf5ad14 100644 --- a/packages/typescript-typings/CHANGELOG.json +++ b/packages/typescript-typings/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.0.6", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "3.0.5", "changes": [ { diff --git a/packages/typescript-typings/CHANGELOG.md b/packages/typescript-typings/CHANGELOG.md index 2e8553a91..1663d40af 100644 --- a/packages/typescript-typings/CHANGELOG.md +++ b/packages/typescript-typings/CHANGELOG.md @@ -5,6 +5,10 @@ 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 diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json index 59e0803eb..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.5", + "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.3", + "ethereum-types": "^1.1.4", "popper.js": "1.14.3" }, "devDependencies": { diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index 74fce56aa..fe66d3f31 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "2.0.8", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "2.0.7", "changes": [ { diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 45553430d..c0437392d 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -5,6 +5,10 @@ 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. diff --git a/packages/utils/package.json b/packages/utils/package.json index 38c729337..a25dc9cff 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@0x/utils", - "version": "2.0.7", + "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.4.0", - "@0x/typescript-typings": "^3.0.5", + "@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.3", + "ethereum-types": "^1.1.4", "ethereumjs-util": "^5.1.1", "ethers": "~4.0.4", "isomorphic-fetch": "^2.2.1", diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json index ccbd9ed81..6b76626a9 100644 --- a/packages/web3-wrapper/CHANGELOG.json +++ b/packages/web3-wrapper/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "3.2.1", + "changes": [ + { + "note": "Dependencies updated" + } + ], + "timestamp": 1544739608 + }, + { "version": "3.2.0", "changes": [ { diff --git a/packages/web3-wrapper/CHANGELOG.md b/packages/web3-wrapper/CHANGELOG.md index 94f50fd92..76ca80e69 100644 --- a/packages/web3-wrapper/CHANGELOG.md +++ b/packages/web3-wrapper/CHANGELOG.md @@ -5,6 +5,10 @@ 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) diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 09fd184d2..e5af24965 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -1,6 +1,6 @@ { "name": "@0x/web3-wrapper", - "version": "3.2.0", + "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.19", - "@0x/json-schemas": "^2.1.3", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "ethereum-types": "^1.1.3", + "@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 d56688049..c24a0ba6e 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "@0x/website", - "version": "0.0.62", + "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.3", + "@0x/asset-buyer": "^3.0.4", "@0x/contract-addresses": "^2.0.0", - "@0x/contract-wrappers": "^4.1.2", - "@0x/json-schemas": "^2.1.3", - "@0x/order-utils": "^3.0.6", - "@0x/react-docs": "^1.0.21", - "@0x/react-shared": "^1.0.24", - "@0x/subproviders": "^2.1.7", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@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.3", + "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 acd17dd06..169b2976b 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', |