aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonid <logvinov.leon@gmail.com>2017-09-06 21:26:29 +0800
committerGitHub <noreply@github.com>2017-09-06 21:26:29 +0800
commitcb44b77d0b64bf4a0808cf1fea488ab2e1a60cf3 (patch)
treef7630683357f6a2273557d7027a1985f8a28f94b
parent92eb68bf2c412d42322ab7f483af91666ccbdcb1 (diff)
parent1baf06531755597e37498005eb2c29aef5114fab (diff)
downloaddexon-0x-contracts-cb44b77d0b64bf4a0808cf1fea488ab2e1a60cf3.tar.gz
dexon-0x-contracts-cb44b77d0b64bf4a0808cf1fea488ab2e1a60cf3.tar.zst
dexon-0x-contracts-cb44b77d0b64bf4a0808cf1fea488ab2e1a60cf3.zip
Merge pull request #156 from 0xProject/feature/custom-abi-decoder
Custom abi decoder
-rw-r--r--package.json1
-rw-r--r--src/0x.ts24
-rw-r--r--src/globals.d.ts4
-rw-r--r--src/types.ts6
-rw-r--r--src/utils/abi_decoder.ts66
-rw-r--r--test/0x.js_test.ts3
-rw-r--r--yarn.lock106
7 files changed, 95 insertions, 115 deletions
diff --git a/package.json b/package.json
index c528447d2..ed9f1943b 100644
--- a/package.json
+++ b/package.json
@@ -91,7 +91,6 @@
},
"dependencies": {
"0x-json-schemas": "^0.5.1",
- "abi-decoder": "^1.0.8",
"bignumber.js": "^4.0.2",
"compare-versions": "^3.0.1",
"es6-promisify": "^5.0.0",
diff --git a/src/0x.ts b/src/0x.ts
index 0af164b1e..bde9360c3 100644
--- a/src/0x.ts
+++ b/src/0x.ts
@@ -12,6 +12,7 @@ import {constants} from './utils/constants';
import {utils} from './utils/utils';
import {signatureUtils} from './utils/signature_utils';
import {assert} from './utils/assert';
+import {AbiDecoder} from './utils/abi_decoder';
import {artifacts} from './artifacts';
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
@@ -70,6 +71,7 @@ export class ZeroEx {
*/
public proxy: TokenTransferProxyWrapper;
private _web3Wrapper: Web3Wrapper;
+ private _abiDecoder: AbiDecoder;
/**
* Verifies that the elliptic curve signature `signature` was generated
* by signing `data` with the private key corresponding to the `signerAddress` address.
@@ -183,7 +185,9 @@ export class ZeroEx {
// We re-assign the send method so that Web3@1.0 providers work with 0x.js
(provider as any).sendAsync = (provider as any).send;
}
- this._registerArtifactsWithinABIDecoder();
+ const artifactJSONs = _.values(artifacts);
+ const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
+ this._abiDecoder = new AbiDecoder(abiArrays);
const gasPrice = _.isUndefined(config) ? undefined : config.gasPrice;
const defaults = {
gasPrice,
@@ -281,16 +285,13 @@ export class ZeroEx {
if (!_.isNull(transactionReceipt)) {
clearInterval(intervalId);
const logsWithDecodedArgs = _.map(transactionReceipt.logs, (log: Web3.LogEntry) => {
- const decodedLog = abiDecoder.decodeLogs([log])[0];
- const decodedArgs = decodedLog.events;
- const args: DecodedLogArgs = {};
- _.forEach(decodedArgs, arg => {
- args[arg.name] = arg.value;
- });
+ const decodedLog = this._abiDecoder.decodeLog(log);
+ if (_.isUndefined(decodedLog)) {
+ return log;
+ }
const logWithDecodedArgs: LogWithDecodedArgs = {
...log,
- args,
- event: decodedLog.name,
+ ...decodedLog,
};
return logWithDecodedArgs;
});
@@ -304,9 +305,4 @@ export class ZeroEx {
});
return txReceiptPromise;
}
- private _registerArtifactsWithinABIDecoder(): void {
- for (const artifact of _.values(artifacts)) {
- abiDecoder.addABI(artifact.abi);
- }
- }
}
diff --git a/src/globals.d.ts b/src/globals.d.ts
index 2120bd45d..467a756a4 100644
--- a/src/globals.d.ts
+++ b/src/globals.d.ts
@@ -89,3 +89,7 @@ declare module 'abi-decoder' {
const addABI: (abi: Web3.AbiDefinition) => void;
const decodeLogs: (logs: Web3.LogEntry[]) => DecodedLog[];
}
+
+declare module 'web3/lib/solidity/coder' {
+ const decodeParams: (types: string[], data: string) => any[];
+}
diff --git a/src/types.ts b/src/types.ts
index 9d3f77127..7e370e3f1 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -402,11 +402,13 @@ export interface DecodedLogArgs {
[argName: string]: ContractEventArg;
}
-export interface LogWithDecodedArgs extends Web3.LogEntry {
+export interface DecodedArgs {
args: DecodedLogArgs;
event: string;
}
+export interface LogWithDecodedArgs extends Web3.LogEntry, DecodedArgs {}
+
export interface TransactionReceiptWithDecodedLogs extends Web3.TransactionReceipt {
- logs: LogWithDecodedArgs[];
+ logs: Array<LogWithDecodedArgs|Web3.LogEntry>;
}
diff --git a/src/utils/abi_decoder.ts b/src/utils/abi_decoder.ts
new file mode 100644
index 000000000..f988a5695
--- /dev/null
+++ b/src/utils/abi_decoder.ts
@@ -0,0 +1,66 @@
+import * as Web3 from 'web3';
+import * as _ from 'lodash';
+import {AbiType, DecodedLogArgs, DecodedArgs} from '../types';
+import * as SolidityCoder from 'web3/lib/solidity/coder';
+
+export class AbiDecoder {
+ private savedABIs: Web3.AbiDefinition[] = [];
+ private methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
+ constructor(abiArrays: Web3.AbiDefinition[][]) {
+ _.map(abiArrays, this.addABI.bind(this));
+ }
+ public decodeLog(logItem: Web3.LogEntry): DecodedArgs|undefined {
+ const methodId = logItem.topics[0];
+ const event = this.methodIds[methodId];
+ if (!_.isUndefined(event)) {
+ const logData = logItem.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 = logItem.topics[topicsIndex];
+ topicsIndex++;
+ } else {
+ value = decodedData[dataIndex];
+ dataIndex++;
+ }
+ if (param.type === 'address') {
+ value = this.padZeros(new Web3().toBigNumber(value).toString(16));
+ } else if (param.type === 'uint256' || param.type === 'uint8' || param.type === 'int' ) {
+ value = new Web3().toBigNumber(value).toString(10);
+ }
+ decodedParams[param.name] = value;
+ });
+
+ return {
+ event: event.name,
+ args: decodedParams,
+ };
+ }
+ }
+ private addABI(abiArray: Web3.AbiDefinition[]): void {
+ _.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;
+ }
+ });
+ this.savedABIs = this.savedABIs.concat(abiArray);
+ }
+ private padZeros(address: string) {
+ let formatted = address;
+ if (_.startsWith(formatted, '0x')) {
+ formatted = formatted.slice(2);
+ }
+
+ formatted = _.padStart(formatted, 40, '0');
+ return `0x${formatted}`;
+ }
+}
diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts
index c453b8dab..5182275a8 100644
--- a/test/0x.js_test.ts
+++ b/test/0x.js_test.ts
@@ -9,6 +9,7 @@ import {constants} from './utils/constants';
import {TokenUtils} from './utils/token_utils';
import {web3Factory} from './utils/web3_factory';
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
+import {LogWithDecodedArgs} from '../src';
const blockchainLifecycle = new BlockchainLifecycle();
chaiSetup.configure();
@@ -223,7 +224,7 @@ describe('ZeroEx library', () => {
const proxyAddress = await zeroEx.proxy.getContractAddressAsync();
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
- const log = txReceiptWithDecodedLogs.logs[0];
+ const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs;
expect(log.event).to.be.equal('Approval');
expect(log.args).to.be.deep.equal({
_owner: coinbase,
diff --git a/yarn.lock b/yarn.lock
index 3b191168e..c3b7f66e4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -66,20 +66,6 @@ abbrev@1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
-abi-decoder@^1.0.8:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.0.8.tgz#7794d864c4b3fd8bab600bdd445ceb01d333ea43"
- dependencies:
- babel-core "^6.23.1"
- babel-loader "^6.3.2"
- babel-plugin-add-module-exports "^0.2.1"
- babel-plugin-transform-es2015-modules-amd "^6.22.0"
- babel-preset-es2015 "^6.22.0"
- chai "^3.5.0"
- mocha "^3.2.0"
- web3 "^0.18.4"
- webpack "^2.2.1"
-
abstract-leveldown@2.4.1, abstract-leveldown@~2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.4.1.tgz#b3bfedb884eb693a12775f0c55e9f0a420ccee64"
@@ -104,15 +90,11 @@ aes-js@^0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d"
-ajv-keywords@^1.1.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
-
ajv-keywords@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.0.tgz#a296e17f7bfae7c1ce4f7e0de53d29cb32162df0"
-ajv@^4.7.0, ajv@^4.9.1:
+ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
dependencies:
@@ -331,7 +313,7 @@ babel-code-frame@^6.22.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
-babel-core@^6.0.14, babel-core@^6.23.1, babel-core@^6.24.1:
+babel-core@^6.0.14, babel-core@^6.24.1:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729"
dependencies:
@@ -443,25 +425,12 @@ babel-helpers@^6.24.1:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-loader@^6.3.2:
- version "6.4.1"
- resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca"
- dependencies:
- find-cache-dir "^0.1.1"
- loader-utils "^0.2.16"
- mkdirp "^0.5.1"
- object-assign "^4.0.1"
-
babel-messages@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-add-module-exports@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
-
babel-plugin-check-es2015-constants@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
@@ -544,7 +513,7 @@ babel-plugin-transform-es2015-literals@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
+babel-plugin-transform-es2015-modules-amd@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
dependencies:
@@ -649,7 +618,7 @@ babel-plugin-transform-strict-mode@^6.24.1:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-preset-es2015@^6.22.0, babel-preset-es2015@^6.24.0:
+babel-preset-es2015@^6.24.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
dependencies:
@@ -1066,14 +1035,6 @@ chai-typescript-typings@^0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/chai-typescript-typings/-/chai-typescript-typings-0.0.0.tgz#52e076d72cf29129c94ab1dba6e33ce3828a0724"
-chai@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
- dependencies:
- assertion-error "^1.0.1"
- deep-eql "^0.1.3"
- type-detect "^1.0.0"
-
chai@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/chai/-/chai-4.0.2.tgz#2f7327c4de6f385dd7787999e2ab02697a32b83b"
@@ -1364,13 +1325,13 @@ debug-log@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f"
-debug@2.6.0, debug@^2.1.1:
+debug@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b"
dependencies:
ms "0.7.2"
-debug@^2.2.0, debug@^2.3.3, debug@^2.6.3:
+debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.3:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
@@ -1380,12 +1341,6 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
-deep-eql@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
- dependencies:
- type-detect "0.1.1"
-
deep-eql@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a"
@@ -2910,15 +2865,6 @@ loader-runner@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
-loader-utils@^0.2.16:
- version "0.2.17"
- resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
- dependencies:
- big.js "^3.1.3"
- emojis-list "^2.0.0"
- json5 "^0.5.0"
- object-assign "^4.0.1"
-
loader-utils@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
@@ -3233,7 +3179,7 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
dependencies:
minimist "0.0.8"
-mocha@^3.2.0, mocha@^3.4.1:
+mocha@^3.4.1:
version "3.4.2"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594"
dependencies:
@@ -4843,14 +4789,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
-type-detect@0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
-
-type-detect@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
-
type-detect@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55"
@@ -4903,7 +4841,7 @@ typescript@2.4.1, typescript@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc"
-uglify-js@^2.6, uglify-js@^2.8.27, uglify-js@^2.8.29:
+uglify-js@^2.6, uglify-js@^2.8.29:
version "2.8.29"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
dependencies:
@@ -5082,7 +5020,7 @@ web3@^0.16.0:
utf8 "^2.1.1"
xmlhttprequest "*"
-web3@^0.18.2, web3@^0.18.4:
+web3@^0.18.2:
version "0.18.4"
resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d"
dependencies:
@@ -5109,32 +5047,6 @@ webpack-sources@^1.0.1:
source-list-map "^2.0.0"
source-map "~0.5.3"
-webpack@^2.2.1:
- version "2.7.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.7.0.tgz#b2a1226804373ffd3d03ea9c6bd525067034f6b1"
- dependencies:
- acorn "^5.0.0"
- acorn-dynamic-import "^2.0.0"
- ajv "^4.7.0"
- ajv-keywords "^1.1.1"
- async "^2.1.2"
- enhanced-resolve "^3.3.0"
- interpret "^1.0.0"
- json-loader "^0.5.4"
- json5 "^0.5.1"
- loader-runner "^2.3.0"
- loader-utils "^0.2.16"
- memory-fs "~0.4.1"
- mkdirp "~0.5.0"
- node-libs-browser "^2.0.0"
- source-map "^0.5.3"
- supports-color "^3.1.0"
- tapable "~0.2.5"
- uglify-js "^2.8.27"
- watchpack "^1.3.1"
- webpack-sources "^1.0.1"
- yargs "^6.0.0"
-
webpack@^3.0.0, webpack@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.1.0.tgz#ac0675e500db835f9ab2369d29ba096f51ad0731"