Merge branch 'development' into feature/testnet-faucets/order-dispenser

* development:
  Attribute the origins of NonceTracker
  Move BlockParamLiteral to shared types package
  Fixes
  Move BlockParam and BlockParamLiteral to shared types
  Rename called to something more readable
  Newline prettier/lint
  Yarn.lock
  Refactor tests for reuse of the fixture subprovider
  Remove re-fetch of transaction count on error
  Disable linter for multiple class declarations
  Remove double declaration
  Enable CIRCLECI and declare web3
  Test faucets to use new NonceTracker
  Update changelog
  Readability and prettier
  Prettify
  Nonce tracker subprovider Caches the nonce when a request to getTransactionCount is made and increments the pending nonce after successful transactions
This commit is contained in:
Brandon Millman
2018-02-06 15:36:00 -08:00
28 changed files with 360 additions and 33 deletions

View File

@@ -1,4 +1,4 @@
import { LogWithDecodedArgs, RawLog } from '@0xproject/types';
import { BlockParamLiteral, LogWithDecodedArgs, RawLog } from '@0xproject/types';
import { AbiDecoder, intervalUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream';
@@ -7,7 +7,6 @@ import * as Web3 from 'web3';
import {
Artifact,
BlockParamLiteral,
BlockRange,
ContractEventArgs,
ContractEvents,

View File

@@ -1,5 +1,5 @@
import { schemas } from '@0xproject/json-schemas';
import { DecodedLogArgs, LogWithDecodedArgs } from '@0xproject/types';
import { BlockParamLiteral, DecodedLogArgs, LogWithDecodedArgs } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
@@ -7,7 +7,6 @@ import * as Web3 from 'web3';
import { artifacts } from '../artifacts';
import {
BlockParamLiteral,
BlockRange,
ECSignature,
EventCallback,

View File

@@ -2,7 +2,6 @@ export { ZeroEx } from './0x';
export {
Order,
BlockParamLiteral,
SignedOrder,
ECSignature,
ZeroExError,
@@ -14,7 +13,6 @@ export {
TokenEvents,
IndexedFilterValues,
BlockRange,
BlockParam,
OrderCancellationRequest,
OrderFillRequest,
LogErrorContractEventArgs,
@@ -44,6 +42,12 @@ export {
OrderState,
} from './types';
export { ContractEventArg, LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
export {
BlockParamLiteral,
BlockParam,
ContractEventArg,
LogWithDecodedArgs,
TransactionReceiptWithDecodedLogs,
} from '@0xproject/types';
export { TransactionReceipt } from '@0xproject/types';

View File

@@ -3,7 +3,9 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import * as Web3 from 'web3';
import { BlockParamLiteral, EventWatcherCallback, ZeroExError } from '../types';
import { BlockParamLiteral } from '@0xproject/types';
import { EventWatcherCallback, ZeroExError } from '../types';
import { assert } from '../utils/assert';
const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;

View File

@@ -1,5 +1,5 @@
import { schemas } from '@0xproject/json-schemas';
import { LogWithDecodedArgs } from '@0xproject/types';
import { BlockParamLiteral, LogWithDecodedArgs } from '@0xproject/types';
import { AbiDecoder, intervalUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
@@ -11,7 +11,6 @@ import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allow
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
import {
ApprovalContractEventArgs,
BlockParamLiteral,
ContractEventArgs,
DepositContractEventArgs,
EtherTokenEvents,

View File

@@ -1,8 +1,8 @@
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
import { BlockParamLiteral } from '../types';
/**
* Copy on read store for balances/proxyAllowances of tokens/accounts

View File

@@ -1,8 +1,8 @@
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
import { BlockParamLiteral } from '../types';
/**
* Copy on read store for filled/cancelled taker amounts

View File

@@ -1,5 +1,7 @@
import { ContractEventArg, LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { BlockParam, BlockParamLiteral, ContractEventArg, LogWithDecodedArgs } from '@0xproject/types';
import * as Web3 from 'web3';
export enum ZeroExError {
@@ -219,16 +221,6 @@ export interface IndexedFilterValues {
[index: string]: ContractEventArg;
}
// Earliest is omitted by design. It is simply an alias for the `0` constant and
// is thus not very helpful. Moreover, this type is used in places that only accept
// `latest` or `pending`.
export enum BlockParamLiteral {
Latest = 'latest',
Pending = 'pending',
}
export type BlockParam = BlockParamLiteral | number;
export interface BlockRange {
fromBlock: BlockParam;
toBlock: BlockParam;

View File

@@ -1,9 +1,10 @@
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
import { BlockParamLiteral, ExchangeContractErrs, TradeSide, TransferType } from '../types';
import { ExchangeContractErrs, TradeSide, TransferType } from '../types';
enum FailureReason {
Balance = 'balance',

View File

@@ -1,9 +1,10 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { ExchangeContractErrs, Token, ZeroEx } from '../src';
import { BlockParamLiteral, TradeSide, TransferType } from '../src/types';
import { TradeSide, TransferType } from '../src/types';
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
import { chaiSetup } from './utils/chai_setup';

View File

@@ -1,4 +1,5 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
@@ -18,7 +19,7 @@ import {
Token,
ZeroEx,
} from '../src';
import { BlockParamLiteral, DoneCallback } from '../src/types';
import { DoneCallback } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';

View File

@@ -1,11 +1,12 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as Sinon from 'sinon';
import * as Web3 from 'web3';
import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src';
import { BlockParamLiteral, TradeSide, TransferType } from '../src/types';
import { TradeSide, TransferType } from '../src/types';
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
import { OrderValidationUtils } from '../src/utils/order_validation_utils';

View File

@@ -1,8 +1,9 @@
# CHANGELOG
## v0.4.0 - _Feburary 02, 2018_
## v0.4.1 - _Febuary 2, 2018_
* InjectedWeb3Subprovider accepts a Provider in the constructor, previously it was a Web3 object.
* Added NonceTrackerSubprovider (#355)
* InjectedWeb3Subprovider accepts a Provider in the constructor, previously it was a Web3 object (#363)
## v0.3.5 - _January 28, 2018_

View File

@@ -33,6 +33,7 @@
},
"devDependencies": {
"@0xproject/tslint-config": "^0.4.7",
"@0xproject/types": "^0.1.9",
"@0xproject/utils": "^0.3.0",
"@types/lodash": "^4.14.86",
"@types/mocha": "^2.2.42",

View File

@@ -13,7 +13,9 @@ declare module 'ethereumjs-tx' {
public r: Buffer;
public s: Buffer;
public v: Buffer;
public nonce: Buffer;
public serialize(): Buffer;
public getSenderAddress(): Buffer;
constructor(txParams: any);
}
export = EthereumTx;
@@ -97,6 +99,24 @@ declare module 'web3-provider-engine' {
}
export = Web3ProviderEngine;
}
declare module 'web3-provider-engine/util/rpc-cache-utils' {
class ProviderEngineRpcUtils {
public static blockTagForPayload(payload: any): string | null;
}
export = ProviderEngineRpcUtils;
}
declare module 'web3-provider-engine/subproviders/fixture' {
import * as Web3 from 'web3';
class FixtureSubprovider {
constructor(staticResponses: any);
public handleRequest(
payload: Web3.JSONRPCRequestPayload,
next: () => void,
end: (err: Error | null, data?: any) => void,
): void;
}
export = FixtureSubprovider;
}
// hdkey declarations
declare module 'hdkey' {

View File

@@ -9,7 +9,8 @@ import { LedgerEthereumClient } from './types';
export { InjectedWeb3Subprovider } from './subproviders/injected_web3';
export { RedundantRPCSubprovider } from './subproviders/redundant_rpc';
export { LedgerSubprovider } from './subproviders/ledger';
export { ECSignature, LedgerWalletSubprovider, LedgerCommunicationClient } from './types';
export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
export { ECSignature, LedgerWalletSubprovider, LedgerCommunicationClient, NonceSubproviderErrors } from './types';
/**
* A factory method for creating a LedgerEthereumClient usable in a browser context.

View File

@@ -60,6 +60,8 @@ export class LedgerSubprovider extends Subprovider {
public setPathIndex(pathIndex: number) {
this._derivationPathIndex = pathIndex;
}
// Required to implement this public interface which doesn't conform to our linting rule.
// tslint:disable-next-line:async-suffix
public async handleRequest(
payload: Web3.JSONRPCRequestPayload,
next: () => void,

View File

@@ -0,0 +1,103 @@
import * as _ from 'lodash';
import EthereumTx = require('ethereumjs-tx');
import ethUtil = require('ethereumjs-util');
import providerEngineUtils = require('web3-provider-engine/util/rpc-cache-utils');
import { BlockParamLiteral } from '@0xproject/types';
import { ErrorCallback, JSONRPCPayload, NonceSubproviderErrors, OptionalNextCallback } from '../types';
import { Subprovider } from './subprovider';
// We do not export this since this is not our error, and we do not throw this error
const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is too low';
/*
This class is heavily inspiried by the Web3ProviderEngine NonceSubprovider
We have added the additional feature of clearing any nonce balues when an error message
describes a nonce value being too low.
*/
export class NonceTrackerSubprovider extends Subprovider {
private _nonceCache: { [address: string]: string } = {};
private static _reconstructTransaction(payload: JSONRPCPayload): EthereumTx {
const raw = payload.params[0];
if (_.isUndefined(raw)) {
throw new Error(NonceSubproviderErrors.EmptyParametersFound);
}
const rawData = ethUtil.toBuffer(raw);
const transaction = new EthereumTx(rawData);
return transaction;
}
private static _determineAddress(payload: JSONRPCPayload): string {
let address: string;
switch (payload.method) {
case 'eth_getTransactionCount':
address = payload.params[0].toLowerCase();
return address;
case 'eth_sendRawTransaction':
const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
const addressRaw = transaction
.getSenderAddress()
.toString('hex')
.toLowerCase();
address = `0x${addressRaw}`;
return address;
default:
throw new Error(NonceSubproviderErrors.CannotDetermineAddressFromPayload);
}
}
// Required to implement this public interface which doesn't conform to our linting rule.
// tslint:disable-next-line:async-suffix
public async handleRequest(payload: JSONRPCPayload, next: OptionalNextCallback, end: ErrorCallback): Promise<void> {
switch (payload.method) {
case 'eth_getTransactionCount':
const requestDefaultBlock = providerEngineUtils.blockTagForPayload(payload);
if (requestDefaultBlock === BlockParamLiteral.Pending) {
const address = NonceTrackerSubprovider._determineAddress(payload);
const cachedResult = this._nonceCache[address];
if (!_.isUndefined(cachedResult)) {
return end(null, cachedResult);
} else {
return next((requestError: Error | null, requestResult: any, cb: any) => {
if (_.isNull(requestError)) {
this._nonceCache[address] = requestResult as string;
}
cb();
});
}
} else {
return next();
}
case 'eth_sendRawTransaction':
return next((sendTransactionError: Error | null, txResult: any, cb: any) => {
if (_.isNull(sendTransactionError)) {
this._handleSuccessfulTransaction(payload);
} else {
this._handleSendTransactionError(payload, sendTransactionError);
}
cb();
});
default:
return next();
}
}
private _handleSuccessfulTransaction(payload: JSONRPCPayload): void {
const address = NonceTrackerSubprovider._determineAddress(payload);
const transaction = NonceTrackerSubprovider._reconstructTransaction(payload);
// Increment the nonce from the previous successfully submitted transaction
let nonce = ethUtil.bufferToInt(transaction.nonce);
nonce++;
let nextHexNonce = nonce.toString(16);
if (nextHexNonce.length % 2) {
nextHexNonce = `0${nextHexNonce}`;
}
const nextPrefixedHexNonce = `0x${nextHexNonce}`;
this._nonceCache[address] = nextPrefixedHexNonce;
}
private _handleSendTransactionError(payload: JSONRPCPayload, err: Error): void {
const address = NonceTrackerSubprovider._determineAddress(payload);
if (this._nonceCache[address] && _.includes(err.message, NONCE_TOO_LOW_ERROR_MESSAGE)) {
delete this._nonceCache[address];
}
}
}

View File

@@ -35,6 +35,7 @@ export class RedundantRPCSubprovider extends Subprovider {
});
});
}
// Required to implement this public interface which doesn't conform to our linting rule.
// tslint:disable-next-line:async-suffix
public async handleRequest(
payload: JSONRPCPayload,

View File

@@ -112,3 +112,11 @@ export enum LedgerSubproviderErrors {
SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
MultipleOpenConnectionsDisallowed = 'MULTIPLE_OPEN_CONNECTIONS_DISALLOWED',
}
export enum NonceSubproviderErrors {
EmptyParametersFound = 'EMPTY_PARAMETERS_FOUND',
CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD',
}
export type OptionalNextCallback = (callback?: (err: Error | null, result: any, cb: any) => void) => void;
export type ErrorCallback = (err: Error | null, data?: any) => void;

View File

@@ -0,0 +1,151 @@
import * as chai from 'chai';
import * as _ from 'lodash';
import Web3ProviderEngine = require('web3-provider-engine');
import FixtureSubprovider = require('web3-provider-engine/subproviders/fixture');
import promisify = require('es6-promisify');
import EthereumTx = require('ethereumjs-tx');
import { NonceTrackerSubprovider } from '../../src';
import { chaiSetup } from '../chai_setup';
const expect = chai.expect;
chaiSetup.configure();
describe('NonceTrackerSubprovider', () => {
let provider: Web3ProviderEngine;
const getTransactionCountPayload = {
jsonrpc: '2.0',
method: 'eth_getTransactionCount',
params: ['0x0', 'pending'],
id: 1,
};
const sendTransactionPayload = {
jsonrpc: '2.0',
method: 'eth_sendRawTransaction',
params: [],
id: 1,
};
const txParams = [
'0x',
'0x09184e72a000',
'0x2710',
'0x0000000000000000000000000000000000000000',
'0x',
'0x7f7465737432000000000000000000000000000000000000000000000000000000600057',
'0x1c',
'0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab',
'0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13',
];
function createFixtureSubprovider() {
let isFirstGetTransactionCount = true;
const fixedBlockNumberAndTransactionCountProvider = new FixtureSubprovider({
eth_getBlockByNumber: '0x01',
eth_getTransactionCount: (data: any, next: any, end: any) => {
// For testing caching we return different results on the second call
if (isFirstGetTransactionCount) {
isFirstGetTransactionCount = false;
end(null, '0x00');
} else {
end(null, '0x99');
}
},
});
return fixedBlockNumberAndTransactionCountProvider;
}
it('successfully caches the transaction count', async () => {
provider = new Web3ProviderEngine();
const nonceTrackerSubprovider = new NonceTrackerSubprovider();
provider.addProvider(nonceTrackerSubprovider);
provider.addProvider(createFixtureSubprovider());
provider.start();
const payload = { ...getTransactionCountPayload, params: ['0x0', 'pending'] };
const response = await promisify(provider.sendAsync, provider)(payload);
expect(response.result).to.be.eq('0x00');
const secondResponse = await promisify(provider.sendAsync, provider)(payload);
expect(secondResponse.result).to.be.eq('0x00');
});
it('does not cache the result for latest transaction count', async () => {
provider = new Web3ProviderEngine();
const nonceTrackerSubprovider = new NonceTrackerSubprovider();
provider.addProvider(nonceTrackerSubprovider);
provider.addProvider(createFixtureSubprovider());
provider.start();
const payload = { ...getTransactionCountPayload, params: ['0x0', 'latest'] };
const response = await promisify(provider.sendAsync, provider)(payload);
expect(response.result).to.be.eq('0x00');
const secondResponse = await promisify(provider.sendAsync, provider)(payload);
expect(secondResponse.result).to.be.eq('0x99');
});
it('clears the cache on a Nonce Too Low Error', async () => {
provider = new Web3ProviderEngine();
const nonceTrackerSubprovider = new NonceTrackerSubprovider();
provider.addProvider(nonceTrackerSubprovider);
provider.addProvider(createFixtureSubprovider());
provider.addProvider(
new FixtureSubprovider({
eth_sendRawTransaction: (data: any, next: any, end: any) => {
end(new Error('Transaction nonce is too low'));
},
}),
);
provider.start();
const noncePayload = {
...getTransactionCountPayload,
params: ['0x1f36f546477cda21bf2296c50976f2740247906f', 'pending'],
};
const transaction = new EthereumTx(txParams);
const txPayload = {
...sendTransactionPayload,
params: [transaction.serialize()],
};
const response = await promisify(provider.sendAsync, provider)(noncePayload);
expect(response.result).to.be.eq('0x00');
const secondResponse = await promisify(provider.sendAsync, provider)(noncePayload);
expect(secondResponse.result).to.be.eq('0x00');
try {
await promisify(provider.sendAsync, provider)(txPayload);
} catch (err) {
const thirdResponse = await promisify(provider.sendAsync, provider)(noncePayload);
expect(thirdResponse.result).to.be.eq('0x99');
}
});
it('increments the used nonce when a transaction successfully submits', async () => {
provider = new Web3ProviderEngine();
const nonceTrackerSubprovider = new NonceTrackerSubprovider();
provider.addProvider(nonceTrackerSubprovider);
provider.addProvider(createFixtureSubprovider());
provider.addProvider(
new FixtureSubprovider({
eth_sendRawTransaction: (data: any, next: any, end: any) => {
end(null);
},
}),
);
provider.start();
const noncePayload = {
...getTransactionCountPayload,
params: ['0x1f36f546477cda21bf2296c50976f2740247906f', 'pending'],
};
const transaction = new EthereumTx(txParams);
const txPayload = {
...sendTransactionPayload,
params: [transaction.serialize()],
};
const response = await promisify(provider.sendAsync, provider)(noncePayload);
expect(response.result).to.be.eq('0x00');
const secondResponse = await promisify(provider.sendAsync, provider)(noncePayload);
expect(secondResponse.result).to.be.eq('0x00');
await promisify(provider.sendAsync, provider)(txPayload);
const thirdResponse = await promisify(provider.sendAsync, provider)(noncePayload);
expect(thirdResponse.result).to.be.eq('0x01');
});
});

View File

@@ -2,6 +2,11 @@ FROM node
WORKDIR /src
# Ledger Provider (in the Subproviders package) requires node-hid at dependency install time
# which compiles and expects certain USB developer library packages to be present
RUN apt-get -qq update && apt-get install -y libhidapi-dev libusb-1.0-0-dev
# Our fork of ledgerco disables requiring node-hid at run time if CIRCLECI is set to true
ENV CIRCLECI=true
COPY package.json .
RUN npm i
RUN npm install forever -g

View File

@@ -17,6 +17,7 @@
"dependencies": {
"0x.js": "^0.32.0",
"@0xproject/utils": "^0.3.0",
"@0xproject/subproviders": "^0.3.5",
"body-parser": "^1.17.1",
"ethereumjs-tx": "^1.3.3",
"ethereumjs-util": "^5.1.1",

View File

@@ -1,5 +1,4 @@
declare module 'rollbar';
declare module 'web3-provider-engine';
declare module 'web3-provider-engine/subproviders/rpc';
declare module 'web3-provider-engine/subproviders/nonce-tracker';
declare module 'web3-provider-engine/subproviders/hooked-wallet';
@@ -24,3 +23,17 @@ declare module 'ethereumjs-tx' {
}
export = EthereumTx;
}
/* tslint:disable */
declare module 'web3-provider-engine' {
class Web3ProviderEngine {
public on(event: string, handler: () => void): void;
public send(payload: any): void;
public sendAsync(payload: any, callback: (error: any, response: any) => void): void;
public addProvider(provider: any): void;
public start(): void;
public stop(): void;
}
export = Web3ProviderEngine;
}
/* tslint:enable */

View File

@@ -1,4 +1,5 @@
import { Order, SignedOrder, ZeroEx } from '0x.js';
import { NonceTrackerSubprovider } from '@0xproject/subproviders';
import { BigNumber } from '@0xproject/utils';
import * as express from 'express';
import * as _ from 'lodash';
@@ -11,7 +12,6 @@ import * as Web3 from 'web3';
(global as any).XMLHttpRequest = undefined;
import ProviderEngine = require('web3-provider-engine');
import HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet');
import NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker');
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
import { configs } from './configs';
@@ -61,7 +61,7 @@ export class Handler {
}
private static _createProviderEngine(rpcUrl: string) {
const engine = new ProviderEngine();
engine.addProvider(new NonceSubprovider());
engine.addProvider(new NonceTrackerSubprovider());
engine.addProvider(new HookedWalletSubprovider(idManagement));
engine.addProvider(
new RpcSubprovider({

View File

@@ -1,3 +1,5 @@
# CHANGELOG
## vx.x.x
* Added BlockLiteralParam and BlockParam, refactored out of 0x.js types. (#355)

View File

@@ -56,3 +56,13 @@ export enum SolidityTypes {
export interface TransactionReceiptWithDecodedLogs extends TransactionReceipt {
logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>;
}
// Earliest is omitted by design. It is simply an alias for the `0` constant and
// is thus not very helpful. Moreover, this type is used in places that only accept
// `latest` or `pending`.
export enum BlockParamLiteral {
Latest = 'latest',
Pending = 'pending',
}
export type BlockParam = BlockParamLiteral | number;

View File

@@ -2,6 +2,15 @@
# yarn lockfile v1
"@0xproject/utils@^0.2.0":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@0xproject/utils/-/utils-0.2.4.tgz#d84d0737f47730e5724a76797d30e716b587a0cf"
dependencies:
bignumber.js "~4.1.0"
js-sha3 "^0.7.0"
lodash "^4.17.4"
web3 "^0.20.0"
"@types/accounting@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@types/accounting/-/accounting-0.4.1.tgz#865d9f5694fd7c438fba34eb4bc82eec6f34cdd5"