Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-onboarding-polish
This commit is contained in:
commit
e693629bbd
@ -53,9 +53,9 @@ jobs:
|
|||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
# HACK(albrow): we need to sleep 15 seconds to ensure the devnet is
|
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
|
||||||
# initialized
|
# initialized
|
||||||
- run: sleep 15 && TEST_PROVIDER=geth yarn wsrun test contracts
|
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts
|
||||||
test-rest:
|
test-rest:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:9
|
- image: circleci/node:9
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"async-child-process": "^1.1.1",
|
"async-child-process": "^1.1.1",
|
||||||
"coveralls": "^3.0.0",
|
"coveralls": "^3.0.0",
|
||||||
"ganache-cli": "^6.1.0",
|
"ganache-cli": "6.1.3",
|
||||||
"lcov-result-merger": "^3.0.0",
|
"lcov-result-merger": "^3.0.0",
|
||||||
"lerna": "^2.5.1",
|
"lerna": "^2.5.1",
|
||||||
"npm-run-all": "^4.1.2",
|
"npm-run-all": "^4.1.2",
|
||||||
|
@ -60,6 +60,13 @@ contract MixinTransactions is
|
|||||||
{
|
{
|
||||||
bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH;
|
bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH;
|
||||||
bytes32 dataHash = keccak256(data);
|
bytes32 dataHash = keccak256(data);
|
||||||
|
// Assembly for more efficiently computing:
|
||||||
|
// keccak256(abi.encode(
|
||||||
|
// EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,
|
||||||
|
// salt,
|
||||||
|
// signerAddress,
|
||||||
|
// keccak256(data)
|
||||||
|
// ));
|
||||||
assembly {
|
assembly {
|
||||||
let memPtr := mload(64)
|
let memPtr := mload(64)
|
||||||
mstore(memPtr, schemaHash)
|
mstore(memPtr, schemaHash)
|
||||||
|
@ -98,6 +98,21 @@ contract LibOrder is
|
|||||||
bytes32 schemaHash = EIP712_ORDER_SCHEMA_HASH;
|
bytes32 schemaHash = EIP712_ORDER_SCHEMA_HASH;
|
||||||
bytes32 makerAssetDataHash = keccak256(order.makerAssetData);
|
bytes32 makerAssetDataHash = keccak256(order.makerAssetData);
|
||||||
bytes32 takerAssetDataHash = keccak256(order.takerAssetData);
|
bytes32 takerAssetDataHash = keccak256(order.takerAssetData);
|
||||||
|
// Assembly for more efficiently computing:
|
||||||
|
// keccak256(abi.encode(
|
||||||
|
// order.makerAddress,
|
||||||
|
// order.takerAddress,
|
||||||
|
// order.feeRecipientAddress,
|
||||||
|
// order.senderAddress,
|
||||||
|
// order.makerAssetAmount,
|
||||||
|
// order.takerAssetAmount,
|
||||||
|
// order.makerFee,
|
||||||
|
// order.takerFee,
|
||||||
|
// order.expirationTimeSeconds,
|
||||||
|
// order.salt,
|
||||||
|
// keccak256(order.makerAssetData),
|
||||||
|
// keccak256(order.takerAssetData)
|
||||||
|
// ));
|
||||||
assembly {
|
assembly {
|
||||||
// Backup
|
// Backup
|
||||||
let temp1 := mload(sub(order, 32))
|
let temp1 := mload(sub(order, 32))
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/subproviders": "^0.10.4",
|
"@0xproject/subproviders": "^0.10.4",
|
||||||
"@0xproject/types": "^0.8.1",
|
"@0xproject/types": "^0.8.1",
|
||||||
|
"@0xproject/utils": "^0.7.1",
|
||||||
"ethereum-types": "^0.0.1",
|
"ethereum-types": "^0.0.1",
|
||||||
"@0xproject/typescript-typings": "^0.4.1",
|
"@0xproject/typescript-typings": "^0.4.1",
|
||||||
"@0xproject/web3-wrapper": "^0.7.1",
|
"@0xproject/web3-wrapper": "^0.7.1",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { logUtils } from '@0xproject/utils';
|
||||||
import { uniqueVersionIds, Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { uniqueVersionIds, Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import { includes } from 'lodash';
|
import { includes } from 'lodash';
|
||||||
|
|
||||||
@ -6,9 +7,17 @@ enum NodeType {
|
|||||||
Ganache = 'GANACHE',
|
Ganache = 'GANACHE',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK(albrow): 🐉 We have to do this so that debug.setHead works correctly.
|
||||||
|
// (Geth does not seem to like debug.setHead(0), so by sending some transactions
|
||||||
|
// we increase the current block number beyond 0). Additionally, some tests seem
|
||||||
|
// to break when there are fewer than 3 blocks in the chain. (We have no idea
|
||||||
|
// why, but it was consistently reproducible).
|
||||||
|
const MINIMUM_BLOCKS = 3;
|
||||||
|
|
||||||
export class BlockchainLifecycle {
|
export class BlockchainLifecycle {
|
||||||
private _web3Wrapper: Web3Wrapper;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
private _snapshotIdsStack: number[];
|
private _snapshotIdsStack: number[];
|
||||||
|
private _addresses: string[] = [];
|
||||||
constructor(web3Wrapper: Web3Wrapper) {
|
constructor(web3Wrapper: Web3Wrapper) {
|
||||||
this._web3Wrapper = web3Wrapper;
|
this._web3Wrapper = web3Wrapper;
|
||||||
this._snapshotIdsStack = [];
|
this._snapshotIdsStack = [];
|
||||||
@ -21,7 +30,13 @@ export class BlockchainLifecycle {
|
|||||||
this._snapshotIdsStack.push(snapshotId);
|
this._snapshotIdsStack.push(snapshotId);
|
||||||
break;
|
break;
|
||||||
case NodeType.Geth:
|
case NodeType.Geth:
|
||||||
const blockNumber = await this._web3Wrapper.getBlockNumberAsync();
|
let blockNumber = await this._web3Wrapper.getBlockNumberAsync();
|
||||||
|
if (blockNumber < MINIMUM_BLOCKS) {
|
||||||
|
// If the minimum block number is not met, force Geth to
|
||||||
|
// mine some blocks by sending some dummy transactions.
|
||||||
|
await this._mineMinimumBlocksAsync();
|
||||||
|
blockNumber = await this._web3Wrapper.getBlockNumberAsync();
|
||||||
|
}
|
||||||
this._snapshotIdsStack.push(blockNumber);
|
this._snapshotIdsStack.push(blockNumber);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -56,4 +71,25 @@ export class BlockchainLifecycle {
|
|||||||
throw new Error(`Unknown client version: ${version}`);
|
throw new Error(`Unknown client version: ${version}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private async _mineMinimumBlocksAsync(): Promise<void> {
|
||||||
|
logUtils.warn('WARNING: minimum block number for tests not met. Mining additional blocks...');
|
||||||
|
if (this._addresses.length === 0) {
|
||||||
|
this._addresses = await this._web3Wrapper.getAvailableAddressesAsync();
|
||||||
|
if (this._addresses.length === 0) {
|
||||||
|
throw new Error('No accounts found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((await this._web3Wrapper.getBlockNumberAsync()) < MINIMUM_BLOCKS) {
|
||||||
|
logUtils.warn('Mining block...');
|
||||||
|
await this._web3Wrapper.awaitTransactionMinedAsync(
|
||||||
|
await this._web3Wrapper.sendTransactionAsync({
|
||||||
|
from: this._addresses[0],
|
||||||
|
to: this._addresses[0],
|
||||||
|
value: '0',
|
||||||
|
}),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
logUtils.warn('Done mining the minimum number of blocks.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ set -e
|
|||||||
# Create log directory for Geth
|
# Create log directory for Geth
|
||||||
mkdir -p /var/log
|
mkdir -p /var/log
|
||||||
|
|
||||||
# Start Geth in background and redirect output to log file
|
# Start Geth and direct output to stdout
|
||||||
/geth \
|
/geth \
|
||||||
--verbosity 5 \
|
--verbosity 5 \
|
||||||
--datadir node0/ \
|
--datadir node0/ \
|
||||||
@ -22,23 +22,4 @@ mkdir -p /var/log
|
|||||||
--mine \
|
--mine \
|
||||||
--etherbase '0xe8816898d851d5b61b7f950627d04d794c07ca37' \
|
--etherbase '0xe8816898d851d5b61b7f950627d04d794c07ca37' \
|
||||||
--unlock '0xe8816898d851d5b61b7f950627d04d794c07ca37,0x5409ed021d9299bf6814279a6a1411a7e866a631,0x6ecbe1db9ef729cbe972c83fb886247691fb6beb,0xe36ea790bc9d7ab70c55260c66d52b1eca985f84,0xe834ec434daba538cd1b9fe1582052b880bd7e63,0x78dc5d2d739606d31509c31d654056a45185ecb6,0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872,0x06cef8e666768cc40cc78cf93d9611019ddcb628,0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d,0x7457d5e02197480db681d3fdf256c7aca21bdc12,0x91c987bf62d25945db517bdaa840a6c661374402' \
|
--unlock '0xe8816898d851d5b61b7f950627d04d794c07ca37,0x5409ed021d9299bf6814279a6a1411a7e866a631,0x6ecbe1db9ef729cbe972c83fb886247691fb6beb,0xe36ea790bc9d7ab70c55260c66d52b1eca985f84,0xe834ec434daba538cd1b9fe1582052b880bd7e63,0x78dc5d2d739606d31509c31d654056a45185ecb6,0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872,0x06cef8e666768cc40cc78cf93d9611019ddcb628,0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d,0x7457d5e02197480db681d3fdf256c7aca21bdc12,0x91c987bf62d25945db517bdaa840a6c661374402' \
|
||||||
--password=node0/password.txt \
|
--password=node0/password.txt
|
||||||
> /var/log/geth &
|
|
||||||
|
|
||||||
# Wait for Geth to unlock the first account
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
# Send some transactions.
|
|
||||||
# HACK(albrow): 🐉 We have to do this so that debug.setHead works correctly.
|
|
||||||
# (Geth does not seem to like debug.setHead(0), so by sending some transactions
|
|
||||||
# we increase the current block number beyond 0). Additionally, some tests seem
|
|
||||||
# to break when there are fewer than 3 blocks in the chain. (We have no idea
|
|
||||||
# why, but it was consistently reproducible).
|
|
||||||
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0x5409ED021D9299bf6814279A6A1411A7e866A631", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
|
|
||||||
sleep 3
|
|
||||||
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0x5409ED021D9299bf6814279A6A1411A7e866A631", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
|
|
||||||
sleep 3
|
|
||||||
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0x5409ED021D9299bf6814279A6A1411A7e866A631", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
|
|
||||||
|
|
||||||
# Use tail to re-attach to the log file and actually see the output.
|
|
||||||
tail -f /var/log/geth
|
|
||||||
|
@ -745,4 +745,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"networks": {}
|
"networks": {}
|
||||||
}
|
}
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
{
|
|
||||||
"schemaVersion": "2.0.0",
|
|
||||||
"contractName": "DummyERC721Receiver",
|
|
||||||
"compilerOutput": {
|
|
||||||
"abi": [
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "_from",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "_tokenId",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "_data",
|
|
||||||
"type": "bytes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "onERC721Received",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "",
|
|
||||||
"type": "bytes4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"anonymous": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"indexed": false,
|
|
||||||
"name": "from",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"indexed": false,
|
|
||||||
"name": "tokenId",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"indexed": false,
|
|
||||||
"name": "data",
|
|
||||||
"type": "bytes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "TokenReceived",
|
|
||||||
"type": "event"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"evm": {
|
|
||||||
"bytecode": {
|
|
||||||
"linkReferences": {},
|
|
||||||
"object": "0x608060405234801561001057600080fd5b5061021c806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f0b9e5ba8114610045575b600080fd5b34801561005157600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526100bb94823573ffffffffffffffffffffffffffffffffffffffff169460248035953695946064949201919081908401838280828437509497506100f09650505050505050565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b60007fefe605af9663e0f15f1dd40dad79f119df71e8d2affb3f6857cb9707c6c4b3ea848484604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561018b578181015183820152602001610173565b50505050905090810190601f1680156101b85780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a1507ff0b9e5ba0000000000000000000000000000000000000000000000000000000093925050505600a165627a7a72305820b4f9087d0d09769494b2e03d6db34350ff32a048f73c050c3eda5fa9b2644dae0029",
|
|
||||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x21C DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x40 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0xF0B9E5BA DUP2 EQ PUSH2 0x45 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x51 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 PUSH1 0x44 CALLDATALOAD DUP2 DUP2 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0xBB SWAP5 DUP3 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP5 PUSH1 0x24 DUP1 CALLDATALOAD SWAP6 CALLDATASIZE SWAP6 SWAP5 PUSH1 0x64 SWAP5 SWAP3 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0xF0 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH32 0xEFE605AF9663E0F15F1DD40DAD79F119DF71E8D2AFFB3F6857CB9707C6C4B3EA DUP5 DUP5 DUP5 PUSH1 0x40 MLOAD DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x18B JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x173 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x1B8 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP5 POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 POP PUSH32 0xF0B9E5BA00000000000000000000000000000000000000000000000000000000 SWAP4 SWAP3 POP POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xb4 0xf9 ADDMOD PUSH30 0xD09769494B2E03D6DB34350FF32A048F73C050C3EDA5FA9B2644DAE0029 ",
|
|
||||||
"sourceMap": "1186:1067:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1186:1067:0;;;;;;;"
|
|
||||||
},
|
|
||||||
"deployedBytecode": {
|
|
||||||
"linkReferences": {},
|
|
||||||
"object": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f0b9e5ba8114610045575b600080fd5b34801561005157600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526100bb94823573ffffffffffffffffffffffffffffffffffffffff169460248035953695946064949201919081908401838280828437509497506100f09650505050505050565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b60007fefe605af9663e0f15f1dd40dad79f119df71e8d2affb3f6857cb9707c6c4b3ea848484604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561018b578181015183820152602001610173565b50505050905090810190601f1680156101b85780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a1507ff0b9e5ba0000000000000000000000000000000000000000000000000000000093925050505600a165627a7a72305820b4f9087d0d09769494b2e03d6db34350ff32a048f73c050c3eda5fa9b2644dae0029",
|
|
||||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x40 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0xF0B9E5BA DUP2 EQ PUSH2 0x45 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x51 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x20 PUSH1 0x4 PUSH1 0x44 CALLDATALOAD DUP2 DUP2 ADD CALLDATALOAD PUSH1 0x1F DUP2 ADD DUP5 SWAP1 DIV DUP5 MUL DUP6 ADD DUP5 ADD SWAP1 SWAP6 MSTORE DUP5 DUP5 MSTORE PUSH2 0xBB SWAP5 DUP3 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP5 PUSH1 0x24 DUP1 CALLDATALOAD SWAP6 CALLDATASIZE SWAP6 SWAP5 PUSH1 0x64 SWAP5 SWAP3 ADD SWAP2 SWAP1 DUP2 SWAP1 DUP5 ADD DUP4 DUP3 DUP1 DUP3 DUP5 CALLDATACOPY POP SWAP5 SWAP8 POP PUSH2 0xF0 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH32 0xEFE605AF9663E0F15F1DD40DAD79F119DF71E8D2AFFB3F6857CB9707C6C4B3EA DUP5 DUP5 DUP5 PUSH1 0x40 MLOAD DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x18B JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x173 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x1B8 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP5 POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 POP PUSH32 0xF0B9E5BA00000000000000000000000000000000000000000000000000000000 SWAP4 SWAP3 POP POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xb4 0xf9 ADDMOD PUSH30 0xD09769494B2E03D6DB34350FF32A048F73C050C3EDA5FA9B2644DAE0029 ",
|
|
||||||
"sourceMap": "1186:1067:0:-;;;;;;;;;;;;;;;;;;;;;;;2014:237;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2014:237:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2014:237:0;;-1:-1:-1;2014:237:0;;-1:-1:-1;;;;;;;2014:237:0;;;;;;;;;;;;;;;;;;;;;2148:6;2175:37;2189:5;2196:8;2206:5;2175:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;2175:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2229:15:0;2014:237;;;;;:::o"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sources": {
|
|
||||||
"current/test/DummyERC721Receiver/DummyERC721Receiver.sol": {
|
|
||||||
"id": 0
|
|
||||||
},
|
|
||||||
"current/tokens/ERC721Token/IERC721Receiver.sol": {
|
|
||||||
"id": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sourceCodes": {
|
|
||||||
"current/test/DummyERC721Receiver/DummyERC721Receiver.sol": "/*\nThe MIT License (MIT)\n\nCopyright (c) 2016 Smart Contract Solutions, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\npragma solidity ^0.4.24;\n\nimport \"../../tokens/ERC721Token/IERC721Receiver.sol\";\n\ncontract DummyERC721Receiver is\n IERC721Receiver\n{\n\n event TokenReceived(\n address from,\n uint256 tokenId,\n bytes data\n );\n\n /**\n * @notice Handle the receipt of an NFT\n * @dev The ERC721 smart contract calls this function on the recipient\n * after a `safetransfer`. This function MAY throw to revert and reject the\n * transfer. This function MUST use 50,000 gas or less. Return of other\n * than the magic value MUST result in the transaction being reverted.\n * Note: the contract address is always the message sender.\n * @param _from The sending address\n * @param _tokenId The NFT identifier which is being transfered\n * @param _data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`\n */\n function onERC721Received(\n address _from,\n uint256 _tokenId,\n bytes _data\n )\n public\n returns (bytes4)\n {\n emit TokenReceived(_from, _tokenId, _data);\n return ERC721_RECEIVED;\n }\n}\n",
|
|
||||||
"current/tokens/ERC721Token/IERC721Receiver.sol": "/*\nThe MIT License (MIT)\n\nCopyright (c) 2016 Smart Contract Solutions, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\npragma solidity ^0.4.24;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * rom ERC721 asset contracts.\n * Modified from https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Receiver.sol\n */\ncontract IERC721Receiver {\n /**\n * @dev Magic value to be returned upon successful reception of an NFT\n * Equals to `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`,\n * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`\n */\n bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;\n\n /**\n * @notice Handle the receipt of an NFT\n * @dev The ERC721 smart contract calls this function on the recipient\n * after a `safetransfer`. This function MAY throw to revert and reject the\n * transfer. This function MUST use 50,000 gas or less. Return of other\n * than the magic value MUST result in the transaction being reverted.\n * Note: the contract address is always the message sender.\n * @param _from The sending address\n * @param _tokenId The NFT identifier which is being transfered\n * @param _data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`\n */\n function onERC721Received(\n address _from,\n uint256 _tokenId,\n bytes _data)\n public\n returns (bytes4);\n}\n"
|
|
||||||
},
|
|
||||||
"sourceTreeHashHex": "0x78d041d511725e5b22accff013b3ca3c813fc2804b0af3a247e6932ffd1c23ae",
|
|
||||||
"compiler": {
|
|
||||||
"name": "solc",
|
|
||||||
"version": "soljson-v0.4.24+commit.e67f0147.js",
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 1000000
|
|
||||||
},
|
|
||||||
"outputSelection": {
|
|
||||||
"*": {
|
|
||||||
"*": [
|
|
||||||
"abi",
|
|
||||||
"evm.bytecode.object",
|
|
||||||
"evm.bytecode.sourceMap",
|
|
||||||
"evm.deployedBytecode.object",
|
|
||||||
"evm.deployedBytecode.sourceMap"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"networks": {}
|
|
||||||
}
|
|
@ -278,4 +278,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"networks": {}
|
"networks": {}
|
||||||
}
|
}
|
||||||
|
@ -278,4 +278,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"networks": {}
|
"networks": {}
|
||||||
}
|
}
|
||||||
|
379
packages/migrations/artifacts/2.0.0/ERC721Token.json
vendored
Normal file
379
packages/migrations/artifacts/2.0.0/ERC721Token.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -2079,4 +2079,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"networks": {}
|
"networks": {}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,89 +0,0 @@
|
|||||||
{
|
|
||||||
"schemaVersion": "2.0.0",
|
|
||||||
"contractName": "IAssetData",
|
|
||||||
"compilerOutput": {
|
|
||||||
"abi": [
|
|
||||||
{
|
|
||||||
"constant": true,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "tokenContract",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tokenId",
|
|
||||||
"type": "uint256"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "receiverData",
|
|
||||||
"type": "bytes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "ERC721Token",
|
|
||||||
"outputs": [],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"constant": true,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "tokenContract",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "ERC20Token",
|
|
||||||
"outputs": [],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "pure",
|
|
||||||
"type": "function"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"evm": {
|
|
||||||
"bytecode": {
|
|
||||||
"linkReferences": {},
|
|
||||||
"object": "0x",
|
|
||||||
"opcodes": "",
|
|
||||||
"sourceMap": ""
|
|
||||||
},
|
|
||||||
"deployedBytecode": {
|
|
||||||
"linkReferences": {},
|
|
||||||
"object": "0x",
|
|
||||||
"opcodes": "",
|
|
||||||
"sourceMap": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sources": {
|
|
||||||
"current/protocol/AssetProxy/interfaces/IAssetData.sol": {
|
|
||||||
"id": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sourceCodes": {
|
|
||||||
"current/protocol/AssetProxy/interfaces/IAssetData.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\n\n// @dev Interface of the asset proxy's assetData.\n// The asset proxies take an ABI encoded `bytes assetData` as argument.\n// This argument is ABI encoded as one of the methods of this interface.\ninterface IAssetData {\n \n function ERC20Token(\n address tokenContract)\n external pure;\n \n function ERC721Token(\n address tokenContract,\n uint256 tokenId,\n bytes receiverData)\n external pure;\n \n}\n"
|
|
||||||
},
|
|
||||||
"sourceTreeHashHex": "0x7fc145f6e88b00700970b3937ba5a88e398a0e66e2abb14f0349209f4d4e49f1",
|
|
||||||
"compiler": {
|
|
||||||
"name": "solc",
|
|
||||||
"version": "soljson-v0.4.24+commit.e67f0147.js",
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 1000000
|
|
||||||
},
|
|
||||||
"outputSelection": {
|
|
||||||
"*": {
|
|
||||||
"*": [
|
|
||||||
"abi",
|
|
||||||
"evm.bytecode.object",
|
|
||||||
"evm.bytecode.sourceMap",
|
|
||||||
"evm.deployedBytecode.object",
|
|
||||||
"evm.deployedBytecode.sourceMap"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"networks": {}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
723
packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json
vendored
Normal file
723
packages/migrations/artifacts/2.0.0/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
329
packages/migrations/artifacts/2.0.0/TestLibs.json
vendored
329
packages/migrations/artifacts/2.0.0/TestLibs.json
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,95 +0,0 @@
|
|||||||
{
|
|
||||||
"schemaVersion": "2.0.0",
|
|
||||||
"contractName": "TestValidator",
|
|
||||||
"compilerOutput": {
|
|
||||||
"abi": [
|
|
||||||
{
|
|
||||||
"constant": true,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "hash",
|
|
||||||
"type": "bytes32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "signerAddress",
|
|
||||||
"type": "address"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "signature",
|
|
||||||
"type": "bytes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "isValidSignature",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "isValid",
|
|
||||||
"type": "bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "view",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "validSigner",
|
|
||||||
"type": "address"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "constructor"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"evm": {
|
|
||||||
"bytecode": {
|
|
||||||
"linkReferences": {},
|
|
||||||
"object": "0x608060405234801561001057600080fd5b50604051602080610134833981016040525160008054600160a060020a03909216600160a060020a031990921691909117905560e3806100516000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416639363470281146043575b600080fd5b348015604e57600080fd5b50607e60048035906024803573ffffffffffffffffffffffffffffffffffffffff16916044359182019101356092565b604080519115158252519081900360200190f35b505060005473ffffffffffffffffffffffffffffffffffffffff9081169116149190505600a165627a7a72305820d56af815348fc993337c155cb13340d950e982ab65a940dff32a1d25f78ca9bb0029",
|
|
||||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP1 PUSH2 0x134 DUP4 CODECOPY DUP2 ADD PUSH1 0x40 MSTORE MLOAD PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP1 SWAP3 AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT SWAP1 SWAP3 AND SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH1 0xE3 DUP1 PUSH2 0x51 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3E JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x93634702 DUP2 EQ PUSH1 0x43 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x7E PUSH1 0x4 DUP1 CALLDATALOAD SWAP1 PUSH1 0x24 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP2 PUSH1 0x44 CALLDATALOAD SWAP2 DUP3 ADD SWAP2 ADD CALLDATALOAD PUSH1 0x92 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST POP POP PUSH1 0x0 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 DUP2 AND SWAP2 AND EQ SWAP2 SWAP1 POP JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xd5 PUSH11 0xF815348FC993337C155CB1 CALLER BLOCKHASH 0xd9 POP 0xe9 DUP3 0xab PUSH6 0xA940DFF32A1D 0x25 0xf7 DUP13 0xa9 0xbb STOP 0x29 ",
|
|
||||||
"sourceMap": "667:864:1:-;;;916:84;8:9:-1;5:2;;;30:1;27;20:12;5:2;916:84:1;;;;;;;;;;;;;967:12;:26;;-1:-1:-1;;;;;967:26:1;;;-1:-1:-1;;;;;;967:26:1;;;;;;;;;667:864;;;;;;"
|
|
||||||
},
|
|
||||||
"deployedBytecode": {
|
|
||||||
"linkReferences": {},
|
|
||||||
"object": "0x608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416639363470281146043575b600080fd5b348015604e57600080fd5b50607e60048035906024803573ffffffffffffffffffffffffffffffffffffffff16916044359182019101356092565b604080519115158252519081900360200190f35b505060005473ffffffffffffffffffffffffffffffffffffffff9081169116149190505600a165627a7a72305820d56af815348fc993337c155cb13340d950e982ab65a940dff32a1d25f78ca9bb0029",
|
|
||||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3E JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x93634702 DUP2 EQ PUSH1 0x43 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x7E PUSH1 0x4 DUP1 CALLDATALOAD SWAP1 PUSH1 0x24 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP2 PUSH1 0x44 CALLDATALOAD SWAP2 DUP3 ADD SWAP2 ADD CALLDATALOAD PUSH1 0x92 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 ISZERO ISZERO DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST POP POP PUSH1 0x0 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 DUP2 AND SWAP2 AND EQ SWAP2 SWAP1 POP JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xd5 PUSH11 0xF815348FC993337C155CB1 CALLER BLOCKHASH 0xd9 POP 0xe9 DUP3 0xab PUSH6 0xA940DFF32A1D 0x25 0xf7 DUP13 0xa9 0xbb STOP 0x29 ",
|
|
||||||
"sourceMap": "667:864:1:-;;;;;;;;;;;;;;;;;;;;;;;1299:230;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1299:230:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1456:12:1;1509;;;;;1492:29;;;;1299:230;-1:-1:-1;1299:230:1:o"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sources": {
|
|
||||||
"current/protocol/Exchange/interfaces/IValidator.sol": {
|
|
||||||
"id": 0
|
|
||||||
},
|
|
||||||
"current/test/TestValidator/TestValidator.sol": {
|
|
||||||
"id": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sourceCodes": {
|
|
||||||
"current/protocol/Exchange/interfaces/IValidator.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\n\ncontract IValidator {\n\n /// @dev Verifies that a signature is valid.\n /// @param hash Message hash that is signed.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof of signing.\n /// @return Validity of order signature.\n function isValidSignature(\n bytes32 hash,\n address signerAddress,\n bytes signature\n )\n external\n view\n returns (bool isValid);\n}\n",
|
|
||||||
"current/test/TestValidator/TestValidator.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\n\nimport \"../../protocol/Exchange/interfaces/IValidator.sol\";\n\ncontract TestValidator is \n IValidator\n{\n\n // The single valid signer for this wallet.\n address VALID_SIGNER;\n\n /// @dev constructs a new `TestValidator` with a single valid signer.\n /// @param validSigner The sole, valid signer.\n constructor (address validSigner) public {\n VALID_SIGNER = validSigner;\n }\n\n /// @dev Verifies that a signature is valid. `signer` must match `VALID_SIGNER`.\n /// @param hash Message hash that is signed.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof of signing.\n /// @return Validity of signature.\n function isValidSignature(\n bytes32 hash,\n address signerAddress,\n bytes signature\n )\n external\n view\n returns (bool isValid)\n {\n return (signerAddress == VALID_SIGNER);\n }\n}\n"
|
|
||||||
},
|
|
||||||
"sourceTreeHashHex": "0x46c9bcd1eaeb97a053a035d7aa8867b98dd8dc7a9faf39d5e2fa41e911c728ee",
|
|
||||||
"compiler": {
|
|
||||||
"name": "solc",
|
|
||||||
"version": "soljson-v0.4.24+commit.e67f0147.js",
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 1000000
|
|
||||||
},
|
|
||||||
"outputSelection": {
|
|
||||||
"*": {
|
|
||||||
"*": [
|
|
||||||
"abi",
|
|
||||||
"evm.bytecode.object",
|
|
||||||
"evm.bytecode.sourceMap",
|
|
||||||
"evm.deployedBytecode.object",
|
|
||||||
"evm.deployedBytecode.sourceMap"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"networks": {}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -327,4 +327,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"networks": {}
|
"networks": {}
|
||||||
}
|
}
|
||||||
|
284
packages/migrations/artifacts/2.0.0/Whitelist.json
vendored
284
packages/migrations/artifacts/2.0.0/Whitelist.json
vendored
File diff suppressed because one or more lines are too long
@ -283,4 +283,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"networks": {}
|
"networks": {}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"contractsDir": "../contracts/src/contracts",
|
"contractsDir": "../contracts/src/contracts",
|
||||||
"compilerSettings": {
|
"compilerSettings": {
|
||||||
|
"optimizer": {
|
||||||
|
"enabled": true,
|
||||||
|
"runs": 1000000
|
||||||
|
},
|
||||||
"outputSelection": {
|
"outputSelection": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": [
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"generate_contract_wrappers:v2":
|
"generate_contract_wrappers:v2":
|
||||||
"abi-gen --abis ${npm_package_config_abis_v2} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/v2/contract_wrappers --backend ethers",
|
"abi-gen --abis ${npm_package_config_abis_v2} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/v2/contract_wrappers --backend ethers",
|
||||||
"compile:v1": "sol-compiler --artifacts-dir artifacts/1.0.0 --contracts Exchange_v1,DummyERC20Token,ZRXToken,WETH9,TokenTransferProxy_v1,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry",
|
"compile:v1": "sol-compiler --artifacts-dir artifacts/1.0.0 --contracts Exchange_v1,DummyERC20Token,ZRXToken,WETH9,TokenTransferProxy_v1,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry",
|
||||||
"compile:v2": "sol-compiler --artifacts-dir artifacts/2.0.0 --contracts ERC20Token,DummyERC20Token,ERC721Token,DummyERC721Token,ERC20Proxy,ERC721Proxy,Exchange,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,ZRXToken,WETH9,IWallet,IValidator"
|
"compile:v2": "sol-compiler --artifacts-dir artifacts/2.0.0 --contracts AssetProxyOwner,ERC20Token,DummyERC20Token,ERC721Token,DummyERC721Token,ERC20Proxy,ERC721Proxy,Exchange,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,ZRXToken,WETH9,IWallet,IValidator"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": {
|
"abis": {
|
||||||
@ -50,6 +50,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/base-contract": "^0.3.4",
|
"@0xproject/base-contract": "^0.3.4",
|
||||||
|
"@0xproject/order-utils": "^1.0.0",
|
||||||
"@0xproject/sol-compiler": "^0.5.2",
|
"@0xproject/sol-compiler": "^0.5.2",
|
||||||
"@0xproject/typescript-typings": "^0.4.1",
|
"@0xproject/typescript-typings": "^0.4.1",
|
||||||
"@0xproject/utils": "^0.7.1",
|
"@0xproject/utils": "^0.7.1",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { assetProxyUtils, constants } from '@0xproject/order-utils';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import { Provider, TxData } from 'ethereum-types';
|
import { Provider, TxData } from 'ethereum-types';
|
||||||
@ -51,7 +52,7 @@ export const runV2MigrationsAsync = async (provider: Provider, artifactsDir: str
|
|||||||
artifacts.Exchange,
|
artifacts.Exchange,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
zrxToken.address,
|
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
|
||||||
);
|
);
|
||||||
artifactsWriter.saveArtifact(exchange);
|
artifactsWriter.saveArtifact(exchange);
|
||||||
|
|
||||||
@ -74,16 +75,37 @@ export const runV2MigrationsAsync = async (provider: Provider, artifactsDir: str
|
|||||||
);
|
);
|
||||||
artifactsWriter.saveArtifact(assetProxyOwner);
|
artifactsWriter.saveArtifact(assetProxyOwner);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
await erc20proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }),
|
await erc20proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||||
|
from: owner,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
await erc20proxy.transferOwnership.sendTransactionAsync(assetProxyOwner.address, { from: owner }),
|
await erc20proxy.transferOwnership.sendTransactionAsync(assetProxyOwner.address, {
|
||||||
|
from: owner,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
await erc721proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }),
|
await erc721proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
|
||||||
|
from: owner,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
await erc721proxy.transferOwnership.sendTransactionAsync(assetProxyOwner.address, { from: owner }),
|
await erc721proxy.transferOwnership.sendTransactionAsync(assetProxyOwner.address, {
|
||||||
|
from: owner,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register the Asset Proxies to the Exchange
|
||||||
|
// HACK: These are exposed in the types package but migrations currently uses an older version
|
||||||
|
// but we can pull the asset data id from the proxies
|
||||||
|
const erc20ProxyId = await erc20proxy.getProxyId.callAsync();
|
||||||
|
const erc721ProxyId = await erc721proxy.getProxyId.callAsync();
|
||||||
|
const oldAddress = constants.NULL_ADDRESS;
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await exchange.registerAssetProxy.sendTransactionAsync(erc20ProxyId, erc20proxy.address, oldAddress),
|
||||||
|
);
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await exchange.registerAssetProxy.sendTransactionAsync(erc721ProxyId, erc721proxy.address, oldAddress),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Dummy ERC20 tokens
|
// Dummy ERC20 tokens
|
||||||
|
@ -52,7 +52,6 @@
|
|||||||
"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": {
|
||||||
"@0xproject/dev-utils": "^0.4.4",
|
"@0xproject/dev-utils": "^0.4.4",
|
||||||
"@0xproject/migrations": "^0.0.8",
|
|
||||||
"@0xproject/monorepo-scripts": "^0.2.1",
|
"@0xproject/monorepo-scripts": "^0.2.1",
|
||||||
"@0xproject/tslint-config": "^0.4.20",
|
"@0xproject/tslint-config": "^0.4.20",
|
||||||
"@types/ethereumjs-abi": "^0.6.0",
|
"@types/ethereumjs-abi": "^0.6.0",
|
||||||
|
@ -15,7 +15,7 @@ export class GanacheSubprovider extends Subprovider {
|
|||||||
* Instantiates a GanacheSubprovider
|
* Instantiates a GanacheSubprovider
|
||||||
* @param opts The desired opts with which to instantiate the Ganache provider
|
* @param opts The desired opts with which to instantiate the Ganache provider
|
||||||
*/
|
*/
|
||||||
constructor(opts: any) {
|
constructor(opts: Ganache.GanacheOpts) {
|
||||||
super();
|
super();
|
||||||
this._ganacheProvider = Ganache.provider(opts);
|
this._ganacheProvider = Ganache.provider(opts);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ declare module 'ganache-core' {
|
|||||||
};
|
};
|
||||||
port?: number;
|
port?: number;
|
||||||
network_id?: number;
|
network_id?: number;
|
||||||
|
networkId?: number;
|
||||||
mnemonic?: string;
|
mnemonic?: string;
|
||||||
|
gasLimit?: number;
|
||||||
}
|
}
|
||||||
// tslint:disable-next-line:completed-docs
|
// tslint:disable-next-line:completed-docs
|
||||||
export function provider(opts: GanacheOpts): Provider;
|
export function provider(opts: GanacheOpts): Provider;
|
||||||
|
@ -48,10 +48,10 @@ const styles: Styles = {
|
|||||||
width: 25,
|
width: 25,
|
||||||
},
|
},
|
||||||
offTrackStyle: {
|
offTrackStyle: {
|
||||||
backgroundColor: colors.allowanceToggleOffTrack,
|
backgroundColor: colors.grey300,
|
||||||
},
|
},
|
||||||
onTrackStyle: {
|
onTrackStyle: {
|
||||||
backgroundColor: colors.allowanceToggleOnTrack,
|
backgroundColor: colors.mediumBlue,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,8 +53,14 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
|
|||||||
public componentWillUnmount(): void {
|
public componentWillUnmount(): void {
|
||||||
this._unlisten();
|
this._unlisten();
|
||||||
}
|
}
|
||||||
public componentDidUpdate(): void {
|
public componentDidUpdate(prevProps: PortalOnboardingFlowProps): void {
|
||||||
this._adjustStepIfShould();
|
this._adjustStepIfShould();
|
||||||
|
if (!prevProps.isRunning && this.props.isRunning) {
|
||||||
|
// On mobile, make sure the wallet is completely visible.
|
||||||
|
if (this.props.screenWidth === ScreenWidths.Sm) {
|
||||||
|
document.querySelector('.wallet').scrollIntoView();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
|
@ -44,12 +44,13 @@ export const DrawerMenu = (props: DrawerMenuProps) => {
|
|||||||
iconName: 'zmdi-portable-wifi',
|
iconName: 'zmdi-portable-wifi',
|
||||||
};
|
};
|
||||||
const menuItemEntries = _.concat(relayerItemEntry, defaultMenuItemEntries);
|
const menuItemEntries = _.concat(relayerItemEntry, defaultMenuItemEntries);
|
||||||
const displayMessage = utils.getReadableAccountState(
|
const accountState = utils.getAccountState(
|
||||||
props.blockchainIsLoaded && !_.isUndefined(props.blockchain),
|
props.blockchainIsLoaded && !_.isUndefined(props.blockchain),
|
||||||
props.providerType,
|
props.providerType,
|
||||||
props.injectedProviderName,
|
props.injectedProviderName,
|
||||||
props.userAddress,
|
props.userAddress,
|
||||||
);
|
);
|
||||||
|
const displayMessage = utils.getReadableAccountState(accountState, props.userAddress);
|
||||||
return (
|
return (
|
||||||
<div style={styles.root}>
|
<div style={styles.root}>
|
||||||
<Header userAddress={props.userAddress} displayMessage={displayMessage} />
|
<Header userAddress={props.userAddress} displayMessage={displayMessage} />
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { colors, constants as sharedConstants } from '@0xproject/react-shared';
|
import { colors, constants as sharedConstants } from '@0xproject/react-shared';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
|
import Help from 'material-ui/svg-icons/action/help';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as DocumentTitle from 'react-document-title';
|
import * as DocumentTitle from 'react-document-title';
|
||||||
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
|
import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
import { Blockchain } from 'ts/blockchain';
|
import { Blockchain } from 'ts/blockchain';
|
||||||
import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog';
|
import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog';
|
||||||
@ -24,7 +24,6 @@ import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar';
|
|||||||
import { TradeHistory } from 'ts/components/trade_history/trade_history';
|
import { TradeHistory } from 'ts/components/trade_history/trade_history';
|
||||||
import { Container } from 'ts/components/ui/container';
|
import { Container } from 'ts/components/ui/container';
|
||||||
import { FlashMessage } from 'ts/components/ui/flash_message';
|
import { FlashMessage } from 'ts/components/ui/flash_message';
|
||||||
import { Island } from 'ts/components/ui/island';
|
|
||||||
import { Text } from 'ts/components/ui/text';
|
import { Text } from 'ts/components/ui/text';
|
||||||
import { Wallet } from 'ts/components/wallet/wallet';
|
import { Wallet } from 'ts/components/wallet/wallet';
|
||||||
import { GenerateOrderForm } from 'ts/containers/generate_order_form';
|
import { GenerateOrderForm } from 'ts/containers/generate_order_form';
|
||||||
@ -319,15 +318,14 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderWallet(): React.ReactNode {
|
private _renderWallet(): React.ReactNode {
|
||||||
const startOnboarding = this._renderStartOnboarding();
|
|
||||||
const isMobile = utils.isMobile(this.props.screenWidth);
|
const isMobile = utils.isMobile(this.props.screenWidth);
|
||||||
// We need room to scroll down for mobile onboarding
|
// We need room to scroll down for mobile onboarding
|
||||||
const marginBottom = isMobile ? '200px' : '15px';
|
const marginBottom = isMobile ? '200px' : '15px';
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Container>
|
<Container className="flex flex-column items-center">
|
||||||
{isMobile && <Container marginBottom="15px">{startOnboarding}</Container>}
|
{isMobile && <Container marginBottom="20px">{this._renderStartOnboarding()}</Container>}
|
||||||
<Container marginBottom={marginBottom}>
|
<Container marginBottom={marginBottom} width="100%">
|
||||||
<Wallet
|
<Wallet
|
||||||
style={
|
style={
|
||||||
!isMobile && this.props.isPortalOnboardingShowing
|
!isMobile && this.props.isPortalOnboardingShowing
|
||||||
@ -355,7 +353,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)}
|
refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
{!isMobile && <Container marginTop="15px">{startOnboarding}</Container>}
|
{!isMobile && <Container marginTop="8px">{this._renderStartOnboarding()}</Container>}
|
||||||
</Container>
|
</Container>
|
||||||
<PortalOnboardingFlow
|
<PortalOnboardingFlow
|
||||||
blockchain={this._blockchain}
|
blockchain={this._blockchain}
|
||||||
@ -366,26 +364,27 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderStartOnboarding(): React.ReactNode {
|
private _renderStartOnboarding(): React.ReactNode {
|
||||||
return (
|
const isMobile = utils.isMobile(this.props.screenWidth);
|
||||||
<Island>
|
const shouldStartOnboarding = !isMobile || this.props.location.pathname === `${WebsitePaths.Portal}/account`;
|
||||||
<Container
|
const startOnboarding = (
|
||||||
marginTop="30px"
|
<Container className="flex items-center center">
|
||||||
marginBottom="30px"
|
<Help style={{ width: '20px', height: '20px' }} color={colors.mediumBlue} />
|
||||||
marginLeft="30px"
|
<Container marginLeft="8px">
|
||||||
marginRight="30px"
|
<Text fontColor={colors.mediumBlue} fontSize="16px" onClick={this._startOnboarding.bind(this)}>
|
||||||
className="flex justify-around items-center"
|
|
||||||
>
|
|
||||||
<ActionAccountBalanceWallet style={{ width: '30px', height: '30px' }} color={colors.orange} />
|
|
||||||
<Text
|
|
||||||
fontColor={colors.grey}
|
|
||||||
fontSize="16px"
|
|
||||||
center={true}
|
|
||||||
onClick={this._startOnboarding.bind(this)}
|
|
||||||
>
|
|
||||||
Learn how to set up your account
|
Learn how to set up your account
|
||||||
</Text>
|
</Text>
|
||||||
</Container>
|
</Container>
|
||||||
</Island>
|
</Container>
|
||||||
|
);
|
||||||
|
return !shouldStartOnboarding ? (
|
||||||
|
<Link
|
||||||
|
to={{ pathname: `${WebsitePaths.Portal}/account`, state: { startOnboarding: true } }}
|
||||||
|
style={{ textDecoration: 'none' }}
|
||||||
|
>
|
||||||
|
{startOnboarding}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
startOnboarding
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,10 +392,6 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
||||||
analytics.logEvent('Portal', 'Onboarding Started - Manual', networkName, this.props.portalOnboardingStep);
|
analytics.logEvent('Portal', 'Onboarding Started - Manual', networkName, this.props.portalOnboardingStep);
|
||||||
this.props.dispatcher.updatePortalOnboardingShowing(true);
|
this.props.dispatcher.updatePortalOnboardingShowing(true);
|
||||||
// On mobile, make sure the wallet is completely visible.
|
|
||||||
if (this.props.screenWidth === ScreenWidths.Sm) {
|
|
||||||
document.querySelector('.wallet').scrollIntoView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private _renderWalletSection(): React.ReactNode {
|
private _renderWalletSection(): React.ReactNode {
|
||||||
return <Section header={<TextHeader labelText="Your Account" />} body={this._renderWallet()} />;
|
return <Section header={<TextHeader labelText="Your Account" />} body={this._renderWallet()} />;
|
||||||
@ -535,11 +530,15 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderRelayerIndexSection(): React.ReactNode {
|
private _renderRelayerIndexSection(): React.ReactNode {
|
||||||
|
return <Section header={<TextHeader labelText="0x Relayers" />} body={this._renderRelayerIndex()} />;
|
||||||
|
}
|
||||||
|
private _renderRelayerIndex(): React.ReactNode {
|
||||||
|
const isMobile = utils.isMobile(this.props.screenWidth);
|
||||||
return (
|
return (
|
||||||
<Section
|
<Container className="flex flex-column items-center">
|
||||||
header={<TextHeader labelText="0x Relayers" />}
|
{isMobile && <Container marginBottom="20px">{this._renderStartOnboarding()}</Container>}
|
||||||
body={<RelayerIndex networkId={this.props.networkId} screenWidth={this.props.screenWidth} />}
|
<RelayerIndex networkId={this.props.networkId} screenWidth={this.props.screenWidth} />
|
||||||
/>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderNotFoundMessage(): React.ReactNode {
|
private _renderNotFoundMessage(): React.ReactNode {
|
||||||
|
@ -6,9 +6,9 @@ export interface SectionProps {
|
|||||||
}
|
}
|
||||||
export const Section = (props: SectionProps) => {
|
export const Section = (props: SectionProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-column" style={{ height: '100%' }}>
|
<div className="flex flex-column">
|
||||||
{props.header}
|
{props.header}
|
||||||
<div className="flex-auto">{props.body}</div>
|
{props.body}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,19 +2,21 @@ import { Styles } from '@0xproject/react-shared';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import CircularProgress from 'material-ui/CircularProgress';
|
import CircularProgress from 'material-ui/CircularProgress';
|
||||||
import RaisedButton from 'material-ui/RaisedButton';
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
|
import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
|
||||||
|
import Lock from 'material-ui/svg-icons/action/lock';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { Blockchain } from 'ts/blockchain';
|
import { Blockchain } from 'ts/blockchain';
|
||||||
import { ProviderPicker } from 'ts/components/top_bar/provider_picker';
|
import { ProviderPicker } from 'ts/components/top_bar/provider_picker';
|
||||||
|
import { AccountConnection } from 'ts/components/ui/account_connection';
|
||||||
import { Container } from 'ts/components/ui/container';
|
import { Container } from 'ts/components/ui/container';
|
||||||
import { DropDown } from 'ts/components/ui/drop_down';
|
import { DropDown } from 'ts/components/ui/drop_down';
|
||||||
import { Identicon } from 'ts/components/ui/identicon';
|
import { Identicon } from 'ts/components/ui/identicon';
|
||||||
import { Image } from 'ts/components/ui/image';
|
|
||||||
import { Island } from 'ts/components/ui/island';
|
import { Island } from 'ts/components/ui/island';
|
||||||
import { Text } from 'ts/components/ui/text';
|
import { Text } from 'ts/components/ui/text';
|
||||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||||
import { colors } from 'ts/style/colors';
|
import { colors } from 'ts/style/colors';
|
||||||
import { ProviderType } from 'ts/types';
|
import { AccountState, ProviderType } from 'ts/types';
|
||||||
import { constants } from 'ts/utils/constants';
|
import { constants } from 'ts/utils/constants';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
|
|
||||||
@ -46,37 +48,13 @@ export class ProviderDisplay extends React.Component<ProviderDisplayProps, Provi
|
|||||||
this.props.providerType,
|
this.props.providerType,
|
||||||
this.props.injectedProviderName,
|
this.props.injectedProviderName,
|
||||||
);
|
);
|
||||||
const displayMessage = utils.getReadableAccountState(
|
|
||||||
this._isBlockchainReady(),
|
|
||||||
this.props.providerType,
|
|
||||||
this.props.injectedProviderName,
|
|
||||||
this.props.userAddress,
|
|
||||||
);
|
|
||||||
// If the "injected" provider is our fallback public node, then we want to
|
|
||||||
// show the "connect a wallet" message instead of the providerName
|
|
||||||
const injectedProviderName = isExternallyInjectedProvider
|
|
||||||
? this.props.injectedProviderName
|
|
||||||
: 'Connect a wallet';
|
|
||||||
const providerTitle =
|
|
||||||
this.props.providerType === ProviderType.Injected ? injectedProviderName : 'Ledger Nano S';
|
|
||||||
const isProviderMetamask = providerTitle === constants.PROVIDER_NAME_METAMASK;
|
|
||||||
const hoverActiveNode = (
|
const hoverActiveNode = (
|
||||||
<Island className="flex items-center p1" style={styles.root}>
|
<Island className="flex items-center py1 px2" style={styles.root}>
|
||||||
<div>
|
{this._renderIcon()}
|
||||||
{this._isBlockchainReady() ? (
|
|
||||||
<Identicon address={this.props.userAddress} diameter={ROOT_HEIGHT} />
|
|
||||||
) : (
|
|
||||||
<CircularProgress size={ROOT_HEIGHT} thickness={2} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<Container marginLeft="12px" marginRight="12px">
|
<Container marginLeft="12px" marginRight="12px">
|
||||||
<Text fontSize="14px" fontColor={colors.darkGrey}>
|
{this._renderDisplayMessage()}
|
||||||
{displayMessage}
|
|
||||||
</Text>
|
|
||||||
</Container>
|
</Container>
|
||||||
{isProviderMetamask && (
|
{this._renderInjectedProvider()}
|
||||||
<Image src="/images/metamask_icon.png" height={ROOT_HEIGHT} width={ROOT_HEIGHT} />
|
|
||||||
)}
|
|
||||||
</Island>
|
</Island>
|
||||||
);
|
);
|
||||||
const hasLedgerProvider = this.props.providerType === ProviderType.Ledger;
|
const hasLedgerProvider = this.props.providerType === ProviderType.Ledger;
|
||||||
@ -168,7 +146,69 @@ export class ProviderDisplay extends React.Component<ProviderDisplayProps, Provi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private _renderIcon(): React.ReactNode {
|
||||||
|
const accountState = this._getAccountState();
|
||||||
|
switch (accountState) {
|
||||||
|
case AccountState.Ready:
|
||||||
|
return <Identicon address={this.props.userAddress} diameter={ROOT_HEIGHT} />;
|
||||||
|
case AccountState.Loading:
|
||||||
|
return <CircularProgress size={ROOT_HEIGHT} thickness={2} />;
|
||||||
|
case AccountState.Locked:
|
||||||
|
return <Lock color={colors.black} />;
|
||||||
|
case AccountState.Disconnected:
|
||||||
|
return <ActionAccountBalanceWallet color={colors.mediumBlue} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private _renderDisplayMessage(): React.ReactNode {
|
||||||
|
const accountState = this._getAccountState();
|
||||||
|
const displayMessage = utils.getReadableAccountState(accountState, this.props.userAddress);
|
||||||
|
const fontColor = this._getDisplayMessageFontColor();
|
||||||
|
return (
|
||||||
|
<Text fontSize="16px" fontColor={fontColor} fontWeight={500}>
|
||||||
|
{displayMessage}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private _getDisplayMessageFontColor(): string {
|
||||||
|
const accountState = this._getAccountState();
|
||||||
|
switch (accountState) {
|
||||||
|
case AccountState.Loading:
|
||||||
|
return colors.darkGrey;
|
||||||
|
case AccountState.Ready:
|
||||||
|
case AccountState.Locked:
|
||||||
|
case AccountState.Disconnected:
|
||||||
|
default:
|
||||||
|
return colors.black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private _renderInjectedProvider(): React.ReactNode {
|
||||||
|
const accountState = this._getAccountState();
|
||||||
|
switch (accountState) {
|
||||||
|
case AccountState.Ready:
|
||||||
|
case AccountState.Locked:
|
||||||
|
return (
|
||||||
|
<AccountConnection
|
||||||
|
accountState={accountState}
|
||||||
|
injectedProviderName={this.props.injectedProviderName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case AccountState.Disconnected:
|
||||||
|
case AccountState.Loading:
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
private _isBlockchainReady(): boolean {
|
private _isBlockchainReady(): boolean {
|
||||||
return this.props.blockchainIsLoaded && !_.isUndefined(this.props.blockchain);
|
return this.props.blockchainIsLoaded && !_.isUndefined(this.props.blockchain);
|
||||||
}
|
}
|
||||||
|
private _getAccountState(): AccountState {
|
||||||
|
return utils.getAccountState(
|
||||||
|
this._isBlockchainReady(),
|
||||||
|
this.props.providerType,
|
||||||
|
this.props.injectedProviderName,
|
||||||
|
this.props.userAddress,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
40
packages/website/ts/components/ui/account_connection.tsx
Normal file
40
packages/website/ts/components/ui/account_connection.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Circle } from 'ts/components/ui/circle';
|
||||||
|
import { Container } from 'ts/components/ui/container';
|
||||||
|
import { Text } from 'ts/components/ui/text';
|
||||||
|
import { colors } from 'ts/style/colors';
|
||||||
|
import { AccountState } from 'ts/types';
|
||||||
|
|
||||||
|
export interface AccountConnectionProps {
|
||||||
|
accountState: AccountState;
|
||||||
|
injectedProviderName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AccountConnection: React.StatelessComponent<AccountConnectionProps> = ({
|
||||||
|
accountState,
|
||||||
|
injectedProviderName,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Container className="flex items-center">
|
||||||
|
<Circle diameter={6} fillColor={getInjectedProviderColor(accountState)} />
|
||||||
|
<Container marginLeft="6px">
|
||||||
|
<Text fontSize="12px" lineHeight="14px" fontColor={colors.darkGrey}>
|
||||||
|
{injectedProviderName}
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getInjectedProviderColor = (accountState: AccountState) => {
|
||||||
|
switch (accountState) {
|
||||||
|
case AccountState.Ready:
|
||||||
|
return colors.limeGreen;
|
||||||
|
case AccountState.Locked:
|
||||||
|
case AccountState.Loading:
|
||||||
|
case AccountState.Disconnected:
|
||||||
|
default:
|
||||||
|
return colors.red;
|
||||||
|
}
|
||||||
|
};
|
16
packages/website/ts/components/ui/circle.tsx
Normal file
16
packages/website/ts/components/ui/circle.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export interface CircleProps {
|
||||||
|
className?: string;
|
||||||
|
diameter: number;
|
||||||
|
fillColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Circle: React.StatelessComponent<CircleProps> = ({ className, diameter, fillColor }) => {
|
||||||
|
const radius = diameter / 2;
|
||||||
|
return (
|
||||||
|
<svg className={className} height={diameter} width={diameter}>
|
||||||
|
<circle cx={radius} cy={radius} r={radius} fill={fillColor} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
@ -14,7 +14,9 @@ export interface ContainerProps {
|
|||||||
backgroundColor?: string;
|
backgroundColor?: string;
|
||||||
borderRadius?: StringOrNum;
|
borderRadius?: StringOrNum;
|
||||||
maxWidth?: StringOrNum;
|
maxWidth?: StringOrNum;
|
||||||
|
maxHeight?: StringOrNum;
|
||||||
width?: StringOrNum;
|
width?: StringOrNum;
|
||||||
|
height?: StringOrNum;
|
||||||
minHeight?: StringOrNum;
|
minHeight?: StringOrNum;
|
||||||
isHidden?: boolean;
|
isHidden?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -2,6 +2,7 @@ import blockies = require('blockies');
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Circle } from 'ts/components/ui/circle';
|
||||||
import { Image } from 'ts/components/ui/image';
|
import { Image } from 'ts/components/ui/image';
|
||||||
import { colors } from 'ts/style/colors';
|
import { colors } from 'ts/style/colors';
|
||||||
|
|
||||||
@ -20,7 +21,6 @@ export class Identicon extends React.Component<IdenticonProps, IdenticonState> {
|
|||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const address = this.props.address;
|
const address = this.props.address;
|
||||||
const diameter = this.props.diameter;
|
const diameter = this.props.diameter;
|
||||||
const radius = diameter / 2;
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="circle relative transitionFix"
|
className="circle relative transitionFix"
|
||||||
@ -40,9 +40,7 @@ export class Identicon extends React.Component<IdenticonProps, IdenticonState> {
|
|||||||
width={diameter}
|
width={diameter}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<svg height={diameter} width={diameter}>
|
<Circle diameter={diameter} fillColor={colors.grey200} />
|
||||||
<circle cx={radius} cy={radius} r={radius} fill={colors.grey200} />
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -15,6 +15,7 @@ export interface TextProps {
|
|||||||
minHeight?: string;
|
minHeight?: string;
|
||||||
center?: boolean;
|
center?: boolean;
|
||||||
fontWeight?: number | string;
|
fontWeight?: number | string;
|
||||||
|
textDecorationLine?: string;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ export const Text = styled(PlainText)`
|
|||||||
font-family: ${props => props.fontFamily};
|
font-family: ${props => props.fontFamily};
|
||||||
font-weight: ${props => props.fontWeight};
|
font-weight: ${props => props.fontWeight};
|
||||||
font-size: ${props => props.fontSize};
|
font-size: ${props => props.fontSize};
|
||||||
|
text-decoration-line: ${props => props.textDecorationLine};
|
||||||
${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
|
${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
|
||||||
${props => (props.center ? 'text-align: center' : '')};
|
${props => (props.center ? 'text-align: center' : '')};
|
||||||
color: ${props => props.fontColor};
|
color: ${props => props.fontColor};
|
||||||
@ -45,6 +47,7 @@ Text.defaultProps = {
|
|||||||
fontColor: colors.black,
|
fontColor: colors.black,
|
||||||
fontSize: '15px',
|
fontSize: '15px',
|
||||||
lineHeight: '1.5em',
|
lineHeight: '1.5em',
|
||||||
|
textDecorationLine: 'none',
|
||||||
Tag: 'div',
|
Tag: 'div',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
146
packages/website/ts/components/wallet/body_overlay.tsx
Normal file
146
packages/website/ts/components/wallet/body_overlay.tsx
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import * as _ from 'lodash';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Blockchain } from 'ts/blockchain';
|
||||||
|
import { Container } from 'ts/components/ui/container';
|
||||||
|
import { Image } from 'ts/components/ui/image';
|
||||||
|
import { Island } from 'ts/components/ui/island';
|
||||||
|
import { Text } from 'ts/components/ui/text';
|
||||||
|
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||||
|
import { colors } from 'ts/style/colors';
|
||||||
|
import { styled } from 'ts/style/theme';
|
||||||
|
import { AccountState, BrowserType, ProviderType } from 'ts/types';
|
||||||
|
import { constants } from 'ts/utils/constants';
|
||||||
|
import { utils } from 'ts/utils/utils';
|
||||||
|
|
||||||
|
const METAMASK_IMG_SRC = '/images/metamask_icon.png';
|
||||||
|
|
||||||
|
export interface BodyOverlayProps {
|
||||||
|
dispatcher: Dispatcher;
|
||||||
|
userAddress: string;
|
||||||
|
injectedProviderName: string;
|
||||||
|
providerType: ProviderType;
|
||||||
|
onToggleLedgerDialog: () => void;
|
||||||
|
blockchain?: Blockchain;
|
||||||
|
blockchainIsLoaded: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BodyOverlayState {}
|
||||||
|
|
||||||
|
export class BodyOverlay extends React.Component<BodyOverlayProps, BodyOverlayState> {
|
||||||
|
public render(): React.ReactNode {
|
||||||
|
const accountState = this._getAccountState();
|
||||||
|
switch (accountState) {
|
||||||
|
case AccountState.Locked:
|
||||||
|
return <LockedOverlay onUseDifferentWalletClicked={this.props.onToggleLedgerDialog} />;
|
||||||
|
case AccountState.Disconnected:
|
||||||
|
return <DisconnectedOverlay onUseDifferentWalletClicked={this.props.onToggleLedgerDialog} />;
|
||||||
|
case AccountState.Ready:
|
||||||
|
case AccountState.Loading:
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private _isBlockchainReady(): boolean {
|
||||||
|
return this.props.blockchainIsLoaded && !_.isUndefined(this.props.blockchain);
|
||||||
|
}
|
||||||
|
private _getAccountState(): AccountState {
|
||||||
|
return utils.getAccountState(
|
||||||
|
this._isBlockchainReady(),
|
||||||
|
this.props.providerType,
|
||||||
|
this.props.injectedProviderName,
|
||||||
|
this.props.userAddress,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LockedOverlayProps {
|
||||||
|
className?: string;
|
||||||
|
onUseDifferentWalletClicked?: () => void;
|
||||||
|
}
|
||||||
|
const PlainLockedOverlay: React.StatelessComponent<LockedOverlayProps> = ({
|
||||||
|
className,
|
||||||
|
onUseDifferentWalletClicked,
|
||||||
|
}) => (
|
||||||
|
<div className={className}>
|
||||||
|
<Container
|
||||||
|
className="flex flex-column items-center"
|
||||||
|
marginBottom="24px"
|
||||||
|
marginTop="24px"
|
||||||
|
marginLeft="48px"
|
||||||
|
marginRight="48px"
|
||||||
|
>
|
||||||
|
<Image src={METAMASK_IMG_SRC} height="70px" />
|
||||||
|
<Container marginTop="12px">
|
||||||
|
<Text fontColor={colors.metaMaskOrange} fontSize="16px" fontWeight="bold">
|
||||||
|
Please Unlock MetaMask
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
<UseDifferentWallet fontColor={colors.darkGrey} onClick={onUseDifferentWalletClicked} />
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
const LockedOverlay = styled(PlainLockedOverlay)`
|
||||||
|
background: ${colors.metaMaskTransparentOrange};
|
||||||
|
border: 1px solid ${colors.metaMaskOrange};
|
||||||
|
border-radius: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface DisconnectedOverlayProps {
|
||||||
|
onUseDifferentWalletClicked?: () => void;
|
||||||
|
}
|
||||||
|
const DisconnectedOverlay = (props: DisconnectedOverlayProps) => {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-column items-center">
|
||||||
|
<GetMetaMask />
|
||||||
|
<UseDifferentWallet fontColor={colors.mediumBlue} onClick={props.onUseDifferentWalletClicked} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface UseDifferentWallet {
|
||||||
|
fontColor: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
const UseDifferentWallet = (props: UseDifferentWallet) => {
|
||||||
|
return (
|
||||||
|
<Container marginTop="12px">
|
||||||
|
<Text fontColor={props.fontColor} fontSize="16px" textDecorationLine="underline" onClick={props.onClick}>
|
||||||
|
Use a different wallet
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GetMetaMask = () => {
|
||||||
|
const browserType = utils.getBrowserType();
|
||||||
|
let extensionLink;
|
||||||
|
switch (browserType) {
|
||||||
|
case BrowserType.Chrome:
|
||||||
|
extensionLink = constants.URL_METAMASK_CHROME_STORE;
|
||||||
|
break;
|
||||||
|
case BrowserType.Firefox:
|
||||||
|
extensionLink = constants.URL_METAMASK_FIREFOX_STORE;
|
||||||
|
break;
|
||||||
|
case BrowserType.Opera:
|
||||||
|
extensionLink = constants.URL_METAMASK_OPERA_STORE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
extensionLink = constants.URL_METAMASK_HOMEPAGE;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a href={extensionLink} target="_blank" style={{ textDecoration: 'none' }}>
|
||||||
|
<Island
|
||||||
|
className="flex items-center py1 px2"
|
||||||
|
style={{ height: 28, borderRadius: 28, backgroundColor: colors.mediumBlue }}
|
||||||
|
>
|
||||||
|
<Image src={METAMASK_IMG_SRC} width="28px" />
|
||||||
|
<Container marginLeft="8px" marginRight="12px">
|
||||||
|
<Text fontColor={colors.white} fontSize="16px" fontWeight={500}>
|
||||||
|
Get MetaMask Wallet
|
||||||
|
</Text>
|
||||||
|
</Container>
|
||||||
|
</Island>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
41
packages/website/ts/components/wallet/null_token_row.tsx
Normal file
41
packages/website/ts/components/wallet/null_token_row.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Circle } from 'ts/components/ui/circle';
|
||||||
|
import { Container } from 'ts/components/ui/container';
|
||||||
|
import { Text } from 'ts/components/ui/text';
|
||||||
|
import { PlaceHolder } from 'ts/components/wallet/placeholder';
|
||||||
|
import { StandardIconRow } from 'ts/components/wallet/standard_icon_row';
|
||||||
|
import { colors } from 'ts/style/colors';
|
||||||
|
|
||||||
|
export interface NullTokenRowProps {
|
||||||
|
iconDimension: number;
|
||||||
|
fillColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NullTokenRow: React.StatelessComponent<NullTokenRowProps> = ({ iconDimension, fillColor }) => {
|
||||||
|
const icon = <Circle diameter={iconDimension} fillColor={fillColor} />;
|
||||||
|
const main = (
|
||||||
|
<div className="flex flex-column">
|
||||||
|
<PlaceHolder hideChildren={true} fillColor={fillColor}>
|
||||||
|
<Text fontSize="16px" fontWeight="bold" lineHeight="1em">
|
||||||
|
0.00 XXX
|
||||||
|
</Text>
|
||||||
|
</PlaceHolder>
|
||||||
|
<Container marginTop="3px">
|
||||||
|
<PlaceHolder hideChildren={true} fillColor={fillColor}>
|
||||||
|
<Text fontSize="14px" fontColor={colors.darkGrey} lineHeight="1em">
|
||||||
|
$0.00
|
||||||
|
</Text>
|
||||||
|
</PlaceHolder>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
const accessory = (
|
||||||
|
<Container marginRight="12px">
|
||||||
|
<PlaceHolder hideChildren={true} fillColor={fillColor}>
|
||||||
|
<Container width="20px" height="14px" />
|
||||||
|
</PlaceHolder>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
return <StandardIconRow icon={icon} main={main} accessory={accessory} />;
|
||||||
|
};
|
25
packages/website/ts/components/wallet/placeholder.tsx
Normal file
25
packages/website/ts/components/wallet/placeholder.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { styled } from 'ts/style/theme';
|
||||||
|
|
||||||
|
export interface PlaceHolderProps {
|
||||||
|
className?: string;
|
||||||
|
hideChildren: React.ReactNode;
|
||||||
|
fillColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PlainPlaceHolder: React.StatelessComponent<PlaceHolderProps> = ({ className, hideChildren, children }) => {
|
||||||
|
const childrenVisibility = hideChildren ? 'hidden' : 'visible';
|
||||||
|
const childrenStyle: React.CSSProperties = { visibility: childrenVisibility };
|
||||||
|
return (
|
||||||
|
<div className={className}>
|
||||||
|
<div style={childrenStyle}>{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PlaceHolder = styled(PlainPlaceHolder)`
|
||||||
|
background-color: ${props => (props.hideChildren ? props.fillColor : 'transparent')};
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 2px;
|
||||||
|
`;
|
44
packages/website/ts/components/wallet/standard_icon_row.tsx
Normal file
44
packages/website/ts/components/wallet/standard_icon_row.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { colors } from 'ts/style/colors';
|
||||||
|
import { styled } from 'ts/style/theme';
|
||||||
|
|
||||||
|
export interface StandardIconRowProps {
|
||||||
|
className?: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
main: React.ReactNode;
|
||||||
|
accessory?: React.ReactNode;
|
||||||
|
minHeight?: string;
|
||||||
|
borderBottomColor?: string;
|
||||||
|
borderBottomStyle?: string;
|
||||||
|
borderWidth?: string;
|
||||||
|
backgroundColor?: string;
|
||||||
|
}
|
||||||
|
const PlainStandardIconRow: React.StatelessComponent<StandardIconRowProps> = ({ className, icon, main, accessory }) => {
|
||||||
|
return (
|
||||||
|
<div className={`flex items-center ${className}`}>
|
||||||
|
<div className="flex items-center px2">{icon}</div>
|
||||||
|
<div className="flex-none pr2">{main}</div>
|
||||||
|
<div className="flex-auto" />
|
||||||
|
<div>{accessory}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const StandardIconRow = styled(PlainStandardIconRow)`
|
||||||
|
min-height: ${props => props.minHeight};
|
||||||
|
border-bottom-color: ${props => props.borderBottomColor};
|
||||||
|
border-bottom-style: ${props => props.borderBottomStyle};
|
||||||
|
border-width: ${props => props.borderWidth};
|
||||||
|
background-color: ${props => props.backgroundColor};
|
||||||
|
`;
|
||||||
|
|
||||||
|
StandardIconRow.defaultProps = {
|
||||||
|
minHeight: '85px',
|
||||||
|
borderBottomColor: colors.walletBorder,
|
||||||
|
borderBottomStyle: 'solid',
|
||||||
|
borderWidth: '1px',
|
||||||
|
backgroundColor: colors.walletDefaultItemBackground,
|
||||||
|
};
|
||||||
|
|
||||||
|
StandardIconRow.displayName = 'StandardIconRow';
|
@ -1,36 +1,31 @@
|
|||||||
import {
|
import { constants as sharedConstants, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared';
|
||||||
constants as sharedConstants,
|
|
||||||
EtherscanLinkSuffixes,
|
|
||||||
Styles,
|
|
||||||
utils as sharedUtils,
|
|
||||||
} from '@0xproject/react-shared';
|
|
||||||
import { BigNumber, errorUtils } from '@0xproject/utils';
|
import { BigNumber, errorUtils } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import CircularProgress from 'material-ui/CircularProgress';
|
|
||||||
import FloatingActionButton from 'material-ui/FloatingActionButton';
|
|
||||||
|
|
||||||
import { ListItem } from 'material-ui/List';
|
|
||||||
import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
|
import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
|
||||||
import ContentAdd from 'material-ui/svg-icons/content/add';
|
|
||||||
import ContentRemove from 'material-ui/svg-icons/content/remove';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import firstBy = require('thenby');
|
import firstBy = require('thenby');
|
||||||
|
|
||||||
import { Blockchain } from 'ts/blockchain';
|
import { Blockchain } from 'ts/blockchain';
|
||||||
|
import { AccountConnection } from 'ts/components/ui/account_connection';
|
||||||
import { Container } from 'ts/components/ui/container';
|
import { Container } from 'ts/components/ui/container';
|
||||||
import { IconButton } from 'ts/components/ui/icon_button';
|
import { IconButton } from 'ts/components/ui/icon_button';
|
||||||
import { Identicon } from 'ts/components/ui/identicon';
|
import { Identicon } from 'ts/components/ui/identicon';
|
||||||
import { Island } from 'ts/components/ui/island';
|
import { Island } from 'ts/components/ui/island';
|
||||||
|
import { Text } from 'ts/components/ui/text';
|
||||||
import { TokenIcon } from 'ts/components/ui/token_icon';
|
import { TokenIcon } from 'ts/components/ui/token_icon';
|
||||||
import { WalletDisconnectedItem } from 'ts/components/wallet/wallet_disconnected_item';
|
import { BodyOverlay } from 'ts/components/wallet/body_overlay';
|
||||||
|
import { NullTokenRow } from 'ts/components/wallet/null_token_row';
|
||||||
|
import { PlaceHolder } from 'ts/components/wallet/placeholder';
|
||||||
|
import { StandardIconRow } from 'ts/components/wallet/standard_icon_row';
|
||||||
import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item';
|
import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item';
|
||||||
import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
|
import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
|
||||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||||
import { colors } from 'ts/style/colors';
|
import { colors } from 'ts/style/colors';
|
||||||
import { styled } from 'ts/style/theme';
|
|
||||||
import {
|
import {
|
||||||
|
AccountState,
|
||||||
BlockchainErrs,
|
BlockchainErrs,
|
||||||
ProviderType,
|
ProviderType,
|
||||||
ScreenWidths,
|
ScreenWidths,
|
||||||
@ -44,7 +39,6 @@ import {
|
|||||||
import { analytics } from 'ts/utils/analytics';
|
import { analytics } from 'ts/utils/analytics';
|
||||||
import { constants } from 'ts/utils/constants';
|
import { constants } from 'ts/utils/constants';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles';
|
|
||||||
|
|
||||||
export interface WalletProps {
|
export interface WalletProps {
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
@ -84,66 +78,16 @@ interface AccessoryItemConfig {
|
|||||||
allowanceToggleConfig?: AllowanceToggleConfig;
|
allowanceToggleConfig?: AllowanceToggleConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles: Styles = {
|
|
||||||
root: {
|
|
||||||
width: '100%',
|
|
||||||
},
|
|
||||||
footerItemInnerDiv: {
|
|
||||||
paddingLeft: 24,
|
|
||||||
borderTopColor: colors.walletBorder,
|
|
||||||
borderTopStyle: 'solid',
|
|
||||||
borderWidth: 1,
|
|
||||||
},
|
|
||||||
borderedItem: {
|
|
||||||
borderBottomColor: colors.walletBorder,
|
|
||||||
borderBottomStyle: 'solid',
|
|
||||||
borderWidth: 1,
|
|
||||||
},
|
|
||||||
tokenItem: {
|
|
||||||
backgroundColor: colors.walletDefaultItemBackground,
|
|
||||||
minHeight: 85,
|
|
||||||
},
|
|
||||||
amountLabel: {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: colors.black,
|
|
||||||
},
|
|
||||||
valueLabel: {
|
|
||||||
color: colors.grey,
|
|
||||||
fontSize: 14,
|
|
||||||
},
|
|
||||||
paddedItem: {
|
|
||||||
paddingTop: 8,
|
|
||||||
paddingBottom: 8,
|
|
||||||
},
|
|
||||||
bodyInnerDiv: {
|
|
||||||
overflow: 'auto',
|
|
||||||
WebkitOverflowScrolling: 'touch',
|
|
||||||
},
|
|
||||||
manageYourWalletText: {
|
|
||||||
color: colors.mediumBlue,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
},
|
|
||||||
loadingBody: {
|
|
||||||
height: 381,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const ETHER_ICON_PATH = '/images/ether.png';
|
const ETHER_ICON_PATH = '/images/ether.png';
|
||||||
const ICON_DIMENSION = 28;
|
const ICON_DIMENSION = 28;
|
||||||
const BODY_ITEM_KEY = 'BODY';
|
const BODY_ITEM_KEY = 'BODY';
|
||||||
const HEADER_ITEM_KEY = 'HEADER';
|
const HEADER_ITEM_KEY = 'HEADER';
|
||||||
const FOOTER_ITEM_KEY = 'FOOTER';
|
|
||||||
const DISCONNECTED_ITEM_KEY = 'DISCONNECTED';
|
|
||||||
const ETHER_ITEM_KEY = 'ETHER';
|
const ETHER_ITEM_KEY = 'ETHER';
|
||||||
const USD_DECIMAL_PLACES = 2;
|
const USD_DECIMAL_PLACES = 2;
|
||||||
const NO_ALLOWANCE_TOGGLE_SPACE_WIDTH = 56;
|
const NO_ALLOWANCE_TOGGLE_SPACE_WIDTH = 56;
|
||||||
const ACCOUNT_PATH = `${WebsitePaths.Portal}/account`;
|
const ACCOUNT_PATH = `${WebsitePaths.Portal}/account`;
|
||||||
|
const PLACEHOLDER_COLOR = colors.grey300;
|
||||||
const ActionButton = styled(FloatingActionButton)`
|
const LOADING_ROWS_COUNT = 6;
|
||||||
button {
|
|
||||||
position: static !important;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export class Wallet extends React.Component<WalletProps, WalletState> {
|
export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||||
public static defaultProps = {
|
public static defaultProps = {
|
||||||
@ -171,72 +115,103 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const isBlockchainLoaded = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError;
|
|
||||||
return (
|
return (
|
||||||
<Island className="flex flex-column wallet" style={{ ...styles.root, ...this.props.style }}>
|
<Island className="flex flex-column wallet" style={this.props.style}>
|
||||||
{isBlockchainLoaded ? this._renderLoadedRows() : this._renderLoadingRows()}
|
{this._isBlockchainReady() ? this._renderLoadedRows() : this._renderLoadingRows()}
|
||||||
</Island>
|
</Island>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
private _renderLoadingRows(): React.ReactNode {
|
||||||
|
return _.concat(this._renderLoadingHeaderRows(), this._renderLoadingBodyRows());
|
||||||
|
}
|
||||||
|
private _renderLoadingHeaderRows(): React.ReactElement<{}> {
|
||||||
|
return this._renderPlainHeaderRow('Loading...');
|
||||||
|
}
|
||||||
|
private _renderLoadingBodyRows(): React.ReactElement<{}> {
|
||||||
|
const bodyStyle = this._getBodyStyle();
|
||||||
|
const loadingRowsRange = _.range(LOADING_ROWS_COUNT);
|
||||||
|
return (
|
||||||
|
<div key={BODY_ITEM_KEY} className="flex flex-column" style={bodyStyle}>
|
||||||
|
{_.map(loadingRowsRange, index => {
|
||||||
|
return <NullTokenRow key={index} iconDimension={ICON_DIMENSION} fillColor={PLACEHOLDER_COLOR} />;
|
||||||
|
})}
|
||||||
|
<Container
|
||||||
|
className="flex items-center"
|
||||||
|
position="absolute"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
maxHeight={bodyStyle.maxHeight}
|
||||||
|
>
|
||||||
|
<div className="mx-auto">
|
||||||
|
<BodyOverlay
|
||||||
|
dispatcher={this.props.dispatcher}
|
||||||
|
userAddress={this.props.userAddress}
|
||||||
|
injectedProviderName={this.props.injectedProviderName}
|
||||||
|
providerType={this.props.providerType}
|
||||||
|
onToggleLedgerDialog={this.props.onToggleLedgerDialog}
|
||||||
|
blockchain={this.props.blockchain}
|
||||||
|
blockchainIsLoaded={this.props.blockchainIsLoaded}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
private _renderLoadedRows(): React.ReactNode {
|
private _renderLoadedRows(): React.ReactNode {
|
||||||
const isAddressAvailable = !_.isEmpty(this.props.userAddress);
|
const isAddressAvailable = !_.isEmpty(this.props.userAddress);
|
||||||
return isAddressAvailable
|
return isAddressAvailable
|
||||||
? _.concat(this._renderConnectedHeaderRows(), this._renderBody(), this._renderFooterRows())
|
? _.concat(this._renderConnectedHeaderRows(), this._renderBody())
|
||||||
: _.concat(this._renderDisconnectedHeaderRows(), this._renderDisconnectedRows());
|
: _.concat(this._renderDisconnectedHeaderRows(), this._renderLoadingBodyRows());
|
||||||
}
|
|
||||||
private _renderLoadingRows(): React.ReactNode {
|
|
||||||
return _.concat(this._renderDisconnectedHeaderRows(), this._renderLoadingBodyRows());
|
|
||||||
}
|
|
||||||
private _renderLoadingBodyRows(): React.ReactElement<{}> {
|
|
||||||
return (
|
|
||||||
<div key={BODY_ITEM_KEY} className="flex items-center" style={styles.loadingBody}>
|
|
||||||
<div className="mx-auto">
|
|
||||||
<CircularProgress size={40} thickness={5} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
private _renderDisconnectedHeaderRows(): React.ReactElement<{}> {
|
private _renderDisconnectedHeaderRows(): React.ReactElement<{}> {
|
||||||
const primaryText = 'wallet';
|
const isExternallyInjectedProvider = utils.isExternallyInjected(
|
||||||
|
this.props.providerType,
|
||||||
|
this.props.injectedProviderName,
|
||||||
|
);
|
||||||
|
const text = isExternallyInjectedProvider ? 'Please unlock MetaMask...' : 'Please connect a wallet...';
|
||||||
|
return this._renderPlainHeaderRow(text);
|
||||||
|
}
|
||||||
|
private _renderPlainHeaderRow(text: string): React.ReactElement<{}> {
|
||||||
return (
|
return (
|
||||||
<StandardIconRow
|
<StandardIconRow
|
||||||
key={HEADER_ITEM_KEY}
|
key={HEADER_ITEM_KEY}
|
||||||
icon={<ActionAccountBalanceWallet color={colors.mediumBlue} />}
|
icon={<ActionAccountBalanceWallet color={colors.grey} />}
|
||||||
main={primaryText.toUpperCase()}
|
main={
|
||||||
style={styles.borderedItem}
|
<Text fontSize="16px" fontColor={colors.grey}>
|
||||||
/>
|
{text}
|
||||||
);
|
</Text>
|
||||||
}
|
// https://github.com/palantir/tslint-react/issues/140
|
||||||
private _renderDisconnectedRows(): React.ReactElement<{}> {
|
// tslint:disable-next-line:jsx-curly-spacing
|
||||||
return (
|
}
|
||||||
<WalletDisconnectedItem
|
minHeight="60px"
|
||||||
key={DISCONNECTED_ITEM_KEY}
|
backgroundColor={colors.white}
|
||||||
providerType={this.props.providerType}
|
|
||||||
injectedProviderName={this.props.injectedProviderName}
|
|
||||||
onToggleLedgerDialog={this.props.onToggleLedgerDialog}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderConnectedHeaderRows(): React.ReactElement<{}> {
|
private _renderConnectedHeaderRows(): React.ReactElement<{}> {
|
||||||
const userAddress = this.props.userAddress;
|
const userAddress = this.props.userAddress;
|
||||||
const primaryText = utils.getAddressBeginAndEnd(userAddress);
|
const accountState = this._getAccountState();
|
||||||
|
const main = (
|
||||||
|
<div className="flex flex-column">
|
||||||
|
<Text fontSize="16px" lineHeight="19px" fontWeight={500}>
|
||||||
|
{utils.getAddressBeginAndEnd(userAddress)}
|
||||||
|
</Text>
|
||||||
|
<AccountConnection accountState={accountState} injectedProviderName={this.props.injectedProviderName} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Link key={HEADER_ITEM_KEY} to={ACCOUNT_PATH} style={{ textDecoration: 'none' }}>
|
<Link key={HEADER_ITEM_KEY} to={ACCOUNT_PATH} style={{ textDecoration: 'none' }}>
|
||||||
<StandardIconRow
|
<StandardIconRow
|
||||||
icon={<Identicon address={userAddress} diameter={ICON_DIMENSION} />}
|
icon={<Identicon address={userAddress} diameter={ICON_DIMENSION} />}
|
||||||
main={primaryText}
|
main={main}
|
||||||
style={styles.borderedItem}
|
minHeight="60px"
|
||||||
|
backgroundColor={colors.white}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private _renderBody(): React.ReactElement<{}> {
|
private _renderBody(): React.ReactElement<{}> {
|
||||||
const bodyStyle: React.CSSProperties = {
|
const bodyStyle = this._getBodyStyle();
|
||||||
...styles.bodyInnerDiv,
|
|
||||||
overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden',
|
|
||||||
// TODO: make this completely responsive
|
|
||||||
maxHeight: this.props.screenWidth !== ScreenWidths.Sm ? 475 : undefined,
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={bodyStyle}
|
style={bodyStyle}
|
||||||
@ -249,6 +224,17 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
private _getBodyStyle(): React.CSSProperties {
|
||||||
|
return {
|
||||||
|
overflow: 'auto',
|
||||||
|
WebkitOverflowScrolling: 'touch',
|
||||||
|
position: 'relative',
|
||||||
|
overflowY: this.state.isHoveringSidebar ? 'scroll' : 'hidden',
|
||||||
|
marginRight: this.state.isHoveringSidebar ? 0 : 4,
|
||||||
|
// TODO: make this completely responsive
|
||||||
|
maxHeight: this.props.screenWidth !== ScreenWidths.Sm ? 475 : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
|
private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
|
||||||
this.setState({
|
this.setState({
|
||||||
isHoveringSidebar: true,
|
isHoveringSidebar: true,
|
||||||
@ -259,51 +245,6 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
isHoveringSidebar: false,
|
isHoveringSidebar: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private _renderFooterRows(): React.ReactElement<{}> {
|
|
||||||
return (
|
|
||||||
<div key={FOOTER_ITEM_KEY}>
|
|
||||||
<ListItem
|
|
||||||
primaryText={
|
|
||||||
<div className="flex">
|
|
||||||
<ActionButton mini={true} zDepth={0} onClick={this.props.onAddToken}>
|
|
||||||
<ContentAdd />
|
|
||||||
</ActionButton>
|
|
||||||
<ActionButton mini={true} zDepth={0} className="px1" onClick={this.props.onRemoveToken}>
|
|
||||||
<ContentRemove />
|
|
||||||
</ActionButton>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
paddingLeft: 10,
|
|
||||||
position: 'relative',
|
|
||||||
top: '50%',
|
|
||||||
transform: 'translateY(33%)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
add/remove tokens
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
disabled={true}
|
|
||||||
innerDivStyle={styles.footerItemInnerDiv}
|
|
||||||
style={styles.borderedItem}
|
|
||||||
/>
|
|
||||||
{this.props.location.pathname !== ACCOUNT_PATH && (
|
|
||||||
<Link to={ACCOUNT_PATH} style={{ textDecoration: 'none' }}>
|
|
||||||
<ListItem
|
|
||||||
primaryText={
|
|
||||||
<div className="flex right" style={styles.manageYourWalletText}>
|
|
||||||
manage your wallet
|
|
||||||
</div>
|
|
||||||
// https://github.com/palantir/tslint-react/issues/140
|
|
||||||
// tslint:disable-next-line:jsx-curly-spacing
|
|
||||||
}
|
|
||||||
style={{ ...styles.paddedItem, ...styles.borderedItem }}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
private _renderEthRows(): React.ReactNode {
|
private _renderEthRows(): React.ReactNode {
|
||||||
const icon = <img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={ETHER_ICON_PATH} />;
|
const icon = <img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={ETHER_ICON_PATH} />;
|
||||||
const primaryText = this._renderAmount(
|
const primaryText = this._renderAmount(
|
||||||
@ -325,7 +266,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
wrappedEtherDirection: Side.Deposit,
|
wrappedEtherDirection: Side.Deposit,
|
||||||
};
|
};
|
||||||
const key = ETHER_ITEM_KEY;
|
const key = ETHER_ITEM_KEY;
|
||||||
return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig, false);
|
return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig);
|
||||||
}
|
}
|
||||||
private _renderTokenRows(): React.ReactNode {
|
private _renderTokenRows(): React.ReactNode {
|
||||||
const trackedTokens = this.props.trackedTokens;
|
const trackedTokens = this.props.trackedTokens;
|
||||||
@ -336,7 +277,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
);
|
);
|
||||||
return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this));
|
return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this));
|
||||||
}
|
}
|
||||||
private _renderTokenRow(token: Token, index: number): React.ReactNode {
|
private _renderTokenRow(token: Token): React.ReactNode {
|
||||||
const tokenState = this.props.trackedTokenStateByAddress[token.address];
|
const tokenState = this.props.trackedTokenStateByAddress[token.address];
|
||||||
if (_.isUndefined(tokenState)) {
|
if (_.isUndefined(tokenState)) {
|
||||||
return null;
|
return null;
|
||||||
@ -364,8 +305,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const key = token.address;
|
const key = token.address;
|
||||||
const isLastRow = index === this.props.trackedTokens.length - 1;
|
return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig);
|
||||||
return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig, isLastRow);
|
|
||||||
}
|
}
|
||||||
private _renderBalanceRow(
|
private _renderBalanceRow(
|
||||||
key: string,
|
key: string,
|
||||||
@ -373,20 +313,12 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
primaryText: React.ReactNode,
|
primaryText: React.ReactNode,
|
||||||
secondaryText: React.ReactNode,
|
secondaryText: React.ReactNode,
|
||||||
accessoryItemConfig: AccessoryItemConfig,
|
accessoryItemConfig: AccessoryItemConfig,
|
||||||
isLastRow: boolean,
|
|
||||||
className?: string,
|
className?: string,
|
||||||
): React.ReactNode {
|
): React.ReactNode {
|
||||||
const shouldShowWrapEtherItem =
|
const shouldShowWrapEtherItem =
|
||||||
!_.isUndefined(this.state.wrappedEtherDirection) &&
|
!_.isUndefined(this.state.wrappedEtherDirection) &&
|
||||||
this.state.wrappedEtherDirection === accessoryItemConfig.wrappedEtherDirection &&
|
this.state.wrappedEtherDirection === accessoryItemConfig.wrappedEtherDirection &&
|
||||||
!_.isUndefined(this.props.userEtherBalanceInWei);
|
!_.isUndefined(this.props.userEtherBalanceInWei);
|
||||||
let additionalStyle;
|
|
||||||
if (shouldShowWrapEtherItem) {
|
|
||||||
additionalStyle = walletItemStyles.focusedItem;
|
|
||||||
} else if (!isLastRow) {
|
|
||||||
additionalStyle = styles.borderedItem;
|
|
||||||
}
|
|
||||||
const style = { ...styles.tokenItem, ...additionalStyle };
|
|
||||||
const etherToken = this._getEthToken();
|
const etherToken = this._getEthToken();
|
||||||
return (
|
return (
|
||||||
<div id={key} key={key} className={`flex flex-column ${className || ''}`}>
|
<div id={key} key={key} className={`flex flex-column ${className || ''}`}>
|
||||||
@ -399,7 +331,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
accessory={this._renderAccessoryItems(accessoryItemConfig)}
|
accessory={this._renderAccessoryItems(accessoryItemConfig)}
|
||||||
style={style}
|
backgroundColor={shouldShowWrapEtherItem ? colors.walletFocusedItemBackground : undefined}
|
||||||
/>
|
/>
|
||||||
{shouldShowWrapEtherItem && (
|
{shouldShowWrapEtherItem && (
|
||||||
<WrapEtherItem
|
<WrapEtherItem
|
||||||
@ -458,13 +390,19 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
): React.ReactNode {
|
): React.ReactNode {
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<PlaceHolder hideChildren={isLoading}>
|
<PlaceHolder hideChildren={isLoading} fillColor={PLACEHOLDER_COLOR}>
|
||||||
<div style={styles.amountLabel}>0.00 XXX</div>
|
<Text fontSize="16px" fontWeight="bold" lineHeight="1em">
|
||||||
|
0.00 XXX
|
||||||
|
</Text>
|
||||||
</PlaceHolder>
|
</PlaceHolder>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const result = utils.getFormattedAmount(amount, decimals, symbol);
|
const result = utils.getFormattedAmount(amount, decimals, symbol);
|
||||||
return <div style={styles.amountLabel}>{result}</div>;
|
return (
|
||||||
|
<Text fontSize="16px" fontWeight="bold" lineHeight="1em">
|
||||||
|
{result}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private _renderValue(
|
private _renderValue(
|
||||||
@ -487,8 +425,10 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
result = '$0.00';
|
result = '$0.00';
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<PlaceHolder hideChildren={isLoading}>
|
<PlaceHolder hideChildren={isLoading} fillColor={PLACEHOLDER_COLOR}>
|
||||||
<div style={styles.valueLabel}>{result}</div>
|
<Text fontSize="14px" fontColor={colors.darkGrey} lineHeight="1em">
|
||||||
|
{result}
|
||||||
|
</Text>
|
||||||
</PlaceHolder>
|
</PlaceHolder>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -541,41 +481,17 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
|||||||
private _getEthToken(): Token {
|
private _getEthToken(): Token {
|
||||||
return utils.getEthToken(this.props.tokenByAddress);
|
return utils.getEthToken(this.props.tokenByAddress);
|
||||||
}
|
}
|
||||||
|
private _isBlockchainReady(): boolean {
|
||||||
|
return this.props.blockchainIsLoaded && !_.isUndefined(this.props.blockchain);
|
||||||
|
}
|
||||||
|
private _getAccountState(): AccountState {
|
||||||
|
return utils.getAccountState(
|
||||||
|
this._isBlockchainReady(),
|
||||||
|
this.props.providerType,
|
||||||
|
this.props.injectedProviderName,
|
||||||
|
this.props.userAddress,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StandardIconRowProps {
|
|
||||||
icon: React.ReactNode;
|
|
||||||
main: React.ReactNode;
|
|
||||||
accessory?: React.ReactNode;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
}
|
|
||||||
const StandardIconRow = (props: StandardIconRowProps) => {
|
|
||||||
return (
|
|
||||||
<div className="flex items-center" style={props.style}>
|
|
||||||
<div className="p2">{props.icon}</div>
|
|
||||||
<div className="flex-none pr2 pt2 pb2">{props.main}</div>
|
|
||||||
<div className="flex-auto" />
|
|
||||||
<div>{props.accessory}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
interface PlaceHolderProps {
|
|
||||||
hideChildren: React.ReactNode;
|
|
||||||
children?: React.ReactNode;
|
|
||||||
}
|
|
||||||
const PlaceHolder = (props: PlaceHolderProps) => {
|
|
||||||
const rootBackgroundColor = props.hideChildren ? colors.lightGrey : 'transparent';
|
|
||||||
const rootStyle: React.CSSProperties = {
|
|
||||||
backgroundColor: rootBackgroundColor,
|
|
||||||
display: 'inline-block',
|
|
||||||
borderRadius: 2,
|
|
||||||
};
|
|
||||||
const childrenVisibility = props.hideChildren ? 'hidden' : 'visible';
|
|
||||||
const childrenStyle: React.CSSProperties = { visibility: childrenVisibility };
|
|
||||||
return (
|
|
||||||
<div style={rootStyle}>
|
|
||||||
<div style={childrenStyle}>{props.children}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
// tslint:disable:max-file-line-count
|
// tslint:disable:max-file-line-count
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
import { Styles } from '@0xproject/react-shared';
|
|
||||||
import FlatButton from 'material-ui/FlatButton';
|
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import { colors } from 'ts/style/colors';
|
|
||||||
import { BrowserType, ProviderType } from 'ts/types';
|
|
||||||
import { constants } from 'ts/utils/constants';
|
|
||||||
import { utils } from 'ts/utils/utils';
|
|
||||||
|
|
||||||
export interface WalletDisconnectedItemProps {
|
|
||||||
providerType: ProviderType;
|
|
||||||
injectedProviderName: string;
|
|
||||||
onToggleLedgerDialog: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles: Styles = {
|
|
||||||
button: {
|
|
||||||
border: colors.walletBorder,
|
|
||||||
borderStyle: 'solid',
|
|
||||||
borderWidth: 1,
|
|
||||||
height: 80,
|
|
||||||
},
|
|
||||||
hrefAdjustment: {
|
|
||||||
paddingTop: 20, // HACK: For some reason when we set the href prop of a FlatButton material-ui reduces the top padding
|
|
||||||
},
|
|
||||||
otherWalletText: {
|
|
||||||
fontSize: 14,
|
|
||||||
color: colors.grey500,
|
|
||||||
textDecoration: 'underline',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const ITEM_HEIGHT = 381;
|
|
||||||
const METAMASK_ICON_WIDTH = 35;
|
|
||||||
const LEDGER_ICON_WIDTH = 30;
|
|
||||||
const BUTTON_BOTTOM_PADDING = 80;
|
|
||||||
|
|
||||||
export const WalletDisconnectedItem: React.StatelessComponent<WalletDisconnectedItemProps> = (
|
|
||||||
props: WalletDisconnectedItemProps,
|
|
||||||
) => {
|
|
||||||
const isExternallyInjectedProvider = utils.isExternallyInjected(props.providerType, props.injectedProviderName);
|
|
||||||
return (
|
|
||||||
<div className="flex flex-center">
|
|
||||||
<div className="mx-auto">
|
|
||||||
<div className="table" style={{ height: ITEM_HEIGHT }}>
|
|
||||||
<div className="table-cell align-middle">
|
|
||||||
<ProviderButton isExternallyInjectedProvider={isExternallyInjectedProvider} />
|
|
||||||
<div className="flex flex-center py2" style={{ paddingBottom: BUTTON_BOTTOM_PADDING }}>
|
|
||||||
<div className="mx-auto">
|
|
||||||
<div onClick={props.onToggleLedgerDialog} style={{ cursor: 'pointer' }}>
|
|
||||||
<img src="/images/ledger_icon.png" style={{ width: LEDGER_ICON_WIDTH }} />
|
|
||||||
<span className="px1" style={styles.otherWalletText}>
|
|
||||||
user other wallet
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface ProviderButtonProps {
|
|
||||||
isExternallyInjectedProvider: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ProviderButton: React.StatelessComponent<ProviderButtonProps> = (props: ProviderButtonProps) => {
|
|
||||||
const browserType = utils.getBrowserType();
|
|
||||||
let extensionLink;
|
|
||||||
if (!props.isExternallyInjectedProvider) {
|
|
||||||
switch (browserType) {
|
|
||||||
case BrowserType.Chrome:
|
|
||||||
extensionLink = constants.URL_METAMASK_CHROME_STORE;
|
|
||||||
break;
|
|
||||||
case BrowserType.Firefox:
|
|
||||||
extensionLink = constants.URL_METAMASK_FIREFOX_STORE;
|
|
||||||
break;
|
|
||||||
case BrowserType.Opera:
|
|
||||||
extensionLink = constants.URL_METAMASK_OPERA_STORE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
extensionLink = constants.URL_METAMASK_HOMEPAGE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<FlatButton
|
|
||||||
label={props.isExternallyInjectedProvider ? 'Please unlock account' : 'Get Metamask Wallet Extension'}
|
|
||||||
labelStyle={{ color: colors.black }}
|
|
||||||
labelPosition="after"
|
|
||||||
primary={true}
|
|
||||||
icon={<img src="/images/metamask_icon.png" width={METAMASK_ICON_WIDTH.toString()} />}
|
|
||||||
style={props.isExternallyInjectedProvider ? styles.button : { ...styles.button, ...styles.hrefAdjustment }}
|
|
||||||
href={extensionLink}
|
|
||||||
target={props.isExternallyInjectedProvider ? undefined : '_blank'}
|
|
||||||
disabled={props.isExternallyInjectedProvider}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
@ -15,7 +15,6 @@ import { analytics } from 'ts/utils/analytics';
|
|||||||
import { constants } from 'ts/utils/constants';
|
import { constants } from 'ts/utils/constants';
|
||||||
import { errorReporter } from 'ts/utils/error_reporter';
|
import { errorReporter } from 'ts/utils/error_reporter';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles';
|
|
||||||
|
|
||||||
export interface WrapEtherItemProps {
|
export interface WrapEtherItemProps {
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
@ -95,7 +94,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
|
|||||||
const topLabelText = isWrappingEth ? 'Convert ETH into WETH 1:1' : 'Convert WETH into ETH 1:1';
|
const topLabelText = isWrappingEth ? 'Convert ETH into WETH 1:1' : 'Convert WETH into ETH 1:1';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex" style={walletItemStyles.focusedItem}>
|
<div className="flex" style={{ backgroundColor: colors.walletFocusedItemBackground }}>
|
||||||
<div>{this._renderIsEthConversionHappeningSpinner()} </div>
|
<div>{this._renderIsEthConversionHappeningSpinner()} </div>
|
||||||
<div className="flex flex-column">
|
<div className="flex flex-column">
|
||||||
<div style={styles.topLabel}>{topLabelText}</div>
|
<div style={styles.topLabel}>{topLabelText}</div>
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Circle } from 'ts/components/ui/circle';
|
||||||
|
|
||||||
export interface ListItemProps {
|
export interface ListItemProps {
|
||||||
bulletColor?: string;
|
bulletColor?: string;
|
||||||
}
|
}
|
||||||
export const ListItem: React.StatelessComponent<ListItemProps> = ({ bulletColor, children }) => {
|
export const ListItem: React.StatelessComponent<ListItemProps> = ({ bulletColor, children }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<svg className="flex-none lg-px2 md-px2 sm-pl2" height="26" width="26">
|
<Circle className="flex-none lg-px2 md-px2 sm-pl2" diameter={26} fillColor={bulletColor || 'transparent'} />
|
||||||
<circle cx="13" cy="13" r="13" fill={bulletColor || 'transparent'} />
|
|
||||||
</svg>
|
|
||||||
<div className="flex-auto px2">{children}</div>
|
<div className="flex-auto px2">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -6,13 +6,13 @@ const appColors = {
|
|||||||
walletDefaultItemBackground: '#fbfbfc',
|
walletDefaultItemBackground: '#fbfbfc',
|
||||||
walletFocusedItemBackground: '#f0f1f4',
|
walletFocusedItemBackground: '#f0f1f4',
|
||||||
allowanceToggleShadow: 'rgba(0, 0, 0, 0)',
|
allowanceToggleShadow: 'rgba(0, 0, 0, 0)',
|
||||||
allowanceToggleOffTrack: '#adadad',
|
|
||||||
allowanceToggleOnTrack: sharedColors.mediumBlue,
|
|
||||||
wrapEtherConfirmationButton: sharedColors.mediumBlue,
|
wrapEtherConfirmationButton: sharedColors.mediumBlue,
|
||||||
drawerMenuBackground: '#4a4a4a',
|
drawerMenuBackground: '#4a4a4a',
|
||||||
menuItemDefaultSelectedBackground: '#424242',
|
menuItemDefaultSelectedBackground: '#424242',
|
||||||
jobsPageBackground: sharedColors.grey50,
|
jobsPageBackground: sharedColors.grey50,
|
||||||
jobsPageOpenPositionRow: sharedColors.grey100,
|
jobsPageOpenPositionRow: sharedColors.grey100,
|
||||||
|
metaMaskOrange: '#f68c24',
|
||||||
|
metaMaskTransparentOrange: 'rgba(255, 248, 242, 0.8)',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const colors = {
|
export const colors = {
|
||||||
|
@ -564,4 +564,11 @@ export enum BrowserType {
|
|||||||
Opera = 'Opera',
|
Opera = 'Opera',
|
||||||
Other = 'Other',
|
Other = 'Other',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum AccountState {
|
||||||
|
Disconnected = 'Disconnected',
|
||||||
|
Ready = 'Ready',
|
||||||
|
Loading = 'Loading',
|
||||||
|
Locked = 'Locked',
|
||||||
|
}
|
||||||
// tslint:disable:max-file-line-count
|
// tslint:disable:max-file-line-count
|
||||||
|
@ -26,7 +26,7 @@ export const constants = {
|
|||||||
NETWORK_ID_TESTRPC: 50,
|
NETWORK_ID_TESTRPC: 50,
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
PROVIDER_NAME_LEDGER: 'Ledger',
|
PROVIDER_NAME_LEDGER: 'Ledger',
|
||||||
PROVIDER_NAME_METAMASK: 'Metamask',
|
PROVIDER_NAME_METAMASK: 'MetaMask',
|
||||||
PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
|
PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
|
||||||
PROVIDER_NAME_MIST: 'Mist',
|
PROVIDER_NAME_MIST: 'Mist',
|
||||||
PROVIDER_NAME_GENERIC: 'Injected Web3',
|
PROVIDER_NAME_GENERIC: 'Injected Web3',
|
||||||
|
@ -9,6 +9,7 @@ import deepEqual = require('deep-equal');
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import {
|
import {
|
||||||
|
AccountState,
|
||||||
BlockchainCallErrs,
|
BlockchainCallErrs,
|
||||||
BrowserType,
|
BrowserType,
|
||||||
Environments,
|
Environments,
|
||||||
@ -192,23 +193,37 @@ export const utils = {
|
|||||||
const truncatedAddress = `${address.substring(0, 6)}...${address.substr(-4)}`; // 0x3d5a...b287
|
const truncatedAddress = `${address.substring(0, 6)}...${address.substr(-4)}`; // 0x3d5a...b287
|
||||||
return truncatedAddress;
|
return truncatedAddress;
|
||||||
},
|
},
|
||||||
getReadableAccountState(
|
getReadableAccountState(accountState: AccountState, userAddress: string): string {
|
||||||
|
switch (accountState) {
|
||||||
|
case AccountState.Loading:
|
||||||
|
return 'Loading...';
|
||||||
|
case AccountState.Ready:
|
||||||
|
return utils.getAddressBeginAndEnd(userAddress);
|
||||||
|
case AccountState.Locked:
|
||||||
|
return 'Please Unlock';
|
||||||
|
case AccountState.Disconnected:
|
||||||
|
return 'Connect a Wallet';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getAccountState(
|
||||||
isBlockchainReady: boolean,
|
isBlockchainReady: boolean,
|
||||||
providerType: ProviderType,
|
providerType: ProviderType,
|
||||||
injectedProviderName: string,
|
injectedProviderName: string,
|
||||||
userAddress?: string,
|
userAddress?: string,
|
||||||
): string {
|
): AccountState {
|
||||||
const isAddressAvailable = !_.isUndefined(userAddress) && !_.isEmpty(userAddress);
|
const isAddressAvailable = !_.isUndefined(userAddress) && !_.isEmpty(userAddress);
|
||||||
const isExternallyInjectedProvider = utils.isExternallyInjected(providerType, injectedProviderName);
|
const isExternallyInjectedProvider = utils.isExternallyInjected(providerType, injectedProviderName);
|
||||||
if (!isBlockchainReady) {
|
if (!isBlockchainReady) {
|
||||||
return 'Loading account';
|
return AccountState.Loading;
|
||||||
} else if (isAddressAvailable) {
|
} else if (isAddressAvailable) {
|
||||||
return utils.getAddressBeginAndEnd(userAddress);
|
return AccountState.Ready;
|
||||||
// tslint:disable-next-line: prefer-conditional-expression
|
// tslint:disable-next-line: prefer-conditional-expression
|
||||||
} else if (isExternallyInjectedProvider) {
|
} else if (isExternallyInjectedProvider) {
|
||||||
return 'Account locked';
|
return AccountState.Locked;
|
||||||
} else {
|
} else {
|
||||||
return 'No wallet detected';
|
return AccountState.Disconnected;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasUniqueNameAndSymbol(tokens: Token[], token: Token): boolean {
|
hasUniqueNameAndSymbol(tokens: Token[], token: Token): boolean {
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import { Styles } from '@0xproject/react-shared';
|
|
||||||
|
|
||||||
import { colors } from 'ts/style/colors';
|
|
||||||
|
|
||||||
export const styles: Styles = {
|
|
||||||
focusedItem: {
|
|
||||||
backgroundColor: colors.walletFocusedItemBackground,
|
|
||||||
},
|
|
||||||
};
|
|
@ -4887,9 +4887,9 @@ functional-red-black-tree@^1.0.1:
|
|||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||||
|
|
||||||
ganache-cli@^6.1.0:
|
ganache-cli@6.1.3:
|
||||||
version "6.1.0"
|
version "6.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.0.tgz#486c846497204b644166b5f0f74c9b41d02bdc25"
|
resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.3.tgz#40323e56c878b5c7275830cb8a4fa75a32f6d468"
|
||||||
dependencies:
|
dependencies:
|
||||||
source-map-support "^0.5.3"
|
source-map-support "^0.5.3"
|
||||||
webpack-cli "^2.0.9"
|
webpack-cli "^2.0.9"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user