Merge branch 'development' into launchKitLanding
* development: (110 commits) fix: fix exceeds block gas limit error chore(instant): fix lint error fix: remove unused vars Send in affiliate info as option Have heartbeat update not trigger errors fix: remove redundant handler feat: make onUnlockWalletClick different based on ON chore: remove wallet panel content for mobile feat: use blue for wallet prompt on mobile feat: use stable version of bowser fix: add http to external url string feat: make onUnlockWalletClick different based on ON chore: remove wallet panel content for mobile feat: use blue for wallet prompt on mobile feat: use stable version of bowser feat: expose webpack-dev-server content to local network fix(website): remove node env definition from webpack fix(website): currentProvider called on undefined chore: update yarn lock feat: use capital values for enums ...
This commit is contained in:
commit
25d0b1e6e5
@ -6,6 +6,7 @@ lib
|
|||||||
/packages/contract-artifacts/artifacts
|
/packages/contract-artifacts/artifacts
|
||||||
/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
|
/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
|
||||||
/packages/json-schemas/schemas
|
/packages/json-schemas/schemas
|
||||||
|
/python-packages/order_utils/src/zero_ex/json_schemas/schemas
|
||||||
/packages/metacoin/src/contract_wrappers
|
/packages/metacoin/src/contract_wrappers
|
||||||
/packages/metacoin/artifacts
|
/packages/metacoin/artifacts
|
||||||
/packages/sra-spec/public/
|
/packages/sra-spec/public/
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ganache": "ganache-cli -p 8545 --networkId 50 -m \"${npm_package_config_mnemonic}\"",
|
"ganache": "ganache-cli -p 8545 --gasLimit 10000000 --networkId 50 -m \"${npm_package_config_mnemonic}\"",
|
||||||
"prettier": "prettier --write '**/*.{ts,tsx,json,md}' --config .prettierrc",
|
"prettier": "prettier --write '**/*.{ts,tsx,json,md}' --config .prettierrc",
|
||||||
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
|
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
|
||||||
"report_coverage": "lcov-result-merger './{packages/*/coverage/lcov.info,python-packages/*/.coverage}' | coveralls",
|
"report_coverage": "lcov-result-merger './{packages/*/coverage/lcov.info,python-packages/*/.coverage}' | coveralls",
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "2.0.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "2.0.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "2.0.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v2.0.4 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v2.0.3 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v2.0.2 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v2.0.1 - _November 9, 2018_
|
## v2.0.1 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "0x.js",
|
"name": "0x.js",
|
||||||
"version": "2.0.1",
|
"version": "2.0.4",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -42,11 +42,11 @@
|
|||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^1.0.15",
|
"@0x/abi-gen": "^1.0.16",
|
||||||
"@0x/abi-gen-wrappers": "^1.0.2",
|
"@0x/abi-gen-wrappers": "^1.0.5",
|
||||||
"@0x/contract-addresses": "^1.1.0",
|
"@0x/contract-addresses": "^1.1.0",
|
||||||
"@0x/dev-utils": "^1.0.14",
|
"@0x/dev-utils": "^1.0.17",
|
||||||
"@0x/migrations": "^2.0.1",
|
"@0x/migrations": "^2.0.4",
|
||||||
"@0x/tslint-config": "^1.0.10",
|
"@0x/tslint-config": "^1.0.10",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/mocha": "^2.2.42",
|
"@types/mocha": "^2.2.42",
|
||||||
@ -73,16 +73,16 @@
|
|||||||
"webpack": "^4.20.2"
|
"webpack": "^4.20.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^1.0.15",
|
"@0x/assert": "^1.0.17",
|
||||||
"@0x/base-contract": "^3.0.3",
|
"@0x/base-contract": "^3.0.6",
|
||||||
"@0x/contract-wrappers": "^3.0.1",
|
"@0x/contract-wrappers": "^4.0.2",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/order-watcher": "^2.2.1",
|
"@0x/order-watcher": "^2.2.4",
|
||||||
"@0x/subproviders": "^2.1.1",
|
"@0x/subproviders": "^2.1.4",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"@types/web3-provider-engine": "^14.0.0",
|
"@types/web3-provider-engine": "^14.0.0",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"ethers": "~4.0.4",
|
"ethers": "~4.0.4",
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "1.0.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "1.0.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "1.0.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.5 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.4 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.3 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v1.0.2 - _November 9, 2018_
|
## v1.0.2 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/abi-gen-wrappers",
|
"name": "@0x/abi-gen-wrappers",
|
||||||
"version": "1.0.2",
|
"version": "1.0.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -30,17 +30,17 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^1.0.15",
|
"@0x/abi-gen": "^1.0.16",
|
||||||
"@0x/tslint-config": "^1.0.10",
|
"@0x/tslint-config": "^1.0.10",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"ethers": "~4.0.4",
|
"ethers": "~4.0.4",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"shx": "^0.2.2"
|
"shx": "^0.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^3.0.3"
|
"@0x/base-contract": "^3.0.6"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "1.0.16",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.15",
|
"version": "1.0.15",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.16 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v1.0.15 - _November 9, 2018_
|
## v1.0.15 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/abi-gen",
|
"name": "@0x/abi-gen",
|
||||||
"version": "1.0.15",
|
"version": "1.0.16",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -32,7 +32,7 @@
|
|||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"chalk": "^2.3.0",
|
"chalk": "^2.3.0",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
|
@ -1,4 +1,22 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "1.0.17",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "1.0.16",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.15",
|
"version": "1.0.15",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.17 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.16 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v1.0.15 - _November 9, 2018_
|
## v1.0.15 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/assert",
|
"name": "@0x/assert",
|
||||||
"version": "1.0.15",
|
"version": "1.0.17",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -44,9 +44,9 @@
|
|||||||
"typescript": "3.0.1"
|
"typescript": "3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/json-schemas": "^2.0.1",
|
"@0x/json-schemas": "^2.1.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"valid-url": "^1.0.9"
|
"valid-url": "^1.0.9"
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,32 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "3.0.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount",
|
||||||
|
"pr": 1252
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1542208198
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "2.2.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "2.2.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.0.0 - _November 14, 2018_
|
||||||
|
|
||||||
|
* update `getBuyQuoteAsync` to return eth spent on assets instead of per unit amount (#1252)
|
||||||
|
|
||||||
|
## v2.2.2 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v2.2.1 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v2.2.0 - _November 9, 2018_
|
## v2.2.0 - _November 9, 2018_
|
||||||
|
|
||||||
* `getAssetBuyerForProvidedOrders` factory function now takes 3 args instead of 4 (#1187)
|
* `getAssetBuyerForProvidedOrders` factory function now takes 3 args instead of 4 (#1187)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/asset-buyer",
|
"name": "@0x/asset-buyer",
|
||||||
"version": "2.2.0",
|
"version": "3.0.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -36,16 +36,16 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^1.0.15",
|
"@0x/assert": "^1.0.17",
|
||||||
"@0x/connect": "^3.0.3",
|
"@0x/connect": "^3.0.6",
|
||||||
"@0x/contract-wrappers": "^3.0.1",
|
"@0x/contract-wrappers": "^4.0.2",
|
||||||
"@0x/json-schemas": "^2.0.1",
|
"@0x/json-schemas": "^2.1.1",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/subproviders": "^2.1.1",
|
"@0x/subproviders": "^2.1.4",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"lodash": "^4.17.10"
|
"lodash": "^4.17.10"
|
||||||
},
|
},
|
||||||
|
@ -54,12 +54,12 @@ export interface BuyQuote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ethPerAssetPrice: The price of one unit of the desired asset in ETH
|
* assetEthAmount: The amount of eth required to pay for the requested asset.
|
||||||
* feeEthAmount: The amount of eth required to pay the affiliate fee.
|
* feeEthAmount: The amount of eth required to pay the affiliate fee.
|
||||||
* totalEthAmount: the total amount of eth required to complete the buy. (Filling orders, feeOrders, and paying affiliate fee)
|
* totalEthAmount: The total amount of eth required to complete the buy (filling orders, feeOrders, and paying affiliate fee).
|
||||||
*/
|
*/
|
||||||
export interface BuyQuoteInfo {
|
export interface BuyQuoteInfo {
|
||||||
ethPerAssetPrice: BigNumber;
|
assetEthAmount: BigNumber;
|
||||||
feeEthAmount: BigNumber;
|
feeEthAmount: BigNumber;
|
||||||
totalEthAmount: BigNumber;
|
totalEthAmount: BigNumber;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export const assert = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
isValidBuyQuoteInfo(variableName: string, buyQuoteInfo: BuyQuoteInfo): void {
|
isValidBuyQuoteInfo(variableName: string, buyQuoteInfo: BuyQuoteInfo): void {
|
||||||
sharedAssert.isBigNumber(`${variableName}.ethPerAssetPrice`, buyQuoteInfo.ethPerAssetPrice);
|
sharedAssert.isBigNumber(`${variableName}.assetEthAmount`, buyQuoteInfo.assetEthAmount);
|
||||||
sharedAssert.isBigNumber(`${variableName}.feeEthAmount`, buyQuoteInfo.feeEthAmount);
|
sharedAssert.isBigNumber(`${variableName}.feeEthAmount`, buyQuoteInfo.feeEthAmount);
|
||||||
sharedAssert.isBigNumber(`${variableName}.totalEthAmount`, buyQuoteInfo.totalEthAmount);
|
sharedAssert.isBigNumber(`${variableName}.totalEthAmount`, buyQuoteInfo.totalEthAmount);
|
||||||
},
|
},
|
||||||
|
@ -106,28 +106,28 @@ function calculateQuoteInfo(
|
|||||||
isMakerAssetZrxToken: boolean,
|
isMakerAssetZrxToken: boolean,
|
||||||
): BuyQuoteInfo {
|
): BuyQuoteInfo {
|
||||||
// find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
|
// find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
|
||||||
let ethAmountToBuyAsset = constants.ZERO_AMOUNT;
|
let assetEthAmount = constants.ZERO_AMOUNT;
|
||||||
let ethAmountToBuyZrx = constants.ZERO_AMOUNT;
|
let zrxEthAmount = constants.ZERO_AMOUNT;
|
||||||
if (isMakerAssetZrxToken) {
|
if (isMakerAssetZrxToken) {
|
||||||
ethAmountToBuyAsset = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
|
assetEthAmount = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
|
||||||
} else {
|
} else {
|
||||||
// find eth and zrx amounts needed to buy
|
// find eth and zrx amounts needed to buy
|
||||||
const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount);
|
const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount);
|
||||||
ethAmountToBuyAsset = ethAndZrxAmountToBuyAsset[0];
|
assetEthAmount = ethAndZrxAmountToBuyAsset[0];
|
||||||
const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1];
|
const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1];
|
||||||
// find eth amount needed to buy zrx
|
// find eth amount needed to buy zrx
|
||||||
ethAmountToBuyZrx = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
|
zrxEthAmount = findEthAmountNeededToBuyZrx(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
|
||||||
}
|
}
|
||||||
/// find the eth amount needed to buy the affiliate fee
|
// eth amount needed to buy the affiliate fee
|
||||||
const ethAmountToBuyAffiliateFee = ethAmountToBuyAsset.mul(feePercentage).ceil();
|
const affiliateFeeEthAmount = assetEthAmount.mul(feePercentage).ceil();
|
||||||
const totalEthAmountWithoutAffiliateFee = ethAmountToBuyAsset.plus(ethAmountToBuyZrx);
|
// eth amount needed for fees is the sum of affiliate fee and zrx fee
|
||||||
const ethAmountTotal = totalEthAmountWithoutAffiliateFee.plus(ethAmountToBuyAffiliateFee);
|
const feeEthAmount = affiliateFeeEthAmount.plus(zrxEthAmount);
|
||||||
// divide into the assetBuyAmount in order to find rate of makerAsset / WETH
|
// eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees
|
||||||
const ethPerAssetPrice = totalEthAmountWithoutAffiliateFee.div(assetBuyAmount);
|
const totalEthAmount = assetEthAmount.plus(feeEthAmount);
|
||||||
return {
|
return {
|
||||||
totalEthAmount: ethAmountTotal,
|
assetEthAmount,
|
||||||
feeEthAmount: ethAmountToBuyAffiliateFee,
|
feeEthAmount,
|
||||||
ethPerAssetPrice,
|
totalEthAmount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,19 +44,24 @@ export const orderProviderResponseProcessor = {
|
|||||||
let unsortedOrders = filteredOrders;
|
let unsortedOrders = filteredOrders;
|
||||||
// if an orderValidator is provided, use on chain information to calculate remaining fillable makerAsset amounts
|
// if an orderValidator is provided, use on chain information to calculate remaining fillable makerAsset amounts
|
||||||
if (!_.isUndefined(orderValidator)) {
|
if (!_.isUndefined(orderValidator)) {
|
||||||
// TODO(bmillman): improvement
|
|
||||||
// try/catch this request and throw a more domain specific error
|
|
||||||
const takerAddresses = _.map(filteredOrders, () => constants.NULL_ADDRESS);
|
const takerAddresses = _.map(filteredOrders, () => constants.NULL_ADDRESS);
|
||||||
const ordersAndTradersInfo = await orderValidator.getOrdersAndTradersInfoAsync(
|
try {
|
||||||
filteredOrders,
|
const ordersAndTradersInfo = await orderValidator.getOrdersAndTradersInfoAsync(
|
||||||
takerAddresses,
|
filteredOrders,
|
||||||
);
|
takerAddresses,
|
||||||
// take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
|
);
|
||||||
unsortedOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
|
// take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
|
||||||
filteredOrders,
|
unsortedOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
|
||||||
ordersAndTradersInfo,
|
filteredOrders,
|
||||||
isMakerAssetZrxToken,
|
ordersAndTradersInfo,
|
||||||
);
|
isMakerAssetZrxToken,
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// Sometimes we observe this call to orderValidator fail with response `0x`
|
||||||
|
// Because of differences in Parity / Geth implementations, its very hard to tell if this response is a "system error"
|
||||||
|
// or a revert. In this case we just swallow these errors and fallback to partial fill information from the SRA.
|
||||||
|
// TODO(bmillman): report these errors so we have an idea of how often we're getting these failures.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// sort orders by rate
|
// sort orders by rate
|
||||||
// TODO(bmillman): optimization
|
// TODO(bmillman): optimization
|
||||||
|
@ -108,17 +108,17 @@ describe('buyQuoteCalculator', () => {
|
|||||||
// 50 eth to fill the first order + 100 eth for fees
|
// 50 eth to fill the first order + 100 eth for fees
|
||||||
const expectedEthAmountForAsset = new BigNumber(50);
|
const expectedEthAmountForAsset = new BigNumber(50);
|
||||||
const expectedEthAmountForZrxFees = new BigNumber(100);
|
const expectedEthAmountForZrxFees = new BigNumber(100);
|
||||||
const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
|
const expectedFillEthAmount = expectedEthAmountForAsset;
|
||||||
const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
||||||
|
const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
|
||||||
const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
|
const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
|
||||||
const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount);
|
expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
|
||||||
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
|
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
|
||||||
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
||||||
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
|
|
||||||
// because we have no slippage protection, minRate is equal to maxRate
|
// because we have no slippage protection, minRate is equal to maxRate
|
||||||
|
expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
|
||||||
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
|
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
|
||||||
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
||||||
expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
|
|
||||||
// test if feePercentage gets passed through
|
// test if feePercentage gets passed through
|
||||||
expect(buyQuote.feePercentage).to.equal(feePercentage);
|
expect(buyQuote.feePercentage).to.equal(feePercentage);
|
||||||
});
|
});
|
||||||
@ -146,23 +146,23 @@ describe('buyQuoteCalculator', () => {
|
|||||||
// 50 eth to fill the first order + 100 eth for fees
|
// 50 eth to fill the first order + 100 eth for fees
|
||||||
const expectedEthAmountForAsset = new BigNumber(50);
|
const expectedEthAmountForAsset = new BigNumber(50);
|
||||||
const expectedEthAmountForZrxFees = new BigNumber(100);
|
const expectedEthAmountForZrxFees = new BigNumber(100);
|
||||||
const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
|
const expectedFillEthAmount = expectedEthAmountForAsset;
|
||||||
const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
||||||
|
const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
|
||||||
const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
|
const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
|
||||||
const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount);
|
expect(buyQuote.bestCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedFillEthAmount);
|
||||||
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
|
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
|
||||||
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
||||||
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
|
|
||||||
// 100 eth to fill the first order + 208 eth for fees
|
// 100 eth to fill the first order + 208 eth for fees
|
||||||
const expectedWorstEthAmountForAsset = new BigNumber(100);
|
const expectedWorstEthAmountForAsset = new BigNumber(100);
|
||||||
const expectedWorstEthAmountForZrxFees = new BigNumber(208);
|
const expectedWorstEthAmountForZrxFees = new BigNumber(208);
|
||||||
const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset.plus(expectedWorstEthAmountForZrxFees);
|
const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset;
|
||||||
const expectedWorstFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
|
const expectedWorstAffiliateFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
|
||||||
|
const expectedWorstFeeEthAmount = expectedWorstAffiliateFeeEthAmount.plus(expectedWorstEthAmountForZrxFees);
|
||||||
const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.plus(expectedWorstFeeEthAmount);
|
const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.plus(expectedWorstFeeEthAmount);
|
||||||
const expectedWorstEthPerAssetPrice = expectedWorstFillEthAmount.div(assetBuyAmount);
|
expect(buyQuote.worstCaseQuoteInfo.assetEthAmount).to.bignumber.equal(expectedWorstFillEthAmount);
|
||||||
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedWorstFeeEthAmount);
|
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedWorstFeeEthAmount);
|
||||||
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount);
|
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount);
|
||||||
expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedWorstEthPerAssetPrice);
|
|
||||||
// test if feePercentage gets passed through
|
// test if feePercentage gets passed through
|
||||||
expect(buyQuote.feePercentage).to.equal(feePercentage);
|
expect(buyQuote.feePercentage).to.equal(feePercentage);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "3.0.6",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "3.0.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "3.0.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.0.6 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v3.0.5 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v3.0.4 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.0.3 - _November 9, 2018_
|
## v3.0.3 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/base-contract",
|
"name": "@0x/base-contract",
|
||||||
"version": "3.0.3",
|
"version": "3.0.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -41,8 +41,8 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"ethers": "~4.0.4",
|
"ethers": "~4.0.4",
|
||||||
"lodash": "^4.17.5"
|
"lodash": "^4.17.5"
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "3.0.6",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "3.0.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "3.0.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v3.0.6 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v3.0.5 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v3.0.4 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v3.0.3 - _November 9, 2018_
|
## v3.0.3 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/connect",
|
"name": "@0x/connect",
|
||||||
"version": "3.0.3",
|
"version": "3.0.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -44,12 +44,12 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^1.0.15",
|
"@0x/assert": "^1.0.17",
|
||||||
"@0x/json-schemas": "^2.0.1",
|
"@0x/json-schemas": "^2.1.1",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"lodash": "^4.17.5",
|
"lodash": "^4.17.5",
|
||||||
"query-string": "^5.0.1",
|
"query-string": "^5.0.1",
|
||||||
"sinon": "^4.0.0",
|
"sinon": "^4.0.0",
|
||||||
|
@ -19,7 +19,6 @@ import { fetchAsync } from '@0x/utils';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as queryString from 'query-string';
|
import * as queryString from 'query-string';
|
||||||
|
|
||||||
import { schemas as clientSchemas } from './schemas/schemas';
|
|
||||||
import { Client, HttpRequestOptions, HttpRequestType } from './types';
|
import { Client, HttpRequestOptions, HttpRequestType } from './types';
|
||||||
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
|
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
|
||||||
|
|
||||||
@ -61,9 +60,9 @@ export class HttpClient implements Client {
|
|||||||
requestOpts?: RequestOpts & AssetPairsRequestOpts & PagedRequestOpts,
|
requestOpts?: RequestOpts & AssetPairsRequestOpts & PagedRequestOpts,
|
||||||
): Promise<AssetPairsResponse> {
|
): Promise<AssetPairsResponse> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.assetPairsRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.assetPairsRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: requestOpts,
|
params: requestOpts,
|
||||||
@ -81,9 +80,9 @@ export class HttpClient implements Client {
|
|||||||
requestOpts?: RequestOpts & OrdersRequestOpts & PagedRequestOpts,
|
requestOpts?: RequestOpts & OrdersRequestOpts & PagedRequestOpts,
|
||||||
): Promise<OrdersResponse> {
|
): Promise<OrdersResponse> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.ordersRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: requestOpts,
|
params: requestOpts,
|
||||||
@ -99,7 +98,7 @@ export class HttpClient implements Client {
|
|||||||
*/
|
*/
|
||||||
public async getOrderAsync(orderHash: string, requestOpts?: RequestOpts): Promise<APIOrder> {
|
public async getOrderAsync(orderHash: string, requestOpts?: RequestOpts): Promise<APIOrder> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
@ -119,10 +118,10 @@ export class HttpClient implements Client {
|
|||||||
request: OrderbookRequest,
|
request: OrderbookRequest,
|
||||||
requestOpts?: RequestOpts & PagedRequestOpts,
|
requestOpts?: RequestOpts & PagedRequestOpts,
|
||||||
): Promise<OrderbookResponse> {
|
): Promise<OrderbookResponse> {
|
||||||
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
|
assert.doesConformToSchema('request', request, schemas.orderBookRequestSchema);
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: _.defaults({}, request, requestOpts),
|
params: _.defaults({}, request, requestOpts),
|
||||||
@ -142,9 +141,9 @@ export class HttpClient implements Client {
|
|||||||
requestOpts?: RequestOpts,
|
requestOpts?: RequestOpts,
|
||||||
): Promise<OrderConfigResponse> {
|
): Promise<OrderConfigResponse> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
assert.doesConformToSchema('request', request, clientSchemas.orderConfigRequestSchema);
|
assert.doesConformToSchema('request', request, schemas.orderConfigRequestSchema);
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: requestOpts,
|
params: requestOpts,
|
||||||
payload: request,
|
payload: request,
|
||||||
@ -160,8 +159,8 @@ export class HttpClient implements Client {
|
|||||||
*/
|
*/
|
||||||
public async getFeeRecipientsAsync(requestOpts?: RequestOpts & PagedRequestOpts): Promise<FeeRecipientsResponse> {
|
public async getFeeRecipientsAsync(requestOpts?: RequestOpts & PagedRequestOpts): Promise<FeeRecipientsResponse> {
|
||||||
if (!_.isUndefined(requestOpts)) {
|
if (!_.isUndefined(requestOpts)) {
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||||
}
|
}
|
||||||
const httpRequestOpts = {
|
const httpRequestOpts = {
|
||||||
params: requestOpts,
|
params: requestOpts,
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
export const assetPairsRequestOptsSchema = {
|
|
||||||
id: '/AssetPairsRequestOpts',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
assetDataA: { $ref: '/hexSchema' },
|
|
||||||
assetDataB: { $ref: '/hexSchema' },
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,24 +0,0 @@
|
|||||||
export const orderConfigRequestSchema = {
|
|
||||||
id: '/OrderConfigRequest',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
makerAddress: { $ref: '/addressSchema' },
|
|
||||||
takerAddress: { $ref: '/addressSchema' },
|
|
||||||
makerAssetAmount: { $ref: '/numberSchema' },
|
|
||||||
takerAssetAmount: { $ref: '/numberSchema' },
|
|
||||||
makerAssetData: { $ref: '/hexSchema' },
|
|
||||||
takerAssetData: { $ref: '/hexSchema' },
|
|
||||||
exchangeAddress: { $ref: '/addressSchema' },
|
|
||||||
expirationTimeSeconds: { $ref: '/numberSchema' },
|
|
||||||
},
|
|
||||||
required: [
|
|
||||||
'makerAddress',
|
|
||||||
'takerAddress',
|
|
||||||
'makerAssetAmount',
|
|
||||||
'takerAssetAmount',
|
|
||||||
'makerAssetData',
|
|
||||||
'takerAssetData',
|
|
||||||
'exchangeAddress',
|
|
||||||
'expirationTimeSeconds',
|
|
||||||
],
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
export const orderBookRequestSchema = {
|
|
||||||
id: '/OrderBookRequest',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
baseAssetData: { $ref: '/hexSchema' },
|
|
||||||
quoteAssetData: { $ref: '/hexSchema' },
|
|
||||||
},
|
|
||||||
required: ['baseAssetData', 'quoteAssetData'],
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
export const ordersRequestOptsSchema = {
|
|
||||||
id: '/OrdersRequestOpts',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
makerAssetProxyId: { $ref: '/hexSchema' },
|
|
||||||
takerAssetProxyId: { $ref: '/hexSchema' },
|
|
||||||
makerAssetAddress: { $ref: '/addressSchema' },
|
|
||||||
takerAssetAddress: { $ref: '/addressSchema' },
|
|
||||||
exchangeAddress: { $ref: '/addressSchema' },
|
|
||||||
senderAddress: { $ref: '/addressSchema' },
|
|
||||||
makerAssetData: { $ref: '/hexSchema' },
|
|
||||||
takerAssetData: { $ref: '/hexSchema' },
|
|
||||||
traderAssetData: { $ref: '/hexSchema' },
|
|
||||||
makerAddress: { $ref: '/addressSchema' },
|
|
||||||
takerAddress: { $ref: '/addressSchema' },
|
|
||||||
traderAddress: { $ref: '/addressSchema' },
|
|
||||||
feeRecipientAddress: { $ref: '/addressSchema' },
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
export const pagedRequestOptsSchema = {
|
|
||||||
id: '/PagedRequestOpts',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
page: { type: 'number' },
|
|
||||||
perPage: { type: 'number' },
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,7 +0,0 @@
|
|||||||
export const requestOptsSchema = {
|
|
||||||
id: '/RequestOpts',
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
networkId: { type: 'number' },
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,15 +0,0 @@
|
|||||||
import { assetPairsRequestOptsSchema } from './asset_pairs_request_opts_schema';
|
|
||||||
import { orderConfigRequestSchema } from './order_config_request_schema';
|
|
||||||
import { orderBookRequestSchema } from './orderbook_request_schema';
|
|
||||||
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
|
|
||||||
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
|
|
||||||
import { requestOptsSchema } from './request_opts_schema';
|
|
||||||
|
|
||||||
export const schemas = {
|
|
||||||
orderConfigRequestSchema,
|
|
||||||
orderBookRequestSchema,
|
|
||||||
ordersRequestOptsSchema,
|
|
||||||
pagedRequestOptsSchema,
|
|
||||||
requestOptsSchema,
|
|
||||||
assetPairsRequestOptsSchema,
|
|
||||||
};
|
|
@ -1,4 +1,22 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "4.0.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "4.0.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
@ -17,7 +35,8 @@
|
|||||||
"Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218)",
|
"Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218)",
|
||||||
"pr": 1235
|
"pr": 1235
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"timestamp": 1542028948
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
@ -5,6 +5,20 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v4.0.2 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v4.0.1 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v4.0.0 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync` (#1235)
|
||||||
|
* Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive (#1235)
|
||||||
|
* Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218) (#1235)
|
||||||
|
|
||||||
## v3.0.1 - _November 9, 2018_
|
## v3.0.1 - _November 9, 2018_
|
||||||
|
|
||||||
* Fix bug in `ForwarderWrapper` where `feeRecipientAddress` was not correctly normalized. (#1178)
|
* Fix bug in `ForwarderWrapper` where `feeRecipientAddress` was not correctly normalized. (#1178)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/contract-wrappers",
|
"name": "@0x/contract-wrappers",
|
||||||
"version": "3.0.1",
|
"version": "4.0.2",
|
||||||
"description": "Smart TS wrappers for 0x smart contracts",
|
"description": "Smart TS wrappers for 0x smart contracts",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"0xproject",
|
"0xproject",
|
||||||
@ -37,9 +37,9 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/dev-utils": "^1.0.14",
|
"@0x/dev-utils": "^1.0.17",
|
||||||
"@0x/migrations": "^2.0.1",
|
"@0x/migrations": "^2.0.4",
|
||||||
"@0x/subproviders": "^2.1.1",
|
"@0x/subproviders": "^2.1.4",
|
||||||
"@0x/tslint-config": "^1.0.10",
|
"@0x/tslint-config": "^1.0.10",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/mocha": "^2.2.42",
|
"@types/mocha": "^2.2.42",
|
||||||
@ -65,17 +65,17 @@
|
|||||||
"web3-provider-engine": "14.0.6"
|
"web3-provider-engine": "14.0.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/abi-gen-wrappers": "^1.0.2",
|
"@0x/abi-gen-wrappers": "^1.0.5",
|
||||||
"@0x/assert": "^1.0.15",
|
"@0x/assert": "^1.0.17",
|
||||||
"@0x/contract-addresses": "^1.1.0",
|
"@0x/contract-addresses": "^1.1.0",
|
||||||
"@0x/contract-artifacts": "^1.1.0",
|
"@0x/contract-artifacts": "^1.1.0",
|
||||||
"@0x/fill-scenarios": "^1.0.9",
|
"@0x/fill-scenarios": "^1.0.12",
|
||||||
"@0x/json-schemas": "^2.0.1",
|
"@0x/json-schemas": "^2.1.1",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"ethereumjs-blockstream": "6.0.0",
|
"ethereumjs-blockstream": "6.0.0",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "contracts",
|
"name": "contracts",
|
||||||
"version": "2.1.51",
|
"version": "2.1.54",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -45,11 +45,11 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0x/abi-gen": "^1.0.15",
|
"@0x/abi-gen": "^1.0.16",
|
||||||
"@0x/dev-utils": "^1.0.14",
|
"@0x/dev-utils": "^1.0.17",
|
||||||
"@0x/sol-compiler": "^1.1.9",
|
"@0x/sol-compiler": "^1.1.12",
|
||||||
"@0x/sol-cov": "^2.1.9",
|
"@0x/sol-cov": "^2.1.12",
|
||||||
"@0x/subproviders": "^2.1.1",
|
"@0x/subproviders": "^2.1.4",
|
||||||
"@0x/tslint-config": "^1.0.10",
|
"@0x/tslint-config": "^1.0.10",
|
||||||
"@types/bn.js": "^4.11.0",
|
"@types/bn.js": "^4.11.0",
|
||||||
"@types/ethereumjs-abi": "^0.6.0",
|
"@types/ethereumjs-abi": "^0.6.0",
|
||||||
@ -71,12 +71,12 @@
|
|||||||
"yargs": "^10.0.3"
|
"yargs": "^10.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^3.0.3",
|
"@0x/base-contract": "^3.0.6",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"@types/js-combinatorics": "^0.5.29",
|
"@types/js-combinatorics": "^0.5.29",
|
||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/dev-tools-pages",
|
"name": "@0x/dev-tools-pages",
|
||||||
"version": "0.0.3",
|
"version": "0.0.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/react-shared": "^1.0.18",
|
"@0x/react-shared": "^1.0.21",
|
||||||
"basscss": "^8.0.3",
|
"basscss": "^8.0.3",
|
||||||
"bowser": "^1.9.3",
|
"bowser": "^1.9.3",
|
||||||
"less": "^2.7.2",
|
"less": "^2.7.2",
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "1.0.17",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "1.0.16",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "1.0.15",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.14",
|
"version": "1.0.14",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.17 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.16 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.15 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v1.0.14 - _November 9, 2018_
|
## v1.0.14 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/dev-utils",
|
"name": "@0x/dev-utils",
|
||||||
"version": "1.0.14",
|
"version": "1.0.17",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -41,11 +41,11 @@
|
|||||||
"typescript": "3.0.1"
|
"typescript": "3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/subproviders": "^2.1.1",
|
"@0x/subproviders": "^2.1.4",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"@types/web3-provider-engine": "^14.0.0",
|
"@types/web3-provider-engine": "^14.0.0",
|
||||||
"chai": "^4.0.1",
|
"chai": "^4.0.1",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
|
@ -1,4 +1,31 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1542208198,
|
||||||
|
"version": "1.0.12",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542134075,
|
||||||
|
"version": "1.0.11",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1542028948,
|
||||||
|
"version": "1.0.10",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.12 - _November 14, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.11 - _November 13, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v1.0.10 - _November 12, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v1.0.9 - _November 9, 2018_
|
## v1.0.9 - _November 9, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/fill-scenarios",
|
"name": "@0x/fill-scenarios",
|
||||||
"version": "1.0.9",
|
"version": "1.0.12",
|
||||||
"description": "0x order fill scenario generator",
|
"description": "0x order fill scenario generator",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
@ -28,14 +28,14 @@
|
|||||||
"typescript": "3.0.1"
|
"typescript": "3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/abi-gen-wrappers": "^1.0.2",
|
"@0x/abi-gen-wrappers": "^1.0.5",
|
||||||
"@0x/base-contract": "^3.0.3",
|
"@0x/base-contract": "^3.0.6",
|
||||||
"@0x/contract-artifacts": "^1.1.0",
|
"@0x/contract-artifacts": "^1.1.0",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"ethers": "~4.0.4",
|
"ethers": "~4.0.4",
|
||||||
"lodash": "^4.17.5"
|
"lodash": "^4.17.5"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0x/instant",
|
"name": "@0x/instant",
|
||||||
"version": "0.0.4",
|
"version": "0.0.7",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.12"
|
"node": ">=6.12"
|
||||||
},
|
},
|
||||||
@ -45,15 +45,16 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/assert": "^1.0.15",
|
"@0x/assert": "^1.0.17",
|
||||||
"@0x/asset-buyer": "^2.2.0",
|
"@0x/asset-buyer": "^3.0.0",
|
||||||
"@0x/json-schemas": "^2.0.1",
|
"@0x/json-schemas": "^2.1.1",
|
||||||
"@0x/order-utils": "^2.0.1",
|
"@0x/order-utils": "^3.0.2",
|
||||||
"@0x/subproviders": "^2.1.1",
|
"@0x/subproviders": "^2.1.4",
|
||||||
"@0x/types": "^1.2.1",
|
"@0x/types": "^1.2.1",
|
||||||
"@0x/typescript-typings": "^3.0.4",
|
"@0x/typescript-typings": "^3.0.4",
|
||||||
"@0x/utils": "^2.0.4",
|
"@0x/utils": "^2.0.5",
|
||||||
"@0x/web3-wrapper": "^3.1.1",
|
"@0x/web3-wrapper": "^3.1.4",
|
||||||
|
"bowser": "^1.9.4",
|
||||||
"copy-to-clipboard": "^3.0.8",
|
"copy-to-clipboard": "^3.0.8",
|
||||||
"ethereum-types": "^1.1.2",
|
"ethereum-types": "^1.1.2",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
@ -82,6 +83,7 @@
|
|||||||
"awesome-typescript-loader": "^5.2.1",
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
"enzyme": "^3.6.0",
|
"enzyme": "^3.6.0",
|
||||||
"enzyme-adapter-react-16": "^1.5.0",
|
"enzyme-adapter-react-16": "^1.5.0",
|
||||||
|
"ip": "^1.1.5",
|
||||||
"jest": "^23.6.0",
|
"jest": "^23.6.0",
|
||||||
"make-promises-safe": "^1.1.0",
|
"make-promises-safe": "^1.1.0",
|
||||||
"npm-run-all": "^4.1.2",
|
"npm-run-all": "^4.1.2",
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { OptionallyScreenSpecific } from '../../style/media';
|
import { OptionallyScreenSpecific } from '../../style/media';
|
||||||
|
import { SlideAnimationState } from '../../types';
|
||||||
|
|
||||||
import { PositionAnimation, PositionAnimationSettings } from './position_animation';
|
import { PositionAnimation, PositionAnimationSettings } from './position_animation';
|
||||||
|
|
||||||
export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
|
|
||||||
export interface SlideAnimationProps {
|
export interface SlideAnimationProps {
|
||||||
animationState: SlideAnimationState;
|
animationState: SlideAnimationState;
|
||||||
slideInSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
|
slideInSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
|
||||||
|
@ -43,7 +43,6 @@ export class BuyButton extends React.Component<BuyButtonProps> {
|
|||||||
onClick={this._handleClick}
|
onClick={this._handleClick}
|
||||||
isDisabled={shouldDisableButton}
|
isDisabled={shouldDisableButton}
|
||||||
fontColor={ColorOption.white}
|
fontColor={ColorOption.white}
|
||||||
fontSize="20px"
|
|
||||||
>
|
>
|
||||||
Buy
|
Buy
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -12,7 +12,6 @@ export interface BuyOrderProgressProps {
|
|||||||
|
|
||||||
export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> = props => {
|
export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> = props => {
|
||||||
const { buyOrderState } = props;
|
const { buyOrderState } = props;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
buyOrderState.processState === OrderProcessState.Processing ||
|
buyOrderState.processState === OrderProcessState.Processing ||
|
||||||
buyOrderState.processState === OrderProcessState.Success ||
|
buyOrderState.processState === OrderProcessState.Success ||
|
||||||
@ -30,6 +29,5 @@ export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> =
|
|||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ export const BuyOrderStateButtons: React.StatelessComponent<BuyOrderStateButtonP
|
|||||||
if (props.buyOrderProcessingState === OrderProcessState.Failure) {
|
if (props.buyOrderProcessingState === OrderProcessState.Failure) {
|
||||||
return (
|
return (
|
||||||
<Flex justify="space-between">
|
<Flex justify="space-between">
|
||||||
<Button width="48%" onClick={props.onRetry} fontColor={ColorOption.white} fontSize="16px">
|
<Button width="48%" onClick={props.onRetry} fontColor={ColorOption.white}>
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
<SecondaryButton width="48%" onClick={props.onViewTransaction}>
|
<SecondaryButton width="48%" onClick={props.onViewTransaction}>
|
||||||
|
23
packages/instant/src/components/coinbase_wallet_logo.tsx
Normal file
23
packages/instant/src/components/coinbase_wallet_logo.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export interface CoinbaseWalletLogoProps {
|
||||||
|
width?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CoinbaseWalletLogo: React.StatelessComponent<CoinbaseWalletLogoProps> = ({ width }) => (
|
||||||
|
<svg width={width} viewBox="0 0 51 51" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="25.5" cy="25.5" r="25.5" fill="#3263E9" />
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M25.5 41C34.0604 41 41 34.0604 41 25.5C41 16.9396 34.0604 10 25.5 10C16.9396 10 10 16.9396 10 25.5C10 34.0604 16.9396 41 25.5 41ZM21.5108 20.5107C20.9586 20.5107 20.5108 20.9584 20.5108 21.5107V29.6223C20.5108 30.1746 20.9586 30.6223 21.5108 30.6223H29.6224C30.1747 30.6223 30.6224 30.1746 30.6224 29.6223V21.5107C30.6224 20.9584 30.1747 20.5107 29.6224 20.5107H21.5108Z"
|
||||||
|
fill="white"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
CoinbaseWalletLogo.displayName = 'CoinbaseWalletLogo';
|
||||||
|
|
||||||
|
CoinbaseWalletLogo.defaultProps = {
|
||||||
|
width: 164,
|
||||||
|
};
|
@ -29,13 +29,19 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
|
|||||||
const { tokens, onTokenSelect } = this.props;
|
const { tokens, onTokenSelect } = this.props;
|
||||||
return (
|
return (
|
||||||
<Container height="100%">
|
<Container height="100%">
|
||||||
|
<Container marginBottom="10px">
|
||||||
|
<Text fontColor={ColorOption.darkGrey} fontSize="18px" fontWeight="600" lineHeight="22px">
|
||||||
|
Select Token
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
<SearchInput
|
<SearchInput
|
||||||
placeholder="Search tokens..."
|
placeholder="Search tokens..."
|
||||||
width="100%"
|
width="100%"
|
||||||
value={this.state.searchQuery}
|
value={this.state.searchQuery}
|
||||||
onChange={this._handleSearchInputChange}
|
onChange={this._handleSearchInputChange}
|
||||||
|
tabIndex={-1}
|
||||||
/>
|
/>
|
||||||
<Container overflow="scroll" height="calc(100% - 80px)" marginTop="10px">
|
<Container overflow="scroll" height="calc(100% - 90px)" marginTop="10px">
|
||||||
{_.map(tokens, token => {
|
{_.map(tokens, token => {
|
||||||
if (!this._isTokenQueryMatch(token)) {
|
if (!this._isTokenQueryMatch(token)) {
|
||||||
return null;
|
return null;
|
||||||
@ -57,8 +63,10 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
|
|||||||
if (_.isUndefined(searchQuery)) {
|
if (_.isUndefined(searchQuery)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const stringToSearch = `${token.metaData.name} ${token.metaData.symbol}`;
|
const searchQueryLowerCase = searchQuery.toLowerCase();
|
||||||
return _.includes(stringToSearch.toLowerCase(), searchQuery.toLowerCase());
|
const tokenName = token.metaData.name.toLowerCase();
|
||||||
|
const tokenSymbol = token.metaData.symbol.toLowerCase();
|
||||||
|
return _.startsWith(tokenSymbol, searchQueryLowerCase) || _.startsWith(tokenName, searchQueryLowerCase);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
META_MASK_CHROME_STORE_URL,
|
||||||
|
META_MASK_FIREFOX_STORE_URL,
|
||||||
|
META_MASK_OPERA_STORE_URL,
|
||||||
|
META_MASK_SITE_URL,
|
||||||
|
} from '../constants';
|
||||||
|
import { ColorOption } from '../style/theme';
|
||||||
|
import { Browser } from '../types';
|
||||||
|
import { envUtil } from '../util/env';
|
||||||
|
|
||||||
|
import { MetaMaskLogo } from './meta_mask_logo';
|
||||||
|
import { StandardPanelContent, StandardPanelContentProps } from './standard_panel_content';
|
||||||
|
import { Button } from './ui/button';
|
||||||
|
|
||||||
|
export interface InstallWalletPanelContentProps {}
|
||||||
|
|
||||||
|
export class InstallWalletPanelContent extends React.Component<InstallWalletPanelContentProps> {
|
||||||
|
public render(): React.ReactNode {
|
||||||
|
const panelProps = this._getStandardPanelContentProps();
|
||||||
|
return <StandardPanelContent {...panelProps} />;
|
||||||
|
}
|
||||||
|
private readonly _getStandardPanelContentProps = (): StandardPanelContentProps => {
|
||||||
|
const browser = envUtil.getBrowser();
|
||||||
|
let description = 'Please install the MetaMask wallet browser extension.';
|
||||||
|
let actionText = 'Learn More';
|
||||||
|
let actionUrl = META_MASK_SITE_URL;
|
||||||
|
switch (browser) {
|
||||||
|
case Browser.Chrome:
|
||||||
|
description = 'Please install the MetaMask wallet browser extension from the Chrome Store.';
|
||||||
|
actionText = 'Get Chrome Extension';
|
||||||
|
actionUrl = META_MASK_CHROME_STORE_URL;
|
||||||
|
break;
|
||||||
|
case Browser.Firefox:
|
||||||
|
description = 'Please install the MetaMask wallet browser extension from the Firefox Store.';
|
||||||
|
actionText = 'Get Firefox Extension';
|
||||||
|
actionUrl = META_MASK_FIREFOX_STORE_URL;
|
||||||
|
break;
|
||||||
|
case Browser.Opera:
|
||||||
|
description = 'Please install the MetaMask wallet browser extension from the Opera Store.';
|
||||||
|
actionText = 'Get Opera Add-on';
|
||||||
|
actionUrl = META_MASK_OPERA_STORE_URL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
image: <MetaMaskLogo width={85} height={80} />,
|
||||||
|
title: 'Install MetaMask',
|
||||||
|
description,
|
||||||
|
moreInfoSettings: {
|
||||||
|
href: META_MASK_SITE_URL,
|
||||||
|
text: 'What is MetaMask?',
|
||||||
|
},
|
||||||
|
action: (
|
||||||
|
<Button
|
||||||
|
href={actionUrl}
|
||||||
|
width="100%"
|
||||||
|
fontColor={ColorOption.white}
|
||||||
|
backgroundColor={ColorOption.darkOrange}
|
||||||
|
>
|
||||||
|
{actionText}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -15,8 +15,8 @@ import { Spinner } from './ui/spinner';
|
|||||||
import { Text } from './ui/text';
|
import { Text } from './ui/text';
|
||||||
|
|
||||||
export interface InstantHeadingProps {
|
export interface InstantHeadingProps {
|
||||||
selectedAssetAmount?: BigNumber;
|
selectedAssetUnitAmount?: BigNumber;
|
||||||
totalEthBaseAmount?: BigNumber;
|
totalEthBaseUnitAmount?: BigNumber;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
quoteRequestState: AsyncProcessState;
|
quoteRequestState: AsyncProcessState;
|
||||||
buyOrderState: OrderState;
|
buyOrderState: OrderState;
|
||||||
@ -32,12 +32,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const iconOrAmounts = this._renderIcon() || this._renderAmountsSection();
|
const iconOrAmounts = this._renderIcon() || this._renderAmountsSection();
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container backgroundColor={ColorOption.primaryColor} padding="20px" width="100%">
|
||||||
backgroundColor={ColorOption.primaryColor}
|
|
||||||
padding="20px"
|
|
||||||
width="100%"
|
|
||||||
borderRadius="3px 3px 0px 0px"
|
|
||||||
>
|
|
||||||
<Container marginBottom="5px">
|
<Container marginBottom="5px">
|
||||||
<Text
|
<Text
|
||||||
letterSpacing="1px"
|
letterSpacing="1px"
|
||||||
@ -104,7 +99,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
if (this.props.quoteRequestState === AsyncProcessState.Pending) {
|
if (this.props.quoteRequestState === AsyncProcessState.Pending) {
|
||||||
return <AmountPlaceholder isPulsating={true} color={PLACEHOLDER_COLOR} />;
|
return <AmountPlaceholder isPulsating={true} color={PLACEHOLDER_COLOR} />;
|
||||||
}
|
}
|
||||||
if (_.isUndefined(this.props.selectedAssetAmount)) {
|
if (_.isUndefined(this.props.selectedAssetUnitAmount)) {
|
||||||
return <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />;
|
return <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />;
|
||||||
}
|
}
|
||||||
return amountFunction();
|
return amountFunction();
|
||||||
@ -113,8 +108,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
private readonly _renderEthAmount = (): React.ReactNode => {
|
private readonly _renderEthAmount = (): React.ReactNode => {
|
||||||
return (
|
return (
|
||||||
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
|
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
|
||||||
{format.ethBaseAmount(
|
{format.ethBaseUnitAmount(
|
||||||
this.props.totalEthBaseAmount,
|
this.props.totalEthBaseUnitAmount,
|
||||||
4,
|
4,
|
||||||
<AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
|
<AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
|
||||||
)}
|
)}
|
||||||
@ -125,8 +120,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
|||||||
private readonly _renderDollarAmount = (): React.ReactNode => {
|
private readonly _renderDollarAmount = (): React.ReactNode => {
|
||||||
return (
|
return (
|
||||||
<Text fontSize="16px" fontColor={ColorOption.white}>
|
<Text fontSize="16px" fontColor={ColorOption.white}>
|
||||||
{format.ethBaseAmountInUsd(
|
{format.ethBaseUnitAmountInUsd(
|
||||||
this.props.totalEthBaseAmount,
|
this.props.totalEthBaseUnitAmount,
|
||||||
this.props.ethUsdPrice,
|
this.props.ethUsdPrice,
|
||||||
2,
|
2,
|
||||||
<AmountPlaceholder isPulsating={false} color={ColorOption.white} />,
|
<AmountPlaceholder isPulsating={false} color={ColorOption.white} />,
|
||||||
|
80
packages/instant/src/components/meta_mask_logo.tsx
Normal file
80
packages/instant/src/components/meta_mask_logo.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export interface MetaMaskLogoProps {
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MetaMaskLogo: React.StatelessComponent<MetaMaskLogoProps> = ({ width, height }) => (
|
||||||
|
<svg width={width} height={height} viewBox="0 0 85 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M80.578 0L47.7107 24.8648L53.542 10.2702L80.578 0Z" fill="#E2761B" />
|
||||||
|
<path d="M4.24075 0L37.1081 25.4053L31.2768 10.2702L4.24075 0Z" fill="#E4761B" />
|
||||||
|
<path d="M68.9152 57.8379L59.9032 71.8919L78.9874 77.2973L84.2886 58.3785L68.9152 57.8379Z" fill="#E4761B" />
|
||||||
|
<path d="M0.53006 58.3785L5.83124 77.2973L24.9155 71.8919L15.9035 57.8379L0.53006 58.3785Z" fill="#E4761B" />
|
||||||
|
<path d="M23.8552 34.5941L18.554 42.7022L37.1082 43.7833L36.5781 23.2428L23.8552 34.5941Z" fill="#E4761B" />
|
||||||
|
<path d="M60.9635 34.5941L47.7106 23.2428V43.7833L66.2647 42.7022L60.9635 34.5941Z" fill="#E4761B" />
|
||||||
|
<path d="M24.9156 71.8914L36.0481 66.4861L26.5059 58.378L24.9156 71.8914Z" fill="#E4761B" />
|
||||||
|
<path d="M48.7709 66.4861L59.9034 71.8914L58.313 58.378L48.7709 66.4861Z" fill="#E4761B" />
|
||||||
|
<path d="M59.9034 71.8919L48.7709 66.4865L49.301 73.5135V76.7567L59.9034 71.8919Z" fill="#D7C1B3" />
|
||||||
|
<path d="M24.9157 71.892L35.518 76.7568V73.5136L36.0482 66.4866L24.9157 71.892Z" fill="#D7C1B3" />
|
||||||
|
<path d="M35.5179 53.5138L25.9758 50.8111L32.8673 47.5678L35.5179 53.5138Z" fill="#233447" />
|
||||||
|
<path d="M49.3009 53.5138L51.9515 47.5678L58.843 50.8111L49.3009 53.5138Z" fill="#233447" />
|
||||||
|
<path d="M24.9155 71.892L26.5059 57.838L15.9035 58.3785L24.9155 71.892Z" fill="#CD6116" />
|
||||||
|
<path d="M58.313 57.838L59.9034 71.892L68.9154 58.3785L58.313 57.838Z" fill="#CD6116" />
|
||||||
|
<path
|
||||||
|
d="M66.2648 42.7025L47.7106 43.7836L49.301 53.5132L51.9516 47.5673L58.8431 50.8106L66.2648 42.7025Z"
|
||||||
|
fill="#CD6116"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M25.9758 50.8106L32.8673 47.5673L35.5179 53.5132L37.1083 43.7836L18.5541 42.7025L25.9758 50.8106Z"
|
||||||
|
fill="#CD6116"
|
||||||
|
/>
|
||||||
|
<path d="M18.5541 42.7024L26.5059 58.378L25.9758 50.8105L18.5541 42.7024Z" fill="#E4751F" />
|
||||||
|
<path d="M58.8431 50.8106L58.313 58.3781L66.2647 42.7025L58.8431 50.8106Z" fill="#E4751F" />
|
||||||
|
<path d="M37.1083 43.7838L35.518 53.5135L37.6384 65.4053L38.1686 49.7297L37.1083 43.7838Z" fill="#E4751F" />
|
||||||
|
<path d="M47.7105 43.7838L46.6503 49.7297L47.1804 65.4053L49.3009 53.5135L47.7105 43.7838Z" fill="#E4751F" />
|
||||||
|
<path
|
||||||
|
d="M49.301 53.5134L47.1805 65.4052L48.7709 66.4863L58.313 58.3782L58.8431 50.8107L49.301 53.5134Z"
|
||||||
|
fill="#F6851B"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M25.9758 50.8107L26.5059 58.3782L36.048 66.4863L37.6384 65.4052L35.5179 53.5134L25.9758 50.8107Z"
|
||||||
|
fill="#F6851B"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M49.3011 76.7568V73.5135L48.771 72.973H36.0482L35.518 73.5135V76.7568L24.9157 71.8919L28.6265 75.1351L36.0482 80H48.771L56.1927 75.1351L59.9035 71.8919L49.3011 76.7568Z"
|
||||||
|
fill="#C0AD9E"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M48.771 66.486L47.1806 65.405H37.6385L36.0482 66.486L35.518 73.513L36.0482 72.9725H48.771L49.3011 73.513L48.771 66.486Z"
|
||||||
|
fill="#161616"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M82.1685 26.4864L84.8191 12.9729L80.5781 0L48.771 24.3242L60.9637 34.5945L78.4576 39.9998L82.1685 35.6755L80.5781 34.0539L83.2287 31.8918L81.1082 30.2702L83.7588 28.108L82.1685 26.4864Z"
|
||||||
|
fill="#763D16"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M0 12.9729L2.65059 26.4864L1.06024 28.108L3.71083 30.2702L1.59036 31.8918L4.24095 34.0539L2.65059 35.6755L6.36142 39.9998L23.8553 34.5945L36.0481 24.3242L4.24095 0L0 12.9729Z"
|
||||||
|
fill="#763D16"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M78.4575 39.9993L60.9636 34.5939L66.2648 42.702L58.313 58.3776H68.9154H84.2888L78.4575 39.9993Z"
|
||||||
|
fill="#F6851B"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M23.8554 34.5939L6.36147 39.9993L0.530167 58.3776H15.9036H26.506L18.5542 42.702L23.8554 34.5939Z"
|
||||||
|
fill="#F6851B"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M47.7106 43.7833L48.7709 24.3239L53.5419 10.2699H31.2769L36.048 24.3239L37.1083 43.7833L37.6384 49.7292V65.4048H47.1805V49.7292L47.7106 43.7833Z"
|
||||||
|
fill="#F6851B"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
MetaMaskLogo.displayName = 'MetaMaskLogo';
|
||||||
|
|
||||||
|
MetaMaskLogo.defaultProps = {
|
||||||
|
width: 85,
|
||||||
|
height: 80,
|
||||||
|
};
|
@ -4,6 +4,7 @@ import * as _ from 'lodash';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { oc } from 'ts-optchain';
|
import { oc } from 'ts-optchain';
|
||||||
|
|
||||||
|
import { BIG_NUMBER_ZERO } from '../constants';
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { format } from '../util/format';
|
import { format } from '../util/format';
|
||||||
|
|
||||||
@ -15,16 +16,23 @@ import { Text } from './ui/text';
|
|||||||
|
|
||||||
export interface OrderDetailsProps {
|
export interface OrderDetailsProps {
|
||||||
buyQuoteInfo?: BuyQuoteInfo;
|
buyQuoteInfo?: BuyQuoteInfo;
|
||||||
|
selectedAssetUnitAmount?: BigNumber;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
}
|
}
|
||||||
export class OrderDetails extends React.Component<OrderDetailsProps> {
|
export class OrderDetails extends React.Component<OrderDetailsProps> {
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const { buyQuoteInfo, ethUsdPrice } = this.props;
|
const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props;
|
||||||
const buyQuoteAccessor = oc(buyQuoteInfo);
|
const buyQuoteAccessor = oc(buyQuoteInfo);
|
||||||
const ethAssetPrice = buyQuoteAccessor.ethPerAssetPrice();
|
const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount();
|
||||||
const ethTokenFee = buyQuoteAccessor.feeEthAmount();
|
const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount();
|
||||||
const totalEthAmount = buyQuoteAccessor.totalEthAmount();
|
const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount();
|
||||||
|
const pricePerTokenEth =
|
||||||
|
!_.isUndefined(assetEthBaseUnitAmount) &&
|
||||||
|
!_.isUndefined(selectedAssetUnitAmount) &&
|
||||||
|
!selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
|
||||||
|
? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil()
|
||||||
|
: undefined;
|
||||||
return (
|
return (
|
||||||
<Container padding="20px" width="100%" flexGrow={1}>
|
<Container padding="20px" width="100%" flexGrow={1}>
|
||||||
<Container marginBottom="10px">
|
<Container marginBottom="10px">
|
||||||
@ -40,20 +48,19 @@ export class OrderDetails extends React.Component<OrderDetailsProps> {
|
|||||||
</Container>
|
</Container>
|
||||||
<EthAmountRow
|
<EthAmountRow
|
||||||
rowLabel="Token Price"
|
rowLabel="Token Price"
|
||||||
ethAmount={ethAssetPrice}
|
ethAmount={pricePerTokenEth}
|
||||||
ethUsdPrice={ethUsdPrice}
|
ethUsdPrice={ethUsdPrice}
|
||||||
isEthAmountInBaseUnits={false}
|
|
||||||
isLoading={this.props.isLoading}
|
isLoading={this.props.isLoading}
|
||||||
/>
|
/>
|
||||||
<EthAmountRow
|
<EthAmountRow
|
||||||
rowLabel="Fee"
|
rowLabel="Fee"
|
||||||
ethAmount={ethTokenFee}
|
ethAmount={feeEthBaseUnitAmount}
|
||||||
ethUsdPrice={ethUsdPrice}
|
ethUsdPrice={ethUsdPrice}
|
||||||
isLoading={this.props.isLoading}
|
isLoading={this.props.isLoading}
|
||||||
/>
|
/>
|
||||||
<EthAmountRow
|
<EthAmountRow
|
||||||
rowLabel="Total Cost"
|
rowLabel="Total Cost"
|
||||||
ethAmount={totalEthAmount}
|
ethAmount={totalEthBaseUnitAmount}
|
||||||
ethUsdPrice={ethUsdPrice}
|
ethUsdPrice={ethUsdPrice}
|
||||||
shouldEmphasize={true}
|
shouldEmphasize={true}
|
||||||
isLoading={this.props.isLoading}
|
isLoading={this.props.isLoading}
|
||||||
@ -81,7 +88,7 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> {
|
|||||||
const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
|
const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
|
||||||
|
|
||||||
const fontWeight = shouldEmphasize ? 700 : 400;
|
const fontWeight = shouldEmphasize ? 700 : 400;
|
||||||
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseAmount : format.ethUnitAmount;
|
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseUnitAmount : format.ethUnitAmount;
|
||||||
return (
|
return (
|
||||||
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
|
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
|
||||||
<Flex justify="space-between">
|
<Flex justify="space-between">
|
||||||
@ -105,7 +112,9 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderUsdSection(): React.ReactNode {
|
private _renderUsdSection(): React.ReactNode {
|
||||||
const usdFormatter = this.props.isEthAmountInBaseUnits ? format.ethBaseAmountInUsd : format.ethUnitAmountInUsd;
|
const usdFormatter = this.props.isEthAmountInBaseUnits
|
||||||
|
? format.ethBaseUnitAmountInUsd
|
||||||
|
: format.ethUnitAmountInUsd;
|
||||||
const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount);
|
const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount);
|
||||||
return shouldHideUsdPriceSection ? null : (
|
return shouldHideUsdPriceSection ? null : (
|
||||||
<Container marginRight="3px" display="inline-block">
|
<Container marginRight="3px" display="inline-block">
|
||||||
|
@ -1,45 +1,114 @@
|
|||||||
import { BigNumber } from '@0x/utils';
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { Network } from '../types';
|
import { Account, AccountState, Network } from '../types';
|
||||||
|
import { envUtil } from '../util/env';
|
||||||
|
|
||||||
|
import { CoinbaseWalletLogo } from './coinbase_wallet_logo';
|
||||||
|
import { MetaMaskLogo } from './meta_mask_logo';
|
||||||
import { PaymentMethodDropdown } from './payment_method_dropdown';
|
import { PaymentMethodDropdown } from './payment_method_dropdown';
|
||||||
import { Circle } from './ui/circle';
|
import { Circle } from './ui/circle';
|
||||||
import { Container } from './ui/container';
|
import { Container } from './ui/container';
|
||||||
import { Flex } from './ui/flex';
|
import { Flex } from './ui/flex';
|
||||||
|
import { Icon } from './ui/icon';
|
||||||
import { Text } from './ui/text';
|
import { Text } from './ui/text';
|
||||||
|
import { WalletPrompt } from './wallet_prompt';
|
||||||
|
|
||||||
export interface PaymentMethodProps {}
|
export interface PaymentMethodProps {
|
||||||
|
account: Account;
|
||||||
|
network: Network;
|
||||||
|
walletName: string;
|
||||||
|
onInstallWalletClick: () => void;
|
||||||
|
onUnlockWalletClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export const PaymentMethod: React.StatelessComponent<PaymentMethodProps> = () => (
|
export class PaymentMethod extends React.Component<PaymentMethodProps> {
|
||||||
<Container padding="20px" width="100%">
|
public render(): React.ReactNode {
|
||||||
<Container marginBottom="10px">
|
return (
|
||||||
<Flex justify="space-between">
|
<Container padding="20px" width="100%">
|
||||||
<Text
|
<Container marginBottom="12px">
|
||||||
letterSpacing="1px"
|
<Flex justify="space-between">
|
||||||
fontColor={ColorOption.primaryColor}
|
<Text
|
||||||
fontWeight={600}
|
letterSpacing="1px"
|
||||||
textTransform="uppercase"
|
fontColor={ColorOption.primaryColor}
|
||||||
fontSize="14px"
|
fontWeight={600}
|
||||||
>
|
textTransform="uppercase"
|
||||||
Payment Method
|
fontSize="14px"
|
||||||
</Text>
|
>
|
||||||
|
{this._renderTitleText()}
|
||||||
|
</Text>
|
||||||
|
{this._renderTitleLabel()}
|
||||||
|
</Flex>
|
||||||
|
</Container>
|
||||||
|
{this._renderMainContent()}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private readonly _renderTitleText = (): string => {
|
||||||
|
const { account } = this.props;
|
||||||
|
switch (account.state) {
|
||||||
|
case AccountState.Loading:
|
||||||
|
return 'loading...';
|
||||||
|
case AccountState.Locked:
|
||||||
|
case AccountState.None:
|
||||||
|
return 'connect your wallet';
|
||||||
|
case AccountState.Ready:
|
||||||
|
return 'payment method';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private readonly _renderTitleLabel = (): React.ReactNode => {
|
||||||
|
const { account } = this.props;
|
||||||
|
if (account.state === AccountState.Ready || account.state === AccountState.Locked) {
|
||||||
|
const circleColor: ColorOption = account.state === AccountState.Ready ? ColorOption.green : ColorOption.red;
|
||||||
|
return (
|
||||||
<Flex>
|
<Flex>
|
||||||
<Circle color={ColorOption.green} diameter={8} />
|
<Circle diameter={8} color={circleColor} />
|
||||||
<Container marginLeft="3px">
|
<Container marginLeft="3px">
|
||||||
<Text fontColor={ColorOption.darkGrey} fontSize="12px">
|
<Text fontColor={ColorOption.darkGrey} fontSize="12px">
|
||||||
MetaMask
|
{this.props.walletName}
|
||||||
</Text>
|
</Text>
|
||||||
</Container>
|
</Container>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
);
|
||||||
</Container>
|
}
|
||||||
<PaymentMethodDropdown
|
return null;
|
||||||
accountAddress="0xa1b2c3d4e5f6g7h8j9k10"
|
};
|
||||||
accountEthBalanceInWei={new BigNumber(10500000000000000000)}
|
private readonly _renderMainContent = (): React.ReactNode => {
|
||||||
network={Network.Mainnet}
|
const { account, network } = this.props;
|
||||||
/>
|
const isMobile = envUtil.isMobileOperatingSystem();
|
||||||
</Container>
|
const logo = isMobile ? <CoinbaseWalletLogo width={22} /> : <MetaMaskLogo width={19} height={18} />;
|
||||||
);
|
const primaryColor = isMobile ? ColorOption.darkBlue : ColorOption.darkOrange;
|
||||||
|
const secondaryColor = isMobile ? ColorOption.lightBlue : ColorOption.lightOrange;
|
||||||
|
const colors = { primaryColor, secondaryColor };
|
||||||
|
switch (account.state) {
|
||||||
|
case AccountState.Loading:
|
||||||
|
// Just take up the same amount of space as the other states.
|
||||||
|
return <Container height="52px" />;
|
||||||
|
case AccountState.Locked:
|
||||||
|
return (
|
||||||
|
<WalletPrompt
|
||||||
|
onClick={this.props.onUnlockWalletClick}
|
||||||
|
image={<Icon width={13} icon="lock" color={ColorOption.black} />}
|
||||||
|
{...colors}
|
||||||
|
>
|
||||||
|
Please Unlock {this.props.walletName}
|
||||||
|
</WalletPrompt>
|
||||||
|
);
|
||||||
|
case AccountState.None:
|
||||||
|
return (
|
||||||
|
<WalletPrompt onClick={this.props.onInstallWalletClick} image={logo} {...colors}>
|
||||||
|
{isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'}
|
||||||
|
</WalletPrompt>
|
||||||
|
);
|
||||||
|
case AccountState.Ready:
|
||||||
|
return (
|
||||||
|
<PaymentMethodDropdown
|
||||||
|
accountAddress={account.address}
|
||||||
|
accountEthBalanceInWei={account.ethBalanceInWei}
|
||||||
|
network={network}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ import copy from 'copy-to-clipboard';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { Network } from '../types';
|
import { Network } from '../types';
|
||||||
|
import { envUtil } from '../util/env';
|
||||||
import { etherscanUtil } from '../util/etherscan';
|
import { etherscanUtil } from '../util/etherscan';
|
||||||
import { format } from '../util/format';
|
import { format } from '../util/format';
|
||||||
|
|
||||||
@ -18,10 +19,13 @@ export class PaymentMethodDropdown extends React.Component<PaymentMethodDropdown
|
|||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const { accountAddress, accountEthBalanceInWei } = this.props;
|
const { accountAddress, accountEthBalanceInWei } = this.props;
|
||||||
const value = format.ethAddress(accountAddress);
|
const value = format.ethAddress(accountAddress);
|
||||||
const label = format.ethBaseAmount(accountEthBalanceInWei, 4, '') as string;
|
const label = format.ethBaseUnitAmount(accountEthBalanceInWei, 4, '') as string;
|
||||||
return <Dropdown value={value} label={label} items={this._getDropdownItemConfigs()} />;
|
return <Dropdown value={value} label={label} items={this._getDropdownItemConfigs()} />;
|
||||||
}
|
}
|
||||||
private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => {
|
private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => {
|
||||||
|
if (envUtil.isMobileOperatingSystem()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const viewOnEtherscan = {
|
const viewOnEtherscan = {
|
||||||
text: 'View on Etherscan',
|
text: 'View on Etherscan',
|
||||||
onClick: this._handleEtherscanClick,
|
onClick: this._handleEtherscanClick,
|
||||||
|
@ -7,9 +7,9 @@ import { Container } from './ui/container';
|
|||||||
import { Spinner } from './ui/spinner';
|
import { Spinner } from './ui/spinner';
|
||||||
|
|
||||||
export const PlacingOrderButton: React.StatelessComponent<{}> = props => (
|
export const PlacingOrderButton: React.StatelessComponent<{}> = props => (
|
||||||
<Button isDisabled={true} width="100%" fontColor={ColorOption.white} fontSize="20px">
|
<Button isDisabled={true} width="100%" fontColor={ColorOption.white}>
|
||||||
<Container display="inline-block" position="relative" top="3px" marginRight="8px">
|
<Container display="inline-block" position="relative" top="3px" marginRight="8px">
|
||||||
<Spinner widthPx={20} heightPx={20} />
|
<Spinner widthPx={16} heightPx={16} />
|
||||||
</Container>
|
</Container>
|
||||||
Placing Order…
|
Placing Order…
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -156,8 +156,6 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
|
|||||||
return `${width}px`;
|
return `${width}px`;
|
||||||
}
|
}
|
||||||
return `${textLengthThreshold}ch`;
|
return `${textLengthThreshold}ch`;
|
||||||
default:
|
|
||||||
return '1ch';
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private readonly _calculateFontSize = (phase: ScalingInputPhase): number => {
|
private readonly _calculateFontSize = (phase: ScalingInputPhase): number => {
|
||||||
|
@ -15,8 +15,6 @@ export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = p
|
|||||||
borderColor={ColorOption.lightGrey}
|
borderColor={ColorOption.lightGrey}
|
||||||
width={props.width}
|
width={props.width}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
fontColor={ColorOption.primaryColor}
|
|
||||||
fontSize="16px"
|
|
||||||
{...buttonProps}
|
{...buttonProps}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
@ -3,9 +3,10 @@ import * as React from 'react';
|
|||||||
import { ScreenSpecification } from '../style/media';
|
import { ScreenSpecification } from '../style/media';
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { zIndex } from '../style/z_index';
|
import { zIndex } from '../style/z_index';
|
||||||
|
import { SlideAnimationState } from '../types';
|
||||||
|
|
||||||
import { PositionAnimationSettings } from './animations/position_animation';
|
import { PositionAnimationSettings } from './animations/position_animation';
|
||||||
import { SlideAnimation, SlideAnimationState } from './animations/slide_animation';
|
import { SlideAnimation } from './animations/slide_animation';
|
||||||
|
|
||||||
import { Container } from './ui/container';
|
import { Container } from './ui/container';
|
||||||
import { Flex } from './ui/flex';
|
import { Flex } from './ui/flex';
|
||||||
|
@ -2,35 +2,25 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { zIndex } from '../style/z_index';
|
import { zIndex } from '../style/z_index';
|
||||||
|
import { SlideAnimationState } from '../types';
|
||||||
|
|
||||||
import { PositionAnimationSettings } from './animations/position_animation';
|
import { PositionAnimationSettings } from './animations/position_animation';
|
||||||
import { SlideAnimation, SlideAnimationState } from './animations/slide_animation';
|
import { SlideAnimation } from './animations/slide_animation';
|
||||||
|
|
||||||
import { Container } from './ui/container';
|
import { Container } from './ui/container';
|
||||||
import { Flex } from './ui/flex';
|
import { Flex } from './ui/flex';
|
||||||
import { Icon } from './ui/icon';
|
import { Icon } from './ui/icon';
|
||||||
import { Text } from './ui/text';
|
|
||||||
|
|
||||||
export interface PanelProps {
|
export interface PanelProps {
|
||||||
title?: string;
|
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Panel: React.StatelessComponent<PanelProps> = ({ title, children, onClose }) => (
|
export const Panel: React.StatelessComponent<PanelProps> = ({ children, onClose }) => (
|
||||||
<Container backgroundColor={ColorOption.white} width="100%" height="100%" zIndex={zIndex.panel} padding="20px">
|
<Container backgroundColor={ColorOption.white} width="100%" height="100%" zIndex={zIndex.panel} padding="20px">
|
||||||
<Flex justify="space-between">
|
<Flex justify="flex-end">
|
||||||
{title && (
|
<Icon padding="5px" width={12} color={ColorOption.lightGrey} icon="closeX" onClick={onClose} />
|
||||||
<Container marginTop="3px">
|
|
||||||
<Text fontColor={ColorOption.darkGrey} fontSize="18px" fontWeight="600" lineHeight="22px">
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
</Container>
|
|
||||||
)}
|
|
||||||
<Container position="relative" bottom="7px">
|
|
||||||
<Icon width={12} color={ColorOption.lightGrey} icon="closeX" onClick={onClose} />
|
|
||||||
</Container>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Container marginTop="10px" height="100%">
|
<Container position="relative" top="-10px" height="100%">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</Container>
|
</Container>
|
||||||
|
62
packages/instant/src/components/standard_panel_content.tsx
Normal file
62
packages/instant/src/components/standard_panel_content.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { ColorOption } from '../style/theme';
|
||||||
|
|
||||||
|
import { Container } from './ui/container';
|
||||||
|
import { Flex } from './ui/flex';
|
||||||
|
import { Text } from './ui/text';
|
||||||
|
|
||||||
|
export interface MoreInfoSettings {
|
||||||
|
text: string;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StandardPanelContentProps {
|
||||||
|
image: React.ReactNode;
|
||||||
|
title?: string;
|
||||||
|
description: string;
|
||||||
|
moreInfoSettings?: MoreInfoSettings;
|
||||||
|
action: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SPACING_BETWEEN_PX = '20px';
|
||||||
|
|
||||||
|
export const StandardPanelContent: React.StatelessComponent<StandardPanelContentProps> = ({
|
||||||
|
image,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
moreInfoSettings,
|
||||||
|
action,
|
||||||
|
}) => (
|
||||||
|
<Container height="100%">
|
||||||
|
<Flex direction="column" height="calc(100% - 58px)">
|
||||||
|
<Container marginBottom={SPACING_BETWEEN_PX}>{image}</Container>
|
||||||
|
{title && (
|
||||||
|
<Container marginBottom={SPACING_BETWEEN_PX}>
|
||||||
|
<Text fontSize="20px" fontWeight={700} fontColor={ColorOption.black}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
<Container marginBottom={SPACING_BETWEEN_PX}>
|
||||||
|
<Text fontSize="14px" fontColor={ColorOption.grey} center={true}>
|
||||||
|
{description}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
<Container marginBottom={SPACING_BETWEEN_PX}>
|
||||||
|
{moreInfoSettings && (
|
||||||
|
<Text
|
||||||
|
center={true}
|
||||||
|
fontSize="13px"
|
||||||
|
textDecorationLine="underline"
|
||||||
|
fontColor={ColorOption.lightGrey}
|
||||||
|
href={moreInfoSettings.href}
|
||||||
|
>
|
||||||
|
{moreInfoSettings.text}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Container>
|
||||||
|
</Flex>
|
||||||
|
<Container>{action}</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
29
packages/instant/src/components/standard_sliding_panel.tsx
Normal file
29
packages/instant/src/components/standard_sliding_panel.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { SlideAnimationState, StandardSlidingPanelContent, StandardSlidingPanelSettings } from '../types';
|
||||||
|
|
||||||
|
import { InstallWalletPanelContent } from './install_wallet_panel_content';
|
||||||
|
import { SlidingPanel } from './sliding_panel';
|
||||||
|
|
||||||
|
export interface StandardSlidingPanelProps extends StandardSlidingPanelSettings {
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StandardSlidingPanel extends React.Component<StandardSlidingPanelProps> {
|
||||||
|
public render(): React.ReactNode {
|
||||||
|
const { animationState, content, onClose } = this.props;
|
||||||
|
return (
|
||||||
|
<SlidingPanel animationState={animationState} onClose={onClose}>
|
||||||
|
{this._getNodeForContent(content)}
|
||||||
|
</SlidingPanel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private readonly _getNodeForContent = (content: StandardSlidingPanelContent): React.ReactNode => {
|
||||||
|
switch (content) {
|
||||||
|
case StandardSlidingPanelContent.InstallWallet:
|
||||||
|
return <InstallWalletPanelContent />;
|
||||||
|
case StandardSlidingPanelContent.None:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -2,7 +2,7 @@ import * as _ from 'lodash';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_WIDTH } from '../constants';
|
import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_WIDTH } from '../constants';
|
||||||
import { ColorOption, keyframes, styled } from '../style/theme';
|
import { ColorOption, css, keyframes, styled } from '../style/theme';
|
||||||
|
|
||||||
import { Container } from './ui/container';
|
import { Container } from './ui/container';
|
||||||
|
|
||||||
@ -20,15 +20,11 @@ export class TimedProgressBar extends React.Component<TimedProgressBarProps, {}>
|
|||||||
private readonly _barRef = React.createRef<HTMLDivElement>();
|
private readonly _barRef = React.createRef<HTMLDivElement>();
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const timedProgressProps = this._calculateTimedProgressProps();
|
const widthAnimationSettings = this._calculateWidthAnimationSettings();
|
||||||
return (
|
return <ProgressBar animationSettings={widthAnimationSettings} ref={this._barRef} />;
|
||||||
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px">
|
|
||||||
<TimedProgress {...timedProgressProps} ref={this._barRef as any} />
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _calculateTimedProgressProps(): TimedProgressProps {
|
private _calculateWidthAnimationSettings(): WidthAnimationSettings {
|
||||||
if (this.props.hasEnded) {
|
if (this.props.hasEnded) {
|
||||||
if (!this._barRef.current) {
|
if (!this._barRef.current) {
|
||||||
throw new Error('ended but no reference');
|
throw new Error('ended but no reference');
|
||||||
@ -60,21 +56,45 @@ const expandingWidthKeyframes = (fromWidth: string, toWidth: string) => {
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface TimedProgressProps {
|
export interface WidthAnimationSettings {
|
||||||
timeMs: number;
|
timeMs: number;
|
||||||
fromWidth: string;
|
fromWidth: string;
|
||||||
toWidth: string;
|
toWidth: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TimedProgress =
|
interface ProgressProps {
|
||||||
|
width?: string;
|
||||||
|
animationSettings?: WidthAnimationSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Progress =
|
||||||
styled.div <
|
styled.div <
|
||||||
TimedProgressProps >
|
ProgressProps >
|
||||||
`
|
`
|
||||||
&& {
|
&& {
|
||||||
background-color: ${props => props.theme[ColorOption.primaryColor]};
|
background-color: ${props => props.theme[ColorOption.primaryColor]};
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
animation: ${props => expandingWidthKeyframes(props.fromWidth, props.toWidth)}
|
${props => (props.width ? `width: ${props.width};` : '')}
|
||||||
${props => props.timeMs}ms linear 1 forwards;
|
${props =>
|
||||||
|
props.animationSettings
|
||||||
|
? css`
|
||||||
|
animation: ${expandingWidthKeyframes(
|
||||||
|
props.animationSettings.fromWidth,
|
||||||
|
props.animationSettings.toWidth,
|
||||||
|
)}
|
||||||
|
${props.animationSettings.timeMs}ms linear 1 forwards;
|
||||||
|
`
|
||||||
|
: ''}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export interface ProgressBarProps extends ProgressProps {}
|
||||||
|
|
||||||
|
export const ProgressBar: React.ComponentType<ProgressBarProps & React.ClassAttributes<{}>> = React.forwardRef(
|
||||||
|
(props, ref) => (
|
||||||
|
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px">
|
||||||
|
<Progress {...props} ref={ref as any} />
|
||||||
|
</Container>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
@ -2,6 +2,9 @@ import { darken, saturate } from 'polished';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ColorOption, styled } from '../../style/theme';
|
import { ColorOption, styled } from '../../style/theme';
|
||||||
|
import { util } from '../../util/util';
|
||||||
|
|
||||||
|
export type ButtonOnClickHandler = (event: React.MouseEvent<HTMLElement>) => void;
|
||||||
|
|
||||||
export interface ButtonProps {
|
export interface ButtonProps {
|
||||||
backgroundColor?: ColorOption;
|
backgroundColor?: ColorOption;
|
||||||
@ -12,15 +15,26 @@ export interface ButtonProps {
|
|||||||
padding?: string;
|
padding?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
href?: string;
|
||||||
|
onClick?: ButtonOnClickHandler;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
|
const PlainButton: React.StatelessComponent<ButtonProps> = ({
|
||||||
<button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
|
children,
|
||||||
{children}
|
isDisabled,
|
||||||
</button>
|
onClick,
|
||||||
);
|
href,
|
||||||
|
type,
|
||||||
|
className,
|
||||||
|
}) => {
|
||||||
|
const computedOnClick = isDisabled ? undefined : href ? util.createOpenUrlInNewWindow(href) : onClick;
|
||||||
|
return (
|
||||||
|
<button type={type} className={className} onClick={computedOnClick} disabled={isDisabled}>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const darkenOnHoverAmount = 0.1;
|
const darkenOnHoverAmount = 0.1;
|
||||||
const darkenOnActiveAmount = 0.2;
|
const darkenOnActiveAmount = 0.2;
|
||||||
@ -31,7 +45,7 @@ export const Button = styled(PlainButton)`
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: ${props => props.fontSize};
|
font-size: ${props => props.fontSize};
|
||||||
font-family: 'Inter UI', sans-serif;
|
font-family: 'Inter UI', sans-serif;
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
color: ${props => props.fontColor && props.theme[props.fontColor]};
|
color: ${props => props.fontColor && props.theme[props.fontColor]};
|
||||||
cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
|
cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
|
||||||
transition: background-color, opacity 0.5s ease;
|
transition: background-color, opacity 0.5s ease;
|
||||||
@ -64,11 +78,10 @@ export const Button = styled(PlainButton)`
|
|||||||
|
|
||||||
Button.defaultProps = {
|
Button.defaultProps = {
|
||||||
backgroundColor: ColorOption.primaryColor,
|
backgroundColor: ColorOption.primaryColor,
|
||||||
borderColor: ColorOption.primaryColor,
|
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
padding: '.6em 1.2em',
|
padding: '.82em 1.2em',
|
||||||
fontSize: '15px',
|
fontSize: '16px',
|
||||||
};
|
};
|
||||||
|
|
||||||
Button.displayName = 'Button';
|
Button.displayName = 'Button';
|
||||||
|
@ -20,7 +20,7 @@ export interface ContainerProps {
|
|||||||
marginBottom?: string;
|
marginBottom?: string;
|
||||||
marginLeft?: string;
|
marginLeft?: string;
|
||||||
padding?: string;
|
padding?: string;
|
||||||
borderRadius?: string;
|
borderRadius?: MediaChoice;
|
||||||
border?: string;
|
border?: string;
|
||||||
borderColor?: ColorOption;
|
borderColor?: ColorOption;
|
||||||
borderTop?: string;
|
borderTop?: string;
|
||||||
@ -57,7 +57,6 @@ export const Container =
|
|||||||
${props => cssRuleIfExists(props, 'margin-bottom')}
|
${props => cssRuleIfExists(props, 'margin-bottom')}
|
||||||
${props => cssRuleIfExists(props, 'margin-left')}
|
${props => cssRuleIfExists(props, 'margin-left')}
|
||||||
${props => cssRuleIfExists(props, 'padding')}
|
${props => cssRuleIfExists(props, 'padding')}
|
||||||
${props => cssRuleIfExists(props, 'border-radius')}
|
|
||||||
${props => cssRuleIfExists(props, 'border')}
|
${props => cssRuleIfExists(props, 'border')}
|
||||||
${props => cssRuleIfExists(props, 'border-top')}
|
${props => cssRuleIfExists(props, 'border-top')}
|
||||||
${props => cssRuleIfExists(props, 'border-bottom')}
|
${props => cssRuleIfExists(props, 'border-bottom')}
|
||||||
@ -70,6 +69,7 @@ export const Container =
|
|||||||
${props => props.display && stylesForMedia<string>('display', props.display)}
|
${props => props.display && stylesForMedia<string>('display', props.display)}
|
||||||
${props => props.width && stylesForMedia<string>('width', props.width)}
|
${props => props.width && stylesForMedia<string>('width', props.width)}
|
||||||
${props => props.height && stylesForMedia<string>('height', props.height)}
|
${props => props.height && stylesForMedia<string>('height', props.height)}
|
||||||
|
${props => props.borderRadius && stylesForMedia<string>('border-radius', props.borderRadius)}
|
||||||
background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
|
background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
|
||||||
border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
|
border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -20,6 +20,7 @@ interface IconInfoMapping {
|
|||||||
success: IconInfo;
|
success: IconInfo;
|
||||||
chevron: IconInfo;
|
chevron: IconInfo;
|
||||||
search: IconInfo;
|
search: IconInfo;
|
||||||
|
lock: IconInfo;
|
||||||
}
|
}
|
||||||
const ICONS: IconInfoMapping = {
|
const ICONS: IconInfoMapping = {
|
||||||
closeX: {
|
closeX: {
|
||||||
@ -58,6 +59,11 @@ const ICONS: IconInfoMapping = {
|
|||||||
path:
|
path:
|
||||||
'M8.39404 5.19727C8.39404 6.96289 6.96265 8.39453 5.19702 8.39453C3.4314 8.39453 2 6.96289 2 5.19727C2 3.43164 3.4314 2 5.19702 2C6.96265 2 8.39404 3.43164 8.39404 5.19727ZM8.09668 9.51074C7.26855 10.0684 6.27075 10.3945 5.19702 10.3945C2.3269 10.3945 0 8.06738 0 5.19727C0 2.32715 2.3269 0 5.19702 0C8.06738 0 10.394 2.32715 10.394 5.19727C10.394 6.27051 10.0686 7.26855 9.51074 8.09668L13.6997 12.2861L12.2854 13.7002L8.09668 9.51074Z',
|
'M8.39404 5.19727C8.39404 6.96289 6.96265 8.39453 5.19702 8.39453C3.4314 8.39453 2 6.96289 2 5.19727C2 3.43164 3.4314 2 5.19702 2C6.96265 2 8.39404 3.43164 8.39404 5.19727ZM8.09668 9.51074C7.26855 10.0684 6.27075 10.3945 5.19702 10.3945C2.3269 10.3945 0 8.06738 0 5.19727C0 2.32715 2.3269 0 5.19702 0C8.06738 0 10.394 2.32715 10.394 5.19727C10.394 6.27051 10.0686 7.26855 9.51074 8.09668L13.6997 12.2861L12.2854 13.7002L8.09668 9.51074Z',
|
||||||
},
|
},
|
||||||
|
lock: {
|
||||||
|
viewBox: '0 0 13 16',
|
||||||
|
path:
|
||||||
|
'M6.47619 0C3.79509 0 1.60489 2.21216 1.60489 4.92014V6.33135C0.717479 6.33135 0 7.05602 0 7.95232V14.379C0 15.2753 0.717479 16 1.60489 16H11.3475C12.2349 16 12.9524 15.2753 12.9524 14.379V7.95232C12.9524 7.05602 12.2349 6.33135 11.3475 6.33135V4.92014C11.3475 2.21216 9.1573 0 6.47619 0ZM9.6482 6.33135H3.30418V4.92014C3.30418 3.16567 4.72026 1.71633 6.47619 1.71633C8.23213 1.71633 9.6482 3.16567 9.6482 4.92014V6.33135Z',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IconProps {
|
export interface IconProps {
|
||||||
|
@ -3,6 +3,7 @@ import * as React from 'react';
|
|||||||
import { ColorOption, styled } from '../../style/theme';
|
import { ColorOption, styled } from '../../style/theme';
|
||||||
|
|
||||||
export interface InputProps {
|
export interface InputProps {
|
||||||
|
tabIndex?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
width?: string;
|
width?: string;
|
||||||
|
@ -2,6 +2,7 @@ import { darken } from 'polished';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ColorOption, styled } from '../../style/theme';
|
import { ColorOption, styled } from '../../style/theme';
|
||||||
|
import { util } from '../../util/util';
|
||||||
|
|
||||||
export interface TextProps {
|
export interface TextProps {
|
||||||
fontColor?: ColorOption;
|
fontColor?: ColorOption;
|
||||||
@ -20,10 +21,16 @@ export interface TextProps {
|
|||||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||||
noWrap?: boolean;
|
noWrap?: boolean;
|
||||||
display?: string;
|
display?: string;
|
||||||
|
href?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Text: React.StatelessComponent<TextProps> = ({ href, onClick, ...rest }) => {
|
||||||
|
const computedOnClick = href ? util.createOpenUrlInNewWindow(href) : onClick;
|
||||||
|
return <StyledText {...rest} onClick={computedOnClick} />;
|
||||||
|
};
|
||||||
|
|
||||||
const darkenOnHoverAmount = 0.3;
|
const darkenOnHoverAmount = 0.3;
|
||||||
export const Text =
|
export const StyledText =
|
||||||
styled.div <
|
styled.div <
|
||||||
TextProps >
|
TextProps >
|
||||||
`
|
`
|
||||||
|
47
packages/instant/src/components/wallet_prompt.tsx
Normal file
47
packages/instant/src/components/wallet_prompt.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { ColorOption } from '../style/theme';
|
||||||
|
|
||||||
|
import { Container } from './ui/container';
|
||||||
|
import { Flex } from './ui/flex';
|
||||||
|
import { Text } from './ui/text';
|
||||||
|
|
||||||
|
export interface WalletPromptProps {
|
||||||
|
image: React.ReactNode;
|
||||||
|
onClick?: () => void;
|
||||||
|
primaryColor: ColorOption;
|
||||||
|
secondaryColor: ColorOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WalletPrompt: React.StatelessComponent<WalletPromptProps> = ({
|
||||||
|
onClick,
|
||||||
|
image,
|
||||||
|
children,
|
||||||
|
secondaryColor,
|
||||||
|
primaryColor,
|
||||||
|
}) => (
|
||||||
|
<Container
|
||||||
|
padding="14.5px"
|
||||||
|
border={`1px solid ${primaryColor}`}
|
||||||
|
backgroundColor={secondaryColor}
|
||||||
|
width="100%"
|
||||||
|
borderRadius="4px"
|
||||||
|
onClick={onClick}
|
||||||
|
cursor={onClick ? 'pointer' : undefined}
|
||||||
|
boxShadowOnHover={!!onClick}
|
||||||
|
>
|
||||||
|
<Flex>
|
||||||
|
{image}
|
||||||
|
<Container marginLeft="10px">
|
||||||
|
<Text fontSize="16px" fontColor={primaryColor}>
|
||||||
|
{children}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
</Flex>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
|
||||||
|
WalletPrompt.defaultProps = {
|
||||||
|
primaryColor: ColorOption.darkOrange,
|
||||||
|
secondaryColor: ColorOption.lightOrange,
|
||||||
|
};
|
@ -1,8 +1,9 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { ZeroExInstantContainer } from '../components/zero_ex_instant_container';
|
||||||
|
|
||||||
import { INJECTED_DIV_CLASS } from '../constants';
|
import { INJECTED_DIV_CLASS } from '../constants';
|
||||||
|
|
||||||
import { ZeroExInstantContainer } from './zero_ex_instant_container';
|
|
||||||
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
||||||
|
|
||||||
export type ZeroExInstantProps = ZeroExInstantProviderProps;
|
export type ZeroExInstantProps = ZeroExInstantProviderProps;
|
||||||
|
@ -1,26 +1,29 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { AvailableERC20TokenSelector } from '../containers/available_erc20_token_selector';
|
import { AvailableERC20TokenSelector } from '../containers/available_erc20_token_selector';
|
||||||
|
import { ConnectedBuyOrderProgressOrPaymentMethod } from '../containers/connected_buy_order_progress_or_payment_method';
|
||||||
|
import { CurrentStandardSlidingPanel } from '../containers/current_standard_sliding_panel';
|
||||||
import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details';
|
import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details';
|
||||||
import { LatestError } from '../containers/latest_error';
|
import { LatestError } from '../containers/latest_error';
|
||||||
import { SelectedAssetBuyOrderProgress } from '../containers/selected_asset_buy_order_progress';
|
|
||||||
import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons';
|
import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons';
|
||||||
import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading';
|
import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading';
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { zIndex } from '../style/z_index';
|
import { zIndex } from '../style/z_index';
|
||||||
|
import { OrderProcessState, SlideAnimationState } from '../types';
|
||||||
|
|
||||||
import { SlideAnimationState } from './animations/slide_animation';
|
|
||||||
import { CSSReset } from './css_reset';
|
import { CSSReset } from './css_reset';
|
||||||
import { SlidingPanel } from './sliding_panel';
|
import { SlidingPanel } from './sliding_panel';
|
||||||
import { Container } from './ui/container';
|
import { Container } from './ui/container';
|
||||||
import { Flex } from './ui/flex';
|
import { Flex } from './ui/flex';
|
||||||
|
|
||||||
export interface ZeroExInstantContainerProps {}
|
export interface ZeroExInstantContainerProps {
|
||||||
|
orderProcessState: OrderProcessState;
|
||||||
|
}
|
||||||
export interface ZeroExInstantContainerState {
|
export interface ZeroExInstantContainerState {
|
||||||
tokenSelectionPanelAnimationState: SlideAnimationState;
|
tokenSelectionPanelAnimationState: SlideAnimationState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ZeroExInstantContainer extends React.Component<ZeroExInstantContainerProps, ZeroExInstantContainerState> {
|
export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantContainerState> {
|
||||||
public state = {
|
public state = {
|
||||||
tokenSelectionPanelAnimationState: 'none' as SlideAnimationState,
|
tokenSelectionPanelAnimationState: 'none' as SlideAnimationState,
|
||||||
};
|
};
|
||||||
@ -40,26 +43,26 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain
|
|||||||
zIndex={zIndex.mainContainer}
|
zIndex={zIndex.mainContainer}
|
||||||
position="relative"
|
position="relative"
|
||||||
backgroundColor={ColorOption.white}
|
backgroundColor={ColorOption.white}
|
||||||
borderRadius="3px"
|
borderRadius={{ default: '3px', sm: '0px' }}
|
||||||
hasBoxShadow={true}
|
hasBoxShadow={true}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
height="100%"
|
height="100%"
|
||||||
>
|
>
|
||||||
<Flex direction="column" justify="flex-start" height="100%">
|
<Flex direction="column" justify="flex-start" height="100%">
|
||||||
<SelectedAssetInstantHeading onSelectAssetClick={this._handleSymbolClick} />
|
<SelectedAssetInstantHeading onSelectAssetClick={this._handleSymbolClick} />
|
||||||
<SelectedAssetBuyOrderProgress />
|
<ConnectedBuyOrderProgressOrPaymentMethod />
|
||||||
<LatestBuyQuoteOrderDetails />
|
<LatestBuyQuoteOrderDetails />
|
||||||
<Container padding="20px" width="100%">
|
<Container padding="20px" width="100%">
|
||||||
<SelectedAssetBuyOrderStateButtons />
|
<SelectedAssetBuyOrderStateButtons />
|
||||||
</Container>
|
</Container>
|
||||||
</Flex>
|
</Flex>
|
||||||
<SlidingPanel
|
<SlidingPanel
|
||||||
title="Select Token"
|
|
||||||
animationState={this.state.tokenSelectionPanelAnimationState}
|
animationState={this.state.tokenSelectionPanelAnimationState}
|
||||||
onClose={this._handlePanelClose}
|
onClose={this._handlePanelClose}
|
||||||
>
|
>
|
||||||
<AvailableERC20TokenSelector onTokenSelect={this._handlePanelClose} />
|
<AvailableERC20TokenSelector onTokenSelect={this._handlePanelClose} />
|
||||||
</SlidingPanel>
|
</SlidingPanel>
|
||||||
|
<CurrentStandardSlidingPanel />
|
||||||
</Container>
|
</Container>
|
||||||
</Container>
|
</Container>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { ZeroExInstantContainer } from '../components/zero_ex_instant_container';
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
|
|
||||||
import { Container } from './ui/container';
|
import { Container } from './ui/container';
|
||||||
import { Flex } from './ui/flex';
|
import { Flex } from './ui/flex';
|
||||||
import { Icon } from './ui/icon';
|
import { Icon } from './ui/icon';
|
||||||
import { Overlay } from './ui/overlay';
|
import { Overlay } from './ui/overlay';
|
||||||
import { ZeroExInstantContainer } from './zero_ex_instant_container';
|
|
||||||
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
||||||
|
|
||||||
export interface ZeroExInstantOverlayProps extends ZeroExInstantProviderProps {
|
export interface ZeroExInstantOverlayProps extends ZeroExInstantProviderProps {
|
||||||
|
@ -73,7 +73,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
|
|||||||
completeAssetMetaDataMap,
|
completeAssetMetaDataMap,
|
||||||
networkId,
|
networkId,
|
||||||
),
|
),
|
||||||
selectedAssetAmount: _.isUndefined(props.defaultAssetBuyAmount)
|
selectedAssetUnitAmount: _.isUndefined(props.defaultAssetBuyAmount)
|
||||||
? undefined
|
? undefined
|
||||||
: new BigNumber(props.defaultAssetBuyAmount),
|
: new BigNumber(props.defaultAssetBuyAmount),
|
||||||
availableAssets: _.isUndefined(props.availableAssetDatas)
|
availableAssets: _.isUndefined(props.availableAssetDatas)
|
||||||
@ -91,12 +91,13 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
|
|||||||
}
|
}
|
||||||
public componentDidMount(): void {
|
public componentDidMount(): void {
|
||||||
const state = this._store.getState();
|
const state = this._store.getState();
|
||||||
|
const dispatch = this._store.dispatch;
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
asyncData.fetchEthPriceAndDispatchToStore(this._store);
|
asyncData.fetchEthPriceAndDispatchToStore(dispatch);
|
||||||
// fetch available assets if none are specified
|
// fetch available assets if none are specified
|
||||||
if (_.isUndefined(state.availableAssets)) {
|
if (_.isUndefined(state.availableAssets)) {
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
asyncData.fetchAvailableAssetDatasAndDispatchToStore(this._store);
|
asyncData.fetchAvailableAssetDatasAndDispatchToStore(state, dispatch);
|
||||||
}
|
}
|
||||||
if (state.providerState.account.state !== AccountState.None) {
|
if (state.providerState.account.state !== AccountState.None) {
|
||||||
this._accountUpdateHeartbeat = generateAccountHeartbeater({
|
this._accountUpdateHeartbeat = generateAccountHeartbeater({
|
||||||
@ -111,8 +112,9 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
|
|||||||
shouldPerformImmediatelyOnStart: false,
|
shouldPerformImmediatelyOnStart: false,
|
||||||
});
|
});
|
||||||
this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
|
this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
|
||||||
|
// Trigger first buyquote fetch
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
asyncData.fetchCurrentBuyQuoteAndDispatchToStore({ store: this._store, shouldSetPending: true });
|
asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, { updateSilently: false });
|
||||||
// warm up the gas price estimator cache just in case we can't
|
// warm up the gas price estimator cache just in case we can't
|
||||||
// grab the gas price estimate when submitting the transaction
|
// grab the gas price estimate when submitting the transaction
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
import { AccountNotReady, AccountState, Network } from './types';
|
import { AccountNotReady, AccountState, Network, ProviderType } from './types';
|
||||||
|
|
||||||
export const BIG_NUMBER_ZERO = new BigNumber(0);
|
export const BIG_NUMBER_ZERO = new BigNumber(0);
|
||||||
export const ETH_DECIMALS = 18;
|
export const ETH_DECIMALS = 18;
|
||||||
@ -19,6 +19,14 @@ export const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
|
|||||||
export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2';
|
export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2';
|
||||||
export const PROGRESS_STALL_AT_WIDTH = '95%';
|
export const PROGRESS_STALL_AT_WIDTH = '95%';
|
||||||
export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200;
|
export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200;
|
||||||
|
export const COINBASE_WALLET_IOS_APP_STORE_URL = 'https://itunes.apple.com/us/app/coinbase-wallet/id1278383455?mt=8';
|
||||||
|
export const COINBASE_WALLET_ANDROID_APP_STORE_URL = 'https://play.google.com/store/apps/details?id=org.toshi&hl=en';
|
||||||
|
export const COINBASE_WALLET_SITE_URL = 'https://wallet.coinbase.com/';
|
||||||
|
export const META_MASK_FIREFOX_STORE_URL = 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/';
|
||||||
|
export const META_MASK_CHROME_STORE_URL =
|
||||||
|
'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en';
|
||||||
|
export const META_MASK_OPERA_STORE_URL = 'https://addons.opera.com/en/extensions/details/metamask/';
|
||||||
|
export const META_MASK_SITE_URL = 'https://metamask.io/';
|
||||||
export const ETHEREUM_NODE_URL_BY_NETWORK = {
|
export const ETHEREUM_NODE_URL_BY_NETWORK = {
|
||||||
[Network.Mainnet]: 'https://mainnet.infura.io/',
|
[Network.Mainnet]: 'https://mainnet.infura.io/',
|
||||||
[Network.Kovan]: 'https://kovan.infura.io/',
|
[Network.Kovan]: 'https://kovan.infura.io/',
|
||||||
@ -33,3 +41,10 @@ export const LOADING_ACCOUNT: AccountNotReady = {
|
|||||||
export const LOCKED_ACCOUNT: AccountNotReady = {
|
export const LOCKED_ACCOUNT: AccountNotReady = {
|
||||||
state: AccountState.Locked,
|
state: AccountState.Locked,
|
||||||
};
|
};
|
||||||
|
export const PROVIDER_TYPE_TO_NAME: { [key in ProviderType]: string } = {
|
||||||
|
[ProviderType.Cipher]: 'Cipher',
|
||||||
|
[ProviderType.MetaMask]: 'MetaMask',
|
||||||
|
[ProviderType.Mist]: 'Mist',
|
||||||
|
[ProviderType.CoinbaseWallet]: 'Coinbase Wallet',
|
||||||
|
[ProviderType.Parity]: 'Parity',
|
||||||
|
};
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
import { PaymentMethod, PaymentMethodProps } from '../components/payment_method';
|
||||||
|
import {
|
||||||
|
COINBASE_WALLET_ANDROID_APP_STORE_URL,
|
||||||
|
COINBASE_WALLET_IOS_APP_STORE_URL,
|
||||||
|
COINBASE_WALLET_SITE_URL,
|
||||||
|
} from '../constants';
|
||||||
|
import { Action, actions } from '../redux/actions';
|
||||||
|
import { asyncData } from '../redux/async_data';
|
||||||
|
import { State } from '../redux/reducer';
|
||||||
|
import { Network, Omit, OperatingSystem, ProviderState, StandardSlidingPanelContent } from '../types';
|
||||||
|
import { envUtil } from '../util/env';
|
||||||
|
|
||||||
|
export interface ConnectedAccountPaymentMethodProps {}
|
||||||
|
|
||||||
|
interface ConnectedState {
|
||||||
|
network: Network;
|
||||||
|
providerState: ProviderState;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConnectedDispatch {
|
||||||
|
openInstallWalletPanel: () => void;
|
||||||
|
unlockWalletAndDispatchToStore: (providerState: ProviderState) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnectedProps = Omit<PaymentMethodProps, keyof ConnectedAccountPaymentMethodProps>;
|
||||||
|
|
||||||
|
type FinalProps = ConnectedProps & ConnectedAccountPaymentMethodProps;
|
||||||
|
|
||||||
|
const mapStateToProps = (state: State, _ownProps: ConnectedAccountPaymentMethodProps): ConnectedState => ({
|
||||||
|
network: state.network,
|
||||||
|
providerState: state.providerState,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (
|
||||||
|
dispatch: Dispatch<Action>,
|
||||||
|
ownProps: ConnectedAccountPaymentMethodProps,
|
||||||
|
): ConnectedDispatch => ({
|
||||||
|
openInstallWalletPanel: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)),
|
||||||
|
unlockWalletAndDispatchToStore: async (providerState: ProviderState) =>
|
||||||
|
asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true),
|
||||||
|
});
|
||||||
|
|
||||||
|
const mergeProps = (
|
||||||
|
connectedState: ConnectedState,
|
||||||
|
connectedDispatch: ConnectedDispatch,
|
||||||
|
ownProps: ConnectedAccountPaymentMethodProps,
|
||||||
|
): FinalProps => ({
|
||||||
|
...ownProps,
|
||||||
|
network: connectedState.network,
|
||||||
|
account: connectedState.providerState.account,
|
||||||
|
walletName: connectedState.providerState.name,
|
||||||
|
onUnlockWalletClick: () => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState),
|
||||||
|
onInstallWalletClick: () => {
|
||||||
|
const isMobile = envUtil.isMobileOperatingSystem();
|
||||||
|
if (!isMobile) {
|
||||||
|
connectedDispatch.openInstallWalletPanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const operatingSystem = envUtil.getOperatingSystem();
|
||||||
|
let url = COINBASE_WALLET_SITE_URL;
|
||||||
|
switch (operatingSystem) {
|
||||||
|
case OperatingSystem.Android:
|
||||||
|
url = COINBASE_WALLET_ANDROID_APP_STORE_URL;
|
||||||
|
break;
|
||||||
|
case OperatingSystem.iOS:
|
||||||
|
url = COINBASE_WALLET_IOS_APP_STORE_URL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
window.open(url, '_blank');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ConnectedAccountPaymentMethod: React.ComponentClass<ConnectedAccountPaymentMethodProps> = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
mergeProps,
|
||||||
|
)(PaymentMethod);
|
@ -0,0 +1,35 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { State } from '../redux/reducer';
|
||||||
|
import { OrderProcessState } from '../types';
|
||||||
|
|
||||||
|
import { ConnectedAccountPaymentMethod } from './connected_account_payment_method';
|
||||||
|
import { SelectedAssetBuyOrderProgress } from './selected_asset_buy_order_progress';
|
||||||
|
|
||||||
|
interface BuyOrderProgressOrPaymentMethodProps {
|
||||||
|
orderProcessState: OrderProcessState;
|
||||||
|
}
|
||||||
|
export const BuyOrderProgressOrPaymentMethod = (props: BuyOrderProgressOrPaymentMethodProps) => {
|
||||||
|
const { orderProcessState } = props;
|
||||||
|
if (
|
||||||
|
orderProcessState === OrderProcessState.Processing ||
|
||||||
|
orderProcessState === OrderProcessState.Success ||
|
||||||
|
orderProcessState === OrderProcessState.Failure
|
||||||
|
) {
|
||||||
|
return <SelectedAssetBuyOrderProgress />;
|
||||||
|
} else {
|
||||||
|
return <ConnectedAccountPaymentMethod />;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ConnectedState extends BuyOrderProgressOrPaymentMethodProps {}
|
||||||
|
|
||||||
|
export interface ConnectedBuyOrderProgressOrPaymentMethodProps {}
|
||||||
|
const mapStateToProps = (state: State, _ownProps: ConnectedBuyOrderProgressOrPaymentMethodProps): ConnectedState => ({
|
||||||
|
orderProcessState: state.buyOrderState.processState,
|
||||||
|
});
|
||||||
|
export const ConnectedBuyOrderProgressOrPaymentMethod: React.ComponentClass<
|
||||||
|
ConnectedBuyOrderProgressOrPaymentMethodProps
|
||||||
|
> = connect(mapStateToProps)(BuyOrderProgressOrPaymentMethod);
|
@ -0,0 +1,31 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
import { StandardSlidingPanel } from '../components/standard_sliding_panel';
|
||||||
|
import { Action, actions } from '../redux/actions';
|
||||||
|
import { State } from '../redux/reducer';
|
||||||
|
import { StandardSlidingPanelSettings } from '../types';
|
||||||
|
|
||||||
|
export interface CurrentStandardSlidingPanelProps {}
|
||||||
|
|
||||||
|
interface ConnectedState extends StandardSlidingPanelSettings {}
|
||||||
|
|
||||||
|
interface ConnectedDispatch {
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: State, _ownProps: CurrentStandardSlidingPanelProps): ConnectedState =>
|
||||||
|
state.standardSlidingPanelSettings;
|
||||||
|
|
||||||
|
const mapDispatchToProps = (
|
||||||
|
dispatch: Dispatch<Action>,
|
||||||
|
ownProps: CurrentStandardSlidingPanelProps,
|
||||||
|
): ConnectedDispatch => ({
|
||||||
|
onClose: () => dispatch(actions.closeStandardSlidingPanel()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const CurrentStandardSlidingPanel: React.ComponentClass<CurrentStandardSlidingPanelProps> = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
)(StandardSlidingPanel);
|
@ -14,6 +14,7 @@ export interface LatestBuyQuoteOrderDetailsProps {}
|
|||||||
|
|
||||||
interface ConnectedState {
|
interface ConnectedState {
|
||||||
buyQuoteInfo?: BuyQuoteInfo;
|
buyQuoteInfo?: BuyQuoteInfo;
|
||||||
|
selectedAssetUnitAmount?: BigNumber;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
}
|
}
|
||||||
@ -21,6 +22,7 @@ interface ConnectedState {
|
|||||||
const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({
|
const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({
|
||||||
// use the worst case quote info
|
// use the worst case quote info
|
||||||
buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(),
|
buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(),
|
||||||
|
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
|
||||||
ethUsdPrice: state.ethUsdPrice,
|
ethUsdPrice: state.ethUsdPrice,
|
||||||
isLoading: state.quoteRequestState === AsyncProcessState.Pending,
|
isLoading: state.quoteRequestState === AsyncProcessState.Pending,
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,6 @@ import * as React from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { SlideAnimationState } from '../components/animations/slide_animation';
|
|
||||||
import { SlidingError } from '../components/sliding_error';
|
import { SlidingError } from '../components/sliding_error';
|
||||||
import { Overlay } from '../components/ui/overlay';
|
import { Overlay } from '../components/ui/overlay';
|
||||||
import { Action } from '../redux/actions';
|
import { Action } from '../redux/actions';
|
||||||
@ -11,7 +10,7 @@ import { State } from '../redux/reducer';
|
|||||||
import { ScreenWidths } from '../style/media';
|
import { ScreenWidths } from '../style/media';
|
||||||
import { generateOverlayBlack } from '../style/theme';
|
import { generateOverlayBlack } from '../style/theme';
|
||||||
import { zIndex } from '../style/z_index';
|
import { zIndex } from '../style/z_index';
|
||||||
import { Asset, DisplayStatus, Omit } from '../types';
|
import { Asset, DisplayStatus, Omit, SlideAnimationState } from '../types';
|
||||||
import { errorFlasher } from '../util/error_flasher';
|
import { errorFlasher } from '../util/error_flasher';
|
||||||
|
|
||||||
export interface LatestErrorComponentProps {
|
export interface LatestErrorComponentProps {
|
||||||
|
@ -14,16 +14,16 @@ export interface InstantHeadingProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ConnectedState {
|
interface ConnectedState {
|
||||||
selectedAssetAmount?: BigNumber;
|
selectedAssetUnitAmount?: BigNumber;
|
||||||
totalEthBaseAmount?: BigNumber;
|
totalEthBaseUnitAmount?: BigNumber;
|
||||||
ethUsdPrice?: BigNumber;
|
ethUsdPrice?: BigNumber;
|
||||||
quoteRequestState: AsyncProcessState;
|
quoteRequestState: AsyncProcessState;
|
||||||
buyOrderState: OrderState;
|
buyOrderState: OrderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
|
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
|
||||||
selectedAssetAmount: state.selectedAssetAmount,
|
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
|
||||||
totalEthBaseAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
|
totalEthBaseUnitAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
|
||||||
ethUsdPrice: state.ethUsdPrice,
|
ethUsdPrice: state.ethUsdPrice,
|
||||||
quoteRequestState: state.quoteRequestState,
|
quoteRequestState: state.quoteRequestState,
|
||||||
buyOrderState: state.buyOrderState,
|
buyOrderState: state.buyOrderState,
|
||||||
|
@ -6,11 +6,11 @@ import * as React from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { ERC20AssetAmountInput } from '../components/erc20_asset_amount_input';
|
import { ERC20AssetAmountInput, ERC20AssetAmountInputProps } from '../components/erc20_asset_amount_input';
|
||||||
import { Action, actions } from '../redux/actions';
|
import { Action, actions } from '../redux/actions';
|
||||||
import { State } from '../redux/reducer';
|
import { State } from '../redux/reducer';
|
||||||
import { ColorOption } from '../style/theme';
|
import { ColorOption } from '../style/theme';
|
||||||
import { AffiliateInfo, ERC20Asset, OrderProcessState } from '../types';
|
import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState } from '../types';
|
||||||
import { buyQuoteUpdater } from '../util/buy_quote_updater';
|
import { buyQuoteUpdater } from '../util/buy_quote_updater';
|
||||||
|
|
||||||
export interface SelectedERC20AssetAmountInputProps {
|
export interface SelectedERC20AssetAmountInputProps {
|
||||||
@ -37,13 +37,7 @@ interface ConnectedDispatch {
|
|||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConnectedProps {
|
type ConnectedProps = Omit<ERC20AssetAmountInputProps, keyof SelectedERC20AssetAmountInputProps>;
|
||||||
value?: BigNumber;
|
|
||||||
asset?: ERC20Asset;
|
|
||||||
onChange: (value?: BigNumber, asset?: ERC20Asset) => void;
|
|
||||||
isDisabled: boolean;
|
|
||||||
numberOfAssetsAvailable?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
type FinalProps = ConnectedProps & SelectedERC20AssetAmountInputProps;
|
type FinalProps = ConnectedProps & SelectedERC20AssetAmountInputProps;
|
||||||
|
|
||||||
@ -59,7 +53,7 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP
|
|||||||
const assetBuyer = state.providerState.assetBuyer;
|
const assetBuyer = state.providerState.assetBuyer;
|
||||||
return {
|
return {
|
||||||
assetBuyer,
|
assetBuyer,
|
||||||
value: state.selectedAssetAmount,
|
value: state.selectedAssetUnitAmount,
|
||||||
asset: selectedAsset,
|
asset: selectedAsset,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
numberOfAssetsAvailable,
|
numberOfAssetsAvailable,
|
||||||
@ -87,7 +81,11 @@ const mapDispatchToProps = (
|
|||||||
// even if it's debounced, give them the illusion it's loading
|
// even if it's debounced, give them the illusion it's loading
|
||||||
dispatch(actions.setQuoteRequestStatePending());
|
dispatch(actions.setQuoteRequestStatePending());
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, true, affiliateInfo);
|
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, {
|
||||||
|
setPending: true,
|
||||||
|
dispatchErrors: true,
|
||||||
|
affiliateInfo,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -8,42 +8,42 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
|
|||||||
'0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498': {
|
'0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
primaryColor: 'rgb(54, 50, 60)',
|
primaryColor: '#333333',
|
||||||
symbol: 'zrx',
|
symbol: 'zrx',
|
||||||
name: '0x',
|
name: '0x',
|
||||||
},
|
},
|
||||||
'0xf47261b000000000000000000000000042d6622dece394b54999fbd73d108123806f6a18': {
|
'0xf47261b000000000000000000000000042d6622dece394b54999fbd73d108123806f6a18': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
primaryColor: '#ec3e6c',
|
primaryColor: '#EC4F81',
|
||||||
symbol: 'spank',
|
symbol: 'spank',
|
||||||
name: 'Spank',
|
name: 'Spank',
|
||||||
},
|
},
|
||||||
'0xf47261b0000000000000000000000000d26114cd6ee289accf82350c8d8487fedb8a0c07': {
|
'0xf47261b0000000000000000000000000d26114cd6ee289accf82350c8d8487fedb8a0c07': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
primaryColor: '#2e61ea',
|
primaryColor: '#2458E7',
|
||||||
symbol: 'omg',
|
symbol: 'omg',
|
||||||
name: 'OmiseGo',
|
name: 'OmiseGo',
|
||||||
},
|
},
|
||||||
'0xf47261b00000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2': {
|
'0xf47261b00000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
primaryColor: '#87e4ca',
|
primaryColor: '#68CCBB',
|
||||||
symbol: 'mkr',
|
symbol: 'mkr',
|
||||||
name: 'Maker',
|
name: 'Maker',
|
||||||
},
|
},
|
||||||
'0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef': {
|
'0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
primaryColor: '#9c326c',
|
primaryColor: '#FF5000',
|
||||||
symbol: 'bat',
|
symbol: 'bat',
|
||||||
name: 'Basic Attention Token',
|
name: 'Basic Attention Token',
|
||||||
},
|
},
|
||||||
'0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e': {
|
'0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
primaryColor: '#5663b0',
|
primaryColor: '#4763D7',
|
||||||
symbol: 'snt',
|
symbol: 'snt',
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
},
|
},
|
||||||
@ -54,27 +54,6 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
|
|||||||
symbol: 'mana',
|
symbol: 'mana',
|
||||||
name: 'Decentraland',
|
name: 'Decentraland',
|
||||||
},
|
},
|
||||||
'0xf47261b0000000000000000000000000a74476443119a942de498590fe1f2454d7d4ac0d': {
|
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
|
||||||
decimals: 18,
|
|
||||||
primaryColor: '#263469',
|
|
||||||
symbol: 'gnt',
|
|
||||||
name: 'Golem',
|
|
||||||
},
|
|
||||||
'0xf47261b000000000000000000000000012480e24eb5bec1a9d4369cab6a80cad3c0a377a': {
|
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
|
||||||
decimals: 18,
|
|
||||||
primaryColor: '#de5445',
|
|
||||||
symbol: 'sub',
|
|
||||||
name: 'Substratum',
|
|
||||||
},
|
|
||||||
'0xf47261b000000000000000000000000008d32b0da63e2C3bcF8019c9c5d849d7a9d791e6': {
|
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
|
||||||
decimals: 18,
|
|
||||||
primaryColor: '#000',
|
|
||||||
symbol: 'dentacoin',
|
|
||||||
name: 'Dentacoin',
|
|
||||||
},
|
|
||||||
'0xf47261b00000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e862': {
|
'0xf47261b00000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e862': {
|
||||||
assetProxyId: AssetProxyId.ERC20,
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
@ -82,4 +61,144 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
|
|||||||
symbol: 'rep',
|
symbol: 'rep',
|
||||||
name: 'Augur',
|
name: 'Augur',
|
||||||
},
|
},
|
||||||
|
'0xf47261b00000000000000000000000000abdace70d3790235af448c88547603b945604ea': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#2c3c8c',
|
||||||
|
symbol: 'dnt',
|
||||||
|
name: 'district0x',
|
||||||
|
},
|
||||||
|
'0xf47261b000000000000000000000000005f4a42e251f2d52b8ed15e9fedaacfcef1fad27': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 12,
|
||||||
|
primaryColor: '#048998',
|
||||||
|
symbol: 'zil',
|
||||||
|
name: 'Zilliqa',
|
||||||
|
},
|
||||||
|
'0xf47261b00000000000000000000000008f8221afbb33998d8584a2b05749ba73c37a938a': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#58BFD6',
|
||||||
|
symbol: 'req',
|
||||||
|
name: 'Request Network',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000e0b7927c4af23765cb51314a0e0521a9645f0e2a': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 9,
|
||||||
|
primaryColor: '#BC9952',
|
||||||
|
symbol: 'dgd',
|
||||||
|
name: 'DigixDao',
|
||||||
|
},
|
||||||
|
'0xf47261b00000000000000000000000004f3afec4e5a3f2a6a1a411def7d7dfe50ee057bf': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 9,
|
||||||
|
primaryColor: '#DEB564',
|
||||||
|
symbol: 'dgx',
|
||||||
|
name: 'Digix Gold Token',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000419d0d8bdd9af5e606ae2232ed285aff190e711b': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 8,
|
||||||
|
primaryColor: '#E40057',
|
||||||
|
symbol: 'fun',
|
||||||
|
name: 'FunFair',
|
||||||
|
},
|
||||||
|
'0xf47261b000000000000000000000000041e5560054824ea6b0732e656e3ad64e20e94e45': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 8,
|
||||||
|
primaryColor: '#04bc24',
|
||||||
|
symbol: 'cvc',
|
||||||
|
name: 'Civic',
|
||||||
|
},
|
||||||
|
'0xf47261b00000000000000000000000005ca9a71b1d01849c0a95490cc00559717fcf0d1d': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#F7296E',
|
||||||
|
symbol: 'ae',
|
||||||
|
name: 'Aeternity',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000408e41876cccdc0f92210600ef50372656052a38': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#233C5A',
|
||||||
|
symbol: 'ren',
|
||||||
|
name: 'Republic Protocol',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#325CD2',
|
||||||
|
symbol: 'link',
|
||||||
|
name: 'ChainLink',
|
||||||
|
},
|
||||||
|
'0xf47261b00000000000000000000000006810e776880c02933d47db1b9fc05908e5386b96': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#48A4C0',
|
||||||
|
symbol: 'gno',
|
||||||
|
name: 'Gnosis',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000960b236a07cf122663c4303350609a66a7b288c0': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#04a29e',
|
||||||
|
symbol: 'ant',
|
||||||
|
name: 'Aragon',
|
||||||
|
},
|
||||||
|
'0xf47261b00000000000000000000000004156d3342d5c385a87d264f90653733592000581': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 8,
|
||||||
|
primaryColor: '#4CABA7',
|
||||||
|
symbol: 'salt',
|
||||||
|
name: 'Salt',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000595832f8fc6bf59c85c527fec3740a1b7a361269': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 6,
|
||||||
|
primaryColor: '#5BC9D4',
|
||||||
|
symbol: 'powr',
|
||||||
|
name: 'PowerLedger',
|
||||||
|
},
|
||||||
|
'0xf47261b00000000000000000000000008eb24319393716668d768dcec29356ae9cffe285': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 8,
|
||||||
|
primaryColor: '#523CE8',
|
||||||
|
symbol: 'agi',
|
||||||
|
name: 'SingularityNET',
|
||||||
|
},
|
||||||
|
'0xf47261b000000000000000000000000039bb259f66e1c59d5abef88375979b4d20d98022': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 8,
|
||||||
|
primaryColor: '#EDB740',
|
||||||
|
symbol: 'wax',
|
||||||
|
name: 'WAX',
|
||||||
|
},
|
||||||
|
'0xf47261b0000000000000000000000000beb9ef514a379b997e0798fdcc901ee474b6d9a1': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#333333',
|
||||||
|
symbol: 'mln',
|
||||||
|
name: 'Melon',
|
||||||
|
},
|
||||||
|
'0xf47261b000000000000000000000000058b6a8a3302369daec383334672404ee733ab239': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#232D37',
|
||||||
|
symbol: 'lpt',
|
||||||
|
name: 'Livepeer',
|
||||||
|
},
|
||||||
|
'0xf47261b000000000000000000000000027054b13b1b798b345b591a4d22e6562d47ea75a': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 4,
|
||||||
|
primaryColor: '#3A74F6',
|
||||||
|
symbol: 'ast',
|
||||||
|
name: 'AirSwap',
|
||||||
|
},
|
||||||
|
'0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359': {
|
||||||
|
assetProxyId: AssetProxyId.ERC20,
|
||||||
|
decimals: 18,
|
||||||
|
primaryColor: '#F2B350',
|
||||||
|
symbol: 'dai',
|
||||||
|
name: 'Dai Stablecoin',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ import { BuyQuote } from '@0x/asset-buyer';
|
|||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { ActionsUnion, AddressAndEthBalanceInWei, Asset } from '../types';
|
import { ActionsUnion, AddressAndEthBalanceInWei, Asset, StandardSlidingPanelContent } from '../types';
|
||||||
|
|
||||||
export interface PlainAction<T extends string> {
|
export interface PlainAction<T extends string> {
|
||||||
type: T;
|
type: T;
|
||||||
@ -26,7 +26,7 @@ export enum ActionTypes {
|
|||||||
SET_ACCOUNT_STATE_READY = 'SET_ACCOUNT_STATE_READY',
|
SET_ACCOUNT_STATE_READY = 'SET_ACCOUNT_STATE_READY',
|
||||||
UPDATE_ACCOUNT_ETH_BALANCE = 'UPDATE_ACCOUNT_ETH_BALANCE',
|
UPDATE_ACCOUNT_ETH_BALANCE = 'UPDATE_ACCOUNT_ETH_BALANCE',
|
||||||
UPDATE_ETH_USD_PRICE = 'UPDATE_ETH_USD_PRICE',
|
UPDATE_ETH_USD_PRICE = 'UPDATE_ETH_USD_PRICE',
|
||||||
UPDATE_SELECTED_ASSET_AMOUNT = 'UPDATE_SELECTED_ASSET_AMOUNT',
|
UPDATE_SELECTED_ASSET_UNIT_AMOUNT = 'UPDATE_SELECTED_ASSET_UNIT_AMOUNT',
|
||||||
SET_BUY_ORDER_STATE_NONE = 'SET_BUY_ORDER_STATE_NONE',
|
SET_BUY_ORDER_STATE_NONE = 'SET_BUY_ORDER_STATE_NONE',
|
||||||
SET_BUY_ORDER_STATE_VALIDATING = 'SET_BUY_ORDER_STATE_VALIDATING',
|
SET_BUY_ORDER_STATE_VALIDATING = 'SET_BUY_ORDER_STATE_VALIDATING',
|
||||||
SET_BUY_ORDER_STATE_PROCESSING = 'SET_BUY_ORDER_STATE_PROCESSING',
|
SET_BUY_ORDER_STATE_PROCESSING = 'SET_BUY_ORDER_STATE_PROCESSING',
|
||||||
@ -41,6 +41,8 @@ export enum ActionTypes {
|
|||||||
HIDE_ERROR = 'HIDE_ERROR',
|
HIDE_ERROR = 'HIDE_ERROR',
|
||||||
CLEAR_ERROR = 'CLEAR_ERROR',
|
CLEAR_ERROR = 'CLEAR_ERROR',
|
||||||
RESET_AMOUNT = 'RESET_AMOUNT',
|
RESET_AMOUNT = 'RESET_AMOUNT',
|
||||||
|
OPEN_STANDARD_SLIDING_PANEL = 'OPEN_STANDARD_SLIDING_PANEL',
|
||||||
|
CLOSE_STANDARD_SLIDING_PANEL = 'CLOSE_STANDARD_SLIDING_PANEL',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
@ -50,7 +52,8 @@ export const actions = {
|
|||||||
updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) =>
|
updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) =>
|
||||||
createAction(ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE, addressAndBalance),
|
createAction(ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE, addressAndBalance),
|
||||||
updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UPDATE_ETH_USD_PRICE, price),
|
updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UPDATE_ETH_USD_PRICE, price),
|
||||||
updateSelectedAssetAmount: (amount?: BigNumber) => createAction(ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT, amount),
|
updateSelectedAssetAmount: (amount?: BigNumber) =>
|
||||||
|
createAction(ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT, amount),
|
||||||
setBuyOrderStateNone: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_NONE),
|
setBuyOrderStateNone: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_NONE),
|
||||||
setBuyOrderStateValidating: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_VALIDATING),
|
setBuyOrderStateValidating: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_VALIDATING),
|
||||||
setBuyOrderStateProcessing: (txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) =>
|
setBuyOrderStateProcessing: (txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) =>
|
||||||
@ -66,4 +69,7 @@ export const actions = {
|
|||||||
hideError: () => createAction(ActionTypes.HIDE_ERROR),
|
hideError: () => createAction(ActionTypes.HIDE_ERROR),
|
||||||
clearError: () => createAction(ActionTypes.CLEAR_ERROR),
|
clearError: () => createAction(ActionTypes.CLEAR_ERROR),
|
||||||
resetAmount: () => createAction(ActionTypes.RESET_AMOUNT),
|
resetAmount: () => createAction(ActionTypes.RESET_AMOUNT),
|
||||||
|
openStandardSlidingPanel: (content: StandardSlidingPanelContent) =>
|
||||||
|
createAction(ActionTypes.OPEN_STANDARD_SLIDING_PANEL, content),
|
||||||
|
closeStandardSlidingPanel: () => createAction(ActionTypes.CLOSE_STANDARD_SLIDING_PANEL),
|
||||||
};
|
};
|
||||||
|
@ -1,102 +1,103 @@
|
|||||||
import { AssetProxyId } from '@0x/types';
|
import { AssetProxyId } from '@0x/types';
|
||||||
|
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { BIG_NUMBER_ZERO } from '../constants';
|
import { BIG_NUMBER_ZERO } from '../constants';
|
||||||
import { AccountState, ERC20Asset, OrderProcessState } from '../types';
|
import { AccountState, ERC20Asset, OrderProcessState, ProviderState } from '../types';
|
||||||
import { assetUtils } from '../util/asset';
|
import { assetUtils } from '../util/asset';
|
||||||
import { buyQuoteUpdater } from '../util/buy_quote_updater';
|
import { buyQuoteUpdater } from '../util/buy_quote_updater';
|
||||||
import { coinbaseApi } from '../util/coinbase_api';
|
import { coinbaseApi } from '../util/coinbase_api';
|
||||||
import { errorFlasher } from '../util/error_flasher';
|
import { errorFlasher } from '../util/error_flasher';
|
||||||
|
|
||||||
import { actions } from './actions';
|
import { actions } from './actions';
|
||||||
import { Store } from './store';
|
import { State } from './reducer';
|
||||||
|
|
||||||
export const asyncData = {
|
export const asyncData = {
|
||||||
fetchEthPriceAndDispatchToStore: async (store: Store) => {
|
fetchEthPriceAndDispatchToStore: async (dispatch: Dispatch) => {
|
||||||
try {
|
try {
|
||||||
const ethUsdPrice = await coinbaseApi.getEthUsdPrice();
|
const ethUsdPrice = await coinbaseApi.getEthUsdPrice();
|
||||||
store.dispatch(actions.updateEthUsdPrice(ethUsdPrice));
|
dispatch(actions.updateEthUsdPrice(ethUsdPrice));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const errorMessage = 'Error fetching ETH/USD price';
|
const errorMessage = 'Error fetching ETH/USD price';
|
||||||
errorFlasher.flashNewErrorMessage(store.dispatch, errorMessage);
|
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
|
||||||
store.dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
|
dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchAvailableAssetDatasAndDispatchToStore: async (store: Store) => {
|
fetchAvailableAssetDatasAndDispatchToStore: async (state: State, dispatch: Dispatch) => {
|
||||||
const { providerState, assetMetaDataMap, network } = store.getState();
|
const { providerState, assetMetaDataMap, network } = state;
|
||||||
const assetBuyer = providerState.assetBuyer;
|
const assetBuyer = providerState.assetBuyer;
|
||||||
try {
|
try {
|
||||||
const assetDatas = await assetBuyer.getAvailableAssetDatasAsync();
|
const assetDatas = await assetBuyer.getAvailableAssetDatasAsync();
|
||||||
const assets = assetUtils.createAssetsFromAssetDatas(assetDatas, assetMetaDataMap, network);
|
const assets = assetUtils.createAssetsFromAssetDatas(assetDatas, assetMetaDataMap, network);
|
||||||
store.dispatch(actions.setAvailableAssets(assets));
|
dispatch(actions.setAvailableAssets(assets));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const errorMessage = 'Could not find any assets';
|
const errorMessage = 'Could not find any assets';
|
||||||
errorFlasher.flashNewErrorMessage(store.dispatch, errorMessage);
|
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
|
||||||
// On error, just specify that none are available
|
// On error, just specify that none are available
|
||||||
store.dispatch(actions.setAvailableAssets([]));
|
dispatch(actions.setAvailableAssets([]));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchAccountInfoAndDispatchToStore: async (options: { store: Store; shouldSetToLoading: boolean }) => {
|
fetchAccountInfoAndDispatchToStore: async (
|
||||||
const { store, shouldSetToLoading } = options;
|
providerState: ProviderState,
|
||||||
const { providerState } = store.getState();
|
dispatch: Dispatch,
|
||||||
|
shouldAttemptUnlock: boolean = false,
|
||||||
|
shouldSetToLoading: boolean = false,
|
||||||
|
) => {
|
||||||
const web3Wrapper = providerState.web3Wrapper;
|
const web3Wrapper = providerState.web3Wrapper;
|
||||||
const provider = providerState.provider;
|
const provider = providerState.provider;
|
||||||
if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) {
|
if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) {
|
||||||
store.dispatch(actions.setAccountStateLoading());
|
dispatch(actions.setAccountStateLoading());
|
||||||
}
|
}
|
||||||
let availableAddresses: string[];
|
let availableAddresses: string[];
|
||||||
try {
|
try {
|
||||||
// TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here
|
// TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here
|
||||||
const isPrivacyModeEnabled = !_.isUndefined((provider as any).enable);
|
const isPrivacyModeEnabled = !_.isUndefined((provider as any).enable);
|
||||||
availableAddresses = isPrivacyModeEnabled
|
availableAddresses =
|
||||||
? await (provider as any).enable()
|
isPrivacyModeEnabled && shouldAttemptUnlock
|
||||||
: await web3Wrapper.getAvailableAddressesAsync();
|
? await (provider as any).enable()
|
||||||
|
: await web3Wrapper.getAvailableAddressesAsync();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
store.dispatch(actions.setAccountStateLocked());
|
dispatch(actions.setAccountStateLocked());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!_.isEmpty(availableAddresses)) {
|
if (!_.isEmpty(availableAddresses)) {
|
||||||
const activeAddress = availableAddresses[0];
|
const activeAddress = availableAddresses[0];
|
||||||
store.dispatch(actions.setAccountStateReady(activeAddress));
|
dispatch(actions.setAccountStateReady(activeAddress));
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
asyncData.fetchAccountBalanceAndDispatchToStore(store);
|
asyncData.fetchAccountBalanceAndDispatchToStore(activeAddress, providerState.web3Wrapper, dispatch);
|
||||||
} else {
|
} else {
|
||||||
store.dispatch(actions.setAccountStateLocked());
|
dispatch(actions.setAccountStateLocked());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchAccountBalanceAndDispatchToStore: async (store: Store) => {
|
fetchAccountBalanceAndDispatchToStore: async (address: string, web3Wrapper: Web3Wrapper, dispatch: Dispatch) => {
|
||||||
const { providerState } = store.getState();
|
|
||||||
const web3Wrapper = providerState.web3Wrapper;
|
|
||||||
const account = providerState.account;
|
|
||||||
if (account.state !== AccountState.Ready) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const address = account.address;
|
|
||||||
const ethBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(address);
|
const ethBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(address);
|
||||||
store.dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));
|
dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// leave balance as is
|
// leave balance as is
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchCurrentBuyQuoteAndDispatchToStore: async (options: { store: Store; shouldSetPending: boolean }) => {
|
fetchCurrentBuyQuoteAndDispatchToStore: async (
|
||||||
const { store, shouldSetPending } = options;
|
state: State,
|
||||||
const { buyOrderState, providerState, selectedAsset, selectedAssetAmount, affiliateInfo } = store.getState();
|
dispatch: Dispatch,
|
||||||
|
options: { updateSilently: boolean },
|
||||||
|
) => {
|
||||||
|
const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state;
|
||||||
const assetBuyer = providerState.assetBuyer;
|
const assetBuyer = providerState.assetBuyer;
|
||||||
if (
|
if (
|
||||||
!_.isUndefined(selectedAssetAmount) &&
|
!_.isUndefined(selectedAssetUnitAmount) &&
|
||||||
!_.isUndefined(selectedAsset) &&
|
!_.isUndefined(selectedAsset) &&
|
||||||
buyOrderState.processState === OrderProcessState.None &&
|
buyOrderState.processState === OrderProcessState.None &&
|
||||||
selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20
|
selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20
|
||||||
) {
|
) {
|
||||||
await buyQuoteUpdater.updateBuyQuoteAsync(
|
await buyQuoteUpdater.updateBuyQuoteAsync(
|
||||||
assetBuyer,
|
assetBuyer,
|
||||||
store.dispatch,
|
dispatch,
|
||||||
selectedAsset as ERC20Asset,
|
selectedAsset as ERC20Asset,
|
||||||
selectedAssetAmount,
|
selectedAssetUnitAmount,
|
||||||
shouldSetPending,
|
{ setPending: !options.updateSilently, dispatchErrors: !options.updateSilently, affiliateInfo },
|
||||||
affiliateInfo,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,8 @@ import {
|
|||||||
OrderProcessState,
|
OrderProcessState,
|
||||||
OrderState,
|
OrderState,
|
||||||
ProviderState,
|
ProviderState,
|
||||||
|
StandardSlidingPanelContent,
|
||||||
|
StandardSlidingPanelSettings,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import { Action, ActionTypes } from './actions';
|
import { Action, ActionTypes } from './actions';
|
||||||
@ -30,6 +32,7 @@ export interface DefaultState {
|
|||||||
buyOrderState: OrderState;
|
buyOrderState: OrderState;
|
||||||
latestErrorDisplayStatus: DisplayStatus;
|
latestErrorDisplayStatus: DisplayStatus;
|
||||||
quoteRequestState: AsyncProcessState;
|
quoteRequestState: AsyncProcessState;
|
||||||
|
standardSlidingPanelSettings: StandardSlidingPanelSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
// State that is required but needs to be derived from the props
|
// State that is required but needs to be derived from the props
|
||||||
@ -41,7 +44,7 @@ interface PropsDerivedState {
|
|||||||
interface OptionalState {
|
interface OptionalState {
|
||||||
selectedAsset: Asset;
|
selectedAsset: Asset;
|
||||||
availableAssets: Asset[];
|
availableAssets: Asset[];
|
||||||
selectedAssetAmount: BigNumber;
|
selectedAssetUnitAmount: BigNumber;
|
||||||
ethUsdPrice: BigNumber;
|
ethUsdPrice: BigNumber;
|
||||||
latestBuyQuote: BuyQuote;
|
latestBuyQuote: BuyQuote;
|
||||||
latestErrorMessage: string;
|
latestErrorMessage: string;
|
||||||
@ -56,6 +59,10 @@ export const DEFAULT_STATE: DefaultState = {
|
|||||||
buyOrderState: { processState: OrderProcessState.None },
|
buyOrderState: { processState: OrderProcessState.None },
|
||||||
latestErrorDisplayStatus: DisplayStatus.Hidden,
|
latestErrorDisplayStatus: DisplayStatus.Hidden,
|
||||||
quoteRequestState: AsyncProcessState.None,
|
quoteRequestState: AsyncProcessState.None,
|
||||||
|
standardSlidingPanelSettings: {
|
||||||
|
animationState: 'none',
|
||||||
|
content: StandardSlidingPanelContent.None,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createReducer = (initialState: State) => {
|
export const createReducer = (initialState: State) => {
|
||||||
@ -66,11 +73,19 @@ export const createReducer = (initialState: State) => {
|
|||||||
case ActionTypes.SET_ACCOUNT_STATE_LOCKED:
|
case ActionTypes.SET_ACCOUNT_STATE_LOCKED:
|
||||||
return reduceStateWithAccount(state, LOCKED_ACCOUNT);
|
return reduceStateWithAccount(state, LOCKED_ACCOUNT);
|
||||||
case ActionTypes.SET_ACCOUNT_STATE_READY: {
|
case ActionTypes.SET_ACCOUNT_STATE_READY: {
|
||||||
const account: AccountReady = {
|
const address = action.data;
|
||||||
|
let newAccount: AccountReady = {
|
||||||
state: AccountState.Ready,
|
state: AccountState.Ready,
|
||||||
address: action.data,
|
address,
|
||||||
};
|
};
|
||||||
return reduceStateWithAccount(state, account);
|
const currentAccount = state.providerState.account;
|
||||||
|
if (currentAccount.state === AccountState.Ready && currentAccount.address === address) {
|
||||||
|
newAccount = {
|
||||||
|
...newAccount,
|
||||||
|
ethBalanceInWei: currentAccount.ethBalanceInWei,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return reduceStateWithAccount(state, newAccount);
|
||||||
}
|
}
|
||||||
case ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE: {
|
case ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE: {
|
||||||
const { address, ethBalanceInWei } = action.data;
|
const { address, ethBalanceInWei } = action.data;
|
||||||
@ -90,10 +105,10 @@ export const createReducer = (initialState: State) => {
|
|||||||
...state,
|
...state,
|
||||||
ethUsdPrice: action.data,
|
ethUsdPrice: action.data,
|
||||||
};
|
};
|
||||||
case ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT:
|
case ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
selectedAssetAmount: action.data,
|
selectedAssetUnitAmount: action.data,
|
||||||
};
|
};
|
||||||
case ActionTypes.UPDATE_LATEST_BUY_QUOTE:
|
case ActionTypes.UPDATE_LATEST_BUY_QUOTE:
|
||||||
const newBuyQuoteIfExists = action.data;
|
const newBuyQuoteIfExists = action.data;
|
||||||
@ -204,13 +219,29 @@ export const createReducer = (initialState: State) => {
|
|||||||
latestBuyQuote: undefined,
|
latestBuyQuote: undefined,
|
||||||
quoteRequestState: AsyncProcessState.None,
|
quoteRequestState: AsyncProcessState.None,
|
||||||
buyOrderState: { processState: OrderProcessState.None },
|
buyOrderState: { processState: OrderProcessState.None },
|
||||||
selectedAssetAmount: undefined,
|
selectedAssetUnitAmount: undefined,
|
||||||
};
|
};
|
||||||
case ActionTypes.SET_AVAILABLE_ASSETS:
|
case ActionTypes.SET_AVAILABLE_ASSETS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
availableAssets: action.data,
|
availableAssets: action.data,
|
||||||
};
|
};
|
||||||
|
case ActionTypes.OPEN_STANDARD_SLIDING_PANEL:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
standardSlidingPanelSettings: {
|
||||||
|
content: action.data,
|
||||||
|
animationState: 'slidIn',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
case ActionTypes.CLOSE_STANDARD_SLIDING_PANEL:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
standardSlidingPanelSettings: {
|
||||||
|
content: state.standardSlidingPanelSettings.content,
|
||||||
|
animationState: 'slidOut',
|
||||||
|
},
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -232,9 +263,9 @@ const reduceStateWithAccount = (state: State, account: Account) => {
|
|||||||
|
|
||||||
const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
|
const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
|
||||||
const selectedAssetIfExists = state.selectedAsset;
|
const selectedAssetIfExists = state.selectedAsset;
|
||||||
const selectedAssetAmountIfExists = state.selectedAssetAmount;
|
const selectedAssetUnitAmountIfExists = state.selectedAssetUnitAmount;
|
||||||
// if no selectedAsset or selectedAssetAmount exists on the current state, return false
|
// if no selectedAsset or selectedAssetAmount exists on the current state, return false
|
||||||
if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetAmountIfExists)) {
|
if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetUnitAmountIfExists)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// if buyQuote's assetData does not match that of the current selected asset, return false
|
// if buyQuote's assetData does not match that of the current selected asset, return false
|
||||||
@ -246,7 +277,7 @@ const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
|
|||||||
const selectedAssetMetaData = selectedAssetIfExists.metaData;
|
const selectedAssetMetaData = selectedAssetIfExists.metaData;
|
||||||
if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) {
|
if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) {
|
||||||
const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount(
|
const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount(
|
||||||
selectedAssetAmountIfExists,
|
selectedAssetUnitAmountIfExists,
|
||||||
selectedAssetMetaData.decimals,
|
selectedAssetMetaData.decimals,
|
||||||
);
|
);
|
||||||
const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount);
|
const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount);
|
||||||
|
@ -17,6 +17,8 @@ export enum ColorOption {
|
|||||||
darkOrange = 'darkOrange',
|
darkOrange = 'darkOrange',
|
||||||
green = 'green',
|
green = 'green',
|
||||||
red = 'red',
|
red = 'red',
|
||||||
|
darkBlue = 'darkBlue',
|
||||||
|
lightBlue = 'lightBlue',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const theme: Theme = {
|
export const theme: Theme = {
|
||||||
@ -32,6 +34,8 @@ export const theme: Theme = {
|
|||||||
darkOrange: '#F2994C',
|
darkOrange: '#F2994C',
|
||||||
green: '#3CB34F',
|
green: '#3CB34F',
|
||||||
red: '#D00000',
|
red: '#D00000',
|
||||||
|
darkBlue: '#135df6',
|
||||||
|
lightBlue: '#F2F7FF',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transparentWhite = 'rgba(255,255,255,0.3)';
|
export const transparentWhite = 'rgba(255,255,255,0.3)';
|
||||||
|
@ -95,6 +95,7 @@ export interface AffiliateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ProviderState {
|
export interface ProviderState {
|
||||||
|
name: string;
|
||||||
provider: Provider;
|
provider: Provider;
|
||||||
assetBuyer: AssetBuyer;
|
assetBuyer: AssetBuyer;
|
||||||
web3Wrapper: Web3Wrapper;
|
web3Wrapper: Web3Wrapper;
|
||||||
@ -125,3 +126,42 @@ export interface AddressAndEthBalanceInWei {
|
|||||||
address: string;
|
address: string;
|
||||||
ethBalanceInWei: BigNumber;
|
ethBalanceInWei: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
|
||||||
|
|
||||||
|
export enum StandardSlidingPanelContent {
|
||||||
|
None = 'NONE',
|
||||||
|
InstallWallet = 'INSTALL_WALLET',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StandardSlidingPanelSettings {
|
||||||
|
animationState: SlideAnimationState;
|
||||||
|
content: StandardSlidingPanelContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Browser {
|
||||||
|
Chrome = 'CHROME',
|
||||||
|
Firefox = 'FIREFOX',
|
||||||
|
Opera = 'OPERA',
|
||||||
|
Safari = 'SAFARI',
|
||||||
|
Edge = 'EDGE',
|
||||||
|
Other = 'OTHER',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OperatingSystem {
|
||||||
|
Android = 'ANDROID',
|
||||||
|
iOS = 'IOS',
|
||||||
|
Mac = 'MAC',
|
||||||
|
Windows = 'WINDOWS',
|
||||||
|
WindowsPhone = 'WINDOWS_PHONE',
|
||||||
|
Linux = 'LINUX',
|
||||||
|
Other = 'OTHER',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProviderType {
|
||||||
|
Parity = 'PARITY',
|
||||||
|
MetaMask = 'META_MASK',
|
||||||
|
Mist = 'MIST',
|
||||||
|
CoinbaseWallet = 'COINBASE_WALLET',
|
||||||
|
Cipher = 'CIPHER',
|
||||||
|
}
|
||||||
|
@ -80,8 +80,6 @@ export const assetUtils = {
|
|||||||
return metaData.symbol.toUpperCase();
|
return metaData.symbol.toUpperCase();
|
||||||
case AssetProxyId.ERC721:
|
case AssetProxyId.ERC721:
|
||||||
return metaData.name;
|
return metaData.name;
|
||||||
default:
|
|
||||||
return defaultName;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formattedSymbolForAsset: (asset?: ERC20Asset, defaultName: string = '???'): string => {
|
formattedSymbolForAsset: (asset?: ERC20Asset, defaultName: string = '???'): string => {
|
||||||
|
@ -15,40 +15,43 @@ export const buyQuoteUpdater = {
|
|||||||
assetBuyer: AssetBuyer,
|
assetBuyer: AssetBuyer,
|
||||||
dispatch: Dispatch<Action>,
|
dispatch: Dispatch<Action>,
|
||||||
asset: ERC20Asset,
|
asset: ERC20Asset,
|
||||||
assetAmount: BigNumber,
|
assetUnitAmount: BigNumber,
|
||||||
setPending = true,
|
options: { setPending: boolean; dispatchErrors: boolean; affiliateInfo?: AffiliateInfo },
|
||||||
affiliateInfo?: AffiliateInfo,
|
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
// get a new buy quote.
|
// get a new buy quote.
|
||||||
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, asset.metaData.decimals);
|
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals);
|
||||||
if (setPending) {
|
if (options.setPending) {
|
||||||
// mark quote as pending
|
// mark quote as pending
|
||||||
dispatch(actions.setQuoteRequestStatePending());
|
dispatch(actions.setQuoteRequestStatePending());
|
||||||
}
|
}
|
||||||
const feePercentage = oc(affiliateInfo).feePercentage();
|
const feePercentage = oc(options.affiliateInfo).feePercentage();
|
||||||
let newBuyQuote: BuyQuote | undefined;
|
let newBuyQuote: BuyQuote | undefined;
|
||||||
try {
|
try {
|
||||||
newBuyQuote = await assetBuyer.getBuyQuoteAsync(asset.assetData, baseUnitValue, { feePercentage });
|
newBuyQuote = await assetBuyer.getBuyQuoteAsync(asset.assetData, baseUnitValue, { feePercentage });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(actions.setQuoteRequestStateFailure());
|
if (options.dispatchErrors) {
|
||||||
let errorMessage;
|
dispatch(actions.setQuoteRequestStateFailure());
|
||||||
if (error.message === AssetBuyerError.InsufficientAssetLiquidity) {
|
let errorMessage;
|
||||||
const assetName = assetUtils.bestNameForAsset(asset, 'of this asset');
|
if (error.message === AssetBuyerError.InsufficientAssetLiquidity) {
|
||||||
errorMessage = `Not enough ${assetName} available`;
|
const assetName = assetUtils.bestNameForAsset(asset, 'of this asset');
|
||||||
} else if (error.message === AssetBuyerError.InsufficientZrxLiquidity) {
|
errorMessage = `Not enough ${assetName} available`;
|
||||||
errorMessage = 'Not enough ZRX available';
|
} else if (error.message === AssetBuyerError.InsufficientZrxLiquidity) {
|
||||||
} else if (
|
errorMessage = 'Not enough ZRX available';
|
||||||
error.message === AssetBuyerError.StandardRelayerApiError ||
|
} else if (
|
||||||
error.message.startsWith(AssetBuyerError.AssetUnavailable)
|
error.message === AssetBuyerError.StandardRelayerApiError ||
|
||||||
) {
|
error.message.startsWith(AssetBuyerError.AssetUnavailable)
|
||||||
const assetName = assetUtils.bestNameForAsset(asset, 'This asset');
|
) {
|
||||||
errorMessage = `${assetName} is currently unavailable`;
|
const assetName = assetUtils.bestNameForAsset(asset, 'This asset');
|
||||||
}
|
errorMessage = `${assetName} is currently unavailable`;
|
||||||
if (!_.isUndefined(errorMessage)) {
|
}
|
||||||
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
|
if (!_.isUndefined(errorMessage)) {
|
||||||
} else {
|
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
|
||||||
throw error;
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: report to error reporter on else
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We have a successful new buy quote
|
// We have a successful new buy quote
|
||||||
|
65
packages/instant/src/util/env.ts
Normal file
65
packages/instant/src/util/env.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import * as bowser from 'bowser';
|
||||||
|
import { Provider } from 'ethereum-types';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { PROVIDER_TYPE_TO_NAME } from '../constants';
|
||||||
|
import { Browser, OperatingSystem, ProviderType } from '../types';
|
||||||
|
|
||||||
|
export const envUtil = {
|
||||||
|
getBrowser(): Browser {
|
||||||
|
if (bowser.chrome) {
|
||||||
|
return Browser.Chrome;
|
||||||
|
} else if (bowser.firefox) {
|
||||||
|
return Browser.Firefox;
|
||||||
|
} else if (bowser.opera) {
|
||||||
|
return Browser.Opera;
|
||||||
|
} else if (bowser.msedge) {
|
||||||
|
return Browser.Edge;
|
||||||
|
} else if (bowser.safari) {
|
||||||
|
return Browser.Safari;
|
||||||
|
} else {
|
||||||
|
return Browser.Other;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isMobileOperatingSystem(): boolean {
|
||||||
|
return bowser.mobile;
|
||||||
|
},
|
||||||
|
getOperatingSystem(): OperatingSystem {
|
||||||
|
if (bowser.android) {
|
||||||
|
return OperatingSystem.Android;
|
||||||
|
} else if (bowser.ios) {
|
||||||
|
return OperatingSystem.iOS;
|
||||||
|
} else if (bowser.mac) {
|
||||||
|
return OperatingSystem.Mac;
|
||||||
|
} else if (bowser.windows) {
|
||||||
|
return OperatingSystem.Windows;
|
||||||
|
} else if (bowser.windowsphone) {
|
||||||
|
return OperatingSystem.WindowsPhone;
|
||||||
|
} else if (bowser.linux) {
|
||||||
|
return OperatingSystem.Linux;
|
||||||
|
} else {
|
||||||
|
return OperatingSystem.Other;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getProviderType(provider: Provider): ProviderType | undefined {
|
||||||
|
if (provider.constructor.name === 'EthereumProvider') {
|
||||||
|
return ProviderType.Mist;
|
||||||
|
} else if ((provider as any).isParity) {
|
||||||
|
return ProviderType.Parity;
|
||||||
|
} else if ((provider as any).isMetaMask) {
|
||||||
|
return ProviderType.MetaMask;
|
||||||
|
} else if (!_.isUndefined(_.get(window, 'SOFA'))) {
|
||||||
|
return ProviderType.CoinbaseWallet;
|
||||||
|
} else if (!_.isUndefined(_.get(window, '__CIPHER__'))) {
|
||||||
|
return ProviderType.Cipher;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
getProviderName(provider: Provider): string {
|
||||||
|
const providerTypeIfExists = envUtil.getProviderType(provider);
|
||||||
|
if (_.isUndefined(providerTypeIfExists)) {
|
||||||
|
return provider.constructor.name;
|
||||||
|
}
|
||||||
|
return PROVIDER_TYPE_TO_NAME[providerTypeIfExists];
|
||||||
|
},
|
||||||
|
};
|
@ -8,9 +8,8 @@ const etherscanPrefix = (networkId: number): string | undefined => {
|
|||||||
return 'kovan.';
|
return 'kovan.';
|
||||||
case Network.Mainnet:
|
case Network.Mainnet:
|
||||||
return '';
|
return '';
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const etherscanUtil = {
|
export const etherscanUtil = {
|
||||||
|
@ -5,15 +5,15 @@ import * as _ from 'lodash';
|
|||||||
import { ETH_DECIMALS } from '../constants';
|
import { ETH_DECIMALS } from '../constants';
|
||||||
|
|
||||||
export const format = {
|
export const format = {
|
||||||
ethBaseAmount: (
|
ethBaseUnitAmount: (
|
||||||
ethBaseAmount?: BigNumber,
|
ethBaseUnitAmount?: BigNumber,
|
||||||
decimalPlaces: number = 4,
|
decimalPlaces: number = 4,
|
||||||
defaultText: React.ReactNode = '0 ETH',
|
defaultText: React.ReactNode = '0 ETH',
|
||||||
): React.ReactNode => {
|
): React.ReactNode => {
|
||||||
if (_.isUndefined(ethBaseAmount)) {
|
if (_.isUndefined(ethBaseUnitAmount)) {
|
||||||
return defaultText;
|
return defaultText;
|
||||||
}
|
}
|
||||||
const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseAmount, ETH_DECIMALS);
|
const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS);
|
||||||
return format.ethUnitAmount(ethUnitAmount, decimalPlaces);
|
return format.ethUnitAmount(ethUnitAmount, decimalPlaces);
|
||||||
},
|
},
|
||||||
ethUnitAmount: (
|
ethUnitAmount: (
|
||||||
@ -27,16 +27,16 @@ export const format = {
|
|||||||
const roundedAmount = ethUnitAmount.round(decimalPlaces).toDigits(decimalPlaces);
|
const roundedAmount = ethUnitAmount.round(decimalPlaces).toDigits(decimalPlaces);
|
||||||
return `${roundedAmount} ETH`;
|
return `${roundedAmount} ETH`;
|
||||||
},
|
},
|
||||||
ethBaseAmountInUsd: (
|
ethBaseUnitAmountInUsd: (
|
||||||
ethBaseAmount?: BigNumber,
|
ethBaseUnitAmount?: BigNumber,
|
||||||
ethUsdPrice?: BigNumber,
|
ethUsdPrice?: BigNumber,
|
||||||
decimalPlaces: number = 2,
|
decimalPlaces: number = 2,
|
||||||
defaultText: React.ReactNode = '$0.00',
|
defaultText: React.ReactNode = '$0.00',
|
||||||
): React.ReactNode => {
|
): React.ReactNode => {
|
||||||
if (_.isUndefined(ethBaseAmount) || _.isUndefined(ethUsdPrice)) {
|
if (_.isUndefined(ethBaseUnitAmount) || _.isUndefined(ethUsdPrice)) {
|
||||||
return defaultText;
|
return defaultText;
|
||||||
}
|
}
|
||||||
const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseAmount, ETH_DECIMALS);
|
const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS);
|
||||||
return format.ethUnitAmountInUsd(ethUnitAmount, ethUsdPrice, decimalPlaces);
|
return format.ethUnitAmountInUsd(ethUnitAmount, ethUsdPrice, decimalPlaces);
|
||||||
},
|
},
|
||||||
ethUnitAmountInUsd: (
|
ethUnitAmountInUsd: (
|
||||||
|
@ -10,13 +10,15 @@ export interface HeartbeatFactoryOptions {
|
|||||||
export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => {
|
export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => {
|
||||||
const { store, shouldPerformImmediatelyOnStart } = options;
|
const { store, shouldPerformImmediatelyOnStart } = options;
|
||||||
return new Heartbeater(async () => {
|
return new Heartbeater(async () => {
|
||||||
await asyncData.fetchAccountInfoAndDispatchToStore({ store, shouldSetToLoading: false });
|
await asyncData.fetchAccountInfoAndDispatchToStore(store.getState().providerState, store.dispatch, false);
|
||||||
}, shouldPerformImmediatelyOnStart);
|
}, shouldPerformImmediatelyOnStart);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateBuyQuoteHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => {
|
export const generateBuyQuoteHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => {
|
||||||
const { store, shouldPerformImmediatelyOnStart } = options;
|
const { store, shouldPerformImmediatelyOnStart } = options;
|
||||||
return new Heartbeater(async () => {
|
return new Heartbeater(async () => {
|
||||||
await asyncData.fetchCurrentBuyQuoteAndDispatchToStore({ store, shouldSetPending: false });
|
await asyncData.fetchCurrentBuyQuoteAndDispatchToStore(store.getState(), store.dispatch, {
|
||||||
|
updateSilently: true,
|
||||||
|
});
|
||||||
}, shouldPerformImmediatelyOnStart);
|
}, shouldPerformImmediatelyOnStart);
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
import { LOADING_ACCOUNT, NO_ACCOUNT } from '../constants';
|
import { LOADING_ACCOUNT, NO_ACCOUNT } from '../constants';
|
||||||
import { Maybe, Network, OrderSource, ProviderState } from '../types';
|
import { Maybe, Network, OrderSource, ProviderState } from '../types';
|
||||||
|
import { envUtil } from '../util/env';
|
||||||
|
|
||||||
import { assetBuyerFactory } from './asset_buyer_factory';
|
import { assetBuyerFactory } from './asset_buyer_factory';
|
||||||
import { providerFactory } from './provider_factory';
|
import { providerFactory } from './provider_factory';
|
||||||
@ -29,6 +30,7 @@ export const providerStateFactory = {
|
|||||||
provider: Provider,
|
provider: Provider,
|
||||||
): ProviderState => {
|
): ProviderState => {
|
||||||
const providerState: ProviderState = {
|
const providerState: ProviderState = {
|
||||||
|
name: envUtil.getProviderName(provider),
|
||||||
provider,
|
provider,
|
||||||
web3Wrapper: new Web3Wrapper(provider),
|
web3Wrapper: new Web3Wrapper(provider),
|
||||||
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),
|
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),
|
||||||
@ -40,6 +42,7 @@ export const providerStateFactory = {
|
|||||||
const injectedProviderIfExists = providerFactory.getInjectedProviderIfExists();
|
const injectedProviderIfExists = providerFactory.getInjectedProviderIfExists();
|
||||||
if (!_.isUndefined(injectedProviderIfExists)) {
|
if (!_.isUndefined(injectedProviderIfExists)) {
|
||||||
const providerState: ProviderState = {
|
const providerState: ProviderState = {
|
||||||
|
name: envUtil.getProviderName(injectedProviderIfExists),
|
||||||
provider: injectedProviderIfExists,
|
provider: injectedProviderIfExists,
|
||||||
web3Wrapper: new Web3Wrapper(injectedProviderIfExists),
|
web3Wrapper: new Web3Wrapper(injectedProviderIfExists),
|
||||||
assetBuyer: assetBuyerFactory.getAssetBuyer(injectedProviderIfExists, orderSource, network),
|
assetBuyer: assetBuyerFactory.getAssetBuyer(injectedProviderIfExists, orderSource, network),
|
||||||
@ -53,6 +56,7 @@ export const providerStateFactory = {
|
|||||||
getInitialProviderStateFallback: (orderSource: OrderSource, network: Network): ProviderState => {
|
getInitialProviderStateFallback: (orderSource: OrderSource, network: Network): ProviderState => {
|
||||||
const provider = providerFactory.getFallbackNoSigningProvider(network);
|
const provider = providerFactory.getFallbackNoSigningProvider(network);
|
||||||
const providerState: ProviderState = {
|
const providerState: ProviderState = {
|
||||||
|
name: envUtil.getProviderName(provider),
|
||||||
provider,
|
provider,
|
||||||
web3Wrapper: new Web3Wrapper(provider),
|
web3Wrapper: new Web3Wrapper(provider),
|
||||||
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),
|
assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network),
|
||||||
|
@ -2,4 +2,5 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
export const util = {
|
export const util = {
|
||||||
boundNoop: _.noop.bind(_),
|
boundNoop: _.noop.bind(_),
|
||||||
|
createOpenUrlInNewWindow: (href: string) => () => window.open(href, '_blank'),
|
||||||
};
|
};
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user