Compare commits
143 Commits
contracts@
...
@0x/react-
Author | SHA1 | Date | |
---|---|---|---|
|
fe1b7f15e8 | ||
|
3f647c259a | ||
|
06dcf24496 | ||
|
77c77631e1 | ||
|
b0e9f58033 | ||
|
4fc457b78b | ||
|
2f6b1273aa | ||
|
da9de70bbc | ||
|
b174a891bc | ||
|
bb79a5e324 | ||
|
9e0c232a73 | ||
|
e02dc13805 | ||
|
820ab062a6 | ||
|
7b4f63a39c | ||
|
3a3fe0e69a | ||
|
5c21d3f6af | ||
|
baba78f545 | ||
|
f03afe6f1b | ||
|
a824264da2 | ||
|
a66c03aa21 | ||
|
bed134c1da | ||
|
d36cf58b82 | ||
|
5527de62ff | ||
|
11f0bebd7f | ||
|
3fb29041b0 | ||
|
161a935003 | ||
|
e8afc66a5a | ||
|
49a9345bf4 | ||
|
d73faf1b81 | ||
|
0c6110b736 | ||
|
2da258f5be | ||
|
e9bf7206bd | ||
|
2b4dcb419e | ||
|
c67632dff5 | ||
|
01b36b4949 | ||
|
711b307e6c | ||
|
1ab19a7c23 | ||
|
7068f7b4d1 | ||
|
79f0324abc | ||
|
b82148ea60 | ||
|
add1cfd261 | ||
|
cdf78494d5 | ||
|
789f573452 | ||
|
22f217807d | ||
|
08797392e0 | ||
|
853c77dc09 | ||
|
0ebbbdfca4 | ||
|
085d34834b | ||
|
b866ce787c | ||
|
4d5bc8b8ee | ||
|
7f013515e7 | ||
|
a4a46dc076 | ||
|
33dbdb0184 | ||
|
0d565fe32f | ||
|
320460feb9 | ||
|
dbce3f8935 | ||
|
c41622c20a | ||
|
348556a544 | ||
|
6fa6579c31 | ||
|
6f61268514 | ||
|
8efc6c2112 | ||
|
b21c1bea46 | ||
|
fd7ba3ecea | ||
|
8aeb18bcc3 | ||
|
9e4a594eb1 | ||
|
3b421ef796 | ||
|
e0c4f58970 | ||
|
df8fd36c94 | ||
|
76b3caa124 | ||
|
0101cd73aa | ||
|
6ef628613e | ||
|
bc960fe8f8 | ||
|
517c620397 | ||
|
498be7ac41 | ||
|
0391f93490 | ||
|
399a7d5fec | ||
|
0d201173ef | ||
|
2d43f312c8 | ||
|
1ec8a4115f | ||
|
753b33aec5 | ||
|
7626d1d6fe | ||
|
d3592d362e | ||
|
a8a1ea92a6 | ||
|
ff027ee36a | ||
|
397b4e2890 | ||
|
ba292ead45 | ||
|
5355f3c538 | ||
|
478330c12d | ||
|
38896c9358 | ||
|
26cbe7ae66 | ||
|
fd83ca2cb8 | ||
|
b1376059d3 | ||
|
4072076965 | ||
|
2bba01c664 | ||
|
93054ae52b | ||
|
5c1b1a1203 | ||
|
433fb3597d | ||
|
acb7e876b2 | ||
|
2c585bfbdc | ||
|
1f0ac47bd9 | ||
|
7460f2796a | ||
|
7249cc7b49 | ||
|
b598827708 | ||
|
128abb39dd | ||
|
79a533940e | ||
|
773cf3cd14 | ||
|
53d0f5b98e | ||
|
3a51bd1e69 | ||
|
3f1f19e344 | ||
|
3aa831ad77 | ||
|
3fd667b3be | ||
|
fa7bd072d0 | ||
|
cc8debe53b | ||
|
36b8c9c5dd | ||
|
474db7c18d | ||
|
daa011f7cb | ||
|
39657b633b | ||
|
2e8f74abce | ||
|
239eada7d9 | ||
|
df91d34315 | ||
|
3980bf39a9 | ||
|
a50f0ca997 | ||
|
d703c13f8e | ||
|
3dacc6157b | ||
|
fd12bdbbd5 | ||
|
297a62fe80 | ||
|
1e39d56cf7 | ||
|
39ae21d693 | ||
|
e45b6c7e98 | ||
|
fc138cd73d | ||
|
990d510d05 | ||
|
dd4d3b10cf | ||
|
eb5f514d25 | ||
|
57318a6ef2 | ||
|
857a35d4f7 | ||
|
624f5cee8d | ||
|
7acaae37a9 | ||
|
801004be66 | ||
|
81fb8d614f | ||
|
3e75daafa1 | ||
|
6696aa46ee | ||
|
14a9770d57 | ||
|
b8d2cc1221 |
@@ -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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -42,11 +42,11 @@
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.15",
|
||||
"@0x/abi-gen-wrappers": "^1.0.2",
|
||||
"@0x/abi-gen": "^1.0.16",
|
||||
"@0x/abi-gen-wrappers": "^1.0.5",
|
||||
"@0x/contract-addresses": "^1.1.0",
|
||||
"@0x/dev-utils": "^1.0.14",
|
||||
"@0x/migrations": "^2.0.1",
|
||||
"@0x/dev-utils": "^1.0.17",
|
||||
"@0x/migrations": "^2.0.4",
|
||||
"@0x/tslint-config": "^1.0.10",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
@@ -73,16 +73,16 @@
|
||||
"webpack": "^4.20.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/assert": "^1.0.15",
|
||||
"@0x/base-contract": "^3.0.3",
|
||||
"@0x/contract-wrappers": "^3.0.1",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/order-watcher": "^2.2.1",
|
||||
"@0x/subproviders": "^2.1.1",
|
||||
"@0x/assert": "^1.0.17",
|
||||
"@0x/base-contract": "^3.0.6",
|
||||
"@0x/contract-wrappers": "^4.0.2",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/order-watcher": "^2.2.4",
|
||||
"@0x/subproviders": "^2.1.4",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"@types/web3-provider-engine": "^14.0.0",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/abi-gen-wrappers",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.5",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -30,17 +30,17 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.15",
|
||||
"@0x/abi-gen": "^1.0.16",
|
||||
"@0x/tslint-config": "^1.0.10",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"ethers": "~4.0.4",
|
||||
"lodash": "^4.17.5",
|
||||
"shx": "^0.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.3"
|
||||
"@0x/base-contract": "^3.0.6"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1542208198,
|
||||
"version": "1.0.16",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.15",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.16 - _November 14, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.15 - _November 9, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/abi-gen",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.16",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -32,7 +32,7 @@
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
||||
"dependencies": {
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"chalk": "^2.3.0",
|
||||
"ethereum-types": "^1.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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.0.17 - _November 14, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.16 - _November 12, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.0.15 - _November 9, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/assert",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.17",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -44,9 +44,9 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/json-schemas": "^2.0.1",
|
||||
"@0x/json-schemas": "^2.1.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"lodash": "^4.17.5",
|
||||
"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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* `getAssetBuyerForProvidedOrders` factory function now takes 3 args instead of 4 (#1187)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/asset-buyer",
|
||||
"version": "2.2.0",
|
||||
"version": "3.0.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -36,16 +36,16 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
|
||||
"dependencies": {
|
||||
"@0x/assert": "^1.0.15",
|
||||
"@0x/connect": "^3.0.3",
|
||||
"@0x/contract-wrappers": "^3.0.1",
|
||||
"@0x/json-schemas": "^2.0.1",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/subproviders": "^2.1.1",
|
||||
"@0x/assert": "^1.0.17",
|
||||
"@0x/connect": "^3.0.6",
|
||||
"@0x/contract-wrappers": "^4.0.2",
|
||||
"@0x/json-schemas": "^2.1.1",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/subproviders": "^2.1.4",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"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.
|
||||
* 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 {
|
||||
ethPerAssetPrice: BigNumber;
|
||||
assetEthAmount: BigNumber;
|
||||
feeEthAmount: BigNumber;
|
||||
totalEthAmount: BigNumber;
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ export const assert = {
|
||||
}
|
||||
},
|
||||
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}.totalEthAmount`, buyQuoteInfo.totalEthAmount);
|
||||
},
|
||||
|
@@ -106,28 +106,28 @@ function calculateQuoteInfo(
|
||||
isMakerAssetZrxToken: boolean,
|
||||
): BuyQuoteInfo {
|
||||
// find the total eth and zrx needed to buy assetAmount from the resultOrders from left to right
|
||||
let ethAmountToBuyAsset = constants.ZERO_AMOUNT;
|
||||
let ethAmountToBuyZrx = constants.ZERO_AMOUNT;
|
||||
let assetEthAmount = constants.ZERO_AMOUNT;
|
||||
let zrxEthAmount = constants.ZERO_AMOUNT;
|
||||
if (isMakerAssetZrxToken) {
|
||||
ethAmountToBuyAsset = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
|
||||
assetEthAmount = findEthAmountNeededToBuyZrx(ordersAndFillableAmounts, assetBuyAmount);
|
||||
} else {
|
||||
// find eth and zrx amounts needed to buy
|
||||
const ethAndZrxAmountToBuyAsset = findEthAndZrxAmountNeededToBuyAsset(ordersAndFillableAmounts, assetBuyAmount);
|
||||
ethAmountToBuyAsset = ethAndZrxAmountToBuyAsset[0];
|
||||
assetEthAmount = ethAndZrxAmountToBuyAsset[0];
|
||||
const zrxAmountToBuyAsset = ethAndZrxAmountToBuyAsset[1];
|
||||
// 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
|
||||
const ethAmountToBuyAffiliateFee = ethAmountToBuyAsset.mul(feePercentage).ceil();
|
||||
const totalEthAmountWithoutAffiliateFee = ethAmountToBuyAsset.plus(ethAmountToBuyZrx);
|
||||
const ethAmountTotal = totalEthAmountWithoutAffiliateFee.plus(ethAmountToBuyAffiliateFee);
|
||||
// divide into the assetBuyAmount in order to find rate of makerAsset / WETH
|
||||
const ethPerAssetPrice = totalEthAmountWithoutAffiliateFee.div(assetBuyAmount);
|
||||
// eth amount needed to buy the affiliate fee
|
||||
const affiliateFeeEthAmount = assetEthAmount.mul(feePercentage).ceil();
|
||||
// eth amount needed for fees is the sum of affiliate fee and zrx fee
|
||||
const feeEthAmount = affiliateFeeEthAmount.plus(zrxEthAmount);
|
||||
// eth amount needed in total is the sum of the amount needed for the asset and the amount needed for fees
|
||||
const totalEthAmount = assetEthAmount.plus(feeEthAmount);
|
||||
return {
|
||||
totalEthAmount: ethAmountTotal,
|
||||
feeEthAmount: ethAmountToBuyAffiliateFee,
|
||||
ethPerAssetPrice,
|
||||
assetEthAmount,
|
||||
feeEthAmount,
|
||||
totalEthAmount,
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -108,17 +108,17 @@ describe('buyQuoteCalculator', () => {
|
||||
// 50 eth to fill the first order + 100 eth for fees
|
||||
const expectedEthAmountForAsset = new BigNumber(50);
|
||||
const expectedEthAmountForZrxFees = new BigNumber(100);
|
||||
const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
|
||||
const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
||||
const expectedFillEthAmount = expectedEthAmountForAsset;
|
||||
const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
||||
const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
|
||||
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.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
||||
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
|
||||
// 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.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
||||
expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
|
||||
// test if feePercentage gets passed through
|
||||
expect(buyQuote.feePercentage).to.equal(feePercentage);
|
||||
});
|
||||
@@ -146,23 +146,23 @@ describe('buyQuoteCalculator', () => {
|
||||
// 50 eth to fill the first order + 100 eth for fees
|
||||
const expectedEthAmountForAsset = new BigNumber(50);
|
||||
const expectedEthAmountForZrxFees = new BigNumber(100);
|
||||
const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
|
||||
const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
||||
const expectedFillEthAmount = expectedEthAmountForAsset;
|
||||
const expectedAffiliateFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
|
||||
const expectedFeeEthAmount = expectedAffiliateFeeEthAmount.plus(expectedEthAmountForZrxFees);
|
||||
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.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
|
||||
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
|
||||
// 100 eth to fill the first order + 208 eth for fees
|
||||
const expectedWorstEthAmountForAsset = new BigNumber(100);
|
||||
const expectedWorstEthAmountForZrxFees = new BigNumber(208);
|
||||
const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset.plus(expectedWorstEthAmountForZrxFees);
|
||||
const expectedWorstFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
|
||||
const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset;
|
||||
const expectedWorstAffiliateFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
|
||||
const expectedWorstFeeEthAmount = expectedWorstAffiliateFeeEthAmount.plus(expectedWorstEthAmountForZrxFees);
|
||||
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.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount);
|
||||
expect(buyQuote.worstCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedWorstEthPerAssetPrice);
|
||||
// test if feePercentage gets passed through
|
||||
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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/base-contract",
|
||||
"version": "3.0.3",
|
||||
"version": "3.0.6",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -41,8 +41,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"ethers": "~4.0.4",
|
||||
"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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/connect",
|
||||
"version": "3.0.3",
|
||||
"version": "3.0.6",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -44,12 +44,12 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
||||
"dependencies": {
|
||||
"@0x/assert": "^1.0.15",
|
||||
"@0x/json-schemas": "^2.0.1",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/assert": "^1.0.17",
|
||||
"@0x/json-schemas": "^2.1.1",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"lodash": "^4.17.5",
|
||||
"query-string": "^5.0.1",
|
||||
"sinon": "^4.0.0",
|
||||
|
@@ -19,7 +19,6 @@ import { fetchAsync } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as queryString from 'query-string';
|
||||
|
||||
import { schemas as clientSchemas } from './schemas/schemas';
|
||||
import { Client, HttpRequestOptions, HttpRequestType } from './types';
|
||||
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
|
||||
|
||||
@@ -61,9 +60,9 @@ export class HttpClient implements Client {
|
||||
requestOpts?: RequestOpts & AssetPairsRequestOpts & PagedRequestOpts,
|
||||
): Promise<AssetPairsResponse> {
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.assetPairsRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.assetPairsRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||
}
|
||||
const httpRequestOpts = {
|
||||
params: requestOpts,
|
||||
@@ -81,9 +80,9 @@ export class HttpClient implements Client {
|
||||
requestOpts?: RequestOpts & OrdersRequestOpts & PagedRequestOpts,
|
||||
): Promise<OrdersResponse> {
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.ordersRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||
}
|
||||
const httpRequestOpts = {
|
||||
params: requestOpts,
|
||||
@@ -99,7 +98,7 @@ export class HttpClient implements Client {
|
||||
*/
|
||||
public async getOrderAsync(orderHash: string, requestOpts?: RequestOpts): Promise<APIOrder> {
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||
}
|
||||
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
||||
const httpRequestOpts = {
|
||||
@@ -119,10 +118,10 @@ export class HttpClient implements Client {
|
||||
request: OrderbookRequest,
|
||||
requestOpts?: RequestOpts & PagedRequestOpts,
|
||||
): Promise<OrderbookResponse> {
|
||||
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
|
||||
assert.doesConformToSchema('request', request, schemas.orderBookRequestSchema);
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||
}
|
||||
const httpRequestOpts = {
|
||||
params: _.defaults({}, request, requestOpts),
|
||||
@@ -142,9 +141,9 @@ export class HttpClient implements Client {
|
||||
requestOpts?: RequestOpts,
|
||||
): Promise<OrderConfigResponse> {
|
||||
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 = {
|
||||
params: requestOpts,
|
||||
payload: request,
|
||||
@@ -160,8 +159,8 @@ export class HttpClient implements Client {
|
||||
*/
|
||||
public async getFeeRecipientsAsync(requestOpts?: RequestOpts & PagedRequestOpts): Promise<FeeRecipientsResponse> {
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.requestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.pagedRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, schemas.requestOptsSchema);
|
||||
}
|
||||
const httpRequestOpts = {
|
||||
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,43 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1542208198,
|
||||
"version": "4.0.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1542134075,
|
||||
"version": "4.0.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note":
|
||||
"Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync`",
|
||||
"pr": 1235
|
||||
},
|
||||
{
|
||||
"note":
|
||||
"Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive",
|
||||
"pr": 1235
|
||||
},
|
||||
{
|
||||
"note":
|
||||
"Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218)",
|
||||
"pr": 1235
|
||||
}
|
||||
],
|
||||
"timestamp": 1542028948
|
||||
},
|
||||
{
|
||||
"version": "3.0.1",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,20 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Fix bug in `ForwarderWrapper` where `feeRecipientAddress` was not correctly normalized. (#1178)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contract-wrappers",
|
||||
"version": "3.0.1",
|
||||
"version": "4.0.2",
|
||||
"description": "Smart TS wrappers for 0x smart contracts",
|
||||
"keywords": [
|
||||
"0xproject",
|
||||
@@ -37,9 +37,9 @@
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0x/dev-utils": "^1.0.14",
|
||||
"@0x/migrations": "^2.0.1",
|
||||
"@0x/subproviders": "^2.1.1",
|
||||
"@0x/dev-utils": "^1.0.17",
|
||||
"@0x/migrations": "^2.0.4",
|
||||
"@0x/subproviders": "^2.1.4",
|
||||
"@0x/tslint-config": "^1.0.10",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
@@ -65,17 +65,17 @@
|
||||
"web3-provider-engine": "14.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/abi-gen-wrappers": "^1.0.2",
|
||||
"@0x/assert": "^1.0.15",
|
||||
"@0x/abi-gen-wrappers": "^1.0.5",
|
||||
"@0x/assert": "^1.0.17",
|
||||
"@0x/contract-addresses": "^1.1.0",
|
||||
"@0x/contract-artifacts": "^1.1.0",
|
||||
"@0x/fill-scenarios": "^1.0.9",
|
||||
"@0x/json-schemas": "^2.0.1",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/fill-scenarios": "^1.0.12",
|
||||
"@0x/json-schemas": "^2.1.1",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"ethereumjs-blockstream": "6.0.0",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
|
@@ -18,6 +18,7 @@ import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_
|
||||
import { methodOptsSchema } from '../schemas/method_opts_schema';
|
||||
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
|
||||
import { txOptsSchema } from '../schemas/tx_opts_schema';
|
||||
import { validateOrderFillableOptsSchema } from '../schemas/validate_order_fillable_opts_schema';
|
||||
import {
|
||||
BlockRange,
|
||||
EventCallback,
|
||||
@@ -1114,6 +1115,9 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
signedOrder: SignedOrder,
|
||||
opts: ValidateOrderFillableOpts = {},
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.doesConformToSchema('opts', opts, validateOrderFillableOptsSchema);
|
||||
|
||||
const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
|
||||
this._erc20TokenWrapper,
|
||||
this._erc721TokenWrapper,
|
||||
@@ -1124,7 +1128,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
|
||||
const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount;
|
||||
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
|
||||
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
|
||||
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider());
|
||||
await orderValidationUtils.validateOrderFillableOrThrowAsync(
|
||||
exchangeTradeSimulator,
|
||||
signedOrder,
|
||||
@@ -1152,7 +1156,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
|
||||
|
||||
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
|
||||
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
|
||||
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider());
|
||||
await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeSimulator,
|
||||
this._web3Wrapper.getProvider(),
|
||||
|
@@ -1,5 +1,6 @@
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
import { AbstractOrderFilledCancelledFetcher } from '@0x/order-utils';
|
||||
import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { BlockParamLiteral } from 'ethereum-types';
|
||||
|
||||
@@ -18,9 +19,18 @@ export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelled
|
||||
});
|
||||
return filledTakerAmount;
|
||||
}
|
||||
public async isOrderCancelledAsync(orderHash: string): Promise<boolean> {
|
||||
public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const isCancelled = await this._exchange.isCancelledAsync(orderHash);
|
||||
return isCancelled;
|
||||
const orderEpoch = await this._exchange.getOrderEpochAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.senderAddress,
|
||||
{
|
||||
defaultBlock: this._stateLayer,
|
||||
},
|
||||
);
|
||||
const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt;
|
||||
return isCancelled || isCancelledByOrderEpoch;
|
||||
}
|
||||
public getZRXAssetData(): string {
|
||||
const zrxAssetData = this._exchange.getZRXAssetData();
|
||||
|
@@ -0,0 +1,7 @@
|
||||
export const validateOrderFillableOptsSchema = {
|
||||
id: '/ValidateOrderFillableOpts',
|
||||
properties: {
|
||||
expectedFillTakerTokenAmount: { $ref: '/wholeNumberSchema' },
|
||||
},
|
||||
type: 'object',
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils';
|
||||
import { FillScenarios } from '@0x/fill-scenarios';
|
||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
|
||||
import { DoneCallback, SignedOrder } from '@0x/types';
|
||||
import { DoneCallback, RevertReason, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import { BlockParamLiteral } from 'ethereum-types';
|
||||
@@ -282,6 +282,19 @@ describe('ExchangeWrapper', () => {
|
||||
expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash);
|
||||
});
|
||||
});
|
||||
describe('#validateOrderFillableOrThrowAsync', () => {
|
||||
it('should throw if signature is invalid', async () => {
|
||||
const signedOrderWithInvalidSignature = {
|
||||
...signedOrder,
|
||||
signature:
|
||||
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403',
|
||||
};
|
||||
|
||||
expect(
|
||||
contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrderWithInvalidSignature),
|
||||
).to.eventually.to.be.rejectedWith(RevertReason.InvalidOrderSignature);
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
it('should check if the signature is valid', async () => {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
|
115
packages/contracts/CHANGELOG.json
Normal file
115
packages/contracts/CHANGELOG.json
Normal file
@@ -0,0 +1,115 @@
|
||||
[
|
||||
{
|
||||
"name": "Forwarder",
|
||||
"version": "1.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Round up when calculating remaining amounts in marketBuy functions",
|
||||
"pr": 1162,
|
||||
"networks": {
|
||||
"1": "0x5468a1dc173652ee28d249c271fa9933144746b1",
|
||||
"3": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e",
|
||||
"42": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Forwarder",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x7afc2d5107af94c462a194d2c21b5bdd238709d6",
|
||||
"3": "0x3983e204b12b3c02fb0638caf2cd406a62e0ead3",
|
||||
"42": "0xd85e2fa7e7e252b27b01bf0d65c946959d2f45b8"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OrderValidator",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x9463e518dea6810309563c81d5266c1b1d149138",
|
||||
"3": "0x90431a90516ab49af23a0530e04e8c7836e7122f",
|
||||
"42": "0xb389da3d204b412df2f75c6afb3d0a7ce0bc283d"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Exchange",
|
||||
"version": "2.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x4f833a24e1f95d70f028921e27040ca56e09ab0b",
|
||||
"3": "0x4530c0483a1633c7a1c97d2c53721caff2caaaaf",
|
||||
"42": "0x35dd2932454449b14cee11a94d3674a936d5d7b2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ERC20Proxy",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e",
|
||||
"3": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
|
||||
"42": "0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ERC721Proxy",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x208e41fb445f1bb1b6780d58356e81405f3e6127",
|
||||
"3": "0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4",
|
||||
"42": "0x2a9127c745688a165106c11cd4d647d2220af821"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "AssetProxyOwner",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v2 deploy",
|
||||
"networks": {
|
||||
"1": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6",
|
||||
"3": "0xf5fa5b5fed2727a0e44ac67f6772e97977aa358b",
|
||||
"42": "0x2c824d2882baa668e0d5202b1e7f2922278703f8"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ZRXToken",
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "protocol v1 deploy",
|
||||
"networks": {
|
||||
"1": "0xe41d2489571d322189246dafa5ebde1f4699f498",
|
||||
"3": "0xff67881f8d12f372d91baae9752eb3631ff0ed00",
|
||||
"42": "0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@@ -1,6 +1,6 @@
|
||||
## Contracts
|
||||
|
||||
Smart contracts that implement the 0x protocol. Addresses of the deployed contracts can be found [here](https://0xproject.com/wiki#Deployed-Addresses).
|
||||
Smart contracts that implement the 0x protocol. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [CHANGELOG](./CHANGELOG.json) of this package.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "contracts",
|
||||
"version": "2.1.51",
|
||||
"version": "2.1.54",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -45,11 +45,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^1.0.15",
|
||||
"@0x/dev-utils": "^1.0.14",
|
||||
"@0x/sol-compiler": "^1.1.9",
|
||||
"@0x/sol-cov": "^2.1.9",
|
||||
"@0x/subproviders": "^2.1.1",
|
||||
"@0x/abi-gen": "^1.0.16",
|
||||
"@0x/dev-utils": "^1.0.17",
|
||||
"@0x/sol-compiler": "^1.1.12",
|
||||
"@0x/sol-cov": "^2.1.12",
|
||||
"@0x/subproviders": "^2.1.4",
|
||||
"@0x/tslint-config": "^1.0.10",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/ethereumjs-abi": "^0.6.0",
|
||||
@@ -71,12 +71,12 @@
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^3.0.3",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/base-contract": "^3.0.6",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereum-types": "^1.1.2",
|
||||
|
@@ -212,13 +212,17 @@ export class ExchangeWrapper {
|
||||
return tx;
|
||||
}
|
||||
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
|
||||
const filledAmount = new BigNumber(await this._exchange.filled.callAsync(orderHashHex));
|
||||
const filledAmount = await this._exchange.filled.callAsync(orderHashHex);
|
||||
return filledAmount;
|
||||
}
|
||||
public async isCancelledAsync(orderHashHex: string): Promise<boolean> {
|
||||
const isCancelled = await this._exchange.cancelled.callAsync(orderHashHex);
|
||||
return isCancelled;
|
||||
}
|
||||
public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise<BigNumber> {
|
||||
const orderEpoch = await this._exchange.orderEpoch.callAsync(makerAddress, senderAddress);
|
||||
return orderEpoch;
|
||||
}
|
||||
public async getOrderInfoAsync(signedOrder: SignedOrder): Promise<OrderInfo> {
|
||||
const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo;
|
||||
return orderInfo;
|
||||
|
@@ -392,7 +392,7 @@ export class FillOrderCombinatorialUtils {
|
||||
);
|
||||
|
||||
// 5. If I fill it by X, what are the resulting balances/allowances/filled amounts expected?
|
||||
const orderValidationUtils = new OrderValidationUtils(orderFilledCancelledFetcher);
|
||||
const orderValidationUtils = new OrderValidationUtils(orderFilledCancelledFetcher, provider);
|
||||
const lazyStore = new BalanceAndProxyAllowanceLazyStore(balanceAndProxyAllowanceFetcher);
|
||||
const exchangeTransferSimulator = new ExchangeTransferSimulator(lazyStore);
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { AbstractOrderFilledCancelledFetcher } from '@0x/order-utils';
|
||||
import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils';
|
||||
import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { ExchangeWrapper } from './exchange_wrapper';
|
||||
@@ -14,9 +15,15 @@ export class SimpleOrderFilledCancelledFetcher implements AbstractOrderFilledCan
|
||||
const filledTakerAmount = new BigNumber(await this._exchangeWrapper.getTakerAssetFilledAmountAsync(orderHash));
|
||||
return filledTakerAmount;
|
||||
}
|
||||
public async isOrderCancelledAsync(orderHash: string): Promise<boolean> {
|
||||
public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const isCancelled = await this._exchangeWrapper.isCancelledAsync(orderHash);
|
||||
return isCancelled;
|
||||
const orderEpoch = await this._exchangeWrapper.getOrderEpochAsync(
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.senderAddress,
|
||||
);
|
||||
const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt;
|
||||
return isCancelled || isCancelledByOrderEpoch;
|
||||
}
|
||||
public getZRXAssetData(): string {
|
||||
return this._zrxAssetData;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/dev-tools-pages",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.6",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@0x/react-shared": "^1.0.18",
|
||||
"@0x/react-shared": "^1.0.21",
|
||||
"basscss": "^8.0.3",
|
||||
"bowser": "^1.9.3",
|
||||
"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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/dev-utils",
|
||||
"version": "1.0.14",
|
||||
"version": "1.0.17",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -41,11 +41,11 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/subproviders": "^2.1.1",
|
||||
"@0x/subproviders": "^2.1.4",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"@types/web3-provider-engine": "^14.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"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",
|
||||
"changes": [
|
||||
|
@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
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_
|
||||
|
||||
* Dependencies updated
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/fill-scenarios",
|
||||
"version": "1.0.9",
|
||||
"version": "1.0.12",
|
||||
"description": "0x order fill scenario generator",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@@ -28,14 +28,14 @@
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/abi-gen-wrappers": "^1.0.2",
|
||||
"@0x/base-contract": "^3.0.3",
|
||||
"@0x/abi-gen-wrappers": "^1.0.5",
|
||||
"@0x/base-contract": "^3.0.6",
|
||||
"@0x/contract-artifacts": "^1.1.0",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"ethers": "~4.0.4",
|
||||
"lodash": "^4.17.5"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/instant",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.7",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -45,15 +45,15 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
|
||||
"dependencies": {
|
||||
"@0x/assert": "^1.0.15",
|
||||
"@0x/asset-buyer": "^2.2.0",
|
||||
"@0x/json-schemas": "^2.0.1",
|
||||
"@0x/order-utils": "^2.0.1",
|
||||
"@0x/subproviders": "^2.1.1",
|
||||
"@0x/assert": "^1.0.17",
|
||||
"@0x/asset-buyer": "^3.0.0",
|
||||
"@0x/json-schemas": "^2.1.1",
|
||||
"@0x/order-utils": "^3.0.2",
|
||||
"@0x/subproviders": "^2.1.4",
|
||||
"@0x/types": "^1.2.1",
|
||||
"@0x/typescript-typings": "^3.0.4",
|
||||
"@0x/utils": "^2.0.4",
|
||||
"@0x/web3-wrapper": "^3.1.1",
|
||||
"@0x/utils": "^2.0.5",
|
||||
"@0x/web3-wrapper": "^3.1.4",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"ethereum-types": "^1.1.2",
|
||||
"lodash": "^4.17.10",
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { OptionallyScreenSpecific } from '../../style/media';
|
||||
import { SlideAnimationState } from '../../types';
|
||||
|
||||
import { PositionAnimation, PositionAnimationSettings } from './position_animation';
|
||||
|
||||
export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
|
||||
export interface SlideAnimationProps {
|
||||
animationState: SlideAnimationState;
|
||||
slideInSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
|
||||
|
@@ -43,7 +43,6 @@ export class BuyButton extends React.Component<BuyButtonProps> {
|
||||
onClick={this._handleClick}
|
||||
isDisabled={shouldDisableButton}
|
||||
fontColor={ColorOption.white}
|
||||
fontSize="20px"
|
||||
>
|
||||
Buy
|
||||
</Button>
|
||||
|
@@ -12,7 +12,6 @@ export interface BuyOrderProgressProps {
|
||||
|
||||
export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> = props => {
|
||||
const { buyOrderState } = props;
|
||||
|
||||
if (
|
||||
buyOrderState.processState === OrderProcessState.Processing ||
|
||||
buyOrderState.processState === OrderProcessState.Success ||
|
||||
@@ -30,6 +29,5 @@ export const BuyOrderProgress: React.StatelessComponent<BuyOrderProgressProps> =
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
@@ -35,7 +35,7 @@ export const BuyOrderStateButtons: React.StatelessComponent<BuyOrderStateButtonP
|
||||
if (props.buyOrderProcessingState === OrderProcessState.Failure) {
|
||||
return (
|
||||
<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
|
||||
</Button>
|
||||
<SecondaryButton width="48%" onClick={props.onViewTransaction}>
|
||||
|
@@ -29,13 +29,18 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
|
||||
const { tokens, onTokenSelect } = this.props;
|
||||
return (
|
||||
<Container height="100%">
|
||||
<Container marginBottom="10px">
|
||||
<Text fontColor={ColorOption.darkGrey} fontSize="18px" fontWeight="600" lineHeight="22px">
|
||||
Select Token
|
||||
</Text>
|
||||
</Container>
|
||||
<SearchInput
|
||||
placeholder="Search tokens..."
|
||||
width="100%"
|
||||
value={this.state.searchQuery}
|
||||
onChange={this._handleSearchInputChange}
|
||||
/>
|
||||
<Container overflow="scroll" height="calc(100% - 80px)" marginTop="10px">
|
||||
<Container overflow="scroll" height="calc(100% - 90px)" marginTop="10px">
|
||||
{_.map(tokens, token => {
|
||||
if (!this._isTokenQueryMatch(token)) {
|
||||
return null;
|
||||
|
@@ -0,0 +1,32 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { META_MASK_CHROME_STORE_URL, META_MASK_SITE_URL } from '../constants';
|
||||
import { ColorOption } from '../style/theme';
|
||||
|
||||
import { MetaMaskLogo } from './meta_mask_logo';
|
||||
import { StandardPanelContent } from './standard_panel_content';
|
||||
import { Button } from './ui/button';
|
||||
|
||||
export interface InstallWalletPanelContentProps {}
|
||||
|
||||
export const InstallWalletPanelContent: React.StatelessComponent<InstallWalletPanelContentProps> = () => (
|
||||
<StandardPanelContent
|
||||
image={<MetaMaskLogo width={85} height={80} />}
|
||||
title="Install MetaMask"
|
||||
description="Please install the MetaMask wallet extension from the Chrome Store."
|
||||
moreInfoSettings={{
|
||||
href: META_MASK_SITE_URL,
|
||||
text: 'What is MetaMask?',
|
||||
}}
|
||||
action={
|
||||
<Button
|
||||
href={META_MASK_CHROME_STORE_URL}
|
||||
width="100%"
|
||||
fontColor={ColorOption.white}
|
||||
backgroundColor={ColorOption.darkOrange}
|
||||
>
|
||||
Get Chrome Extension
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
@@ -15,8 +15,8 @@ import { Spinner } from './ui/spinner';
|
||||
import { Text } from './ui/text';
|
||||
|
||||
export interface InstantHeadingProps {
|
||||
selectedAssetAmount?: BigNumber;
|
||||
totalEthBaseAmount?: BigNumber;
|
||||
selectedAssetUnitAmount?: BigNumber;
|
||||
totalEthBaseUnitAmount?: BigNumber;
|
||||
ethUsdPrice?: BigNumber;
|
||||
quoteRequestState: AsyncProcessState;
|
||||
buyOrderState: OrderState;
|
||||
@@ -104,7 +104,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
||||
if (this.props.quoteRequestState === AsyncProcessState.Pending) {
|
||||
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 amountFunction();
|
||||
@@ -113,8 +113,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
||||
private readonly _renderEthAmount = (): React.ReactNode => {
|
||||
return (
|
||||
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
|
||||
{format.ethBaseAmount(
|
||||
this.props.totalEthBaseAmount,
|
||||
{format.ethBaseUnitAmount(
|
||||
this.props.totalEthBaseUnitAmount,
|
||||
4,
|
||||
<AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
|
||||
)}
|
||||
@@ -125,8 +125,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
|
||||
private readonly _renderDollarAmount = (): React.ReactNode => {
|
||||
return (
|
||||
<Text fontSize="16px" fontColor={ColorOption.white}>
|
||||
{format.ethBaseAmountInUsd(
|
||||
this.props.totalEthBaseAmount,
|
||||
{format.ethBaseUnitAmountInUsd(
|
||||
this.props.totalEthBaseUnitAmount,
|
||||
this.props.ethUsdPrice,
|
||||
2,
|
||||
<AmountPlaceholder isPulsating={false} color={ColorOption.white} />,
|
||||
|
78
packages/instant/src/components/meta_mask_logo.tsx
Normal file
78
packages/instant/src/components/meta_mask_logo.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
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.defaultProps = {
|
||||
width: 85,
|
||||
height: 80,
|
||||
};
|
@@ -4,6 +4,7 @@ import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import { oc } from 'ts-optchain';
|
||||
|
||||
import { BIG_NUMBER_ZERO } from '../constants';
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { format } from '../util/format';
|
||||
|
||||
@@ -15,16 +16,23 @@ import { Text } from './ui/text';
|
||||
|
||||
export interface OrderDetailsProps {
|
||||
buyQuoteInfo?: BuyQuoteInfo;
|
||||
selectedAssetUnitAmount?: BigNumber;
|
||||
ethUsdPrice?: BigNumber;
|
||||
isLoading: boolean;
|
||||
}
|
||||
export class OrderDetails extends React.Component<OrderDetailsProps> {
|
||||
public render(): React.ReactNode {
|
||||
const { buyQuoteInfo, ethUsdPrice } = this.props;
|
||||
const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props;
|
||||
const buyQuoteAccessor = oc(buyQuoteInfo);
|
||||
const ethAssetPrice = buyQuoteAccessor.ethPerAssetPrice();
|
||||
const ethTokenFee = buyQuoteAccessor.feeEthAmount();
|
||||
const totalEthAmount = buyQuoteAccessor.totalEthAmount();
|
||||
const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount();
|
||||
const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount();
|
||||
const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount();
|
||||
const pricePerTokenEth =
|
||||
!_.isUndefined(assetEthBaseUnitAmount) &&
|
||||
!_.isUndefined(selectedAssetUnitAmount) &&
|
||||
!selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
|
||||
? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil()
|
||||
: undefined;
|
||||
return (
|
||||
<Container padding="20px" width="100%" flexGrow={1}>
|
||||
<Container marginBottom="10px">
|
||||
@@ -40,20 +48,19 @@ export class OrderDetails extends React.Component<OrderDetailsProps> {
|
||||
</Container>
|
||||
<EthAmountRow
|
||||
rowLabel="Token Price"
|
||||
ethAmount={ethAssetPrice}
|
||||
ethAmount={pricePerTokenEth}
|
||||
ethUsdPrice={ethUsdPrice}
|
||||
isEthAmountInBaseUnits={false}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
<EthAmountRow
|
||||
rowLabel="Fee"
|
||||
ethAmount={ethTokenFee}
|
||||
ethAmount={feeEthBaseUnitAmount}
|
||||
ethUsdPrice={ethUsdPrice}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
<EthAmountRow
|
||||
rowLabel="Total Cost"
|
||||
ethAmount={totalEthAmount}
|
||||
ethAmount={totalEthBaseUnitAmount}
|
||||
ethUsdPrice={ethUsdPrice}
|
||||
shouldEmphasize={true}
|
||||
isLoading={this.props.isLoading}
|
||||
@@ -81,7 +88,7 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> {
|
||||
const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
|
||||
|
||||
const fontWeight = shouldEmphasize ? 700 : 400;
|
||||
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseAmount : format.ethUnitAmount;
|
||||
const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseUnitAmount : format.ethUnitAmount;
|
||||
return (
|
||||
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
|
||||
<Flex justify="space-between">
|
||||
@@ -105,7 +112,9 @@ export class EthAmountRow extends React.Component<EthAmountRowProps> {
|
||||
);
|
||||
}
|
||||
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);
|
||||
return shouldHideUsdPriceSection ? null : (
|
||||
<Container marginRight="3px" display="inline-block">
|
||||
|
@@ -1,45 +1,132 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { Network } from '../types';
|
||||
import { Account, AccountState, Network } from '../types';
|
||||
|
||||
import { MetaMaskLogo } from './meta_mask_logo';
|
||||
import { PaymentMethodDropdown } from './payment_method_dropdown';
|
||||
import { Circle } from './ui/circle';
|
||||
import { Container } from './ui/container';
|
||||
import { Flex } from './ui/flex';
|
||||
import { Icon } from './ui/icon';
|
||||
import { Text } from './ui/text';
|
||||
|
||||
export interface PaymentMethodProps {}
|
||||
export interface PaymentMethodProps {
|
||||
account: Account;
|
||||
network: Network;
|
||||
onInstallWalletClick: () => void;
|
||||
onUnlockWalletClick: () => void;
|
||||
}
|
||||
|
||||
export const PaymentMethod: React.StatelessComponent<PaymentMethodProps> = () => (
|
||||
<Container padding="20px" width="100%">
|
||||
<Container marginBottom="10px">
|
||||
<Flex justify="space-between">
|
||||
<Text
|
||||
letterSpacing="1px"
|
||||
fontColor={ColorOption.primaryColor}
|
||||
fontWeight={600}
|
||||
textTransform="uppercase"
|
||||
fontSize="14px"
|
||||
>
|
||||
Payment Method
|
||||
</Text>
|
||||
<Flex>
|
||||
<Circle color={ColorOption.green} diameter={8} />
|
||||
export class PaymentMethod extends React.Component<PaymentMethodProps> {
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
<Container padding="20px" width="100%">
|
||||
<Container marginBottom="12px">
|
||||
<Flex justify="space-between">
|
||||
<Text
|
||||
letterSpacing="1px"
|
||||
fontColor={ColorOption.primaryColor}
|
||||
fontWeight={600}
|
||||
textTransform="uppercase"
|
||||
fontSize="14px"
|
||||
>
|
||||
{this._renderTitleText()}
|
||||
</Text>
|
||||
<Flex>{this._renderTitleLabel()}</Flex>
|
||||
</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 (
|
||||
<React.Fragment>
|
||||
<Circle diameter={8} color={circleColor} />
|
||||
<Container marginLeft="3px">
|
||||
<Text fontColor={ColorOption.darkGrey} fontSize="12px">
|
||||
MetaMask
|
||||
</Text>
|
||||
</Container>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Container>
|
||||
<PaymentMethodDropdown
|
||||
accountAddress="0xa1b2c3d4e5f6g7h8j9k10"
|
||||
accountEthBalanceInWei={new BigNumber(10500000000000000000)}
|
||||
network={Network.Mainnet}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
private readonly _renderMainContent = (): React.ReactNode => {
|
||||
const { account, network } = this.props;
|
||||
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} />}
|
||||
>
|
||||
Please Unlock MetaMask
|
||||
</WalletPrompt>
|
||||
);
|
||||
case AccountState.None:
|
||||
return (
|
||||
<WalletPrompt
|
||||
onClick={this.props.onInstallWalletClick}
|
||||
image={<MetaMaskLogo width={19} height={18} />}
|
||||
>
|
||||
Install MetaMask
|
||||
</WalletPrompt>
|
||||
);
|
||||
case AccountState.Ready:
|
||||
return (
|
||||
<PaymentMethodDropdown
|
||||
accountAddress={account.address}
|
||||
accountEthBalanceInWei={account.ethBalanceInWei}
|
||||
network={network}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
interface WalletPromptProps {
|
||||
image: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const WalletPrompt: React.StatelessComponent<WalletPromptProps> = ({ onClick, image, children }) => (
|
||||
<Container
|
||||
padding="14.5px"
|
||||
border={`1px solid ${ColorOption.darkOrange}`}
|
||||
backgroundColor={ColorOption.lightOrange}
|
||||
width="100%"
|
||||
borderRadius="4px"
|
||||
onClick={onClick}
|
||||
cursor={onClick ? 'pointer' : undefined}
|
||||
boxShadowOnHover={!!onClick}
|
||||
>
|
||||
<Flex>
|
||||
<Container marginRight="10px">{image}</Container>
|
||||
<Text fontSize="16px" fontColor={ColorOption.darkOrange}>
|
||||
{children}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
|
@@ -18,7 +18,7 @@ export class PaymentMethodDropdown extends React.Component<PaymentMethodDropdown
|
||||
public render(): React.ReactNode {
|
||||
const { accountAddress, accountEthBalanceInWei } = this.props;
|
||||
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()} />;
|
||||
}
|
||||
private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => {
|
||||
|
@@ -7,9 +7,9 @@ import { Container } from './ui/container';
|
||||
import { Spinner } from './ui/spinner';
|
||||
|
||||
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">
|
||||
<Spinner widthPx={20} heightPx={20} />
|
||||
<Spinner widthPx={16} heightPx={16} />
|
||||
</Container>
|
||||
Placing Order…
|
||||
</Button>
|
||||
|
@@ -156,8 +156,6 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
|
||||
return `${width}px`;
|
||||
}
|
||||
return `${textLengthThreshold}ch`;
|
||||
default:
|
||||
return '1ch';
|
||||
}
|
||||
};
|
||||
private readonly _calculateFontSize = (phase: ScalingInputPhase): number => {
|
||||
|
@@ -15,8 +15,6 @@ export const SecondaryButton: React.StatelessComponent<SecondaryButtonProps> = p
|
||||
borderColor={ColorOption.lightGrey}
|
||||
width={props.width}
|
||||
onClick={props.onClick}
|
||||
fontColor={ColorOption.primaryColor}
|
||||
fontSize="16px"
|
||||
{...buttonProps}
|
||||
>
|
||||
{props.children}
|
||||
|
@@ -3,9 +3,10 @@ import * as React from 'react';
|
||||
import { ScreenSpecification } from '../style/media';
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { zIndex } from '../style/z_index';
|
||||
import { SlideAnimationState } from '../types';
|
||||
|
||||
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 { Flex } from './ui/flex';
|
||||
|
@@ -2,35 +2,25 @@ import * as React from 'react';
|
||||
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { zIndex } from '../style/z_index';
|
||||
import { SlideAnimationState } from '../types';
|
||||
|
||||
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 { Flex } from './ui/flex';
|
||||
import { Icon } from './ui/icon';
|
||||
import { Text } from './ui/text';
|
||||
|
||||
export interface PanelProps {
|
||||
title?: string;
|
||||
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">
|
||||
<Flex justify="space-between">
|
||||
{title && (
|
||||
<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 justify="flex-end">
|
||||
<Icon padding="5px" width={12} color={ColorOption.lightGrey} icon="closeX" onClick={onClose} />
|
||||
</Flex>
|
||||
<Container marginTop="10px" height="100%">
|
||||
<Container position="relative" top="-10px" height="100%">
|
||||
{children}
|
||||
</Container>
|
||||
</Container>
|
||||
|
60
packages/instant/src/components/standard_panel_content.tsx
Normal file
60
packages/instant/src/components/standard_panel_content.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
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>
|
||||
<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 { 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';
|
||||
|
||||
@@ -20,15 +20,11 @@ export class TimedProgressBar extends React.Component<TimedProgressBarProps, {}>
|
||||
private readonly _barRef = React.createRef<HTMLDivElement>();
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const timedProgressProps = this._calculateTimedProgressProps();
|
||||
return (
|
||||
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px">
|
||||
<TimedProgress {...timedProgressProps} ref={this._barRef as any} />
|
||||
</Container>
|
||||
);
|
||||
const widthAnimationSettings = this._calculateWidthAnimationSettings();
|
||||
return <ProgressBar animationSettings={widthAnimationSettings} ref={this._barRef} />;
|
||||
}
|
||||
|
||||
private _calculateTimedProgressProps(): TimedProgressProps {
|
||||
private _calculateWidthAnimationSettings(): WidthAnimationSettings {
|
||||
if (this.props.hasEnded) {
|
||||
if (!this._barRef.current) {
|
||||
throw new Error('ended but no reference');
|
||||
@@ -60,21 +56,45 @@ const expandingWidthKeyframes = (fromWidth: string, toWidth: string) => {
|
||||
`;
|
||||
};
|
||||
|
||||
interface TimedProgressProps {
|
||||
export interface WidthAnimationSettings {
|
||||
timeMs: number;
|
||||
fromWidth: string;
|
||||
toWidth: string;
|
||||
}
|
||||
|
||||
export const TimedProgress =
|
||||
interface ProgressProps {
|
||||
width?: string;
|
||||
animationSettings?: WidthAnimationSettings;
|
||||
}
|
||||
|
||||
export const Progress =
|
||||
styled.div <
|
||||
TimedProgressProps >
|
||||
ProgressProps >
|
||||
`
|
||||
&& {
|
||||
background-color: ${props => props.theme[ColorOption.primaryColor]};
|
||||
border-radius: 6px;
|
||||
height: 6px;
|
||||
animation: ${props => expandingWidthKeyframes(props.fromWidth, props.toWidth)}
|
||||
${props => props.timeMs}ms linear 1 forwards;
|
||||
${props => (props.width ? `width: ${props.width};` : '')}
|
||||
${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 { ColorOption, styled } from '../../style/theme';
|
||||
import { util } from '../../util/util';
|
||||
|
||||
export type ButtonOnClickHandler = (event: React.MouseEvent<HTMLElement>) => void;
|
||||
|
||||
export interface ButtonProps {
|
||||
backgroundColor?: ColorOption;
|
||||
@@ -12,15 +15,26 @@ export interface ButtonProps {
|
||||
padding?: string;
|
||||
type?: string;
|
||||
isDisabled?: boolean;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
href?: string;
|
||||
onClick?: ButtonOnClickHandler;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
|
||||
<button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
const PlainButton: React.StatelessComponent<ButtonProps> = ({
|
||||
children,
|
||||
isDisabled,
|
||||
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 darkenOnActiveAmount = 0.2;
|
||||
@@ -31,7 +45,7 @@ export const Button = styled(PlainButton)`
|
||||
box-sizing: border-box;
|
||||
font-size: ${props => props.fontSize};
|
||||
font-family: 'Inter UI', sans-serif;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
color: ${props => props.fontColor && props.theme[props.fontColor]};
|
||||
cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
|
||||
transition: background-color, opacity 0.5s ease;
|
||||
@@ -64,11 +78,10 @@ export const Button = styled(PlainButton)`
|
||||
|
||||
Button.defaultProps = {
|
||||
backgroundColor: ColorOption.primaryColor,
|
||||
borderColor: ColorOption.primaryColor,
|
||||
width: 'auto',
|
||||
isDisabled: false,
|
||||
padding: '.6em 1.2em',
|
||||
fontSize: '15px',
|
||||
padding: '.82em 1.2em',
|
||||
fontSize: '16px',
|
||||
};
|
||||
|
||||
Button.displayName = 'Button';
|
||||
|
@@ -20,6 +20,7 @@ interface IconInfoMapping {
|
||||
success: IconInfo;
|
||||
chevron: IconInfo;
|
||||
search: IconInfo;
|
||||
lock: IconInfo;
|
||||
}
|
||||
const ICONS: IconInfoMapping = {
|
||||
closeX: {
|
||||
@@ -58,6 +59,11 @@ const ICONS: IconInfoMapping = {
|
||||
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',
|
||||
},
|
||||
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 {
|
||||
|
@@ -1,11 +1,15 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { overlayBlack, styled } from '../../style/theme';
|
||||
import { generateMediaWrapper, ScreenWidths } from '../../style/media';
|
||||
import { generateOverlayBlack, styled } from '../../style/theme';
|
||||
import { zIndex } from '../../style/z_index';
|
||||
|
||||
export interface OverlayProps {
|
||||
zIndex?: number;
|
||||
backgroundColor?: string;
|
||||
width?: string;
|
||||
height?: string;
|
||||
showMaxWidth?: ScreenWidths;
|
||||
}
|
||||
|
||||
export const Overlay =
|
||||
@@ -20,12 +24,16 @@ export const Overlay =
|
||||
left: 0;
|
||||
z-index: ${props => props.zIndex}
|
||||
background-color: ${props => props.backgroundColor};
|
||||
${props => props.width && `width: ${props.width};`}
|
||||
${props => props.height && `height: ${props.height};`}
|
||||
display: ${props => (props.showMaxWidth ? 'none' : 'block')};
|
||||
${props => props.showMaxWidth && generateMediaWrapper(props.showMaxWidth)`display: block;`}
|
||||
}
|
||||
`;
|
||||
|
||||
Overlay.defaultProps = {
|
||||
zIndex: zIndex.overlayDefault,
|
||||
backgroundColor: overlayBlack,
|
||||
backgroundColor: generateOverlayBlack(0.6),
|
||||
};
|
||||
|
||||
Overlay.displayName = 'Overlay';
|
||||
|
@@ -2,6 +2,7 @@ import { darken } from 'polished';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption, styled } from '../../style/theme';
|
||||
import { util } from '../../util/util';
|
||||
|
||||
export interface TextProps {
|
||||
fontColor?: ColorOption;
|
||||
@@ -20,10 +21,16 @@ export interface TextProps {
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
noWrap?: boolean;
|
||||
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;
|
||||
export const Text =
|
||||
export const StyledText =
|
||||
styled.div <
|
||||
TextProps >
|
||||
`
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { ZeroExInstantContainer } from '../components/zero_ex_instant_container';
|
||||
|
||||
import { INJECTED_DIV_CLASS } from '../constants';
|
||||
|
||||
import { ZeroExInstantContainer } from './zero_ex_instant_container';
|
||||
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
||||
|
||||
export type ZeroExInstantProps = ZeroExInstantProviderProps;
|
||||
|
@@ -1,26 +1,29 @@
|
||||
import * as React from 'react';
|
||||
|
||||
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 { 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 { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading';
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { zIndex } from '../style/z_index';
|
||||
import { OrderProcessState, SlideAnimationState } from '../types';
|
||||
|
||||
import { SlideAnimationState } from './animations/slide_animation';
|
||||
import { CSSReset } from './css_reset';
|
||||
import { SlidingPanel } from './sliding_panel';
|
||||
import { Container } from './ui/container';
|
||||
import { Flex } from './ui/flex';
|
||||
|
||||
export interface ZeroExInstantContainerProps {}
|
||||
export interface ZeroExInstantContainerProps {
|
||||
orderProcessState: OrderProcessState;
|
||||
}
|
||||
export interface ZeroExInstantContainerState {
|
||||
tokenSelectionPanelAnimationState: SlideAnimationState;
|
||||
}
|
||||
|
||||
export class ZeroExInstantContainer extends React.Component<ZeroExInstantContainerProps, ZeroExInstantContainerState> {
|
||||
export class ZeroExInstantContainer extends React.Component<{}, ZeroExInstantContainerState> {
|
||||
public state = {
|
||||
tokenSelectionPanelAnimationState: 'none' as SlideAnimationState,
|
||||
};
|
||||
@@ -47,19 +50,19 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain
|
||||
>
|
||||
<Flex direction="column" justify="flex-start" height="100%">
|
||||
<SelectedAssetInstantHeading onSelectAssetClick={this._handleSymbolClick} />
|
||||
<SelectedAssetBuyOrderProgress />
|
||||
<ConnectedBuyOrderProgressOrPaymentMethod />
|
||||
<LatestBuyQuoteOrderDetails />
|
||||
<Container padding="20px" width="100%">
|
||||
<SelectedAssetBuyOrderStateButtons />
|
||||
</Container>
|
||||
</Flex>
|
||||
<SlidingPanel
|
||||
title="Select Token"
|
||||
animationState={this.state.tokenSelectionPanelAnimationState}
|
||||
onClose={this._handlePanelClose}
|
||||
>
|
||||
<AvailableERC20TokenSelector onTokenSelect={this._handlePanelClose} />
|
||||
</SlidingPanel>
|
||||
<CurrentStandardSlidingPanel />
|
||||
</Container>
|
||||
</Container>
|
||||
</React.Fragment>
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { ZeroExInstantContainer } from '../components/zero_ex_instant_container';
|
||||
import { ColorOption } from '../style/theme';
|
||||
|
||||
import { Container } from './ui/container';
|
||||
import { Flex } from './ui/flex';
|
||||
import { Icon } from './ui/icon';
|
||||
import { Overlay } from './ui/overlay';
|
||||
import { ZeroExInstantContainer } from './zero_ex_instant_container';
|
||||
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
||||
|
||||
export interface ZeroExInstantOverlayProps extends ZeroExInstantProviderProps {
|
||||
|
@@ -5,15 +5,18 @@ import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
|
||||
import { ACCOUNT_UPDATE_INTERVAL_TIME_MS, BUY_QUOTE_UPDATE_INTERVAL_TIME_MS } from '../constants';
|
||||
import { SelectedAssetThemeProvider } from '../containers/selected_asset_theme_provider';
|
||||
import { asyncData } from '../redux/async_data';
|
||||
import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer';
|
||||
import { store, Store } from '../redux/store';
|
||||
import { fonts } from '../style/fonts';
|
||||
import { AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types';
|
||||
import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types';
|
||||
import { assetUtils } from '../util/asset';
|
||||
import { errorFlasher } from '../util/error_flasher';
|
||||
import { gasPriceEstimator } from '../util/gas_price_estimator';
|
||||
import { Heartbeater } from '../util/heartbeater';
|
||||
import { generateAccountHeartbeater, generateBuyQuoteHeartbeater } from '../util/heartbeater_factory';
|
||||
import { providerStateFactory } from '../util/provider_state_factory';
|
||||
|
||||
fonts.include();
|
||||
@@ -37,6 +40,9 @@ export interface ZeroExInstantProviderOptionalProps {
|
||||
|
||||
export class ZeroExInstantProvider extends React.Component<ZeroExInstantProviderProps> {
|
||||
private readonly _store: Store;
|
||||
private _accountUpdateHeartbeat?: Heartbeater;
|
||||
private _buyQuoteHeartbeat?: Heartbeater;
|
||||
|
||||
// TODO(fragosti): Write tests for this beast once we inject a provider.
|
||||
private static _mergeDefaultStateWithProps(
|
||||
props: ZeroExInstantProviderProps,
|
||||
@@ -67,7 +73,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
|
||||
completeAssetMetaDataMap,
|
||||
networkId,
|
||||
),
|
||||
selectedAssetAmount: _.isUndefined(props.defaultAssetBuyAmount)
|
||||
selectedAssetUnitAmount: _.isUndefined(props.defaultAssetBuyAmount)
|
||||
? undefined
|
||||
: new BigNumber(props.defaultAssetBuyAmount),
|
||||
availableAssets: _.isUndefined(props.availableAssetDatas)
|
||||
@@ -85,17 +91,29 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
|
||||
}
|
||||
public componentDidMount(): void {
|
||||
const state = this._store.getState();
|
||||
const dispatch = this._store.dispatch;
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
asyncData.fetchEthPriceAndDispatchToStore(this._store);
|
||||
asyncData.fetchEthPriceAndDispatchToStore(dispatch);
|
||||
// fetch available assets if none are specified
|
||||
if (_.isUndefined(state.availableAssets)) {
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
asyncData.fetchAvailableAssetDatasAndDispatchToStore(this._store);
|
||||
asyncData.fetchAvailableAssetDatasAndDispatchToStore(state, dispatch);
|
||||
}
|
||||
if (state.providerState.account.state !== AccountState.None) {
|
||||
this._accountUpdateHeartbeat = generateAccountHeartbeater({
|
||||
store: this._store,
|
||||
shouldPerformImmediatelyOnStart: true,
|
||||
});
|
||||
this._accountUpdateHeartbeat.start(ACCOUNT_UPDATE_INTERVAL_TIME_MS);
|
||||
}
|
||||
|
||||
this._buyQuoteHeartbeat = generateBuyQuoteHeartbeater({
|
||||
store: this._store,
|
||||
shouldPerformImmediatelyOnStart: false,
|
||||
});
|
||||
this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
asyncData.fetchAccountInfoAndDispatchToStore(this._store);
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
asyncData.fetchCurrentBuyQuoteAndDispatchToStore(this._store);
|
||||
asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, true);
|
||||
// warm up the gas price estimator cache just in case we can't
|
||||
// grab the gas price estimate when submitting the transaction
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
@@ -103,6 +121,14 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
this._flashErrorIfWrongNetwork();
|
||||
}
|
||||
public componentWillUnmount(): void {
|
||||
if (this._accountUpdateHeartbeat) {
|
||||
this._accountUpdateHeartbeat.stop();
|
||||
}
|
||||
if (this._buyQuoteHeartbeat) {
|
||||
this._buyQuoteHeartbeat.stop();
|
||||
}
|
||||
}
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
<ReduxProvider store={this._store}>
|
||||
|
@@ -11,12 +11,17 @@ export const WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX = 'Transaction fa
|
||||
export const GWEI_IN_WEI = new BigNumber(1000000000);
|
||||
export const ONE_SECOND_MS = 1000;
|
||||
export const ONE_MINUTE_MS = ONE_SECOND_MS * 60;
|
||||
export const ACCOUNT_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 5;
|
||||
export const BUY_QUOTE_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 15;
|
||||
export const DEFAULT_GAS_PRICE = GWEI_IN_WEI.mul(6);
|
||||
export const DEFAULT_ESTIMATED_TRANSACTION_TIME_MS = ONE_MINUTE_MS * 2;
|
||||
export const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info';
|
||||
export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2';
|
||||
export const PROGRESS_STALL_AT_WIDTH = '95%';
|
||||
export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200;
|
||||
export const META_MASK_CHROME_STORE_URL =
|
||||
'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en';
|
||||
export const META_MASK_SITE_URL = 'https://metamask.io/';
|
||||
export const ETHEREUM_NODE_URL_BY_NETWORK = {
|
||||
[Network.Mainnet]: 'https://mainnet.infura.io/',
|
||||
[Network.Kovan]: 'https://kovan.infura.io/',
|
||||
@@ -31,6 +36,3 @@ export const LOADING_ACCOUNT: AccountNotReady = {
|
||||
export const LOCKED_ACCOUNT: AccountNotReady = {
|
||||
state: AccountState.Locked,
|
||||
};
|
||||
export const ERROR_ACCOUNT: AccountNotReady = {
|
||||
state: AccountState.Error,
|
||||
};
|
||||
|
@@ -0,0 +1,59 @@
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
import { PaymentMethod, PaymentMethodProps } from '../components/payment_method';
|
||||
import { Action, actions } from '../redux/actions';
|
||||
import { asyncData } from '../redux/async_data';
|
||||
import { State } from '../redux/reducer';
|
||||
import { Network, Omit, ProviderState, StandardSlidingPanelContent } from '../types';
|
||||
|
||||
export interface ConnectedAccountPaymentMethodProps {}
|
||||
|
||||
interface ConnectedState {
|
||||
network: Network;
|
||||
providerState: ProviderState;
|
||||
}
|
||||
|
||||
interface ConnectedDispatch {
|
||||
onInstallWalletClick: () => 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 => ({
|
||||
onInstallWalletClick: () => 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,
|
||||
onInstallWalletClick: connectedDispatch.onInstallWalletClick,
|
||||
onUnlockWalletClick: () => {
|
||||
connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState);
|
||||
},
|
||||
});
|
||||
|
||||
export const ConnectedAccountPaymentMethod: React.ComponentClass<ConnectedAccountPaymentMethodProps> = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
mergeProps,
|
||||
)(PaymentMethod);
|
@@ -0,0 +1,36 @@
|
||||
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 />;
|
||||
}
|
||||
if (orderProcessState === OrderProcessState.None) {
|
||||
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 {
|
||||
buyQuoteInfo?: BuyQuoteInfo;
|
||||
selectedAssetUnitAmount?: BigNumber;
|
||||
ethUsdPrice?: BigNumber;
|
||||
isLoading: boolean;
|
||||
}
|
||||
@@ -21,6 +22,7 @@ interface ConnectedState {
|
||||
const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({
|
||||
// use the worst case quote info
|
||||
buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(),
|
||||
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
|
||||
ethUsdPrice: state.ethUsdPrice,
|
||||
isLoading: state.quoteRequestState === AsyncProcessState.Pending,
|
||||
});
|
||||
|
@@ -1,35 +1,59 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
import { SlideAnimationState } from '../components/animations/slide_animation';
|
||||
import { SlidingError } from '../components/sliding_error';
|
||||
import { Overlay } from '../components/ui/overlay';
|
||||
import { Action } from '../redux/actions';
|
||||
import { State } from '../redux/reducer';
|
||||
import { Asset, DisplayStatus } from '../types';
|
||||
import { ScreenWidths } from '../style/media';
|
||||
import { generateOverlayBlack } from '../style/theme';
|
||||
import { zIndex } from '../style/z_index';
|
||||
import { Asset, DisplayStatus, Omit, SlideAnimationState } from '../types';
|
||||
import { errorFlasher } from '../util/error_flasher';
|
||||
|
||||
export interface LatestErrorComponentProps {
|
||||
asset?: Asset;
|
||||
latestErrorMessage?: string;
|
||||
animationState: SlideAnimationState;
|
||||
shouldRenderOverlay: boolean;
|
||||
onOverlayClick: () => void;
|
||||
}
|
||||
|
||||
export const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => {
|
||||
if (!props.latestErrorMessage) {
|
||||
return <div />;
|
||||
}
|
||||
return <SlidingError animationState={props.animationState} icon="😢" message={props.latestErrorMessage} />;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SlidingError animationState={props.animationState} icon="😢" message={props.latestErrorMessage} />
|
||||
{props.shouldRenderOverlay && (
|
||||
<Overlay
|
||||
onClick={props.onOverlayClick}
|
||||
zIndex={zIndex.containerOverlay}
|
||||
showMaxWidth={ScreenWidths.Sm}
|
||||
backgroundColor={generateOverlayBlack(0.4)}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
interface ConnectedState {
|
||||
asset?: Asset;
|
||||
latestErrorMessage?: string;
|
||||
animationState: SlideAnimationState;
|
||||
}
|
||||
export interface LatestErrorProps {}
|
||||
interface ConnectedState extends Omit<LatestErrorComponentProps, 'onOverlayClick'> {}
|
||||
const mapStateToProps = (state: State, _ownProps: LatestErrorProps): ConnectedState => ({
|
||||
asset: state.selectedAsset,
|
||||
latestErrorMessage: state.latestErrorMessage,
|
||||
animationState: state.latestErrorDisplayStatus === DisplayStatus.Present ? 'slidIn' : 'slidOut',
|
||||
shouldRenderOverlay: state.latestErrorDisplayStatus === DisplayStatus.Present,
|
||||
});
|
||||
|
||||
export const LatestError = connect(mapStateToProps)(LatestErrorComponent);
|
||||
type ConnectedDispatch = Pick<LatestErrorComponentProps, 'onOverlayClick'>;
|
||||
const mapDispatchToProps = (dispatch: Dispatch<Action>, _ownProps: LatestErrorProps): ConnectedDispatch => ({
|
||||
onOverlayClick: () => {
|
||||
errorFlasher.clearError(dispatch);
|
||||
},
|
||||
});
|
||||
|
||||
export const LatestError = connect(mapStateToProps, mapDispatchToProps)(LatestErrorComponent);
|
||||
|
@@ -14,16 +14,16 @@ export interface InstantHeadingProps {
|
||||
}
|
||||
|
||||
interface ConnectedState {
|
||||
selectedAssetAmount?: BigNumber;
|
||||
totalEthBaseAmount?: BigNumber;
|
||||
selectedAssetUnitAmount?: BigNumber;
|
||||
totalEthBaseUnitAmount?: BigNumber;
|
||||
ethUsdPrice?: BigNumber;
|
||||
quoteRequestState: AsyncProcessState;
|
||||
buyOrderState: OrderState;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({
|
||||
selectedAssetAmount: state.selectedAssetAmount,
|
||||
totalEthBaseAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
|
||||
selectedAssetUnitAmount: state.selectedAssetUnitAmount,
|
||||
totalEthBaseUnitAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(),
|
||||
ethUsdPrice: state.ethUsdPrice,
|
||||
quoteRequestState: state.quoteRequestState,
|
||||
buyOrderState: state.buyOrderState,
|
||||
|
@@ -6,11 +6,11 @@ import * as React from 'react';
|
||||
import { connect } from 'react-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 { State } from '../redux/reducer';
|
||||
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';
|
||||
|
||||
export interface SelectedERC20AssetAmountInputProps {
|
||||
@@ -37,13 +37,7 @@ interface ConnectedDispatch {
|
||||
) => void;
|
||||
}
|
||||
|
||||
interface ConnectedProps {
|
||||
value?: BigNumber;
|
||||
asset?: ERC20Asset;
|
||||
onChange: (value?: BigNumber, asset?: ERC20Asset) => void;
|
||||
isDisabled: boolean;
|
||||
numberOfAssetsAvailable?: number;
|
||||
}
|
||||
type ConnectedProps = Omit<ERC20AssetAmountInputProps, keyof SelectedERC20AssetAmountInputProps>;
|
||||
|
||||
type FinalProps = ConnectedProps & SelectedERC20AssetAmountInputProps;
|
||||
|
||||
@@ -59,7 +53,7 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP
|
||||
const assetBuyer = state.providerState.assetBuyer;
|
||||
return {
|
||||
assetBuyer,
|
||||
value: state.selectedAssetAmount,
|
||||
value: state.selectedAssetUnitAmount,
|
||||
asset: selectedAsset,
|
||||
isDisabled,
|
||||
numberOfAssetsAvailable,
|
||||
@@ -69,7 +63,7 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP
|
||||
|
||||
const debouncedUpdateBuyQuoteAsync = _.debounce(buyQuoteUpdater.updateBuyQuoteAsync.bind(buyQuoteUpdater), 200, {
|
||||
trailing: true,
|
||||
});
|
||||
}) as typeof buyQuoteUpdater.updateBuyQuoteAsync;
|
||||
|
||||
const mapDispatchToProps = (
|
||||
dispatch: Dispatch<Action>,
|
||||
@@ -87,7 +81,7 @@ const mapDispatchToProps = (
|
||||
// even if it's debounced, give them the illusion it's loading
|
||||
dispatch(actions.setQuoteRequestStatePending());
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, affiliateInfo);
|
||||
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, true, affiliateInfo);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@@ -8,42 +8,42 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
|
||||
'0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
primaryColor: 'rgb(54, 50, 60)',
|
||||
primaryColor: '#333333',
|
||||
symbol: 'zrx',
|
||||
name: '0x',
|
||||
},
|
||||
'0xf47261b000000000000000000000000042d6622dece394b54999fbd73d108123806f6a18': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
primaryColor: '#ec3e6c',
|
||||
primaryColor: '#EC4F81',
|
||||
symbol: 'spank',
|
||||
name: 'Spank',
|
||||
},
|
||||
'0xf47261b0000000000000000000000000d26114cd6ee289accf82350c8d8487fedb8a0c07': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
primaryColor: '#2e61ea',
|
||||
primaryColor: '#2458E7',
|
||||
symbol: 'omg',
|
||||
name: 'OmiseGo',
|
||||
},
|
||||
'0xf47261b00000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
primaryColor: '#87e4ca',
|
||||
primaryColor: '#68CCBB',
|
||||
symbol: 'mkr',
|
||||
name: 'Maker',
|
||||
},
|
||||
'0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
primaryColor: '#9c326c',
|
||||
primaryColor: '#FF5000',
|
||||
symbol: 'bat',
|
||||
name: 'Basic Attention Token',
|
||||
},
|
||||
'0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
primaryColor: '#5663b0',
|
||||
primaryColor: '#4763D7',
|
||||
symbol: 'snt',
|
||||
name: 'Status',
|
||||
},
|
||||
@@ -54,27 +54,6 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
|
||||
symbol: 'mana',
|
||||
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': {
|
||||
assetProxyId: AssetProxyId.ERC20,
|
||||
decimals: 18,
|
||||
@@ -82,4 +61,144 @@ export const assetMetaDataMap: ObjectMap<AssetMetaData> = {
|
||||
symbol: 'rep',
|
||||
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 * as _ from 'lodash';
|
||||
|
||||
import { ActionsUnion, AddressAndEthBalanceInWei, Asset } from '../types';
|
||||
import { ActionsUnion, AddressAndEthBalanceInWei, Asset, StandardSlidingPanelContent } from '../types';
|
||||
|
||||
export interface PlainAction<T extends string> {
|
||||
type: T;
|
||||
@@ -23,11 +23,10 @@ function createAction<T extends string, P>(type: T, data?: P): PlainAction<T> |
|
||||
export enum ActionTypes {
|
||||
SET_ACCOUNT_STATE_LOADING = 'SET_ACCOUNT_STATE_LOADING',
|
||||
SET_ACCOUNT_STATE_LOCKED = 'SET_ACCOUNT_STATE_LOCKED',
|
||||
SET_ACCOUNT_STATE_ERROR = 'SET_ACCOUNT_STATE_ERROR',
|
||||
SET_ACCOUNT_STATE_READY = 'SET_ACCOUNT_STATE_READY',
|
||||
UPDATE_ACCOUNT_ETH_BALANCE = 'UPDATE_ACCOUNT_ETH_BALANCE',
|
||||
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_VALIDATING = 'SET_BUY_ORDER_STATE_VALIDATING',
|
||||
SET_BUY_ORDER_STATE_PROCESSING = 'SET_BUY_ORDER_STATE_PROCESSING',
|
||||
@@ -42,17 +41,19 @@ export enum ActionTypes {
|
||||
HIDE_ERROR = 'HIDE_ERROR',
|
||||
CLEAR_ERROR = 'CLEAR_ERROR',
|
||||
RESET_AMOUNT = 'RESET_AMOUNT',
|
||||
OPEN_STANDARD_SLIDING_PANEL = 'OPEN_STANDARD_SLIDING_PANEL',
|
||||
CLOSE_STANDARD_SLIDING_PANEL = 'CLOSE_STANDARD_SLIDING_PANEL',
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
setAccountStateLoading: () => createAction(ActionTypes.SET_ACCOUNT_STATE_LOADING),
|
||||
setAccountStateLocked: () => createAction(ActionTypes.SET_ACCOUNT_STATE_LOCKED),
|
||||
setAccountStateError: () => createAction(ActionTypes.SET_ACCOUNT_STATE_ERROR),
|
||||
setAccountStateReady: (address: string) => createAction(ActionTypes.SET_ACCOUNT_STATE_READY, address),
|
||||
updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) =>
|
||||
createAction(ActionTypes.UPDATE_ACCOUNT_ETH_BALANCE, addressAndBalance),
|
||||
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),
|
||||
setBuyOrderStateValidating: () => createAction(ActionTypes.SET_BUY_ORDER_STATE_VALIDATING),
|
||||
setBuyOrderStateProcessing: (txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) =>
|
||||
@@ -68,4 +69,7 @@ export const actions = {
|
||||
hideError: () => createAction(ActionTypes.HIDE_ERROR),
|
||||
clearError: () => createAction(ActionTypes.CLEAR_ERROR),
|
||||
resetAmount: () => createAction(ActionTypes.RESET_AMOUNT),
|
||||
openStandardSlidingPanel: (content: StandardSlidingPanelContent) =>
|
||||
createAction(ActionTypes.OPEN_STANDARD_SLIDING_PANEL, content),
|
||||
closeStandardSlidingPanel: () => createAction(ActionTypes.CLOSE_STANDARD_SLIDING_PANEL),
|
||||
};
|
||||
|
@@ -1,92 +1,103 @@
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
import { BIG_NUMBER_ZERO } from '../constants';
|
||||
import { AccountState, ERC20Asset } from '../types';
|
||||
import { AccountState, ERC20Asset, OrderProcessState, ProviderState } from '../types';
|
||||
import { assetUtils } from '../util/asset';
|
||||
import { buyQuoteUpdater } from '../util/buy_quote_updater';
|
||||
import { coinbaseApi } from '../util/coinbase_api';
|
||||
import { errorFlasher } from '../util/error_flasher';
|
||||
|
||||
import { actions } from './actions';
|
||||
import { Store } from './store';
|
||||
import { State } from './reducer';
|
||||
|
||||
export const asyncData = {
|
||||
fetchEthPriceAndDispatchToStore: async (store: Store) => {
|
||||
fetchEthPriceAndDispatchToStore: async (dispatch: Dispatch) => {
|
||||
try {
|
||||
const ethUsdPrice = await coinbaseApi.getEthUsdPrice();
|
||||
store.dispatch(actions.updateEthUsdPrice(ethUsdPrice));
|
||||
dispatch(actions.updateEthUsdPrice(ethUsdPrice));
|
||||
} catch (e) {
|
||||
const errorMessage = 'Error fetching ETH/USD price';
|
||||
errorFlasher.flashNewErrorMessage(store.dispatch, errorMessage);
|
||||
store.dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
|
||||
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
|
||||
dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO));
|
||||
}
|
||||
},
|
||||
fetchAvailableAssetDatasAndDispatchToStore: async (store: Store) => {
|
||||
const { providerState, assetMetaDataMap, network } = store.getState();
|
||||
fetchAvailableAssetDatasAndDispatchToStore: async (state: State, dispatch: Dispatch) => {
|
||||
const { providerState, assetMetaDataMap, network } = state;
|
||||
const assetBuyer = providerState.assetBuyer;
|
||||
try {
|
||||
const assetDatas = await assetBuyer.getAvailableAssetDatasAsync();
|
||||
const assets = assetUtils.createAssetsFromAssetDatas(assetDatas, assetMetaDataMap, network);
|
||||
store.dispatch(actions.setAvailableAssets(assets));
|
||||
dispatch(actions.setAvailableAssets(assets));
|
||||
} catch (e) {
|
||||
const errorMessage = 'Could not find any assets';
|
||||
errorFlasher.flashNewErrorMessage(store.dispatch, errorMessage);
|
||||
errorFlasher.flashNewErrorMessage(dispatch, errorMessage);
|
||||
// On error, just specify that none are available
|
||||
store.dispatch(actions.setAvailableAssets([]));
|
||||
dispatch(actions.setAvailableAssets([]));
|
||||
}
|
||||
},
|
||||
fetchAccountInfoAndDispatchToStore: async (store: Store) => {
|
||||
const { providerState } = store.getState();
|
||||
fetchAccountInfoAndDispatchToStore: async (
|
||||
providerState: ProviderState,
|
||||
dispatch: Dispatch,
|
||||
shouldAttemptUnlock: boolean = false,
|
||||
shouldSetToLoading: boolean = false,
|
||||
) => {
|
||||
const web3Wrapper = providerState.web3Wrapper;
|
||||
if (providerState.account.state !== AccountState.Loading) {
|
||||
store.dispatch(actions.setAccountStateLoading());
|
||||
const provider = providerState.provider;
|
||||
if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) {
|
||||
dispatch(actions.setAccountStateLoading());
|
||||
}
|
||||
let availableAddresses: string[];
|
||||
try {
|
||||
availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
// TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here
|
||||
const isPrivacyModeEnabled = !_.isUndefined((provider as any).enable);
|
||||
availableAddresses =
|
||||
isPrivacyModeEnabled && shouldAttemptUnlock
|
||||
? await (provider as any).enable()
|
||||
: await web3Wrapper.getAvailableAddressesAsync();
|
||||
} catch (e) {
|
||||
store.dispatch(actions.setAccountStateError());
|
||||
dispatch(actions.setAccountStateLocked());
|
||||
return;
|
||||
}
|
||||
if (!_.isEmpty(availableAddresses)) {
|
||||
const activeAddress = availableAddresses[0];
|
||||
store.dispatch(actions.setAccountStateReady(activeAddress));
|
||||
dispatch(actions.setAccountStateReady(activeAddress));
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
asyncData.fetchAccountBalanceAndDispatchToStore(store);
|
||||
asyncData.fetchAccountBalanceAndDispatchToStore(activeAddress, providerState.web3Wrapper, dispatch);
|
||||
} else {
|
||||
store.dispatch(actions.setAccountStateLocked());
|
||||
dispatch(actions.setAccountStateLocked());
|
||||
}
|
||||
},
|
||||
fetchAccountBalanceAndDispatchToStore: async (store: Store) => {
|
||||
const { providerState } = store.getState();
|
||||
const web3Wrapper = providerState.web3Wrapper;
|
||||
const account = providerState.account;
|
||||
if (account.state !== AccountState.Ready) {
|
||||
return;
|
||||
}
|
||||
fetchAccountBalanceAndDispatchToStore: async (address: string, web3Wrapper: Web3Wrapper, dispatch: Dispatch) => {
|
||||
try {
|
||||
const address = account.address;
|
||||
const ethBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(address);
|
||||
store.dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));
|
||||
dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));
|
||||
} catch (e) {
|
||||
// leave balance as is
|
||||
return;
|
||||
}
|
||||
},
|
||||
fetchCurrentBuyQuoteAndDispatchToStore: async (store: Store) => {
|
||||
const { providerState, selectedAsset, selectedAssetAmount, affiliateInfo } = store.getState();
|
||||
fetchCurrentBuyQuoteAndDispatchToStore: async (
|
||||
state: State,
|
||||
dispatch: Dispatch,
|
||||
shouldSetPending: boolean = false,
|
||||
) => {
|
||||
const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state;
|
||||
const assetBuyer = providerState.assetBuyer;
|
||||
if (
|
||||
!_.isUndefined(selectedAssetAmount) &&
|
||||
!_.isUndefined(selectedAssetUnitAmount) &&
|
||||
!_.isUndefined(selectedAsset) &&
|
||||
buyOrderState.processState === OrderProcessState.None &&
|
||||
selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20
|
||||
) {
|
||||
await buyQuoteUpdater.updateBuyQuoteAsync(
|
||||
assetBuyer,
|
||||
store.dispatch,
|
||||
dispatch,
|
||||
selectedAsset as ERC20Asset,
|
||||
selectedAssetAmount,
|
||||
selectedAssetUnitAmount,
|
||||
shouldSetPending,
|
||||
affiliateInfo,
|
||||
);
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import { BigNumber } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { ERROR_ACCOUNT, LOADING_ACCOUNT, LOCKED_ACCOUNT } from '../constants';
|
||||
import { LOADING_ACCOUNT, LOCKED_ACCOUNT } from '../constants';
|
||||
import { assetMetaDataMap } from '../data/asset_meta_data_map';
|
||||
import {
|
||||
Account,
|
||||
@@ -19,6 +19,8 @@ import {
|
||||
OrderProcessState,
|
||||
OrderState,
|
||||
ProviderState,
|
||||
StandardSlidingPanelContent,
|
||||
StandardSlidingPanelSettings,
|
||||
} from '../types';
|
||||
|
||||
import { Action, ActionTypes } from './actions';
|
||||
@@ -30,6 +32,7 @@ export interface DefaultState {
|
||||
buyOrderState: OrderState;
|
||||
latestErrorDisplayStatus: DisplayStatus;
|
||||
quoteRequestState: AsyncProcessState;
|
||||
standardSlidingPanelSettings: StandardSlidingPanelSettings;
|
||||
}
|
||||
|
||||
// State that is required but needs to be derived from the props
|
||||
@@ -41,7 +44,7 @@ interface PropsDerivedState {
|
||||
interface OptionalState {
|
||||
selectedAsset: Asset;
|
||||
availableAssets: Asset[];
|
||||
selectedAssetAmount: BigNumber;
|
||||
selectedAssetUnitAmount: BigNumber;
|
||||
ethUsdPrice: BigNumber;
|
||||
latestBuyQuote: BuyQuote;
|
||||
latestErrorMessage: string;
|
||||
@@ -56,6 +59,10 @@ export const DEFAULT_STATE: DefaultState = {
|
||||
buyOrderState: { processState: OrderProcessState.None },
|
||||
latestErrorDisplayStatus: DisplayStatus.Hidden,
|
||||
quoteRequestState: AsyncProcessState.None,
|
||||
standardSlidingPanelSettings: {
|
||||
animationState: 'none',
|
||||
content: StandardSlidingPanelContent.None,
|
||||
},
|
||||
};
|
||||
|
||||
export const createReducer = (initialState: State) => {
|
||||
@@ -65,14 +72,20 @@ export const createReducer = (initialState: State) => {
|
||||
return reduceStateWithAccount(state, LOADING_ACCOUNT);
|
||||
case ActionTypes.SET_ACCOUNT_STATE_LOCKED:
|
||||
return reduceStateWithAccount(state, LOCKED_ACCOUNT);
|
||||
case ActionTypes.SET_ACCOUNT_STATE_ERROR:
|
||||
return reduceStateWithAccount(state, ERROR_ACCOUNT);
|
||||
case ActionTypes.SET_ACCOUNT_STATE_READY: {
|
||||
const account: AccountReady = {
|
||||
const address = action.data;
|
||||
let newAccount: AccountReady = {
|
||||
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: {
|
||||
const { address, ethBalanceInWei } = action.data;
|
||||
@@ -92,10 +105,10 @@ export const createReducer = (initialState: State) => {
|
||||
...state,
|
||||
ethUsdPrice: action.data,
|
||||
};
|
||||
case ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT:
|
||||
case ActionTypes.UPDATE_SELECTED_ASSET_UNIT_AMOUNT:
|
||||
return {
|
||||
...state,
|
||||
selectedAssetAmount: action.data,
|
||||
selectedAssetUnitAmount: action.data,
|
||||
};
|
||||
case ActionTypes.UPDATE_LATEST_BUY_QUOTE:
|
||||
const newBuyQuoteIfExists = action.data;
|
||||
@@ -206,13 +219,29 @@ export const createReducer = (initialState: State) => {
|
||||
latestBuyQuote: undefined,
|
||||
quoteRequestState: AsyncProcessState.None,
|
||||
buyOrderState: { processState: OrderProcessState.None },
|
||||
selectedAssetAmount: undefined,
|
||||
selectedAssetUnitAmount: undefined,
|
||||
};
|
||||
case ActionTypes.SET_AVAILABLE_ASSETS:
|
||||
return {
|
||||
...state,
|
||||
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:
|
||||
return state;
|
||||
}
|
||||
@@ -234,9 +263,9 @@ const reduceStateWithAccount = (state: State, account: Account) => {
|
||||
|
||||
const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
|
||||
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 (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetAmountIfExists)) {
|
||||
if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetUnitAmountIfExists)) {
|
||||
return false;
|
||||
}
|
||||
// if buyQuote's assetData does not match that of the current selected asset, return false
|
||||
@@ -248,7 +277,7 @@ const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => {
|
||||
const selectedAssetMetaData = selectedAssetIfExists.metaData;
|
||||
if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) {
|
||||
const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount(
|
||||
selectedAssetAmountIfExists,
|
||||
selectedAssetUnitAmountIfExists,
|
||||
selectedAssetMetaData.decimals,
|
||||
);
|
||||
const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount);
|
||||
|
@@ -8,7 +8,7 @@ export enum ScreenWidths {
|
||||
Lg = 64,
|
||||
}
|
||||
|
||||
const generateMediaWrapper = (screenWidth: ScreenWidths) => (...args: any[]) => css`
|
||||
export const generateMediaWrapper = (screenWidth: ScreenWidths) => (...args: any[]) => css`
|
||||
@media (max-width: ${screenWidth}em) {
|
||||
${css.apply(css, args)};
|
||||
}
|
||||
|
@@ -35,7 +35,10 @@ export const theme: Theme = {
|
||||
};
|
||||
|
||||
export const transparentWhite = 'rgba(255,255,255,0.3)';
|
||||
export const overlayBlack = 'rgba(0, 0, 0, 0.6)';
|
||||
export const completelyTransparent = 'rga(0, 0, 0, 0)';
|
||||
|
||||
export const generateOverlayBlack = (opacity = 0.6) => {
|
||||
return `rgba(0, 0, 0, ${opacity})`;
|
||||
};
|
||||
|
||||
export { styled, css, keyframes, withTheme, createGlobalStyle, ThemeProvider };
|
||||
|
@@ -3,6 +3,7 @@ export const zIndex = {
|
||||
mainContainer: 20,
|
||||
dropdownItems: 30,
|
||||
panel: 40,
|
||||
containerOverlay: 45,
|
||||
errorPopup: 50,
|
||||
overlayDefault: 100,
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import { Provider } from 'ethereum-types';
|
||||
|
||||
// Reusable
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
export type Maybe<T> = T | undefined;
|
||||
export enum AsyncProcessState {
|
||||
None = 'NONE',
|
||||
@@ -101,11 +102,10 @@ export interface ProviderState {
|
||||
}
|
||||
|
||||
export enum AccountState {
|
||||
None = 'NONE,',
|
||||
Loading = 'LOADING',
|
||||
Ready = 'READY',
|
||||
Locked = 'LOCKED', // TODO(bmillman): break this up into locked / privacy mode enabled
|
||||
Error = 'ERROR',
|
||||
None = 'NONE,',
|
||||
Locked = 'LOCKED',
|
||||
}
|
||||
|
||||
export interface AccountReady {
|
||||
@@ -114,7 +114,7 @@ export interface AccountReady {
|
||||
ethBalanceInWei?: BigNumber;
|
||||
}
|
||||
export interface AccountNotReady {
|
||||
state: AccountState.None | AccountState.Loading | AccountState.Locked | AccountState.Error;
|
||||
state: AccountState.None | AccountState.Loading | AccountState.Locked;
|
||||
}
|
||||
|
||||
export type Account = AccountReady | AccountNotReady;
|
||||
@@ -125,3 +125,15 @@ export interface AddressAndEthBalanceInWei {
|
||||
address: string;
|
||||
ethBalanceInWei: BigNumber;
|
||||
}
|
||||
|
||||
export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
|
||||
|
||||
export enum StandardSlidingPanelContent {
|
||||
None = 'NONE',
|
||||
InstallWallet = 'INSTALL_WALLET',
|
||||
}
|
||||
|
||||
export interface StandardSlidingPanelSettings {
|
||||
animationState: SlideAnimationState;
|
||||
content: StandardSlidingPanelContent;
|
||||
}
|
||||
|
@@ -80,8 +80,6 @@ export const assetUtils = {
|
||||
return metaData.symbol.toUpperCase();
|
||||
case AssetProxyId.ERC721:
|
||||
return metaData.name;
|
||||
default:
|
||||
return defaultName;
|
||||
}
|
||||
},
|
||||
formattedSymbolForAsset: (asset?: ERC20Asset, defaultName: string = '???'): string => {
|
||||
|
@@ -15,13 +15,16 @@ export const buyQuoteUpdater = {
|
||||
assetBuyer: AssetBuyer,
|
||||
dispatch: Dispatch<Action>,
|
||||
asset: ERC20Asset,
|
||||
assetAmount: BigNumber,
|
||||
assetUnitAmount: BigNumber,
|
||||
setPending = true,
|
||||
affiliateInfo?: AffiliateInfo,
|
||||
): Promise<void> => {
|
||||
// get a new buy quote.
|
||||
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetAmount, asset.metaData.decimals);
|
||||
// mark quote as pending
|
||||
dispatch(actions.setQuoteRequestStatePending());
|
||||
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals);
|
||||
if (setPending) {
|
||||
// mark quote as pending
|
||||
dispatch(actions.setQuoteRequestStatePending());
|
||||
}
|
||||
const feePercentage = oc(affiliateInfo).feePercentage();
|
||||
let newBuyQuote: BuyQuote | undefined;
|
||||
try {
|
||||
|
@@ -8,9 +8,8 @@ const etherscanPrefix = (networkId: number): string | undefined => {
|
||||
return 'kovan.';
|
||||
case Network.Mainnet:
|
||||
return '';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
export const etherscanUtil = {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user