aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website')
-rw-r--r--packages/website/ts/artifacts/Exchange.json610
-rw-r--r--packages/website/ts/blockchain.ts37
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx5
-rw-r--r--packages/website/ts/components/onboarding/onboarding_flow.tsx4
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx5
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx2
-rw-r--r--packages/website/ts/types.ts3
7 files changed, 657 insertions, 9 deletions
diff --git a/packages/website/ts/artifacts/Exchange.json b/packages/website/ts/artifacts/Exchange.json
new file mode 100644
index 000000000..af8db7360
--- /dev/null
+++ b/packages/website/ts/artifacts/Exchange.json
@@ -0,0 +1,610 @@
+{
+ "contract_name": "Exchange",
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "numerator",
+ "type": "uint256"
+ },
+ {
+ "name": "denominator",
+ "type": "uint256"
+ },
+ {
+ "name": "target",
+ "type": "uint256"
+ }
+ ],
+ "name": "isRoundingError",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "filled",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "cancelled",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "fillTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "shouldThrowOnInsufficientBalanceOrAllowance",
+ "type": "bool"
+ },
+ {
+ "name": "v",
+ "type": "uint8[]"
+ },
+ {
+ "name": "r",
+ "type": "bytes32[]"
+ },
+ {
+ "name": "s",
+ "type": "bytes32[]"
+ }
+ ],
+ "name": "fillOrdersUpTo",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ },
+ {
+ "name": "cancelTakerTokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "cancelOrder",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "ZRX_TOKEN_CONTRACT",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "fillTakerTokenAmounts",
+ "type": "uint256[]"
+ },
+ {
+ "name": "v",
+ "type": "uint8[]"
+ },
+ {
+ "name": "r",
+ "type": "bytes32[]"
+ },
+ {
+ "name": "s",
+ "type": "bytes32[]"
+ }
+ ],
+ "name": "batchFillOrKillOrders",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ },
+ {
+ "name": "fillTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "fillOrKillOrder",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getUnavailableTakerTokenAmount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "signer",
+ "type": "address"
+ },
+ {
+ "name": "hash",
+ "type": "bytes32"
+ },
+ {
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "isValidSignature",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "numerator",
+ "type": "uint256"
+ },
+ {
+ "name": "denominator",
+ "type": "uint256"
+ },
+ {
+ "name": "target",
+ "type": "uint256"
+ }
+ ],
+ "name": "getPartialAmount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "TOKEN_TRANSFER_PROXY_CONTRACT",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "fillTakerTokenAmounts",
+ "type": "uint256[]"
+ },
+ {
+ "name": "shouldThrowOnInsufficientBalanceOrAllowance",
+ "type": "bool"
+ },
+ {
+ "name": "v",
+ "type": "uint8[]"
+ },
+ {
+ "name": "r",
+ "type": "bytes32[]"
+ },
+ {
+ "name": "s",
+ "type": "bytes32[]"
+ }
+ ],
+ "name": "batchFillOrders",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "cancelTakerTokenAmounts",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "batchCancelOrders",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ },
+ {
+ "name": "fillTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "shouldThrowOnInsufficientBalanceOrAllowance",
+ "type": "bool"
+ },
+ {
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "fillOrder",
+ "outputs": [
+ {
+ "name": "filledTakerTokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ }
+ ],
+ "name": "getOrderHash",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "EXTERNAL_QUERY_GAS_LIMIT",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint16"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "VERSION",
+ "outputs": [
+ {
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "name": "_zrxToken",
+ "type": "address"
+ },
+ {
+ "name": "_tokenTransferProxy",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "maker",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "taker",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "feeRecipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "makerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "takerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "filledMakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "filledTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "paidMakerFee",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "paidTakerFee",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "name": "tokens",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "LogFill",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "maker",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "feeRecipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "makerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "takerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "cancelledMakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "cancelledTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "name": "tokens",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "LogCancel",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "errorId",
+ "type": "uint8"
+ },
+ {
+ "indexed": true,
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "LogError",
+ "type": "event"
+ }
+ ],
+ "networks": {
+ "1": {
+ "address": "0x12459c951127e0c374ff9105dda097662a027093"
+ },
+ "3": {
+ "address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
+ },
+ "4": {
+ "address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
+ },
+ "42": {
+ "address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
+ },
+ "50": {
+ "address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
+ }
+ }
+}
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 9ef9bbe22..fde134b18 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -66,6 +66,9 @@ import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
import * as MintableArtifacts from '../contracts/Mintable.json';
+// HACK: remove this hard-coded abi and use @0xproject/contract-wrappers
+import * as Exchange from './artifacts/Exchange.json';
+
const BLOCK_NUMBER_BACK_TRACK = 50;
const GWEI_IN_WEI = 1000000000;
@@ -89,6 +92,7 @@ export class Blockchain {
private _userAddressIfExists: string;
private _ledgerSubprovider: LedgerSubprovider;
private _defaultGasPrice: BigNumber;
+ private _watchGasPriceIntervalId: NodeJS.Timer;
private static _getNameGivenProvider(provider: Provider): string {
const providerType = utils.getProviderType(provider);
const providerNameIfExists = providerToName[providerType];
@@ -196,13 +200,11 @@ export class Blockchain {
}
constructor(dispatcher: Dispatcher) {
this._dispatcher = dispatcher;
- const defaultGasPrice = GWEI_IN_WEI * 30;
+ const defaultGasPrice = GWEI_IN_WEI * 40;
this._defaultGasPrice = new BigNumber(defaultGasPrice);
// We need a unique reference to this function so we can use it to unsubcribe.
this._injectedProviderUpdateHandler = this._handleInjectedProviderUpdateAsync.bind(this);
// tslint:disable-next-line:no-floating-promises
- this._updateDefaultGasPriceAsync();
- // tslint:disable-next-line:no-floating-promises
this._onPageLoadInitFireAndForgetAsync();
}
public async networkIdUpdatedFireAndForgetAsync(newNetworkId: number): Promise<void> {
@@ -537,6 +539,7 @@ export class Blockchain {
this._blockchainWatcher.destroy();
this._injectedProviderObservable.unsubscribe(this._injectedProviderUpdateHandler);
this._stopWatchingExchangeLogFillEvents();
+ this._stopWatchingGasPrice();
}
public async fetchTokenInformationAsync(): Promise<void> {
utils.assert(
@@ -624,7 +627,9 @@ export class Blockchain {
);
const provider = this._contractWrappers.getProvider();
const web3Wrapper = new Web3Wrapper(provider);
- web3Wrapper.abiDecoder.addABI(this._contractWrappers.exchange.abi);
+ // HACK: remove this hard-coded abi and use @0xproject/contract-wrappers
+ const exchangeAbi = _.get(Exchange, 'abi', []);
+ web3Wrapper.abiDecoder.addABI(exchangeAbi);
const receipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
return receipt;
}
@@ -798,8 +803,30 @@ export class Blockchain {
this._updateProviderName(injectedWeb3IfExists);
const shouldPollUserAddress = true;
const shouldUseLedgerProvider = false;
+ this._startWatchingGasPrice();
await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedgerProvider);
}
+ private _startWatchingGasPrice(): void {
+ if (!_.isUndefined(this._watchGasPriceIntervalId)) {
+ return; // we are already watching
+ }
+ const oneMinuteInMs = 60000;
+ // tslint:disable-next-line:no-floating-promises
+ this._updateDefaultGasPriceAsync();
+ this._watchGasPriceIntervalId = intervalUtils.setAsyncExcludingInterval(
+ this._updateDefaultGasPriceAsync.bind(this),
+ oneMinuteInMs,
+ (err: Error) => {
+ logUtils.log(`Watching gas price failed: ${err.stack}`);
+ this._stopWatchingGasPrice();
+ },
+ );
+ }
+ private _stopWatchingGasPrice(): void {
+ if (!_.isUndefined(this._watchGasPriceIntervalId)) {
+ intervalUtils.clearAsyncExcludingInterval(this._watchGasPriceIntervalId);
+ }
+ }
private async _resetOrInitializeAsync(
networkId: number,
shouldPollUserAddress: boolean = false,
@@ -895,7 +922,7 @@ export class Blockchain {
private async _updateDefaultGasPriceAsync(): Promise<void> {
try {
const gasInfo = await backendClient.getGasInfoAsync();
- const gasPriceInGwei = new BigNumber(gasInfo.average / 10);
+ const gasPriceInGwei = new BigNumber(gasInfo.fast / 10);
const gasPriceInWei = gasPriceInGwei.mul(1000000000);
this._defaultGasPrice = gasPriceInWei;
} catch (err) {
diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
index 38e4732a4..d2f373d67 100644
--- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
+++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
@@ -29,7 +29,7 @@ interface LedgerConfigDialogProps {
toggleDialogFn: (isOpen: boolean) => void;
dispatcher: Dispatcher;
blockchain: Blockchain;
- networkId: number;
+ networkId?: number;
providerType: ProviderType;
}
@@ -44,6 +44,9 @@ interface LedgerConfigDialogState {
}
export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, LedgerConfigDialogState> {
+ public static defaultProps = {
+ networkId: 1,
+ };
constructor(props: LedgerConfigDialogProps) {
super(props);
const derivationPathIfExists = props.blockchain.getLedgerDerivationPathIfExists();
diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx
index c2b4a4ca7..46dc897bd 100644
--- a/packages/website/ts/components/onboarding/onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx
@@ -44,12 +44,14 @@ export interface OnboardingFlowProps {
updateOnboardingStep: (stepIndex: number) => void;
disableOverlay?: boolean;
isMobile: boolean;
+ disableCloseOnClickOutside?: boolean;
}
export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
public static defaultProps = {
disableOverlay: false,
isMobile: false,
+ disableCloseOnClickOutside: false,
};
public render(): React.ReactNode {
if (!this.props.isRunning) {
@@ -86,7 +88,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
}
return (
<div>
- <Overlay onClick={this.props.onClose} />
+ <Overlay onClick={this.props.disableCloseOnClickOutside ? undefined : this.props.onClose} />
{onboardingElement}
</div>
);
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
index 1c2c92fd1..503f2163d 100644
--- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -23,7 +23,7 @@ import {
WrapEthOnboardingStep3,
} from 'ts/components/onboarding/wrap_eth_onboarding_step';
import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
-import { ProviderType, ScreenWidths, Token, TokenByAddress, TokenStateByAddress } from 'ts/types';
+import { BrowserType, ProviderType, ScreenWidths, Token, TokenByAddress, TokenStateByAddress } from 'ts/types';
import { analytics } from 'ts/utils/analytics';
import { utils } from 'ts/utils/utils';
@@ -68,6 +68,7 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
}
}
public render(): React.ReactNode {
+ const browserType = utils.getBrowserType();
return (
<OnboardingFlow
steps={this._getSteps()}
@@ -77,6 +78,8 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
updateOnboardingStep={this._updateOnboardingStep.bind(this)}
disableOverlay={this.props.screenWidth === ScreenWidths.Sm}
isMobile={this.props.screenWidth === ScreenWidths.Sm}
+ // This is necessary to ensure onboarding stays open once the user unlocks metamask and clicks away
+ disableCloseOnClickOutside={browserType === BrowserType.Firefox || browserType === BrowserType.Opera}
/>
);
}
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index de3b91ad0..1c7dafca0 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -270,7 +270,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
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,
+ maxHeight: !utils.isMobileWidth(this.props.screenWidth) ? 'calc(90vh - 300px)' : undefined,
};
}
private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index f7324e87a..27b219682 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -552,7 +552,10 @@ export interface WebsiteBackendTokenInfo {
}
export interface WebsiteBackendGasInfo {
+ safeSlow: number;
average: number;
+ fast: number;
+ fastest: number;
}
export interface WebsiteBackendJobInfo {