Merge branch 'development' into feature/instant/misc-close-analytics

This commit is contained in:
Steve Klebanoff 2018-11-29 15:45:35 -08:00
commit 702dbbae54
141 changed files with 7033 additions and 411 deletions

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "2.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "2.0.5", "version": "2.0.5",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.0.6 - _November 28, 2018_
* Dependencies updated
## v2.0.5 - _November 21, 2018_ ## v2.0.5 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "0x.js", "name": "0x.js",
"version": "2.0.5", "version": "2.0.6",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -42,10 +42,10 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@0x/abi-gen-wrappers": "^1.1.0", "@0x/abi-gen-wrappers": "^2.0.0",
"@0x/contract-addresses": "^1.2.0", "@0x/contract-addresses": "^2.0.0",
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/migrations": "^2.1.0", "@0x/migrations": "^2.2.0",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42", "@types/mocha": "^2.2.42",
@ -73,15 +73,15 @@
}, },
"dependencies": { "dependencies": {
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/contract-wrappers": "^4.1.0", "@0x/contract-wrappers": "^4.1.1",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/order-watcher": "^2.2.5", "@0x/order-watcher": "^2.2.6",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/web3-provider-engine": "^14.0.0", "@types/web3-provider-engine": "^14.0.0",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethers": "~4.0.4", "ethers": "~4.0.4",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"version": "1.0.0", "version": "1.0.0",
"changes": [ "changes": [

View File

@ -0,0 +1,14 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.1 - _November 28, 2018_
* Dependencies updated
## v1.0.0 - _Invalid date_
* Initial publish (#1305)

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/abi-gen-templates", "name": "@0x/abi-gen-templates",
"version": "1.0.0", "version": "1.0.1",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@ -6,7 +6,8 @@
"pr": 1309, "pr": 1309,
"note": "Update Exchange artifact to receive ZRX asset data as a constructor argument" "note": "Update Exchange artifact to receive ZRX asset data as a constructor argument"
} }
] ],
"timestamp": 1543401373
}, },
{ {
"version": "1.1.0", "version": "1.1.0",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.0.0 - _November 28, 2018_
* Update Exchange artifact to receive ZRX asset data as a constructor argument (#1309)
## v1.1.0 - _November 21, 2018_ ## v1.1.0 - _November 21, 2018_
* `deployFrom0xArtifactAsync` additionally accepts artifacts that conform to the `SimpleContractArtifact` interface (#1298) * `deployFrom0xArtifactAsync` additionally accepts artifacts that conform to the `SimpleContractArtifact` interface (#1298)

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/abi-gen-wrappers", "name": "@0x/abi-gen-wrappers",
"version": "1.1.0", "version": "2.0.0",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -31,18 +31,18 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^1.0.17", "@0x/abi-gen": "^1.0.17",
"@0x/abi-gen-templates": "^1.0.0", "@0x/abi-gen-templates": "^1.0.1",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethers": "~4.0.4", "ethers": "~4.0.4",
"lodash": "^4.17.5", "lodash": "^4.17.5",
"shx": "^0.2.2" "shx": "^0.2.2"
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^3.0.7" "@0x/base-contract": "^3.0.8"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "3.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"version": "3.0.1", "version": "3.0.1",
"changes": [ "changes": [

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v3.0.2 - _November 28, 2018_
* Dependencies updated
## v3.0.1 - _November 21, 2018_ ## v3.0.1 - _November 21, 2018_
* Dependencies updated (#1276) * Dependencies updated (#1276)

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/asset-buyer", "name": "@0x/asset-buyer",
"version": "3.0.1", "version": "3.0.2",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -37,15 +37,15 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
"dependencies": { "dependencies": {
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/connect": "^3.0.7", "@0x/connect": "^3.0.8",
"@0x/contract-wrappers": "^4.1.0", "@0x/contract-wrappers": "^4.1.1",
"@0x/json-schemas": "^2.1.2", "@0x/json-schemas": "^2.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"lodash": "^4.17.5" "lodash": "^4.17.5"
}, },

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "3.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "3.0.7", "version": "3.0.7",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v3.0.8 - _November 28, 2018_
* Dependencies updated
## v3.0.7 - _November 21, 2018_ ## v3.0.7 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/base-contract", "name": "@0x/base-contract",
"version": "3.0.7", "version": "3.0.8",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -42,7 +42,7 @@
"dependencies": { "dependencies": {
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethers": "~4.0.4", "ethers": "~4.0.4",
"lodash": "^4.17.5" "lodash": "^4.17.5"

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "3.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "3.0.7", "version": "3.0.7",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v3.0.8 - _November 28, 2018_
* Dependencies updated
## v3.0.7 - _November 21, 2018_ ## v3.0.7 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/connect", "name": "@0x/connect",
"version": "3.0.7", "version": "3.0.8",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -46,7 +46,7 @@
"dependencies": { "dependencies": {
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/json-schemas": "^2.1.2", "@0x/json-schemas": "^2.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",

View File

@ -1,4 +1,18 @@
[ [
{
"version": "2.0.0",
"changes": [
{
"note": "Redeployed Rinkeby with testnet Exchange artifact",
"pr": 1318
},
{
"note": "Added Ganache snapshot addresses for network 50",
"pr": 1318
}
],
"timestamp": 1543401373
},
{ {
"version": "1.2.0", "version": "1.2.0",
"changes": [ "changes": [

View File

@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.0.0 - _November 28, 2018_
* Redeployed Rinkeby with testnet Exchange artifact (#1318)
* Added Ganache snapshot addresses for network 50 (#1318)
## v1.2.0 - _November 21, 2018_ ## v1.2.0 - _November 21, 2018_
* Rinkeby Deployment * Rinkeby Deployment

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/contract-addresses", "name": "@0x/contract-addresses",
"version": "1.2.0", "version": "2.0.0",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@ -16,6 +16,7 @@ export enum NetworkId {
Ropsten = 3, Ropsten = 3,
Rinkeby = 4, Rinkeby = 4,
Kovan = 42, Kovan = 42,
Ganache = 50,
} }
const networkToAddresses: { [networkId: number]: ContractAddresses } = { const networkToAddresses: { [networkId: number]: ContractAddresses } = {
@ -40,14 +41,14 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = {
orderValidator: '0x90431a90516ab49af23a0530e04e8c7836e7122f', orderValidator: '0x90431a90516ab49af23a0530e04e8c7836e7122f',
}, },
4: { 4: {
erc20Proxy: '0x3e809c563c15a295e832e37053798ddc8d6c8dab', exchange: '0xbce0b5f6eb618c565c3e5f5cd69652bbc279f44e',
erc721Proxy: '0x8e1ff02637cb5e39f2fa36c14706aa348b065b09', erc20Proxy: '0x2f5ae4f6106e89b4147651688a92256885c5f410',
zrxToken: '0x2727e688b8fd40b198cd5fe6e408e00494a06f07', erc721Proxy: '0x7656d773e11ff7383a14dcf09a9c50990481cd10',
zrxToken: '0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa',
etherToken: '0xc778417e063141139fce010982780140aa0cd5ab', etherToken: '0xc778417e063141139fce010982780140aa0cd5ab',
exchange: '0x22ebc052f43a88efa06379426120718170f2204e', assetProxyOwner: '0xe1703da878afcebff5b7624a826902af475b9c03',
assetProxyOwner: '0x1da52d1d3a3acfa0a1836b737393b4e9931268fc', forwarder: '0x2d40589abbdee84961f3a7656b9af7adb0ee5ab4',
forwarder: '0xd2dbf3250a764eaaa94fa0c84ed87c0edc8ed04e', orderValidator: '0x0c5173a51e26b29d6126c686756fb9fbef71f762',
orderValidator: '0x39c3fc9f4d8430af2713306ce80c584752d9e1c7',
}, },
42: { 42: {
erc20Proxy: '0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e', erc20Proxy: '0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e',
@ -59,6 +60,17 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = {
forwarder: '0x17992e4ffb22730138e4b62aaa6367fa9d3699a6', forwarder: '0x17992e4ffb22730138e4b62aaa6367fa9d3699a6',
orderValidator: '0xb389da3d204b412df2f75c6afb3d0a7ce0bc283d', orderValidator: '0xb389da3d204b412df2f75c6afb3d0a7ce0bc283d',
}, },
// NetworkId 50 represents our Ganache snapshot generated from migrations.
50: {
exchange: '0x48bacb9266a570d521063ef5dd96e61686dbe788',
erc20Proxy: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
erc721Proxy: '0x1d7022f5b17d2f8b695918fb48fa1089c9f85401',
zrxToken: '0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c',
etherToken: '0x0b1ba0af832d7c05fd64161e0db78e85978e8082',
assetProxyOwner: '0x34d402f14d58e001d8efbe6585051bf9706aa064',
forwarder: '0xb69e673309512a9d726f87304c6984054f87a93b',
orderValidator: '0xe86bb98fcf9bff3512c74589b78fb168200cc546',
},
}; };
/** /**

View File

@ -6,7 +6,8 @@
"pr": 1309, "pr": 1309,
"note": "Update Exchange artifact to receive ZRX asset data as a constructor argument" "note": "Update Exchange artifact to receive ZRX asset data as a constructor argument"
} }
] ],
"timestamp": 1543401373
}, },
{ {
"version": "1.1.0", "version": "1.1.0",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.1.2 - _November 28, 2018_
* Update Exchange artifact to receive ZRX asset data as a constructor argument (#1309)
## v1.1.0 - _November 9, 2018_ ## v1.1.0 - _November 9, 2018_
* Update Forwarder artifact (#1192) * Update Forwarder artifact (#1192)

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/contract-artifacts", "name": "@0x/contract-artifacts",
"version": "1.1.0", "version": "1.1.2",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "4.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"version": "4.1.0", "version": "4.1.0",
"changes": [ "changes": [

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v4.1.1 - _November 28, 2018_
* Dependencies updated
## v4.1.0 - _November 21, 2018_ ## v4.1.0 - _November 21, 2018_
* Add a `nonce` field for `TxOpts` so that it's now possible to re-broadcast stuck transactions with a higher gas amount (#1292) * Add a `nonce` field for `TxOpts` so that it's now possible to re-broadcast stuck transactions with a higher gas amount (#1292)

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/contract-wrappers", "name": "@0x/contract-wrappers",
"version": "4.1.0", "version": "4.1.1",
"description": "Smart TS wrappers for 0x smart contracts", "description": "Smart TS wrappers for 0x smart contracts",
"keywords": [ "keywords": [
"0xproject", "0xproject",
@ -37,9 +37,9 @@
"node": ">=6.0.0" "node": ">=6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/migrations": "^2.1.0", "@0x/migrations": "^2.2.0",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42", "@types/mocha": "^2.2.42",
@ -65,17 +65,17 @@
"web3-provider-engine": "14.0.6" "web3-provider-engine": "14.0.6"
}, },
"dependencies": { "dependencies": {
"@0x/abi-gen-wrappers": "^1.1.0", "@0x/abi-gen-wrappers": "^2.0.0",
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/contract-addresses": "^1.2.0", "@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.0", "@0x/contract-artifacts": "^1.1.2",
"@0x/fill-scenarios": "^1.0.13", "@0x/fill-scenarios": "^1.0.14",
"@0x/json-schemas": "^2.1.2", "@0x/json-schemas": "^2.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethereumjs-blockstream": "6.0.0", "ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1", "ethereumjs-util": "^5.1.1",

View File

@ -1,4 +1,14 @@
[ [
{
"name": "MultiAssetProxy",
"version": "1.0.0",
"changes": [
{
"note": "Add MultiAssetProxy implementation",
"pr": 1224
}
]
},
{ {
"name": "OrderValidator", "name": "OrderValidator",
"version": "1.0.1", "version": "1.0.1",

View File

@ -38,6 +38,7 @@
"IValidator", "IValidator",
"IWallet", "IWallet",
"MixinAuthorizable", "MixinAuthorizable",
"MultiAssetProxy",
"MultiSigWallet", "MultiSigWallet",
"MultiSigWalletWithTimeLock", "MultiSigWalletWithTimeLock",
"OrderValidator", "OrderValidator",

View File

@ -0,0 +1,300 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity 0.4.24;
import "../Exchange/MixinAssetProxyDispatcher.sol";
import "./MixinAuthorizable.sol";
contract MultiAssetProxy is
MixinAssetProxyDispatcher,
MixinAuthorizable
{
// Id of this proxy.
bytes4 constant internal PROXY_ID = bytes4(keccak256("MultiAsset(uint256[],bytes[])"));
// solhint-disable-next-line payable-fallback
function ()
external
{
assembly {
// The first 4 bytes of calldata holds the function selector
let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
// `transferFrom` will be called with the following parameters:
// assetData Encoded byte array.
// from Address to transfer asset from.
// to Address to transfer asset to.
// amount Amount of asset to transfer.
// bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
// where k is the key left padded to 32 bytes and p is the storage slot
mstore(0, caller)
mstore(32, authorized_slot)
// Revert if authorized[msg.sender] == false
if iszero(sload(keccak256(0, 64))) {
// Revert with `Error("SENDER_NOT_AUTHORIZED")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
mstore(96, 0)
revert(0, 100)
}
// `transferFrom`.
// The function is marked `external`, so no abi decoding is done for
// us. Instead, we expect the `calldata` memory to contain the
// following:
//
// | Area | Offset | Length | Contents |
// |----------|--------|---------|-------------------------------------|
// | Header | 0 | 4 | function selector |
// | Params | | 4 * 32 | function parameters: |
// | | 4 | | 1. offset to assetData (*) |
// | | 36 | | 2. from |
// | | 68 | | 3. to |
// | | 100 | | 4. amount |
// | Data | | | assetData: |
// | | 132 | 32 | assetData Length |
// | | 164 | ** | assetData Contents |
//
// (*): offset is computed from start of function parameters, so offset
// by an additional 4 bytes in the calldata.
//
// (**): see table below to compute length of assetData Contents
//
// WARNING: The ABIv2 specification allows additional padding between
// the Params and Data section. This will result in a larger
// offset to assetData.
// Load offset to `assetData`
let assetDataOffset := calldataload(4)
// Asset data itself is encoded as follows:
//
// | Area | Offset | Length | Contents |
// |----------|-------------|---------|-------------------------------------|
// | Header | 0 | 4 | assetProxyId |
// | Params | | 2 * 32 | function parameters: |
// | | 4 | | 1. offset to amounts (*) |
// | | 36 | | 2. offset to nestedAssetData (*) |
// | Data | | | amounts: |
// | | 68 | 32 | amounts Length |
// | | 100 | a | amounts Contents |
// | | | | nestedAssetData: |
// | | 100 + a | 32 | nestedAssetData Length |
// | | 132 + a | b | nestedAssetData Contents (offsets) |
// | | 132 + a + b | | nestedAssetData[0, ..., len] |
// In order to find the offset to `amounts`, we must add:
// 4 (function selector)
// + assetDataOffset
// + 32 (assetData len)
// + 4 (assetProxyId)
let amountsOffset := calldataload(add(assetDataOffset, 40))
// In order to find the offset to `nestedAssetData`, we must add:
// 4 (function selector)
// + assetDataOffset
// + 32 (assetData len)
// + 4 (assetProxyId)
// + 32 (amounts offset)
let nestedAssetDataOffset := calldataload(add(assetDataOffset, 72))
// In order to find the start of the `amounts` contents, we must add:
// 4 (function selector)
// + assetDataOffset
// + 32 (assetData len)
// + 4 (assetProxyId)
// + amountsOffset
// + 32 (amounts len)
let amountsContentsStart := add(assetDataOffset, add(amountsOffset, 72))
// Load number of elements in `amounts`
let amountsLen := calldataload(sub(amountsContentsStart, 32))
// In order to find the start of the `nestedAssetData` contents, we must add:
// 4 (function selector)
// + assetDataOffset
// + 32 (assetData len)
// + 4 (assetProxyId)
// + nestedAssetDataOffset
// + 32 (nestedAssetData len)
let nestedAssetDataContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, 72))
// Load number of elements in `nestedAssetData`
let nestedAssetDataLen := calldataload(sub(nestedAssetDataContentsStart, 32))
// Revert if number of elements in `amounts` differs from number of elements in `nestedAssetData`
if iszero(eq(amountsLen, nestedAssetDataLen)) {
// Revert with `Error("LENGTH_MISMATCH")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000000f4c454e4754485f4d49534d4154434800000000000000000000000000)
mstore(96, 0)
revert(0, 100)
}
// Copy `transferFrom` selector, offset to `assetData`, `from`, and `to` from calldata to memory
calldatacopy(
0, // memory can safely be overwritten from beginning
0, // start of calldata
100 // length of selector (4) and 3 params (32 * 3)
)
// Overwrite existing offset to `assetData` with our own
mstore(4, 128)
// Load `amount`
let amount := calldataload(100)
// Calculate number of bytes in `amounts` contents
let amountsByteLen := mul(amountsLen, 32)
// Initialize `assetProxyId` and `assetProxy` to 0
let assetProxyId := 0
let assetProxy := 0
// Loop through `amounts` and `nestedAssetData`, calling `transferFrom` for each respective element
for {let i := 0} lt(i, amountsByteLen) {i := add(i, 32)} {
// Calculate the total amount
let amountsElement := calldataload(add(amountsContentsStart, i))
let totalAmount := mul(amountsElement, amount)
// Revert if multiplication resulted in an overflow
if iszero(eq(div(totalAmount, amount), amountsElement)) {
// Revert with `Error("UINT256_OVERFLOW")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
mstore(96, 0)
revert(0, 100)
}
// Write `totalAmount` to memory
mstore(100, totalAmount)
// Load offset to `nestedAssetData[i]`
let nestedAssetDataElementOffset := calldataload(add(nestedAssetDataContentsStart, i))
// In order to find the start of the `nestedAssetData[i]` contents, we must add:
// 4 (function selector)
// + assetDataOffset
// + 32 (assetData len)
// + 4 (assetProxyId)
// + nestedAssetDataOffset
// + 32 (nestedAssetData len)
// + nestedAssetDataElementOffset
// + 32 (nestedAssetDataElement len)
let nestedAssetDataElementContentsStart := add(assetDataOffset, add(nestedAssetDataOffset, add(nestedAssetDataElementOffset, 104)))
// Load length of `nestedAssetData[i]`
let nestedAssetDataElementLenStart := sub(nestedAssetDataElementContentsStart, 32)
let nestedAssetDataElementLen := calldataload(nestedAssetDataElementLenStart)
// Revert if the `nestedAssetData` does not contain a 4 byte `assetProxyId`
if lt(nestedAssetDataElementLen, 4) {
// Revert with `Error("LENGTH_GREATER_THAN_3_REQUIRED")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000001e4c454e4754485f475245415445525f5448414e5f335f524551554952)
mstore(96, 0x4544000000000000000000000000000000000000000000000000000000000000)
revert(0, 100)
}
// Load AssetProxy id
let currentAssetProxyId := and(
calldataload(nestedAssetDataElementContentsStart),
0xffffffff00000000000000000000000000000000000000000000000000000000
)
// Only load `assetProxy` if `currentAssetProxyId` does not equal `assetProxyId`
// We do not need to check if `currentAssetProxyId` is 0 since `assetProxy` is also initialized to 0
if iszero(eq(currentAssetProxyId, assetProxyId)) {
// Update `assetProxyId`
assetProxyId := currentAssetProxyId
// To lookup a value in a mapping, we load from the storage location keccak256(k, p),
// where k is the key left padded to 32 bytes and p is the storage slot
mstore(132, assetProxyId)
mstore(164, assetProxies_slot)
assetProxy := sload(keccak256(132, 64))
}
// Revert if AssetProxy with given id does not exist
if iszero(assetProxy) {
// Revert with `Error("ASSET_PROXY_DOES_NOT_EXIST")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000001a41535345545f50524f58595f444f45535f4e4f545f45584953540000)
mstore(96, 0)
revert(0, 100)
}
// Copy `nestedAssetData[i]` from calldata to memory
calldatacopy(
132, // memory slot after `amounts[i]`
nestedAssetDataElementLenStart, // location of `nestedAssetData[i]` in calldata
add(nestedAssetDataElementLen, 32) // `nestedAssetData[i].length` plus 32 byte length
)
// call `assetProxy.transferFrom`
let success := call(
gas, // forward all gas
assetProxy, // call address of asset proxy
0, // don't send any ETH
0, // pointer to start of input
add(164, nestedAssetDataElementLen), // length of input
0, // write output over memory that won't be reused
0 // don't copy output to memory
)
// Revert with reason given by AssetProxy if `transferFrom` call failed
if iszero(success) {
returndatacopy(
0, // copy to memory at 0
0, // copy from return data at 0
returndatasize() // copy all return data
)
revert(0, returndatasize())
}
}
// Return if no `transferFrom` calls reverted
return(0, 0)
}
// Revert if undefined function is called
revert(0, 0)
}
}
/// @dev Gets the proxy id associated with the proxy address.
/// @return Proxy id.
function getProxyId()
external
pure
returns (bytes4)
{
return PROXY_ID;
}
}

View File

@ -18,6 +18,7 @@
// solhint-disable // solhint-disable
pragma solidity 0.4.24; pragma solidity 0.4.24;
pragma experimental ABIEncoderV2;
// @dev Interface of the asset proxy's assetData. // @dev Interface of the asset proxy's assetData.
@ -26,15 +27,18 @@ pragma solidity 0.4.24;
interface IAssetData { interface IAssetData {
function ERC20Token(address tokenContract) function ERC20Token(address tokenContract)
external external;
pure;
function ERC721Token( function ERC721Token(
address tokenContract, address tokenContract,
uint256 tokenId, uint256 tokenId
bytes receiverData
) )
external external;
pure;
function MultiAsset(
uint256[] amounts,
bytes[] nestedAssetData
)
external;
} }

View File

@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "contracts", "name": "contracts",
"version": "2.1.55", "version": "2.1.56",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -19,7 +19,8 @@
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html", "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha", "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit", "run_mocha":
"mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile": "sol-compiler --contracts-dir contracts", "compile": "sol-compiler --contracts-dir contracts",
"clean": "shx rm -rf lib generated-artifacts generated-wrappers", "clean": "shx rm -rf lib generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers", "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
@ -32,7 +33,8 @@
"lint-contracts": "solhint contracts/**/**/**/**/*.sol" "lint-contracts": "solhint contracts/**/**/**/**/*.sol"
}, },
"config": { "config": {
"abis": "generated-artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|ERC20Proxy|ERC721Token|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|Whitelist|WETH9|ZRXToken).json" "abis":
"generated-artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|ERC20Proxy|ERC721Token|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiAssetProxy|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|Whitelist|WETH9|ZRXToken).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -46,10 +48,10 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^1.0.17", "@0x/abi-gen": "^1.0.17",
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/sol-compiler": "^1.1.13", "@0x/sol-compiler": "^1.1.14",
"@0x/sol-cov": "^2.1.13", "@0x/sol-cov": "^2.1.14",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/bn.js": "^4.11.0", "@types/bn.js": "^4.11.0",
"@types/ethereumjs-abi": "^0.6.0", "@types/ethereumjs-abi": "^0.6.0",
@ -71,12 +73,12 @@
"yargs": "^10.0.3" "yargs": "^10.0.3"
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/js-combinatorics": "^0.5.29", "@types/js-combinatorics": "^0.5.29",
"bn.js": "^4.11.8", "bn.js": "^4.11.8",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",

View File

@ -19,6 +19,7 @@ import * as InvalidERC721Receiver from '../../generated-artifacts/InvalidERC721R
import * as IValidator from '../../generated-artifacts/IValidator.json'; import * as IValidator from '../../generated-artifacts/IValidator.json';
import * as IWallet from '../../generated-artifacts/IWallet.json'; import * as IWallet from '../../generated-artifacts/IWallet.json';
import * as MixinAuthorizable from '../../generated-artifacts/MixinAuthorizable.json'; import * as MixinAuthorizable from '../../generated-artifacts/MixinAuthorizable.json';
import * as MultiAssetProxy from '../../generated-artifacts/MultiAssetProxy.json';
import * as MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json'; import * as MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json';
import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json'; import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
import * as OrderValidator from '../../generated-artifacts/OrderValidator.json'; import * as OrderValidator from '../../generated-artifacts/OrderValidator.json';
@ -57,6 +58,7 @@ export const artifacts = {
IWallet: IWallet as ContractArtifact, IWallet: IWallet as ContractArtifact,
InvalidERC721Receiver: InvalidERC721Receiver as ContractArtifact, InvalidERC721Receiver: InvalidERC721Receiver as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact, MixinAuthorizable: MixinAuthorizable as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
MultiSigWallet: MultiSigWallet as ContractArtifact, MultiSigWallet: MultiSigWallet as ContractArtifact,
MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact, MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact,
OrderValidator: OrderValidator as ContractArtifact, OrderValidator: OrderValidator as ContractArtifact,

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,8 @@ import { DummyNoReturnERC20TokenContract } from '../../generated-wrappers/dummy_
import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy'; import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy';
import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy'; import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated-wrappers/exchange'; import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated-wrappers/exchange';
import { IAssetDataContract } from '../../generated-wrappers/i_asset_data';
import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_proxy';
import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token'; import { ReentrantERC20TokenContract } from '../../generated-wrappers/reentrant_erc20_token';
import { TestStaticCallReceiverContract } from '../../generated-wrappers/test_static_call_receiver'; import { TestStaticCallReceiverContract } from '../../generated-wrappers/test_static_call_receiver';
import { artifacts } from '../../src/artifacts'; import { artifacts } from '../../src/artifacts';
@ -31,6 +33,11 @@ import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const assetDataInterface = new IAssetDataContract(
artifacts.IAssetData.compilerOutput.abi,
constants.NULL_ADDRESS,
provider,
);
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
describe('Exchange core', () => { describe('Exchange core', () => {
let makerAddress: string; let makerAddress: string;
@ -47,6 +54,7 @@ describe('Exchange core', () => {
let exchange: ExchangeContract; let exchange: ExchangeContract;
let erc20Proxy: ERC20ProxyContract; let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract; let erc721Proxy: ERC721ProxyContract;
let multiAssetProxy: MultiAssetProxyContract;
let maliciousWallet: TestStaticCallReceiverContract; let maliciousWallet: TestStaticCallReceiverContract;
let maliciousValidator: TestStaticCallReceiverContract; let maliciousValidator: TestStaticCallReceiverContract;
@ -76,44 +84,26 @@ describe('Exchange core', () => {
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner); erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
// Deploy AssetProxies, Exchange, tokens, and malicious contracts
erc20Proxy = await erc20Wrapper.deployProxyAsync();
erc721Proxy = await erc721Wrapper.deployProxyAsync();
multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
artifacts.MultiAssetProxy,
provider,
txDefaults,
);
const numDummyErc20ToDeploy = 3; const numDummyErc20ToDeploy = 3;
[erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync( [erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
numDummyErc20ToDeploy, numDummyErc20ToDeploy,
constants.DUMMY_TOKEN_DECIMALS, constants.DUMMY_TOKEN_DECIMALS,
); );
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync(); [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
erc721Proxy = await erc721Wrapper.deployProxyAsync();
await erc721Wrapper.setBalancesAndAllowancesAsync();
const erc721Balances = await erc721Wrapper.getBalancesAsync();
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
erc721TakerAssetIds = erc721Balances[takerAddress][erc721Token.address];
exchange = await ExchangeContract.deployFrom0xArtifactAsync( exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange, artifacts.Exchange,
provider, provider,
txDefaults, txDefaults,
assetDataUtils.encodeERC20AssetData(zrxToken.address), assetDataUtils.encodeERC20AssetData(zrxToken.address),
); );
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
maliciousWallet = maliciousValidator = await TestStaticCallReceiverContract.deployFrom0xArtifactAsync( maliciousWallet = maliciousValidator = await TestStaticCallReceiverContract.deployFrom0xArtifactAsync(
artifacts.TestStaticCallReceiver, artifacts.TestStaticCallReceiver,
provider, provider,
@ -126,9 +116,72 @@ describe('Exchange core', () => {
exchange.address, exchange.address,
); );
// Configure ERC20Proxy
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Configure ERC721Proxy
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Configure MultiAssetProxy
await web3Wrapper.awaitTransactionSuccessAsync(
await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc721Proxy.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Configure Exchange
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner);
// Configure ERC20 tokens
await erc20Wrapper.setBalancesAndAllowancesAsync();
// Configure ERC721 tokens
await erc721Wrapper.setBalancesAndAllowancesAsync();
const erc721Balances = await erc721Wrapper.getBalancesAsync();
erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address];
erc721TakerAssetIds = erc721Balances[takerAddress][erc721Token.address];
// Configure order defaults
defaultMakerAssetAddress = erc20TokenA.address; defaultMakerAssetAddress = erc20TokenA.address;
defaultTakerAssetAddress = erc20TokenB.address; defaultTakerAssetAddress = erc20TokenB.address;
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
@ -707,6 +760,292 @@ describe('Exchange core', () => {
}); });
}); });
describe('Testing exchange of multiple assets', () => {
it('should allow multiple assets to be exchanged for a single asset', async () => {
const makerAmounts = [new BigNumber(10), new BigNumber(20)];
const makerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
];
const makerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
makerAmounts,
makerNestedAssetData,
);
const makerAssetAmount = new BigNumber(1);
const takerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
const takerAssetAmount = new BigNumber(10);
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData,
takerAssetData,
makerAssetAmount,
takerAssetAmount,
makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT,
});
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
expect(finalMakerBalanceA).to.be.bignumber.equal(
initialMakerBalanceA.minus(makerAmounts[0].times(makerAssetAmount)),
);
expect(finalMakerBalanceB).to.be.bignumber.equal(
initialMakerBalanceB.minus(makerAmounts[1].times(makerAssetAmount)),
);
expect(finalMakerZrxBalance).to.be.bignumber.equal(initialMakerZrxBalance.plus(takerAssetAmount));
expect(finalTakerBalanceA).to.be.bignumber.equal(
initialTakerBalanceA.plus(makerAmounts[0].times(makerAssetAmount)),
);
expect(finalTakerBalanceB).to.be.bignumber.equal(
initialTakerBalanceB.plus(makerAmounts[1].times(makerAssetAmount)),
);
expect(finalTakerZrxBalance).to.be.bignumber.equal(initialTakerZrxBalance.minus(takerAssetAmount));
});
it('should allow multiple assets to be exchanged for multiple assets', async () => {
const makerAmounts = [new BigNumber(10), new BigNumber(20)];
const makerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
];
const makerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
makerAmounts,
makerNestedAssetData,
);
const makerAssetAmount = new BigNumber(1);
const takerAmounts = [new BigNumber(10), new BigNumber(1)];
const takerAssetId = erc721TakerAssetIds[0];
const takerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(zrxToken.address),
assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
];
const takerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
takerAmounts,
takerNestedAssetData,
);
const takerAssetAmount = new BigNumber(1);
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData,
takerAssetData,
makerAssetAmount,
takerAssetAmount,
makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT,
});
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
const finalOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
expect(finalMakerBalanceA).to.be.bignumber.equal(
initialMakerBalanceA.minus(makerAmounts[0].times(makerAssetAmount)),
);
expect(finalMakerBalanceB).to.be.bignumber.equal(
initialMakerBalanceB.minus(makerAmounts[1].times(makerAssetAmount)),
);
expect(finalMakerZrxBalance).to.be.bignumber.equal(
initialMakerZrxBalance.plus(takerAmounts[0].times(takerAssetAmount)),
);
expect(finalTakerBalanceA).to.be.bignumber.equal(
initialTakerBalanceA.plus(makerAmounts[0].times(makerAssetAmount)),
);
expect(finalTakerBalanceB).to.be.bignumber.equal(
initialTakerBalanceB.plus(makerAmounts[1].times(makerAssetAmount)),
);
expect(finalTakerZrxBalance).to.be.bignumber.equal(
initialTakerZrxBalance.minus(takerAmounts[0].times(takerAssetAmount)),
);
expect(finalOwnerTakerAsset).to.be.equal(makerAddress);
});
it('should allow an order selling multiple assets to be partially filled', async () => {
const makerAmounts = [new BigNumber(10), new BigNumber(20)];
const makerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
];
const makerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
makerAmounts,
makerNestedAssetData,
);
const makerAssetAmount = new BigNumber(30);
const takerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
const takerAssetAmount = new BigNumber(10);
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData,
takerAssetData,
makerAssetAmount,
takerAssetAmount,
makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT,
});
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
const takerAssetFillAmount = takerAssetAmount.dividedToIntegerBy(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount,
});
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
expect(finalMakerBalanceA).to.be.bignumber.equal(
initialMakerBalanceA.minus(
makerAmounts[0].times(
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalMakerBalanceB).to.be.bignumber.equal(
initialMakerBalanceB.minus(
makerAmounts[1].times(
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalMakerZrxBalance).to.be.bignumber.equal(
initialMakerZrxBalance.plus(
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
);
expect(finalTakerBalanceA).to.be.bignumber.equal(
initialTakerBalanceA.plus(
makerAmounts[0].times(
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalTakerBalanceB).to.be.bignumber.equal(
initialTakerBalanceB.plus(
makerAmounts[1].times(
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalTakerZrxBalance).to.be.bignumber.equal(
initialTakerZrxBalance.minus(
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
);
});
it('should allow an order buying multiple assets to be partially filled', async () => {
const takerAmounts = [new BigNumber(10), new BigNumber(20)];
const takerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address),
];
const takerAssetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(
takerAmounts,
takerNestedAssetData,
);
const takerAssetAmount = new BigNumber(30);
const makerAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
const makerAssetAmount = new BigNumber(10);
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData,
takerAssetData,
makerAssetAmount,
takerAssetAmount,
makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT,
});
const initialMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const initialMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const initialMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const initialTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const initialTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const initialTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
const takerAssetFillAmount = takerAssetAmount.dividedToIntegerBy(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount,
});
const finalMakerBalanceA = await erc20TokenA.balanceOf.callAsync(makerAddress);
const finalMakerBalanceB = await erc20TokenB.balanceOf.callAsync(makerAddress);
const finalMakerZrxBalance = await zrxToken.balanceOf.callAsync(makerAddress);
const finalTakerBalanceA = await erc20TokenA.balanceOf.callAsync(takerAddress);
const finalTakerBalanceB = await erc20TokenB.balanceOf.callAsync(takerAddress);
const finalTakerZrxBalance = await zrxToken.balanceOf.callAsync(takerAddress);
expect(finalMakerBalanceA).to.be.bignumber.equal(
initialMakerBalanceA.plus(
takerAmounts[0].times(
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalMakerBalanceB).to.be.bignumber.equal(
initialMakerBalanceB.plus(
takerAmounts[1].times(
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalMakerZrxBalance).to.be.bignumber.equal(
initialMakerZrxBalance.minus(
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
);
expect(finalTakerBalanceA).to.be.bignumber.equal(
initialTakerBalanceA.minus(
takerAmounts[0].times(
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalTakerBalanceB).to.be.bignumber.equal(
initialTakerBalanceB.minus(
takerAmounts[1].times(
takerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
),
);
expect(finalTakerZrxBalance).to.be.bignumber.equal(
initialTakerZrxBalance.plus(
makerAssetAmount.times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount),
),
);
});
});
describe('getOrderInfo', () => { describe('getOrderInfo', () => {
beforeEach(async () => { beforeEach(async () => {
signedOrder = await orderFactory.newSignedOrderAsync(); signedOrder = await orderFactory.newSignedOrderAsync();

View File

@ -35,7 +35,7 @@ export const constants = {
DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(0), DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(0),
NULL_BYTES: '0x', NULL_BYTES: '0x',
NUM_DUMMY_ERC20_TO_DEPLOY: 3, NUM_DUMMY_ERC20_TO_DEPLOY: 3,
NUM_DUMMY_ERC721_TO_DEPLOY: 1, NUM_DUMMY_ERC721_TO_DEPLOY: 2,
NUM_ERC721_TOKENS_TO_MINT: 2, NUM_ERC721_TOKENS_TO_MINT: 2,
NULL_ADDRESS: '0x0000000000000000000000000000000000000000', NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),

View File

@ -29,7 +29,8 @@ export class ERC721Wrapper {
this._contractOwnerAddress = contractOwnerAddress; this._contractOwnerAddress = contractOwnerAddress;
} }
public async deployDummyTokensAsync(): Promise<DummyERC721TokenContract[]> { public async deployDummyTokensAsync(): Promise<DummyERC721TokenContract[]> {
for (let i = 0; i < constants.NUM_DUMMY_ERC721_TO_DEPLOY; i++) { // tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY)) {
this._dummyTokenContracts.push( this._dummyTokenContracts.push(
await DummyERC721TokenContract.deployFrom0xArtifactAsync( await DummyERC721TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC721Token, artifacts.DummyERC721Token,
@ -61,7 +62,8 @@ export class ERC721Wrapper {
this._initialTokenIdsByOwner = {}; this._initialTokenIdsByOwner = {};
for (const dummyTokenContract of this._dummyTokenContracts) { for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) { for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
for (let i = 0; i < constants.NUM_ERC721_TOKENS_TO_MINT; i++) { // tslint:disable-next-line:no-unused-variable
for (const i of _.times(constants.NUM_ERC721_TOKENS_TO_MINT)) {
const tokenId = generatePseudoRandomSalt(); const tokenId = generatePseudoRandomSalt();
await this.mintAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress); await this.mintAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress])) { if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress])) {

View File

@ -26,6 +26,7 @@
"./generated-artifacts/IWallet.json", "./generated-artifacts/IWallet.json",
"./generated-artifacts/InvalidERC721Receiver.json", "./generated-artifacts/InvalidERC721Receiver.json",
"./generated-artifacts/MixinAuthorizable.json", "./generated-artifacts/MixinAuthorizable.json",
"./generated-artifacts/MultiAssetProxy.json",
"./generated-artifacts/MultiSigWallet.json", "./generated-artifacts/MultiSigWallet.json",
"./generated-artifacts/MultiSigWalletWithTimeLock.json", "./generated-artifacts/MultiSigWalletWithTimeLock.json",
"./generated-artifacts/OrderValidator.json", "./generated-artifacts/OrderValidator.json",

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/dev-tools-pages", "name": "@0x/dev-tools-pages",
"version": "0.0.7", "version": "0.0.8",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -16,7 +16,7 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@0x/react-shared": "^1.0.22", "@0x/react-shared": "^1.0.23",
"basscss": "^8.0.3", "basscss": "^8.0.3",
"bowser": "^1.9.3", "bowser": "^1.9.3",
"less": "^2.7.2", "less": "^2.7.2",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.0.19",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "1.0.18", "version": "1.0.18",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.0.19 - _November 28, 2018_
* Dependencies updated
## v1.0.18 - _November 21, 2018_ ## v1.0.18 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -27,6 +27,21 @@ If your project is in [TypeScript](https://www.typescriptlang.org/), add the fol
} }
``` ```
## Troubleshooting
If you are still seeing TS type errors complaining about missing DOM types such as `Response`:
```
error TS2304: Cannot find name 'Response'.
```
Then you need to explicitly add the `dom` lib to your compiler options in `tsconfig.json`. The `dom` library is included by default, but customizing the `lib` option can cause it to be dropped.
```
"compilerOptions": {
"lib": [..., "dom"],
```
## Contributing ## Contributing
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository. We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/dev-utils", "name": "@0x/dev-utils",
"version": "1.0.18", "version": "1.0.19",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -41,11 +41,11 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/web3-provider-engine": "^14.0.0", "@types/web3-provider-engine": "^14.0.0",
"chai": "^4.0.1", "chai": "^4.0.1",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",

View File

@ -283,6 +283,11 @@ export interface RawLogEntry {
export enum SolidityTypes { export enum SolidityTypes {
Address = 'address', Address = 'address',
Bool = 'bool',
Bytes = 'bytes',
Int = 'int',
String = 'string',
Tuple = 'tuple',
Uint256 = 'uint256', Uint256 = 'uint256',
Uint8 = 'uint8', Uint8 = 'uint8',
Uint = 'uint', Uint = 'uint',

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.0.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "1.0.13", "version": "1.0.13",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.0.14 - _November 28, 2018_
* Dependencies updated
## v1.0.13 - _November 21, 2018_ ## v1.0.13 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/fill-scenarios", "name": "@0x/fill-scenarios",
"version": "1.0.13", "version": "1.0.14",
"description": "0x order fill scenario generator", "description": "0x order fill scenario generator",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
@ -28,14 +28,14 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/abi-gen-wrappers": "^1.1.0", "@0x/abi-gen-wrappers": "^2.0.0",
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/contract-artifacts": "^1.1.0", "@0x/contract-artifacts": "^1.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethers": "~4.0.4", "ethers": "~4.0.4",
"lodash": "^4.17.5" "lodash": "^4.17.5"

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/instant", "name": "@0x/instant",
"version": "1.0.1", "version": "1.0.2",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -46,14 +46,14 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": { "dependencies": {
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/asset-buyer": "^3.0.1", "@0x/asset-buyer": "^3.0.2",
"@0x/json-schemas": "^2.1.2", "@0x/json-schemas": "^2.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"bowser": "^1.9.4", "bowser": "^1.9.4",
"copy-to-clipboard": "^3.0.8", "copy-to-clipboard": "^3.0.8",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",

View File

@ -19,12 +19,12 @@ export interface ERC20TokenSelectorProps {
} }
export interface ERC20TokenSelectorState { export interface ERC20TokenSelectorState {
searchQuery?: string; searchQuery: string;
} }
export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps> { export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps> {
public state: ERC20TokenSelectorState = { public state: ERC20TokenSelectorState = {
searchQuery: undefined, searchQuery: '',
}; };
public render(): React.ReactNode { public render(): React.ReactNode {
const { tokens, onTokenSelect } = this.props; const { tokens, onTokenSelect } = this.props;
@ -62,10 +62,10 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
}; };
private readonly _isTokenQueryMatch = (token: ERC20Asset): boolean => { private readonly _isTokenQueryMatch = (token: ERC20Asset): boolean => {
const { searchQuery } = this.state; const { searchQuery } = this.state;
if (_.isUndefined(searchQuery)) { const searchQueryLowerCase = searchQuery.toLowerCase().trim();
if (searchQueryLowerCase === '') {
return true; return true;
} }
const searchQueryLowerCase = searchQuery.toLowerCase();
const tokenName = token.metaData.name.toLowerCase(); const tokenName = token.metaData.name.toLowerCase();
const tokenSymbol = token.metaData.symbol.toLowerCase(); const tokenSymbol = token.metaData.symbol.toLowerCase();
return _.startsWith(tokenSymbol, searchQueryLowerCase) || _.startsWith(tokenName, searchQueryLowerCase); return _.startsWith(tokenSymbol, searchQueryLowerCase) || _.startsWith(tokenName, searchQueryLowerCase);

View File

@ -8,7 +8,9 @@ import {
} from '../constants'; } from '../constants';
import { ColorOption } from '../style/theme'; import { ColorOption } from '../style/theme';
import { Browser } from '../types'; import { Browser } from '../types';
import { analytics } from '../util/analytics';
import { envUtil } from '../util/env'; import { envUtil } from '../util/env';
import { util } from '../util/util';
import { MetaMaskLogo } from './meta_mask_logo'; import { MetaMaskLogo } from './meta_mask_logo';
import { StandardPanelContent, StandardPanelContentProps } from './standard_panel_content'; import { StandardPanelContent, StandardPanelContentProps } from './standard_panel_content';
@ -45,6 +47,10 @@ export class InstallWalletPanelContent extends React.Component<InstallWalletPane
default: default:
break; break;
} }
const onActionClick = () => {
analytics.trackInstallWalletModalClickedGet();
util.createOpenUrlInNewWindow(actionUrl)();
};
return { return {
image: <MetaMaskLogo width={85} height={80} />, image: <MetaMaskLogo width={85} height={80} />,
title: 'Install MetaMask', title: 'Install MetaMask',
@ -52,10 +58,11 @@ export class InstallWalletPanelContent extends React.Component<InstallWalletPane
moreInfoSettings: { moreInfoSettings: {
href: META_MASK_SITE_URL, href: META_MASK_SITE_URL,
text: 'What is MetaMask?', text: 'What is MetaMask?',
onClick: analytics.trackInstallWalletModalClickedExplanation,
}, },
action: ( action: (
<Button <Button
href={actionUrl} onClick={onActionClick}
width="100%" width="100%"
fontColor={ColorOption.white} fontColor={ColorOption.white}
backgroundColor={ColorOption.darkOrange} backgroundColor={ColorOption.darkOrange}

View File

@ -98,6 +98,12 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
inputWidthPx: this._getInputWidthInPx(), inputWidthPx: this._getInputWidthInPx(),
}; };
} }
public componentDidMount(): void {
// Trigger an initial notification of the calculated fontSize.
const currentPhase = ScalingInput.getPhaseFromProps(this.props);
const currentFontSize = ScalingInput.calculateFontSizeFromProps(this.props, currentPhase);
this.props.onFontSizeChange(currentFontSize);
}
public componentDidUpdate( public componentDidUpdate(
prevProps: ScalingInputProps, prevProps: ScalingInputProps,
prevState: ScalingInputState, prevState: ScalingInputState,

View File

@ -1,6 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { ColorOption } from '../style/theme'; import { ColorOption } from '../style/theme';
import { util } from '../util/util';
import { Container } from './ui/container'; import { Container } from './ui/container';
import { Flex } from './ui/flex'; import { Flex } from './ui/flex';
@ -9,6 +10,7 @@ import { Text } from './ui/text';
export interface MoreInfoSettings { export interface MoreInfoSettings {
text: string; text: string;
href: string; href: string;
onClick?: () => void;
} }
export interface StandardPanelContentProps { export interface StandardPanelContentProps {
@ -21,6 +23,15 @@ export interface StandardPanelContentProps {
const SPACING_BETWEEN_PX = '20px'; const SPACING_BETWEEN_PX = '20px';
const onMoreInfoClick = (href: string, onClick?: () => void) => {
return () => {
if (onClick) {
onClick();
}
util.createOpenUrlInNewWindow(href)();
};
};
export const StandardPanelContent: React.StatelessComponent<StandardPanelContentProps> = ({ export const StandardPanelContent: React.StatelessComponent<StandardPanelContentProps> = ({
image, image,
title, title,
@ -50,7 +61,7 @@ export const StandardPanelContent: React.StatelessComponent<StandardPanelContent
fontSize="13px" fontSize="13px"
textDecorationLine="underline" textDecorationLine="underline"
fontColor={ColorOption.lightGrey} fontColor={ColorOption.lightGrey}
href={moreInfoSettings.href} onClick={onMoreInfoClick(moreInfoSettings.href, moreInfoSettings.onClick)}
> >
{moreInfoSettings.text} {moreInfoSettings.text}
</Text> </Text>

View File

@ -1,8 +1,9 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import { transparentize } from 'polished';
import * as React from 'react'; import * as React from 'react';
import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_WIDTH } from '../constants'; import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_WIDTH } from '../constants';
import { ColorOption, css, keyframes, styled } from '../style/theme'; import { ColorOption, css, keyframes, styled, ThemeConsumer } from '../style/theme';
import { Container } from './ui/container'; import { Container } from './ui/container';
@ -93,8 +94,16 @@ export interface ProgressBarProps extends ProgressProps {}
export const ProgressBar: React.ComponentType<ProgressBarProps & React.ClassAttributes<{}>> = React.forwardRef( export const ProgressBar: React.ComponentType<ProgressBarProps & React.ClassAttributes<{}>> = React.forwardRef(
(props, ref) => ( (props, ref) => (
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px"> <ThemeConsumer>
<Progress {...props} ref={ref as any} /> {theme => (
</Container> <Container
width="100%"
borderRadius="6px"
rawBackgroundColor={transparentize(0.5, theme[ColorOption.primaryColor])}
>
<Progress {...props} ref={ref as any} />
</Container>
)}
</ThemeConsumer>
), ),
); );

View File

@ -27,6 +27,7 @@ export interface ContainerProps {
borderBottom?: string; borderBottom?: string;
className?: string; className?: string;
backgroundColor?: ColorOption; backgroundColor?: ColorOption;
rawBackgroundColor?: string;
hasBoxShadow?: boolean; hasBoxShadow?: boolean;
zIndex?: number; zIndex?: number;
whiteSpace?: string; whiteSpace?: string;
@ -38,6 +39,16 @@ export interface ContainerProps {
flexGrow?: string | number; flexGrow?: string | number;
} }
const getBackgroundColor = (theme: any, backgroundColor?: ColorOption, rawBackgroundColor?: string): string => {
if (backgroundColor) {
return theme[backgroundColor] as string;
}
if (rawBackgroundColor) {
return rawBackgroundColor;
}
return 'none';
};
export const Container = export const Container =
styled.div < styled.div <
ContainerProps > ContainerProps >
@ -70,7 +81,7 @@ export const Container =
${props => props.width && stylesForMedia<string>('width', props.width)} ${props => props.width && stylesForMedia<string>('width', props.width)}
${props => props.height && stylesForMedia<string>('height', props.height)} ${props => props.height && stylesForMedia<string>('height', props.height)}
${props => props.borderRadius && stylesForMedia<string>('border-radius', props.borderRadius)} ${props => props.borderRadius && stylesForMedia<string>('border-radius', props.borderRadius)}
background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')}; background-color: ${props => getBackgroundColor(props.theme, props.backgroundColor, props.rawBackgroundColor)};
border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')}; border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
&:hover { &:hover {
${props => ${props =>

View File

@ -1,4 +1,3 @@
import { darken } from 'polished';
import * as React from 'react'; import * as React from 'react';
import { ColorOption, styled } from '../../style/theme'; import { ColorOption, styled } from '../../style/theme';
@ -31,7 +30,7 @@ export const Text: React.StatelessComponent<TextProps> = ({ href, onClick, ...re
return <StyledText {...rest} onClick={computedOnClick} />; return <StyledText {...rest} onClick={computedOnClick} />;
}; };
const darkenOnHoverAmount = 0.3; const opacityOnHoverAmount = 0.5;
export const StyledText = export const StyledText =
styled.div < styled.div <
TextProps > TextProps >
@ -56,8 +55,7 @@ export const StyledText =
${props => (props.textAlign ? `text-align: ${props.textAlign}` : '')}; ${props => (props.textAlign ? `text-align: ${props.textAlign}` : '')};
${props => (props.width ? `width: ${props.width}` : '')}; ${props => (props.width ? `width: ${props.width}` : '')};
&:hover { &:hover {
${props => ${props => (props.onClick ? `opacity: ${opacityOnHoverAmount};` : '')};
props.onClick ? `color: ${darken(darkenOnHoverAmount, props.theme[props.fontColor || 'white'])}` : ''};
} }
} }
`; `;

View File

@ -11,7 +11,7 @@ import { asyncData } from '../redux/async_data';
import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer'; import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer';
import { store, Store } from '../redux/store'; import { store, Store } from '../redux/store';
import { fonts } from '../style/fonts'; import { fonts } from '../style/fonts';
import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types'; import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource, QuoteFetchOrigin } from '../types';
import { analytics, disableAnalytics } from '../util/analytics'; import { analytics, disableAnalytics } from '../util/analytics';
import { assetUtils } from '../util/asset'; import { assetUtils } from '../util/asset';
import { errorFlasher } from '../util/error_flasher'; import { errorFlasher } from '../util/error_flasher';
@ -115,7 +115,9 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS); this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS);
// Trigger first buyquote fetch // Trigger first buyquote fetch
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, { updateSilently: false }); asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, QuoteFetchOrigin.Manual, {
updateSilently: false,
});
// warm up the gas price estimator cache just in case we can't // warm up the gas price estimator cache just in case we can't
// grab the gas price estimate when submitting the transaction // grab the gas price estimate when submitting the transaction
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises

View File

@ -11,7 +11,7 @@ import {
import { Action, actions } from '../redux/actions'; import { Action, actions } from '../redux/actions';
import { asyncData } from '../redux/async_data'; import { asyncData } from '../redux/async_data';
import { State } from '../redux/reducer'; import { State } from '../redux/reducer';
import { Network, Omit, OperatingSystem, ProviderState, StandardSlidingPanelContent } from '../types'; import { Network, Omit, OperatingSystem, ProviderState, StandardSlidingPanelContent, WalletSuggestion } from '../types';
import { analytics } from '../util/analytics'; import { analytics } from '../util/analytics';
import { envUtil } from '../util/env'; import { envUtil } from '../util/env';
@ -60,23 +60,28 @@ const mergeProps = (
onUnlockWalletClick: () => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState), onUnlockWalletClick: () => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState),
onInstallWalletClick: () => { onInstallWalletClick: () => {
const isMobile = envUtil.isMobileOperatingSystem(); const isMobile = envUtil.isMobileOperatingSystem();
if (!isMobile) { const walletSuggestion: WalletSuggestion = isMobile
? WalletSuggestion.CoinbaseWallet
: WalletSuggestion.MetaMask;
analytics.trackInstallWalletClicked(walletSuggestion);
if (walletSuggestion === WalletSuggestion.MetaMask) {
connectedDispatch.openInstallWalletPanel(); connectedDispatch.openInstallWalletPanel();
return; } else {
const operatingSystem = envUtil.getOperatingSystem();
let url = COINBASE_WALLET_SITE_URL;
switch (operatingSystem) {
case OperatingSystem.Android:
url = COINBASE_WALLET_ANDROID_APP_STORE_URL;
break;
case OperatingSystem.iOS:
url = COINBASE_WALLET_IOS_APP_STORE_URL;
break;
default:
break;
}
window.open(url, '_blank');
} }
const operatingSystem = envUtil.getOperatingSystem();
let url = COINBASE_WALLET_SITE_URL;
switch (operatingSystem) {
case OperatingSystem.Android:
url = COINBASE_WALLET_ANDROID_APP_STORE_URL;
break;
case OperatingSystem.iOS:
url = COINBASE_WALLET_IOS_APP_STORE_URL;
break;
default:
break;
}
window.open(url, '_blank');
}, },
}); });

View File

@ -10,7 +10,7 @@ import { ERC20AssetAmountInput, ERC20AssetAmountInputProps } from '../components
import { Action, actions } from '../redux/actions'; import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer'; import { State } from '../redux/reducer';
import { ColorOption } from '../style/theme'; import { ColorOption } from '../style/theme';
import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState } from '../types'; import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState, QuoteFetchOrigin } from '../types';
import { buyQuoteUpdater } from '../util/buy_quote_updater'; import { buyQuoteUpdater } from '../util/buy_quote_updater';
export interface SelectedERC20AssetAmountInputProps { export interface SelectedERC20AssetAmountInputProps {
@ -88,7 +88,7 @@ const mapDispatchToProps = (
// even if it's debounced, give them the illusion it's loading // even if it's debounced, give them the illusion it's loading
dispatch(actions.setQuoteRequestStatePending()); dispatch(actions.setQuoteRequestStatePending());
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, { debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, QuoteFetchOrigin.Manual, {
setPending: true, setPending: true,
dispatchErrors: true, dispatchErrors: true,
affiliateInfo, affiliateInfo,

View File

@ -3,7 +3,7 @@ import * as _ from 'lodash';
import { Middleware } from 'redux'; import { Middleware } from 'redux';
import { ETH_DECIMALS } from '../constants'; import { ETH_DECIMALS } from '../constants';
import { Account, AccountState } from '../types'; import { Account, AccountState, StandardSlidingPanelContent } from '../types';
import { analytics } from '../util/analytics'; import { analytics } from '../util/analytics';
import { Action, ActionTypes } from './actions'; import { Action, ActionTypes } from './actions';
@ -77,6 +77,18 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction
}); });
} }
break; break;
case ActionTypes.OPEN_STANDARD_SLIDING_PANEL:
const openSlidingContent = curState.standardSlidingPanelSettings.content;
if (openSlidingContent === StandardSlidingPanelContent.InstallWallet) {
analytics.trackInstallWalletModalOpened();
}
break;
case ActionTypes.CLOSE_STANDARD_SLIDING_PANEL:
const closeSlidingContent = curState.standardSlidingPanelSettings.content;
if (closeSlidingContent === StandardSlidingPanelContent.InstallWallet) {
analytics.trackInstallWalletModalClosed();
}
break;
} }
return nextAction; return nextAction;

View File

@ -4,7 +4,7 @@ import * as _ from 'lodash';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import { BIG_NUMBER_ZERO } from '../constants'; import { BIG_NUMBER_ZERO } from '../constants';
import { AccountState, ERC20Asset, OrderProcessState, ProviderState } from '../types'; import { AccountState, ERC20Asset, OrderProcessState, ProviderState, QuoteFetchOrigin } from '../types';
import { analytics } from '../util/analytics'; import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset'; import { assetUtils } from '../util/asset';
import { buyQuoteUpdater } from '../util/buy_quote_updater'; import { buyQuoteUpdater } from '../util/buy_quote_updater';
@ -84,6 +84,7 @@ export const asyncData = {
fetchCurrentBuyQuoteAndDispatchToStore: async ( fetchCurrentBuyQuoteAndDispatchToStore: async (
state: State, state: State,
dispatch: Dispatch, dispatch: Dispatch,
fetchOrigin: QuoteFetchOrigin,
options: { updateSilently: boolean }, options: { updateSilently: boolean },
) => { ) => {
const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state; const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state;
@ -99,7 +100,12 @@ export const asyncData = {
dispatch, dispatch,
selectedAsset as ERC20Asset, selectedAsset as ERC20Asset,
selectedAssetUnitAmount, selectedAssetUnitAmount,
{ setPending: !options.updateSilently, dispatchErrors: !options.updateSilently, affiliateInfo }, fetchOrigin,
{
setPending: !options.updateSilently,
dispatchErrors: !options.updateSilently,
affiliateInfo,
},
); );
} }
}, },

View File

@ -1,6 +1,14 @@
import * as styledComponents from 'styled-components'; import * as styledComponents from 'styled-components';
const { default: styled, css, keyframes, withTheme, createGlobalStyle, ThemeProvider } = styledComponents; const {
default: styled,
css,
keyframes,
withTheme,
createGlobalStyle,
ThemeConsumer,
ThemeProvider,
} = styledComponents;
export type Theme = { [key in ColorOption]: string }; export type Theme = { [key in ColorOption]: string };
@ -45,4 +53,4 @@ export const generateOverlayBlack = (opacity = 0.6) => {
return `rgba(0, 0, 0, ${opacity})`; return `rgba(0, 0, 0, ${opacity})`;
}; };
export { styled, css, keyframes, withTheme, createGlobalStyle, ThemeProvider }; export { styled, css, keyframes, withTheme, createGlobalStyle, ThemeConsumer, ThemeProvider };

View File

@ -21,6 +21,11 @@ export enum OrderProcessState {
Failure = 'FAILURE', Failure = 'FAILURE',
} }
export enum QuoteFetchOrigin {
Manual = 'Manual',
Heartbeat = 'Heartbeat',
}
export interface SimulatedProgress { export interface SimulatedProgress {
startTimeUnix: number; startTimeUnix: number;
expectedEndTimeUnix: number; expectedEndTimeUnix: number;
@ -149,6 +154,11 @@ export enum Browser {
Other = 'OTHER', Other = 'OTHER',
} }
export enum WalletSuggestion {
CoinbaseWallet = 'Coinbase Wallet',
MetaMask = 'MetaMask',
}
export enum OperatingSystem { export enum OperatingSystem {
Android = 'ANDROID', Android = 'ANDROID',
iOS = 'IOS', iOS = 'IOS',

View File

@ -1,7 +1,16 @@
import { BuyQuote } from '@0x/asset-buyer'; import { BuyQuote } from '@0x/asset-buyer';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { AffiliateInfo, Asset, Network, OrderProcessState, OrderSource, ProviderState } from '../types'; import {
AffiliateInfo,
Asset,
Network,
OrderSource,
ProviderState,
QuoteFetchOrigin,
WalletSuggestion,
} from '../types';
import { EventProperties, heapUtil } from './heap'; import { EventProperties, heapUtil } from './heap';
@ -34,11 +43,18 @@ enum EventNames {
BUY_TX_SUBMITTED = 'Buy - Tx Submitted', BUY_TX_SUBMITTED = 'Buy - Tx Submitted',
BUY_TX_SUCCEEDED = 'Buy - Tx Succeeded', BUY_TX_SUCCEEDED = 'Buy - Tx Succeeded',
BUY_TX_FAILED = 'Buy - Tx Failed', BUY_TX_FAILED = 'Buy - Tx Failed',
INSTALL_WALLET_CLICKED = 'Install Wallet - Clicked',
INSTALL_WALLET_MODAL_OPENED = 'Install Wallet - Modal - Opened',
INSTALL_WALLET_MODAL_CLICKED_EXPLANATION = 'Install Wallet - Modal - Clicked Explanation',
INSTALL_WALLET_MODAL_CLICKED_GET = 'Install Wallet - Modal - Clicked Get',
INSTALL_WALLET_MODAL_CLOSED = 'Install Wallet - Modal - Closed',
TOKEN_SELECTOR_OPENED = 'Token Selector - Opened', TOKEN_SELECTOR_OPENED = 'Token Selector - Opened',
TOKEN_SELECTOR_CLOSED = 'Token Selector - Closed', TOKEN_SELECTOR_CLOSED = 'Token Selector - Closed',
TOKEN_SELECTOR_CHOSE = 'Token Selector - Chose', TOKEN_SELECTOR_CHOSE = 'Token Selector - Chose',
TOKEN_SELECTOR_SEARCHED = 'Token Selector - Searched', TOKEN_SELECTOR_SEARCHED = 'Token Selector - Searched',
TRANSACTION_VIEWED = 'Transaction - Viewed', TRANSACTION_VIEWED = 'Transaction - Viewed',
QUOTE_FETCHED = 'Quote - Fetched',
QUOTE_ERROR = 'Quote - Error',
} }
const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => { const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => {
@ -173,6 +189,14 @@ export const analytics = {
expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix,
actualTxTimeMs: new Date().getTime() - startTimeUnix, actualTxTimeMs: new Date().getTime() - startTimeUnix,
}), }),
trackInstallWalletClicked: (walletSuggestion: WalletSuggestion) =>
trackingEventFnWithPayload(EventNames.INSTALL_WALLET_CLICKED)({ walletSuggestion }),
trackInstallWalletModalClickedExplanation: trackingEventFnWithoutPayload(
EventNames.INSTALL_WALLET_MODAL_CLICKED_EXPLANATION,
),
trackInstallWalletModalClickedGet: trackingEventFnWithoutPayload(EventNames.INSTALL_WALLET_MODAL_CLICKED_GET),
trackInstallWalletModalOpened: trackingEventFnWithoutPayload(EventNames.INSTALL_WALLET_MODAL_OPENED),
trackInstallWalletModalClosed: trackingEventFnWithoutPayload(EventNames.INSTALL_WALLET_MODAL_CLOSED),
trackTokenSelectorOpened: trackingEventFnWithoutPayload(EventNames.TOKEN_SELECTOR_OPENED), trackTokenSelectorOpened: trackingEventFnWithoutPayload(EventNames.TOKEN_SELECTOR_OPENED),
trackTokenSelectorClosed: (closedVia: TokenSelectorClosedVia) => trackTokenSelectorClosed: (closedVia: TokenSelectorClosedVia) =>
trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CLOSED)({ closedVia }), trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CLOSED)({ closedVia }),
@ -182,4 +206,16 @@ export const analytics = {
trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_SEARCHED)({ searchText }), trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_SEARCHED)({ searchText }),
trackTransactionViewed: (orderProcesState: OrderProcessState) => trackTransactionViewed: (orderProcesState: OrderProcessState) =>
trackingEventFnWithPayload(EventNames.TRANSACTION_VIEWED)({ orderState: orderProcesState }), trackingEventFnWithPayload(EventNames.TRANSACTION_VIEWED)({ orderState: orderProcesState }),
trackQuoteFetched: (buyQuote: BuyQuote, fetchOrigin: QuoteFetchOrigin) =>
trackingEventFnWithPayload(EventNames.QUOTE_FETCHED)({
...buyQuoteEventProperties(buyQuote),
fetchOrigin,
}),
trackQuoteError: (errorMessage: string, assetBuyAmount: BigNumber, fetchOrigin: QuoteFetchOrigin) => {
trackingEventFnWithPayload(EventNames.QUOTE_ERROR)({
errorMessage,
assetBuyAmount: assetBuyAmount.toString(),
fetchOrigin,
});
},
}; };

View File

@ -6,7 +6,8 @@ import { Dispatch } from 'redux';
import { oc } from 'ts-optchain'; import { oc } from 'ts-optchain';
import { Action, actions } from '../redux/actions'; import { Action, actions } from '../redux/actions';
import { AffiliateInfo, ERC20Asset } from '../types'; import { AffiliateInfo, ERC20Asset, QuoteFetchOrigin } from '../types';
import { analytics } from '../util/analytics';
import { assetUtils } from '../util/asset'; import { assetUtils } from '../util/asset';
import { errorFlasher } from '../util/error_flasher'; import { errorFlasher } from '../util/error_flasher';
@ -16,7 +17,12 @@ export const buyQuoteUpdater = {
dispatch: Dispatch<Action>, dispatch: Dispatch<Action>,
asset: ERC20Asset, asset: ERC20Asset,
assetUnitAmount: BigNumber, assetUnitAmount: BigNumber,
options: { setPending: boolean; dispatchErrors: boolean; affiliateInfo?: AffiliateInfo }, fetchOrigin: QuoteFetchOrigin,
options: {
setPending: boolean;
dispatchErrors: boolean;
affiliateInfo?: AffiliateInfo;
},
): Promise<void> => { ): Promise<void> => {
// get a new buy quote. // get a new buy quote.
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals); const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals);
@ -31,6 +37,7 @@ export const buyQuoteUpdater = {
} catch (error) { } catch (error) {
if (options.dispatchErrors) { if (options.dispatchErrors) {
dispatch(actions.setQuoteRequestStateFailure()); dispatch(actions.setQuoteRequestStateFailure());
analytics.trackQuoteError(error.message ? error.message : 'other', baseUnitValue, fetchOrigin);
let errorMessage; let errorMessage;
if (error.message === AssetBuyerError.InsufficientAssetLiquidity) { if (error.message === AssetBuyerError.InsufficientAssetLiquidity) {
const assetName = assetUtils.bestNameForAsset(asset, 'of this asset'); const assetName = assetUtils.bestNameForAsset(asset, 'of this asset');
@ -58,5 +65,6 @@ export const buyQuoteUpdater = {
errorFlasher.clearError(dispatch); errorFlasher.clearError(dispatch);
// invalidate the last buy quote. // invalidate the last buy quote.
dispatch(actions.updateLatestBuyQuote(newBuyQuote)); dispatch(actions.updateLatestBuyQuote(newBuyQuote));
analytics.trackQuoteFetched(newBuyQuote, fetchOrigin);
}, },
}; };

View File

@ -1,5 +1,6 @@
import { asyncData } from '../redux/async_data'; import { asyncData } from '../redux/async_data';
import { Store } from '../redux/store'; import { Store } from '../redux/store';
import { QuoteFetchOrigin } from '../types';
import { Heartbeater } from './heartbeater'; import { Heartbeater } from './heartbeater';
@ -17,8 +18,13 @@ export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): He
export const generateBuyQuoteHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => { export const generateBuyQuoteHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => {
const { store, shouldPerformImmediatelyOnStart } = options; const { store, shouldPerformImmediatelyOnStart } = options;
return new Heartbeater(async () => { return new Heartbeater(async () => {
await asyncData.fetchCurrentBuyQuoteAndDispatchToStore(store.getState(), store.dispatch, { await asyncData.fetchCurrentBuyQuoteAndDispatchToStore(
updateSilently: true, store.getState(),
}); store.dispatch,
QuoteFetchOrigin.Heartbeat,
{
updateSilently: true,
},
);
}, shouldPerformImmediatelyOnStart); }, shouldPerformImmediatelyOnStart);
}; };

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/metacoin", "name": "@0x/metacoin",
"version": "0.0.29", "version": "0.0.30",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -30,15 +30,15 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@0x/abi-gen": "^1.0.17", "@0x/abi-gen": "^1.0.17",
"@0x/abi-gen-templates": "^1.0.0", "@0x/abi-gen-templates": "^1.0.1",
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/sol-cov": "^2.1.13", "@0x/sol-cov": "^2.1.14",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/mocha": "^5.2.2", "@types/mocha": "^5.2.2",
"copyfiles": "^2.0.0", "copyfiles": "^2.0.0",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
@ -47,8 +47,8 @@
"run-s": "^0.0.0" "run-s": "^0.0.0"
}, },
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/sol-compiler": "^1.1.13", "@0x/sol-compiler": "^1.1.14",
"chai": "^4.0.1", "chai": "^4.0.1",
"chai-as-promised": "^7.1.0", "chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1", "chai-bignumber": "^2.0.1",

View File

@ -14,7 +14,8 @@
"note": "Fund the Forwarder with ZRX for fees.", "note": "Fund the Forwarder with ZRX for fees.",
"pr": 1309 "pr": 1309
} }
] ],
"timestamp": 1543401373
}, },
{ {
"version": "2.1.0", "version": "2.1.0",

View File

@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.2.0 - _November 28, 2018_
* Add CLI `0x-migrate` for running the 0x migrations in a language-agnostic way (#1324)
* Deploy testnet Exchange arfitact. Previously mainnet Exchange artifact was deployed. (#1309)
* Fund the Forwarder with ZRX for fees. (#1309)
## v2.1.0 - _November 21, 2018_ ## v2.1.0 - _November 21, 2018_
* Export all type declarations used by the public interface, as well as the `ContractAddresses` mapping (#1301) * Export all type declarations used by the public interface, as well as the `ContractAddresses` mapping (#1301)

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/migrations", "name": "@0x/migrations",
"version": "2.1.0", "version": "2.2.0",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -26,7 +26,7 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@types/yargs": "^10.0.0", "@types/yargs": "^10.0.0",
@ -39,16 +39,16 @@
"yargs": "^10.0.3" "yargs": "^10.0.3"
}, },
"dependencies": { "dependencies": {
"@0x/abi-gen-wrappers": "^1.1.0", "@0x/abi-gen-wrappers": "^2.0.0",
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/contract-addresses": "^1.2.0", "@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.0", "@0x/contract-artifacts": "^1.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/sol-compiler": "^1.1.13", "@0x/sol-compiler": "^1.1.14",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@ledgerhq/hw-app-eth": "^4.3.0", "@ledgerhq/hw-app-eth": "^4.3.0",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethers": "~4.0.4", "ethers": "~4.0.4",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "3.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "3.0.3", "version": "3.0.3",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v3.0.4 - _November 28, 2018_
* Dependencies updated
## v3.0.3 - _November 21, 2018_ ## v3.0.3 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/order-utils", "name": "@0x/order-utils",
"version": "3.0.3", "version": "3.0.4",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -35,7 +35,7 @@
}, },
"homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md",
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/bn.js": "^4.11.0", "@types/bn.js": "^4.11.0",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
@ -53,15 +53,15 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/abi-gen-wrappers": "^1.1.0", "@0x/abi-gen-wrappers": "^2.0.0",
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/contract-artifacts": "^1.1.0", "@0x/contract-artifacts": "^1.1.2",
"@0x/json-schemas": "^2.1.2", "@0x/json-schemas": "^2.1.2",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/node": "*", "@types/node": "*",
"bn.js": "^4.11.8", "bn.js": "^4.11.8",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "2.2.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "2.2.5", "version": "2.2.5",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.2.6 - _November 28, 2018_
* Dependencies updated
## v2.2.5 - _November 21, 2018_ ## v2.2.5 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/order-watcher", "name": "@0x/order-watcher",
"version": "2.2.5", "version": "2.2.6",
"description": "An order watcher daemon that watches for order validity", "description": "An order watcher daemon that watches for order validity",
"keywords": [ "keywords": [
"0x", "0x",
@ -33,8 +33,8 @@
"node": ">=6.0.0" "node": ">=6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/migrations": "^2.1.0", "@0x/migrations": "^2.2.0",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/bintrees": "^1.0.2", "@types/bintrees": "^1.0.2",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
@ -57,19 +57,19 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/abi-gen-wrappers": "^1.1.0", "@0x/abi-gen-wrappers": "^2.0.0",
"@0x/assert": "^1.0.18", "@0x/assert": "^1.0.18",
"@0x/base-contract": "^3.0.7", "@0x/base-contract": "^3.0.8",
"@0x/contract-addresses": "^1.2.0", "@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.0", "@0x/contract-artifacts": "^1.1.2",
"@0x/contract-wrappers": "^4.1.0", "@0x/contract-wrappers": "^4.1.1",
"@0x/fill-scenarios": "^1.0.13", "@0x/fill-scenarios": "^1.0.14",
"@0x/json-schemas": "^2.1.2", "@0x/json-schemas": "^2.1.2",
"@0x/order-utils": "^3.0.3", "@0x/order-utils": "^3.0.4",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"bintrees": "^1.0.2", "bintrees": "^1.0.2",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethereumjs-blockstream": "6.0.0", "ethereumjs-blockstream": "6.0.0",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.0.20",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "1.0.19", "version": "1.0.19",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.0.20 - _November 28, 2018_
* Dependencies updated
## v1.0.19 - _November 21, 2018_ ## v1.0.19 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/react-docs", "name": "@0x/react-docs",
"version": "1.0.19", "version": "1.0.20",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -24,7 +24,7 @@
"url": "https://github.com/0xProject/0x-monorepo.git" "url": "https://github.com/0xProject/0x-monorepo.git"
}, },
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/compare-versions": "^3.0.0", "@types/compare-versions": "^3.0.0",
"@types/styled-components": "^4.0.0", "@types/styled-components": "^4.0.0",
@ -34,7 +34,7 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/react-shared": "^1.0.22", "@0x/react-shared": "^1.0.23",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.0.23",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "1.0.22", "version": "1.0.22",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.0.23 - _November 28, 2018_
* Dependencies updated
## v1.0.22 - _November 21, 2018_ ## v1.0.22 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/react-shared", "name": "@0x/react-shared",
"version": "1.0.22", "version": "1.0.23",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -25,7 +25,7 @@
"url": "https://github.com/0xProject/0x-monorepo.git" "url": "https://github.com/0xProject/0x-monorepo.git"
}, },
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"make-promises-safe": "^1.1.0", "make-promises-safe": "^1.1.0",
"shx": "^0.2.2", "shx": "^0.2.2",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.1.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "1.1.13", "version": "1.1.13",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.1.14 - _November 28, 2018_
* Dependencies updated
## v1.1.13 - _November 21, 2018_ ## v1.1.13 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/sol-compiler", "name": "@0x/sol-compiler",
"version": "1.1.13", "version": "1.1.14",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -42,7 +42,7 @@
}, },
"homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-compiler/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/packages/sol-compiler/README.md",
"devDependencies": { "devDependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/tslint-config": "^1.0.10", "@0x/tslint-config": "^1.0.10",
"@types/mkdirp": "^0.5.2", "@types/mkdirp": "^0.5.2",
"@types/require-from-string": "^1.2.0", "@types/require-from-string": "^1.2.0",
@ -71,7 +71,7 @@
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/yargs": "^11.0.0", "@types/yargs": "^11.0.0",
"chalk": "^2.3.0", "chalk": "^2.3.0",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "2.1.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "2.1.13", "version": "2.1.13",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.1.14 - _November 28, 2018_
* Dependencies updated
## v2.1.13 - _November 21, 2018_ ## v2.1.13 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/sol-cov", "name": "@0x/sol-cov",
"version": "2.1.13", "version": "2.1.14",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -42,12 +42,12 @@
}, },
"homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md", "homepage": "https://github.com/0xProject/0x.js/packages/sol-cov/README.md",
"dependencies": { "dependencies": {
"@0x/dev-utils": "^1.0.18", "@0x/dev-utils": "^1.0.19",
"@0x/sol-compiler": "^1.1.13", "@0x/sol-compiler": "^1.1.14",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@types/solidity-parser-antlr": "^0.2.0", "@types/solidity-parser-antlr": "^0.2.0",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethereumjs-util": "^5.1.1", "ethereumjs-util": "^5.1.1",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "1.0.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "1.0.8", "version": "1.0.8",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.0.9 - _November 28, 2018_
* Dependencies updated
## v1.0.8 - _November 21, 2018_ ## v1.0.8 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/sol-doc", "name": "@0x/sol-doc",
"version": "1.0.8", "version": "1.0.9",
"description": "Solidity documentation generator", "description": "Solidity documentation generator",
"main": "lib/src/index.js", "main": "lib/src/index.js",
"types": "lib/src/index.d.js", "types": "lib/src/index.d.js",
@ -25,7 +25,7 @@
"author": "F. Eugene Aumson", "author": "F. Eugene Aumson",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@0x/sol-compiler": "^1.1.13", "@0x/sol-compiler": "^1.1.14",
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",

View File

@ -1,4 +1,13 @@
[ [
{
"timestamp": 1543401373,
"version": "2.1.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "2.1.5", "version": "2.1.5",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v2.1.6 - _November 28, 2018_
* Dependencies updated
## v2.1.5 - _November 21, 2018_ ## v2.1.5 - _November 21, 2018_
* Dependencies updated * Dependencies updated

View File

@ -1,6 +1,6 @@
{ {
"name": "@0x/subproviders", "name": "@0x/subproviders",
"version": "2.1.5", "version": "2.1.6",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -33,7 +33,7 @@
"@0x/types": "^1.3.0", "@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"@ledgerhq/hw-app-eth": "^4.3.0", "@ledgerhq/hw-app-eth": "^4.3.0",
"@ledgerhq/hw-transport-u2f": "4.24.0", "@ledgerhq/hw-transport-u2f": "4.24.0",
"@types/eth-lightwallet": "^3.0.0", "@types/eth-lightwallet": "^3.0.0",

View File

@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "@0x/testnet-faucets", "name": "@0x/testnet-faucets",
"version": "1.0.57", "version": "1.0.58",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@ -18,11 +18,11 @@
"author": "Fabio Berger", "author": "Fabio Berger",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"0x.js": "^2.0.5", "0x.js": "^2.0.6",
"@0x/subproviders": "^2.1.5", "@0x/subproviders": "^2.1.6",
"@0x/typescript-typings": "^3.0.4", "@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6", "@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5", "@0x/web3-wrapper": "^3.1.6",
"body-parser": "^1.17.1", "body-parser": "^1.17.1",
"ethereum-types": "^1.1.2", "ethereum-types": "^1.1.2",
"ethereumjs-tx": "^1.3.5", "ethereumjs-tx": "^1.3.5",

View File

@ -1,4 +1,13 @@
[ [
{
"version": "1.4.0",
"changes": [
{
"note": "Add `LengthMismatch` and `LengthGreaterThan3Required` revert reasons",
"pr": 1224
}
]
},
{ {
"version": "1.3.0", "version": "1.3.0",
"changes": [ "changes": [

View File

@ -195,6 +195,7 @@ export enum RevertReason {
FailedExecution = 'FAILED_EXECUTION', FailedExecution = 'FAILED_EXECUTION',
AssetProxyAlreadyExists = 'ASSET_PROXY_ALREADY_EXISTS', AssetProxyAlreadyExists = 'ASSET_PROXY_ALREADY_EXISTS',
LengthGreaterThan0Required = 'LENGTH_GREATER_THAN_0_REQUIRED', LengthGreaterThan0Required = 'LENGTH_GREATER_THAN_0_REQUIRED',
LengthGreaterThan3Required = 'LENGTH_GREATER_THAN_3_REQUIRED',
LengthGreaterThan131Required = 'LENGTH_GREATER_THAN_131_REQUIRED', LengthGreaterThan131Required = 'LENGTH_GREATER_THAN_131_REQUIRED',
Length0Required = 'LENGTH_0_REQUIRED', Length0Required = 'LENGTH_0_REQUIRED',
Length65Required = 'LENGTH_65_REQUIRED', Length65Required = 'LENGTH_65_REQUIRED',
@ -209,6 +210,7 @@ export enum RevertReason {
MakerNotWhitelisted = 'MAKER_NOT_WHITELISTED', MakerNotWhitelisted = 'MAKER_NOT_WHITELISTED',
TakerNotWhitelisted = 'TAKER_NOT_WHITELISTED', TakerNotWhitelisted = 'TAKER_NOT_WHITELISTED',
AssetProxyDoesNotExist = 'ASSET_PROXY_DOES_NOT_EXIST', AssetProxyDoesNotExist = 'ASSET_PROXY_DOES_NOT_EXIST',
LengthMismatch = 'LENGTH_MISMATCH',
LibBytesGreaterThanZeroLengthRequired = 'GREATER_THAN_ZERO_LENGTH_REQUIRED', LibBytesGreaterThanZeroLengthRequired = 'GREATER_THAN_ZERO_LENGTH_REQUIRED',
LibBytesGreaterOrEqualTo4LengthRequired = 'GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED', LibBytesGreaterOrEqualTo4LengthRequired = 'GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED',
LibBytesGreaterOrEqualTo20LengthRequired = 'GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED', LibBytesGreaterOrEqualTo20LengthRequired = 'GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED',

View File

@ -1,4 +1,14 @@
[ [
{
"timestamp": 1543448882,
"version": "2.0.7",
"changes": [
{
"note":
"Optimized ABI Encoder/Decoder. Generates compressed calldata to save gas. Generates human-readable calldata to aid development."
}
]
},
{ {
"timestamp": 1542821676, "timestamp": 1542821676,
"version": "2.0.6", "version": "2.0.6",

View File

@ -33,6 +33,9 @@
"@types/lodash": "4.14.104", "@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42", "@types/mocha": "^2.2.42",
"chai": "^4.0.1", "chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0", "make-promises-safe": "^1.1.0",
"mocha": "^4.1.0", "mocha": "^4.1.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
@ -57,4 +60,4 @@
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }
} }

View File

@ -0,0 +1,58 @@
import { DataItem } from 'ethereum-types';
import * as _ from 'lodash';
import { Calldata } from '../calldata/calldata';
import { CalldataBlock } from '../calldata/calldata_block';
import { RawCalldata } from '../calldata/raw_calldata';
import { constants } from '../utils/constants';
import { DecodingRules, EncodingRules } from '../utils/rules';
import { DataTypeFactory } from './interfaces';
export abstract class DataType {
private readonly _dataItem: DataItem;
private readonly _factory: DataTypeFactory;
constructor(dataItem: DataItem, factory: DataTypeFactory) {
this._dataItem = dataItem;
this._factory = factory;
}
public getDataItem(): DataItem {
return this._dataItem;
}
public getFactory(): DataTypeFactory {
return this._factory;
}
public encode(value: any, rules?: EncodingRules, selector?: string): string {
const rules_ = _.isUndefined(rules) ? constants.DEFAULT_ENCODING_RULES : rules;
const calldata = new Calldata(rules_);
if (!_.isUndefined(selector)) {
calldata.setSelector(selector);
}
const block = this.generateCalldataBlock(value);
calldata.setRoot(block);
const encodedCalldata = calldata.toString();
return encodedCalldata;
}
public decode(calldata: string, rules?: DecodingRules, selector?: string): any {
if (!_.isUndefined(selector) && !_.startsWith(calldata, selector)) {
throw new Error(
`Tried to decode calldata, but it was missing the function selector. Expected prefix '${selector}'. Got '${calldata}'.`,
);
}
const hasSelector = !_.isUndefined(selector);
const rawCalldata = new RawCalldata(calldata, hasSelector);
const rules_ = _.isUndefined(rules) ? constants.DEFAULT_DECODING_RULES : rules;
const value = this.generateValue(rawCalldata, rules_);
return value;
}
public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock;
public abstract generateValue(calldata: RawCalldata, rules: DecodingRules): any;
public abstract getSignature(): string;
public abstract isStatic(): boolean;
}

Some files were not shown because too many files have changed in this diff Show More