Move log decoding to AbiDecoder

This commit is contained in:
Leonid Logvinov
2017-10-03 12:31:46 +03:00
parent a9681072ee
commit 6bbdc98ba2
2 changed files with 38 additions and 54 deletions

View File

@@ -302,7 +302,8 @@ export class ZeroEx {
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash); const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
if (!_.isNull(transactionReceipt)) { if (!_.isNull(transactionReceipt)) {
intervalUtils.clearAsyncExcludingInterval(intervalId); intervalUtils.clearAsyncExcludingInterval(intervalId);
const logsWithDecodedArgs = _.map(transactionReceipt.logs, this.tryToDecodeLogOrNoOp.bind(this)); const tryToDecodeLogOrNoOp = this._abiDecoder.tryToDecodeLogOrNoOp.bind(this._abiDecoder);
const logsWithDecodedArgs = _.map(transactionReceipt.logs, tryToDecodeLogOrNoOp);
const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = { const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
...transactionReceipt, ...transactionReceipt,
logs: logsWithDecodedArgs, logs: logsWithDecodedArgs,
@@ -313,26 +314,6 @@ export class ZeroEx {
}); });
return txReceiptPromise; return txReceiptPromise;
} }
/**
* Gets historical logs without creating a subscription
* @param filter Filter object
* @return Array of logs that match the filter
*/
public async getLogsAsync(filter: FilterObject): Promise<RawLog[]> {
const logs = await this._web3Wrapper.getLogsAsync(filter);
return logs;
}
private tryToDecodeLogOrNoOp(log: Web3.LogEntry): LogWithDecodedArgs|Web3.LogEntry {
const decodedLog = this._abiDecoder.decodeLog(log);
if (_.isUndefined(decodedLog)) {
return log;
}
const logWithDecodedArgs: LogWithDecodedArgs = {
...log,
...decodedLog,
};
return logWithDecodedArgs;
}
/* /*
* HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from
* an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle. * an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle.

View File

@@ -1,7 +1,7 @@
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js'; import * as BigNumber from 'bignumber.js';
import {AbiType, DecodedLogArgs, DecodedArgs} from '../types'; import {AbiType, DecodedLogArgs, DecodedArgs, LogWithDecodedArgs} from '../types';
import * as SolidityCoder from 'web3/lib/solidity/coder'; import * as SolidityCoder from 'web3/lib/solidity/coder';
export class AbiDecoder { export class AbiDecoder {
@@ -10,40 +10,43 @@ export class AbiDecoder {
constructor(abiArrays: Web3.AbiDefinition[][]) { constructor(abiArrays: Web3.AbiDefinition[][]) {
_.map(abiArrays, this.addABI.bind(this)); _.map(abiArrays, this.addABI.bind(this));
} }
public decodeLog(logItem: Web3.LogEntry): DecodedArgs|undefined { public tryToDecodeLogOrNoOp(log: Web3.LogEntry): LogWithDecodedArgs|Web3.LogEntry {
const methodId = logItem.topics[0]; const methodId = log.topics[0];
const event = this.methodIds[methodId]; const event = this.methodIds[methodId];
if (!_.isUndefined(event)) { if (_.isUndefined(event)) {
const logData = logItem.data; return log;
const decodedParams: DecodedLogArgs = {};
let dataIndex = 0;
let topicsIndex = 1;
const nonIndexedInputs = _.filter(event.inputs, input => !input.indexed);
const dataTypes = _.map(nonIndexedInputs, input => input.type);
const decodedData = SolidityCoder.decodeParams(dataTypes, logData.slice(2));
_.map(event.inputs, (param: Web3.EventParameter) => {
let value;
if (param.indexed) {
value = logItem.topics[topicsIndex];
topicsIndex++;
} else {
value = decodedData[dataIndex];
dataIndex++;
}
if (param.type === 'address') {
value = this.padZeros(new BigNumber(value).toString(16));
} else if (param.type === 'uint256' || param.type === 'uint8' || param.type === 'int' ) {
value = new BigNumber(value);
}
decodedParams[param.name] = value;
});
return {
event: event.name,
args: decodedParams,
};
} }
const logData = log.data;
const decodedParams: DecodedLogArgs = {};
let dataIndex = 0;
let topicsIndex = 1;
const nonIndexedInputs = _.filter(event.inputs, input => !input.indexed);
const dataTypes = _.map(nonIndexedInputs, input => input.type);
const decodedData = SolidityCoder.decodeParams(dataTypes, logData.slice(2));
_.map(event.inputs, (param: Web3.EventParameter) => {
let value;
if (param.indexed) {
value = log.topics[topicsIndex];
topicsIndex++;
} else {
value = decodedData[dataIndex];
dataIndex++;
}
if (param.type === 'address') {
value = this.padZeros(new BigNumber(value).toString(16));
} else if (param.type === 'uint256' || param.type === 'uint8' || param.type === 'int' ) {
value = new BigNumber(value);
}
decodedParams[param.name] = value;
});
return {
...log,
event: event.name,
args: decodedParams,
};
} }
private addABI(abiArray: Web3.AbiDefinition[]): void { private addABI(abiArray: Web3.AbiDefinition[]): void {
_.map(abiArray, (abi: Web3.AbiDefinition) => { _.map(abiArray, (abi: Web3.AbiDefinition) => {