Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erc logging #80

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 45 additions & 22 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const { sha3, BN } = require("web3-utils");
const abiCoder = require("web3-eth-abi");

// topic id erc20 and erc721
const transferSignature = "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
const state = {
savedABIs: [],
methodIDs: {},
erc20IDs:{}
};

function _getABIs() {
Expand Down Expand Up @@ -32,7 +34,11 @@ function _addABI(abiArray) {
")"
);
if (abi.type === "event") {
state.methodIDs[signature.slice(2)] = abi;
// add erc20 event in separate array
if ( state.methodIDs[signature.slice(2)] && signature.slice(2) === transferSignature)
state.erc20IDs[[signature.slice(2)]] = abi;
else
state.methodIDs[signature.slice(2)] = abi;
} else {
state.methodIDs[signature.slice(2, 10)] = abi;
}
Expand Down Expand Up @@ -131,12 +137,30 @@ function _decodeMethod(data) {
}

function _decodeLogs(logs) {
return logs.filter(log => log.topics.length > 0).map((logItem) => {
const methodID = logItem.topics[0].slice(2);
const method = state.methodIDs[methodID];
const logsToProcess = logs.filter(log => log.topics.length > 0);
const resultSet = [];
for (let index = 0; index < logsToProcess.length; index++) {
let method;
const log = logsToProcess[index];
const methodID = log.topics[0].slice(2);
// methodid mathches with erc20 transfer event and topic count length is 3
// it means its erc20 transaction
if (methodID === transferSignature && log.topics.length<3){
continue
}
else if (methodID === transferSignature && log.topics.length===3){
method = state.erc20IDs[methodID];
// if the dev have not supplied the erc721 abi, we will fetch erc20 method event info from methods
if (!method){
method = state.methodIDs[methodID];
}
}

else
method = state.methodIDs[methodID];
let decodedParams = [];
if (method) {
const logData = logItem.data;
let decodedParams = [];
const logData = log.data;
let dataIndex = 0;
let topicsIndex = 1;

Expand All @@ -146,27 +170,26 @@ function _decodeLogs(logs) {
dataTypes.push(input.type);
}
});

const decodedData = abiCoder.decodeParameters(
dataTypes,
logData.slice(2)
);

// Loop topic and data to get the params
method.inputs.map(function(param) {
let decodedP = {
name: param.name,
type: param.type,
};

if (param.indexed) {
decodedP.value = logItem.topics[topicsIndex];
decodedP.value = log.topics[topicsIndex];
topicsIndex++;
} else {
decodedP.value = decodedData[dataIndex];
dataIndex++;
}

if (param.type === "address") {
decodedP.value = decodedP.value.toLowerCase();
// 42 because len(0x) + 40
Expand All @@ -177,31 +200,31 @@ function _decodeLogs(logs) {
decodedP.value = temp.join("");
}
}

if (
param.type === "uint256" ||
param.type === "uint8" ||
param.type === "int"
param.type === "uint8" ||
param.type === "int"
) {
// ensure to remove leading 0x for hex numbers
if (typeof decodedP.value === "string" && decodedP.value.startsWith("0x")) {
decodedP.value = new BN(decodedP.value.slice(2), 16).toString(10);
} else {
decodedP.value = new BN(decodedP.value).toString(10);
}

}

decodedParams.push(decodedP);
});

return {
resultSet.push({
name: method.name,
events: decodedParams,
address: logItem.address,
};
address: log.address,
});
}
});
}
return resultSet;
}

module.exports = {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"main": "index.js",
"scripts": {
"pretest": "eslint --ignore-path .eslintignore .",
"lint": "./node_modules/.bin/eslint ./",
"lint:fix": "eslint ./ --fix",
"test": "mocha test",
"dist": "webpack"
},
Expand Down
68 changes: 68 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,72 @@ describe("abi decoder", function () {
expect(Object.keys(methods)).to.have.length(39);
});

it("decode erc20 logs", () => {
const testABI = [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"}];
abiDecoder.addABI(testABI);
const testLogs = [
{
data: "0x00000000000000000000000000000000000000000000000c1b1c7851eb4743ed",
topics: [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000009963c5d9b0a02d6316e546677c73932b0a60df1f",
"0x000000000000000000000000fd79fa24d5a883e90ed60d1c080f49cba6c925da",
],
address: "0x2E10348eE563dEc5FE483DE558D1946b7A3372c2"
}
];
const decodedLogs = abiDecoder.decodeLogs(testLogs);
expect(decodedLogs).to.be.an("array");
expect(decodedLogs).to.have.length(1);
expect(decodedLogs[0].name).to.equal("Transfer");
expect(decodedLogs[0].events).to.have.length(3);
expect(decodedLogs[0].address).to.equal("0x2E10348eE563dEc5FE483DE558D1946b7A3372c2");
expect(decodedLogs[0].events[0].name).to.equal("from");
expect(decodedLogs[0].events[0].type).to.equal("address");
expect(decodedLogs[0].events[0].value).to.equal("0x9963c5d9b0a02d6316e546677c73932b0a60df1f");
expect(decodedLogs[0].events[1].name).to.equal("to");
expect(decodedLogs[0].events[1].type).to.equal("address");
expect(decodedLogs[0].events[1].value).to.equal("0xfd79fa24d5a883e90ed60d1c080f49cba6c925da");
expect(decodedLogs[0].events[2].type).to.equal("uint256");
expect(decodedLogs[0].events[2].name).to.equal("value");
expect(decodedLogs[0].events[2].value).to.equal("223314497516121572333");

});
it("decode erc721 logs", () => {
const testABI = [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}],"name":"Transfer","type":"event"}];
abiDecoder.addABI(testABI);
const testLogs = [
{
data: "0x00000000000000000000000000000000000000000000000c1b1c7851eb4743ed",
topics: [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000009963c5d9b0a02d6316e546677c73932b0a60df1f",
"0x000000000000000000000000fd79fa24d5a883e90ed60d1c080f49cba6c925da",
],
address: "0x2E10348eE563dEc5FE483DE558D1946b7A3372c2"
}
];
const decodedLogs = abiDecoder.decodeLogs(testLogs);
expect(decodedLogs).to.be.an("array");
expect(decodedLogs).to.have.length(1);
expect(decodedLogs[0].name).to.equal("Transfer");
expect(decodedLogs[0].events).to.have.length(3);
expect(decodedLogs[0].address).to.equal("0x2E10348eE563dEc5FE483DE558D1946b7A3372c2");
expect(decodedLogs[0].events[0].name).to.equal("from");
expect(decodedLogs[0].events[0].type).to.equal("address");
expect(decodedLogs[0].events[0].value).to.equal("0x9963c5d9b0a02d6316e546677c73932b0a60df1f");
expect(decodedLogs[0].events[1].name).to.equal("to");
expect(decodedLogs[0].events[1].type).to.equal("address");
expect(decodedLogs[0].events[1].value).to.equal("0xfd79fa24d5a883e90ed60d1c080f49cba6c925da");
expect(decodedLogs[0].events[2].type).to.equal("uint256");
expect(decodedLogs[0].events[2].name).to.equal("value");
expect(decodedLogs[0].events[2].value).to.equal("223314497516121572333");

});

});