Use as a backend to decode event args
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.4.0 - _TBD, 2018_
|
||||
|
||||
* Use `ethers-contracts` as a backend to decode event args (#413)
|
||||
|
||||
## v0.3.2 - _February 9, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"dependencies": {
|
||||
"@0xproject/types": "^0.2.3",
|
||||
"bignumber.js": "~4.1.0",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"js-sha3": "^0.7.0",
|
||||
"lodash": "^4.17.4",
|
||||
"web3": "^0.20.0"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AbiType, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes } from '@0xproject/types';
|
||||
import * as ethersContracts from 'ethers-contracts';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
|
||||
|
||||
import { BigNumber } from './configured_bignumber';
|
||||
|
||||
@@ -27,31 +27,29 @@ export class AbiDecoder {
|
||||
if (_.isUndefined(event)) {
|
||||
return log;
|
||||
}
|
||||
const ethersInterface = new ethersContracts.Interface([event]);
|
||||
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('0x'.length));
|
||||
const decodedData = ethersInterface.events[event.name].parse(log.data);
|
||||
|
||||
let failedToDecode = false;
|
||||
_.forEach(event.inputs, (param: Web3.EventParameter) => {
|
||||
_.forEach(event.inputs, (param: Web3.EventParameter, idx: number) => {
|
||||
// Indexed parameters are stored in topics. Non-indexed ones in decodedData
|
||||
let value: BigNumber | string = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
|
||||
let value: BigNumber | string | number = param.indexed ? log.topics[topicsIndex++] : decodedData[idx];
|
||||
if (_.isUndefined(value)) {
|
||||
failedToDecode = true;
|
||||
return;
|
||||
}
|
||||
if (param.type === SolidityTypes.Address) {
|
||||
value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
|
||||
} else if (
|
||||
param.type === SolidityTypes.Uint256 ||
|
||||
param.type === SolidityTypes.Uint8 ||
|
||||
param.type === SolidityTypes.Uint
|
||||
) {
|
||||
} else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) {
|
||||
value = new BigNumber(value);
|
||||
} else if (param.type === SolidityTypes.Uint8) {
|
||||
value = new BigNumber(value).toNumber();
|
||||
}
|
||||
decodedParams[param.name] = value;
|
||||
});
|
||||
@@ -67,11 +65,14 @@ export class AbiDecoder {
|
||||
}
|
||||
}
|
||||
private _addABI(abiArray: Web3.AbiDefinition[]): void {
|
||||
if (_.isUndefined(abiArray)) {
|
||||
return;
|
||||
}
|
||||
const ethersInterface = new ethersContracts.Interface(abiArray);
|
||||
_.map(abiArray, (abi: Web3.AbiDefinition) => {
|
||||
if (abi.type === AbiType.Event) {
|
||||
const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`;
|
||||
const signatureHash = new Web3().sha3(signature);
|
||||
this._methodIds[signatureHash] = abi;
|
||||
const topic = ethersInterface.events[abi.name].topic;
|
||||
this._methodIds[topic] = abi;
|
||||
}
|
||||
});
|
||||
this._savedABIs = this._savedABIs.concat(abiArray);
|
||||
|
||||
29
packages/utils/src/globals.d.ts
vendored
29
packages/utils/src/globals.d.ts
vendored
@@ -1,3 +1,28 @@
|
||||
declare module 'web3/lib/solidity/coder' {
|
||||
const decodeParams: (types: string[], data: string) => any[];
|
||||
declare module 'ethers-contracts' {
|
||||
export interface TransactionDescription {
|
||||
name: string;
|
||||
signature: string;
|
||||
sighash: string;
|
||||
data: string;
|
||||
}
|
||||
export interface CallDescription extends TransactionDescription {
|
||||
parse: (...args: any[]) => any;
|
||||
}
|
||||
export interface FunctionDescription {
|
||||
(...params: any[]): TransactionDescription | CallDescription;
|
||||
inputs: { names: string[]; types: string[] };
|
||||
outputs: { names: string[]; types: string[] };
|
||||
}
|
||||
export interface EventDescription {
|
||||
parse: (...args: any[]) => any;
|
||||
inputs: { names: string[]; types: string[] };
|
||||
signature: string;
|
||||
topic: string;
|
||||
}
|
||||
// tslint:disable-next-line:max-classes-per-file
|
||||
export class Interface {
|
||||
public functions: { [functionName: string]: FunctionDescription };
|
||||
public events: { [eventName: string]: EventDescription };
|
||||
constructor(abi: any);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user