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,
"version": "2.0.5",

View File

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

View File

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

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1543401373,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.0",
"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",
"version": "1.0.0",
"version": "1.0.1",
"engines": {
"node": ">=6.12"
},

View File

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

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
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_
* `deployFrom0xArtifactAsync` additionally accepts artifacts that conform to the `SimpleContractArtifact` interface (#1298)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
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_
* Rinkeby Deployment

View File

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

View File

@ -16,6 +16,7 @@ export enum NetworkId {
Ropsten = 3,
Rinkeby = 4,
Kovan = 42,
Ganache = 50,
}
const networkToAddresses: { [networkId: number]: ContractAddresses } = {
@ -40,14 +41,14 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = {
orderValidator: '0x90431a90516ab49af23a0530e04e8c7836e7122f',
},
4: {
erc20Proxy: '0x3e809c563c15a295e832e37053798ddc8d6c8dab',
erc721Proxy: '0x8e1ff02637cb5e39f2fa36c14706aa348b065b09',
zrxToken: '0x2727e688b8fd40b198cd5fe6e408e00494a06f07',
exchange: '0xbce0b5f6eb618c565c3e5f5cd69652bbc279f44e',
erc20Proxy: '0x2f5ae4f6106e89b4147651688a92256885c5f410',
erc721Proxy: '0x7656d773e11ff7383a14dcf09a9c50990481cd10',
zrxToken: '0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa',
etherToken: '0xc778417e063141139fce010982780140aa0cd5ab',
exchange: '0x22ebc052f43a88efa06379426120718170f2204e',
assetProxyOwner: '0x1da52d1d3a3acfa0a1836b737393b4e9931268fc',
forwarder: '0xd2dbf3250a764eaaa94fa0c84ed87c0edc8ed04e',
orderValidator: '0x39c3fc9f4d8430af2713306ce80c584752d9e1c7',
assetProxyOwner: '0xe1703da878afcebff5b7624a826902af475b9c03',
forwarder: '0x2d40589abbdee84961f3a7656b9af7adb0ee5ab4',
orderValidator: '0x0c5173a51e26b29d6126c686756fb9fbef71f762',
},
42: {
erc20Proxy: '0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e',
@ -59,6 +60,17 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = {
forwarder: '0x17992e4ffb22730138e4b62aaa6367fa9d3699a6',
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,
"note": "Update Exchange artifact to receive ZRX asset data as a constructor argument"
}
]
],
"timestamp": 1543401373
},
{
"version": "1.1.0",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
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_
* Update Forwarder artifact (#1192)

View File

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

View File

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

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.1.1 - _November 28, 2018_
* Dependencies updated
## 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)

View File

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

View File

@ -38,6 +38,7 @@
"IValidator",
"IWallet",
"MixinAuthorizable",
"MultiAssetProxy",
"MultiSigWallet",
"MultiSigWalletWithTimeLock",
"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
pragma solidity 0.4.24;
pragma experimental ABIEncoderV2;
// @dev Interface of the asset proxy's assetData.
@ -26,15 +27,18 @@ pragma solidity 0.4.24;
interface IAssetData {
function ERC20Token(address tokenContract)
external
pure;
external;
function ERC721Token(
address tokenContract,
uint256 tokenId,
bytes receiverData
uint256 tokenId
)
external
pure;
external;
function MultiAsset(
uint256[] amounts,
bytes[] nestedAssetData
)
external;
}

View File

@ -1,7 +1,7 @@
{
"private": true,
"name": "contracts",
"version": "2.1.55",
"version": "2.1.56",
"engines": {
"node": ">=6.12"
},
@ -19,7 +19,8 @@
"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: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",
"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",
@ -32,7 +33,8 @@
"lint-contracts": "solhint contracts/**/**/**/**/*.sol"
},
"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": {
"type": "git",
@ -46,10 +48,10 @@
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
"devDependencies": {
"@0x/abi-gen": "^1.0.17",
"@0x/dev-utils": "^1.0.18",
"@0x/sol-compiler": "^1.1.13",
"@0x/sol-cov": "^2.1.13",
"@0x/subproviders": "^2.1.5",
"@0x/dev-utils": "^1.0.19",
"@0x/sol-compiler": "^1.1.14",
"@0x/sol-cov": "^2.1.14",
"@0x/subproviders": "^2.1.6",
"@0x/tslint-config": "^1.0.10",
"@types/bn.js": "^4.11.0",
"@types/ethereumjs-abi": "^0.6.0",
@ -71,12 +73,12 @@
"yargs": "^10.0.3"
},
"dependencies": {
"@0x/base-contract": "^3.0.7",
"@0x/order-utils": "^3.0.3",
"@0x/base-contract": "^3.0.8",
"@0x/order-utils": "^3.0.4",
"@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5",
"@0x/web3-wrapper": "^3.1.6",
"@types/js-combinatorics": "^0.5.29",
"bn.js": "^4.11.8",
"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 IWallet from '../../generated-artifacts/IWallet.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 MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
import * as OrderValidator from '../../generated-artifacts/OrderValidator.json';
@ -57,6 +58,7 @@ export const artifacts = {
IWallet: IWallet as ContractArtifact,
InvalidERC721Receiver: InvalidERC721Receiver as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
MultiSigWallet: MultiSigWallet as ContractArtifact,
MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock 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 { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
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 { TestStaticCallReceiverContract } from '../../generated-wrappers/test_static_call_receiver';
import { artifacts } from '../../src/artifacts';
@ -31,6 +33,11 @@ import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const assetDataInterface = new IAssetDataContract(
artifacts.IAssetData.compilerOutput.abi,
constants.NULL_ADDRESS,
provider,
);
// tslint:disable:no-unnecessary-type-assertion
describe('Exchange core', () => {
let makerAddress: string;
@ -47,6 +54,7 @@ describe('Exchange core', () => {
let exchange: ExchangeContract;
let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract;
let multiAssetProxy: MultiAssetProxyContract;
let maliciousWallet: TestStaticCallReceiverContract;
let maliciousValidator: TestStaticCallReceiverContract;
@ -76,44 +84,26 @@ describe('Exchange core', () => {
erc20Wrapper = new ERC20Wrapper(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;
[erc20TokenA, erc20TokenB, zrxToken] = await erc20Wrapper.deployDummyTokensAsync(
numDummyErc20ToDeploy,
constants.DUMMY_TOKEN_DECIMALS,
);
erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync();
[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(
artifacts.Exchange,
provider,
txDefaults,
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(
artifacts.TestStaticCallReceiver,
provider,
@ -126,9 +116,72 @@ describe('Exchange core', () => {
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;
defaultTakerAssetAddress = erc20TokenB.address;
const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS,
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', () => {
beforeEach(async () => {
signedOrder = await orderFactory.newSignedOrderAsync();

View File

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

View File

@ -29,7 +29,8 @@ export class ERC721Wrapper {
this._contractOwnerAddress = contractOwnerAddress;
}
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(
await DummyERC721TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC721Token,
@ -61,7 +62,8 @@ export class ERC721Wrapper {
this._initialTokenIdsByOwner = {};
for (const dummyTokenContract of this._dummyTokenContracts) {
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();
await this.mintAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress])) {

View File

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

View File

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

View File

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

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.19 - _November 28, 2018_
* Dependencies updated
## v1.0.18 - _November 21, 2018_
* 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
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",
"version": "1.0.18",
"version": "1.0.19",
"engines": {
"node": ">=6.12"
},
@ -41,11 +41,11 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/subproviders": "^2.1.5",
"@0x/subproviders": "^2.1.6",
"@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5",
"@0x/web3-wrapper": "^3.1.6",
"@types/web3-provider-engine": "^14.0.0",
"chai": "^4.0.1",
"ethereum-types": "^1.1.2",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,9 @@
import * as _ from 'lodash';
import { transparentize } from 'polished';
import * as React from 'react';
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';
@ -93,8 +94,16 @@ export interface ProgressBarProps extends ProgressProps {}
export const ProgressBar: React.ComponentType<ProgressBarProps & React.ClassAttributes<{}>> = React.forwardRef(
(props, ref) => (
<Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px">
<ThemeConsumer>
{theme => (
<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;
className?: string;
backgroundColor?: ColorOption;
rawBackgroundColor?: string;
hasBoxShadow?: boolean;
zIndex?: number;
whiteSpace?: string;
@ -38,6 +39,16 @@ export interface ContainerProps {
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 =
styled.div <
ContainerProps >
@ -70,7 +81,7 @@ export const Container =
${props => props.width && stylesForMedia<string>('width', props.width)}
${props => props.height && stylesForMedia<string>('height', props.height)}
${props => props.borderRadius && stylesForMedia<string>('border-radius', props.borderRadius)}
background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
background-color: ${props => getBackgroundColor(props.theme, props.backgroundColor, props.rawBackgroundColor)};
border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
&:hover {
${props =>

View File

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

View File

@ -11,7 +11,7 @@ import { asyncData } from '../redux/async_data';
import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer';
import { store, Store } from '../redux/store';
import { fonts } from '../style/fonts';
import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource } from '../types';
import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource, QuoteFetchOrigin } from '../types';
import { analytics, disableAnalytics } from '../util/analytics';
import { assetUtils } from '../util/asset';
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);
// Trigger first buyquote fetch
// 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
// grab the gas price estimate when submitting the transaction
// tslint:disable-next-line:no-floating-promises

View File

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

View File

@ -10,7 +10,7 @@ import { ERC20AssetAmountInput, ERC20AssetAmountInputProps } from '../components
import { Action, actions } from '../redux/actions';
import { State } from '../redux/reducer';
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';
export interface SelectedERC20AssetAmountInputProps {
@ -88,7 +88,7 @@ const mapDispatchToProps = (
// even if it's debounced, give them the illusion it's loading
dispatch(actions.setQuoteRequestStatePending());
// tslint:disable-next-line:no-floating-promises
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, {
debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, QuoteFetchOrigin.Manual, {
setPending: true,
dispatchErrors: true,
affiliateInfo,

View File

@ -3,7 +3,7 @@ import * as _ from 'lodash';
import { Middleware } from 'redux';
import { ETH_DECIMALS } from '../constants';
import { Account, AccountState } from '../types';
import { Account, AccountState, StandardSlidingPanelContent } from '../types';
import { analytics } from '../util/analytics';
import { Action, ActionTypes } from './actions';
@ -77,6 +77,18 @@ export const analyticsMiddleware: Middleware = store => next => middlewareAction
});
}
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;

View File

@ -4,7 +4,7 @@ import * as _ from 'lodash';
import { Dispatch } from 'redux';
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 { assetUtils } from '../util/asset';
import { buyQuoteUpdater } from '../util/buy_quote_updater';
@ -84,6 +84,7 @@ export const asyncData = {
fetchCurrentBuyQuoteAndDispatchToStore: async (
state: State,
dispatch: Dispatch,
fetchOrigin: QuoteFetchOrigin,
options: { updateSilently: boolean },
) => {
const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state;
@ -99,7 +100,12 @@ export const asyncData = {
dispatch,
selectedAsset as ERC20Asset,
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';
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 };
@ -45,4 +53,4 @@ export const generateOverlayBlack = (opacity = 0.6) => {
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',
}
export enum QuoteFetchOrigin {
Manual = 'Manual',
Heartbeat = 'Heartbeat',
}
export interface SimulatedProgress {
startTimeUnix: number;
expectedEndTimeUnix: number;
@ -149,6 +154,11 @@ export enum Browser {
Other = 'OTHER',
}
export enum WalletSuggestion {
CoinbaseWallet = 'Coinbase Wallet',
MetaMask = 'MetaMask',
}
export enum OperatingSystem {
Android = 'ANDROID',
iOS = 'IOS',

View File

@ -1,7 +1,16 @@
import { BuyQuote } from '@0x/asset-buyer';
import { BigNumber } from '@0x/utils';
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';
@ -34,11 +43,18 @@ enum EventNames {
BUY_TX_SUBMITTED = 'Buy - Tx Submitted',
BUY_TX_SUCCEEDED = 'Buy - Tx Succeeded',
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_CLOSED = 'Token Selector - Closed',
TOKEN_SELECTOR_CHOSE = 'Token Selector - Chose',
TOKEN_SELECTOR_SEARCHED = 'Token Selector - Searched',
TRANSACTION_VIEWED = 'Transaction - Viewed',
QUOTE_FETCHED = 'Quote - Fetched',
QUOTE_ERROR = 'Quote - Error',
}
const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => {
@ -173,6 +189,14 @@ export const analytics = {
expectedTxTimeMs: expectedEndTimeUnix - 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),
trackTokenSelectorClosed: (closedVia: TokenSelectorClosedVia) =>
trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_CLOSED)({ closedVia }),
@ -182,4 +206,16 @@ export const analytics = {
trackingEventFnWithPayload(EventNames.TOKEN_SELECTOR_SEARCHED)({ searchText }),
trackTransactionViewed: (orderProcesState: OrderProcessState) =>
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 { 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 { errorFlasher } from '../util/error_flasher';
@ -16,7 +17,12 @@ export const buyQuoteUpdater = {
dispatch: Dispatch<Action>,
asset: ERC20Asset,
assetUnitAmount: BigNumber,
options: { setPending: boolean; dispatchErrors: boolean; affiliateInfo?: AffiliateInfo },
fetchOrigin: QuoteFetchOrigin,
options: {
setPending: boolean;
dispatchErrors: boolean;
affiliateInfo?: AffiliateInfo;
},
): Promise<void> => {
// get a new buy quote.
const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals);
@ -31,6 +37,7 @@ export const buyQuoteUpdater = {
} catch (error) {
if (options.dispatchErrors) {
dispatch(actions.setQuoteRequestStateFailure());
analytics.trackQuoteError(error.message ? error.message : 'other', baseUnitValue, fetchOrigin);
let errorMessage;
if (error.message === AssetBuyerError.InsufficientAssetLiquidity) {
const assetName = assetUtils.bestNameForAsset(asset, 'of this asset');
@ -58,5 +65,6 @@ export const buyQuoteUpdater = {
errorFlasher.clearError(dispatch);
// invalidate the last buy quote.
dispatch(actions.updateLatestBuyQuote(newBuyQuote));
analytics.trackQuoteFetched(newBuyQuote, fetchOrigin);
},
};

View File

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

View File

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

View File

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

View File

@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only.
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_
* 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",
"version": "2.1.0",
"version": "2.2.0",
"engines": {
"node": ">=6.12"
},
@ -26,7 +26,7 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0x/dev-utils": "^1.0.18",
"@0x/dev-utils": "^1.0.19",
"@0x/tslint-config": "^1.0.10",
"@0x/types": "^1.3.0",
"@types/yargs": "^10.0.0",
@ -39,16 +39,16 @@
"yargs": "^10.0.3"
},
"dependencies": {
"@0x/abi-gen-wrappers": "^1.1.0",
"@0x/base-contract": "^3.0.7",
"@0x/contract-addresses": "^1.2.0",
"@0x/contract-artifacts": "^1.1.0",
"@0x/order-utils": "^3.0.3",
"@0x/sol-compiler": "^1.1.13",
"@0x/subproviders": "^2.1.5",
"@0x/abi-gen-wrappers": "^2.0.0",
"@0x/base-contract": "^3.0.8",
"@0x/contract-addresses": "^2.0.0",
"@0x/contract-artifacts": "^1.1.2",
"@0x/order-utils": "^3.0.4",
"@0x/sol-compiler": "^1.1.14",
"@0x/subproviders": "^2.1.6",
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.5",
"@0x/web3-wrapper": "^3.1.6",
"@ledgerhq/hw-app-eth": "^4.3.0",
"ethereum-types": "^1.1.2",
"ethers": "~4.0.4",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
{
"name": "@0x/subproviders",
"version": "2.1.5",
"version": "2.1.6",
"engines": {
"node": ">=6.12"
},
@ -33,7 +33,7 @@
"@0x/types": "^1.3.0",
"@0x/typescript-typings": "^3.0.4",
"@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-transport-u2f": "4.24.0",
"@types/eth-lightwallet": "^3.0.0",

View File

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

View File

@ -195,6 +195,7 @@ export enum RevertReason {
FailedExecution = 'FAILED_EXECUTION',
AssetProxyAlreadyExists = 'ASSET_PROXY_ALREADY_EXISTS',
LengthGreaterThan0Required = 'LENGTH_GREATER_THAN_0_REQUIRED',
LengthGreaterThan3Required = 'LENGTH_GREATER_THAN_3_REQUIRED',
LengthGreaterThan131Required = 'LENGTH_GREATER_THAN_131_REQUIRED',
Length0Required = 'LENGTH_0_REQUIRED',
Length65Required = 'LENGTH_65_REQUIRED',
@ -209,6 +210,7 @@ export enum RevertReason {
MakerNotWhitelisted = 'MAKER_NOT_WHITELISTED',
TakerNotWhitelisted = 'TAKER_NOT_WHITELISTED',
AssetProxyDoesNotExist = 'ASSET_PROXY_DOES_NOT_EXIST',
LengthMismatch = 'LENGTH_MISMATCH',
LibBytesGreaterThanZeroLengthRequired = 'GREATER_THAN_ZERO_LENGTH_REQUIRED',
LibBytesGreaterOrEqualTo4LengthRequired = 'GREATER_OR_EQUAL_TO_4_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,
"version": "2.0.6",

View File

@ -33,6 +33,9 @@
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"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",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",

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