Remove Lodash as a dependency in BaseContract
This commit is contained in:
parent
be52079182
commit
aa10844d9e
@ -304,13 +304,15 @@ export class {{contractName}}Contract extends BaseContract {
|
|||||||
this._subscriptionManager = new SubscriptionManager<{{contractName}}EventArgs, {{contractName}}Events>(
|
this._subscriptionManager = new SubscriptionManager<{{contractName}}EventArgs, {{contractName}}Events>(
|
||||||
{{contractName}}Contract.ABI(),
|
{{contractName}}Contract.ABI(),
|
||||||
this._web3Wrapper,
|
this._web3Wrapper,
|
||||||
);{{/if~}}
|
);
|
||||||
|
{{/if~}}
|
||||||
|
|
||||||
{{contractName}}Contract.ABI().forEach((item, index) => {
|
{{contractName}}Contract.ABI().forEach((item, index) => {
|
||||||
if (item.type === 'function') {
|
if (item.type === 'function') {
|
||||||
const methodAbi = item as MethodAbi;
|
const methodAbi = item as MethodAbi;
|
||||||
this._methodABIIndex[methodAbi.name] = index;
|
this._methodABIIndex[methodAbi.name] = index;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@
|
|||||||
"ethereumjs-vm": "^4.0.0",
|
"ethereumjs-vm": "^4.0.0",
|
||||||
"ethers": "~4.0.4",
|
"ethers": "~4.0.4",
|
||||||
"js-sha3": "^0.7.0",
|
"js-sha3": "^0.7.0",
|
||||||
"lodash": "^4.17.11",
|
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
@ -29,7 +29,6 @@ import Account from 'ethereumjs-account';
|
|||||||
import * as util from 'ethereumjs-util';
|
import * as util from 'ethereumjs-util';
|
||||||
import { default as VM } from 'ethereumjs-vm';
|
import { default as VM } from 'ethereumjs-vm';
|
||||||
import PStateManager from 'ethereumjs-vm/dist/state/promisified';
|
import PStateManager from 'ethereumjs-vm/dist/state/promisified';
|
||||||
import * as _ from 'lodash';
|
|
||||||
|
|
||||||
export { methodAbiToFunctionSignature } from './utils';
|
export { methodAbiToFunctionSignature } from './utils';
|
||||||
|
|
||||||
@ -100,7 +99,7 @@ export class BaseContract {
|
|||||||
values: any[],
|
values: any[],
|
||||||
formatter: (type: string, value: any) => any,
|
formatter: (type: string, value: any) => any,
|
||||||
): any {
|
): any {
|
||||||
return _.map(values, (value: any, i: number) => formatABIDataItem(abis[i], value, formatter));
|
return values.map((value: any, i: number) => formatABIDataItem(abis[i], value, formatter));
|
||||||
}
|
}
|
||||||
protected static _lowercaseAddress(type: string, value: string): string {
|
protected static _lowercaseAddress(type: string, value: string): string {
|
||||||
return type === 'address' ? value.toLowerCase() : value;
|
return type === 'address' ? value.toLowerCase() : value;
|
||||||
@ -109,8 +108,7 @@ export class BaseContract {
|
|||||||
return BigNumber.isBigNumber(value) ? value.toString() : value;
|
return BigNumber.isBigNumber(value) ? value.toString() : value;
|
||||||
}
|
}
|
||||||
protected static _lookupConstructorAbi(abi: ContractAbi): ConstructorAbi {
|
protected static _lookupConstructorAbi(abi: ContractAbi): ConstructorAbi {
|
||||||
const constructorAbiIfExists = _.find(
|
const constructorAbiIfExists = abi.find(
|
||||||
abi,
|
|
||||||
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor,
|
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor,
|
||||||
// tslint:disable-next-line:no-unnecessary-type-assertion
|
// tslint:disable-next-line:no-unnecessary-type-assertion
|
||||||
) as ConstructorAbi | undefined;
|
) as ConstructorAbi | undefined;
|
||||||
@ -180,15 +178,14 @@ export class BaseContract {
|
|||||||
txData: T,
|
txData: T,
|
||||||
estimateGasAsync?: (txData: T) => Promise<number>,
|
estimateGasAsync?: (txData: T) => Promise<number>,
|
||||||
): Promise<TxData> {
|
): Promise<TxData> {
|
||||||
const removeUndefinedProperties = _.pickBy.bind(_);
|
const txDataWithDefaults = BaseContract._removeUndefinedProperties<T>(txData);
|
||||||
const txDataWithDefaults = removeUndefinedProperties(txData);
|
|
||||||
if (txDataWithDefaults.gas === undefined && estimateGasAsync !== undefined) {
|
if (txDataWithDefaults.gas === undefined && estimateGasAsync !== undefined) {
|
||||||
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults);
|
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults);
|
||||||
}
|
}
|
||||||
if (txDataWithDefaults.from !== undefined) {
|
if (txDataWithDefaults.from !== undefined) {
|
||||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||||
}
|
}
|
||||||
return txDataWithDefaults;
|
return txDataWithDefaults as TxData;
|
||||||
}
|
}
|
||||||
protected static _assertCallParams(callData: Partial<CallData>, defaultBlock?: BlockParam): void {
|
protected static _assertCallParams(callData: Partial<CallData>, defaultBlock?: BlockParam): void {
|
||||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||||
@ -200,6 +197,11 @@ export class BaseContract {
|
|||||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static _removeUndefinedProperties<T>(props: any): T {
|
||||||
|
const clonedProps = { ...props };
|
||||||
|
Object.keys(clonedProps).forEach(key => clonedProps[key] === undefined && delete clonedProps[key]);
|
||||||
|
return clonedProps;
|
||||||
|
}
|
||||||
protected _promiseWithTransactionHash(
|
protected _promiseWithTransactionHash(
|
||||||
txHashPromise: Promise<string>,
|
txHashPromise: Promise<string>,
|
||||||
opts: AwaitTransactionSuccessOpts,
|
opts: AwaitTransactionSuccessOpts,
|
||||||
@ -224,19 +226,19 @@ export class BaseContract {
|
|||||||
// 1. Optional param passed in to public method call
|
// 1. Optional param passed in to public method call
|
||||||
// 2. Global config passed in at library instantiation
|
// 2. Global config passed in at library instantiation
|
||||||
// 3. Gas estimate calculation + safety margin
|
// 3. Gas estimate calculation + safety margin
|
||||||
const removeUndefinedProperties = _.pickBy.bind(_);
|
// tslint:disable-next-line:no-object-literal-type-assertion
|
||||||
const txDataWithDefaults = {
|
const txDataWithDefaults = {
|
||||||
to: this.address,
|
to: this.address,
|
||||||
...removeUndefinedProperties(this._web3Wrapper.getContractDefaults()),
|
...this._web3Wrapper.getContractDefaults(),
|
||||||
...removeUndefinedProperties(txData),
|
...BaseContract._removeUndefinedProperties(txData),
|
||||||
};
|
} as T;
|
||||||
if (txDataWithDefaults.gas === undefined && estimateGasAsync !== undefined) {
|
if (txDataWithDefaults.gas === undefined && estimateGasAsync !== undefined) {
|
||||||
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults);
|
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults);
|
||||||
}
|
}
|
||||||
if (txDataWithDefaults.from !== undefined) {
|
if (txDataWithDefaults.from !== undefined) {
|
||||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||||
}
|
}
|
||||||
return txDataWithDefaults;
|
return txDataWithDefaults as TxData;
|
||||||
}
|
}
|
||||||
protected async _evmExecAsync(encodedData: string): Promise<string> {
|
protected async _evmExecAsync(encodedData: string): Promise<string> {
|
||||||
const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex');
|
const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex');
|
||||||
@ -300,7 +302,7 @@ export class BaseContract {
|
|||||||
return abiEncoder;
|
return abiEncoder;
|
||||||
}
|
}
|
||||||
protected _lookupAbi(functionSignature: string): MethodAbi {
|
protected _lookupAbi(functionSignature: string): MethodAbi {
|
||||||
const methodAbi = _.find(this.abi, (abiDefinition: AbiDefinition) => {
|
const methodAbi = this.abi.find((abiDefinition: AbiDefinition) => {
|
||||||
if (abiDefinition.type !== AbiType.Function) {
|
if (abiDefinition.type !== AbiType.Function) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -362,14 +364,16 @@ export class BaseContract {
|
|||||||
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Function,
|
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Function,
|
||||||
) as MethodAbi[];
|
) as MethodAbi[];
|
||||||
this._abiEncoderByFunctionSignature = {};
|
this._abiEncoderByFunctionSignature = {};
|
||||||
_.each(methodAbis, methodAbi => {
|
methodAbis.forEach(methodAbi => {
|
||||||
const abiEncoder = new AbiEncoder.Method(methodAbi);
|
const abiEncoder = new AbiEncoder.Method(methodAbi);
|
||||||
const functionSignature = abiEncoder.getSignature();
|
const functionSignature = abiEncoder.getSignature();
|
||||||
this._abiEncoderByFunctionSignature[functionSignature] = abiEncoder;
|
this._abiEncoderByFunctionSignature[functionSignature] = abiEncoder;
|
||||||
this._web3Wrapper.abiDecoder.addABI(abi, contractName);
|
this._web3Wrapper.abiDecoder.addABI(abi, contractName);
|
||||||
});
|
});
|
||||||
_.each(logDecodeDependencies, (dependencyAbi, dependencyName) => {
|
if (logDecodeDependencies) {
|
||||||
this._web3Wrapper.abiDecoder.addABI(dependencyAbi, dependencyName);
|
Object.entries(logDecodeDependencies).forEach(([dependencyName, dependencyAbi]) =>
|
||||||
});
|
this._web3Wrapper.abiDecoder.addABI(dependencyAbi, dependencyName),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import {
|
|||||||
RawLogEntry,
|
RawLogEntry,
|
||||||
} from 'ethereum-types';
|
} from 'ethereum-types';
|
||||||
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
|
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
|
||||||
import * as _ from 'lodash';
|
|
||||||
|
|
||||||
import { EventCallback, IndexedFilterValues } from '@0x/types';
|
import { EventCallback, IndexedFilterValues } from '@0x/types';
|
||||||
|
|
||||||
@ -48,10 +47,8 @@ export class SubscriptionManager<ContractEventArgs, ContractEvents extends strin
|
|||||||
this._onLogRemovedSubscriptionToken = undefined;
|
this._onLogRemovedSubscriptionToken = undefined;
|
||||||
}
|
}
|
||||||
public unsubscribeAll(): void {
|
public unsubscribeAll(): void {
|
||||||
const filterTokens = _.keys(this._filterCallbacks);
|
const filterTokens = Object.keys(this._filterCallbacks);
|
||||||
_.each(filterTokens, filterToken => {
|
filterTokens.forEach(filterToken => this.unsubscribe(filterToken));
|
||||||
this.unsubscribe(filterToken);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
public unsubscribe(filterToken: string, err?: Error): void {
|
public unsubscribe(filterToken: string, err?: Error): void {
|
||||||
if (this._filters[filterToken] === undefined) {
|
if (this._filters[filterToken] === undefined) {
|
||||||
@ -63,7 +60,7 @@ export class SubscriptionManager<ContractEventArgs, ContractEvents extends strin
|
|||||||
}
|
}
|
||||||
delete this._filters[filterToken];
|
delete this._filters[filterToken];
|
||||||
delete this._filterCallbacks[filterToken];
|
delete this._filterCallbacks[filterToken];
|
||||||
if (_.isEmpty(this._filters)) {
|
if (Object.keys(this._filters).length === 0) {
|
||||||
this._stopBlockAndLogStream();
|
this._stopBlockAndLogStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +91,7 @@ export class SubscriptionManager<ContractEventArgs, ContractEvents extends strin
|
|||||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||||
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
|
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
|
||||||
const logs = await this._web3Wrapper.getLogsAsync(filter);
|
const logs = await this._web3Wrapper.getLogsAsync(filter);
|
||||||
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
|
const logsWithDecodedArguments = logs.map(this._tryToDecodeLogOrNoop.bind(this)) as any[];
|
||||||
return logsWithDecodedArguments;
|
return logsWithDecodedArguments;
|
||||||
}
|
}
|
||||||
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
|
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
|
||||||
@ -111,7 +108,8 @@ export class SubscriptionManager<ContractEventArgs, ContractEvents extends strin
|
|||||||
): void {
|
): void {
|
||||||
const logs: LogEntry[] = rawLogs.map(rawLog => marshaller.unmarshalLog(rawLog));
|
const logs: LogEntry[] = rawLogs.map(rawLog => marshaller.unmarshalLog(rawLog));
|
||||||
logs.forEach(log => {
|
logs.forEach(log => {
|
||||||
_.forEach(this._filters, (filter: FilterObject, filterToken: string) => {
|
Object.keys(this._filters).forEach((filterToken: string) => {
|
||||||
|
const filter = this._filters[filterToken];
|
||||||
if (filterUtils.matchesFilter(log, filter)) {
|
if (filterUtils.matchesFilter(log, filter)) {
|
||||||
const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
|
const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
|
||||||
const logEvent = {
|
const logEvent = {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import { DataItem, MethodAbi } from 'ethereum-types';
|
import { DataItem, MethodAbi } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
|
||||||
|
|
||||||
// tslint:disable-next-line:completed-docs
|
// tslint:disable-next-line:completed-docs
|
||||||
export function formatABIDataItem(abi: DataItem, value: any, formatter: (type: string, value: any) => any): any {
|
export function formatABIDataItem(abi: DataItem, value: any, formatter: (type: string, value: any) => any): any {
|
||||||
const trailingArrayRegex = /\[\d*\]$/;
|
const trailingArrayRegex = /\[\d*\]$/;
|
||||||
if (abi.type.match(trailingArrayRegex)) {
|
if (abi.type.match(trailingArrayRegex)) {
|
||||||
const arrayItemType = abi.type.replace(trailingArrayRegex, '');
|
const arrayItemType = abi.type.replace(trailingArrayRegex, '');
|
||||||
return _.map(value, val => {
|
return value.map((val: any) => {
|
||||||
const arrayItemAbi = {
|
const arrayItemAbi = {
|
||||||
...abi,
|
...abi,
|
||||||
type: arrayItemType,
|
type: arrayItemType,
|
||||||
@ -15,9 +14,15 @@ export function formatABIDataItem(abi: DataItem, value: any, formatter: (type: s
|
|||||||
});
|
});
|
||||||
} else if (abi.type === 'tuple') {
|
} else if (abi.type === 'tuple') {
|
||||||
const formattedTuple: { [componentName: string]: DataItem } = {};
|
const formattedTuple: { [componentName: string]: DataItem } = {};
|
||||||
_.forEach(abi.components, componentABI => {
|
if (abi.components) {
|
||||||
formattedTuple[componentABI.name] = formatABIDataItem(componentABI, value[componentABI.name], formatter);
|
abi.components.forEach(componentABI => {
|
||||||
|
formattedTuple[componentABI.name] = formatABIDataItem(
|
||||||
|
componentABI,
|
||||||
|
value[componentABI.name],
|
||||||
|
formatter,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return formattedTuple;
|
return formattedTuple;
|
||||||
} else {
|
} else {
|
||||||
return formatter(abi.type, value);
|
return formatter(abi.type, value);
|
||||||
|
@ -3,7 +3,6 @@ import { BigNumber } from '@0x/utils';
|
|||||||
import { BlockRange, ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types';
|
import { BlockRange, ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import * as jsSHA3 from 'js-sha3';
|
import * as jsSHA3 from 'js-sha3';
|
||||||
import * as _ from 'lodash';
|
|
||||||
import * as uuid from 'uuid/v4';
|
import * as uuid from 'uuid/v4';
|
||||||
|
|
||||||
const TOPIC_LENGTH = 32;
|
const TOPIC_LENGTH = 32;
|
||||||
@ -19,7 +18,8 @@ export const filterUtils = {
|
|||||||
abi: ContractAbi,
|
abi: ContractAbi,
|
||||||
blockRange?: BlockRange,
|
blockRange?: BlockRange,
|
||||||
): FilterObject {
|
): FilterObject {
|
||||||
const eventAbi = _.find(abi, { name: eventName }) as EventAbi;
|
// tslint:disable:next-line no-unnecessary-type-assertion
|
||||||
|
const eventAbi = abi.find(abiDefinition => (abiDefinition as EventAbi).name === eventName) as EventAbi;
|
||||||
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi);
|
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi);
|
||||||
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
||||||
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
|
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
|
||||||
@ -37,7 +37,7 @@ export const filterUtils = {
|
|||||||
return filter;
|
return filter;
|
||||||
},
|
},
|
||||||
getEventSignatureFromAbiByName(eventAbi: EventAbi): string {
|
getEventSignatureFromAbiByName(eventAbi: EventAbi): string {
|
||||||
const types = _.map(eventAbi.inputs, 'type');
|
const types = eventAbi.inputs.map(i => i.type);
|
||||||
const signature = `${eventAbi.name}(${types.join(',')})`;
|
const signature = `${eventAbi.name}(${types.join(',')})`;
|
||||||
return signature;
|
return signature;
|
||||||
},
|
},
|
||||||
@ -76,15 +76,15 @@ export const filterUtils = {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
|
doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
|
||||||
const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
|
const matchesTopic = logTopics.map((logTopic, i) => filterUtils.matchesTopic(logTopic, filterTopics[i]));
|
||||||
const doesMatchTopics = _.every(matchesTopic);
|
const doesMatchTopics = matchesTopic.every(m => m);
|
||||||
return doesMatchTopics;
|
return doesMatchTopics;
|
||||||
},
|
},
|
||||||
matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
|
matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
|
||||||
if (_.isArray(filterTopic)) {
|
if (Array.isArray(filterTopic)) {
|
||||||
return _.includes(filterTopic, logTopic);
|
return filterTopic.includes(logTopic);
|
||||||
}
|
}
|
||||||
if (_.isString(filterTopic)) {
|
if (typeof filterTopic === 'string') {
|
||||||
return filterTopic === logTopic;
|
return filterTopic === logTopic;
|
||||||
}
|
}
|
||||||
// null topic is a wildcard
|
// null topic is a wildcard
|
||||||
|
Loading…
x
Reference in New Issue
Block a user