Socket
Socket
Sign inDemoInstall

ethjs-abi

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ethjs-abi - npm Package Compare versions

Comparing version 0.1.8 to 0.1.9

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# 0.1.9 -- event and log decoding
1. Event and log decoding methods
# 0.1.7 -- handles empty address decode nicely

@@ -2,0 +6,0 @@

@@ -20,3 +20,3 @@ 'use strict';

if (types.length !== values.length) {
throw new Error('[ethjs-abi] while encoding params, types/values mismatch, types length ' + types.length + ' should be ' + values.length);
throw new Error('[ethjs-abi] while encoding params, types/values mismatch, Your contract requires ' + types.length + ' types (arguments), and you passed in ' + values.length);
}

@@ -68,2 +68,4 @@

function decodeParams(names, types, data) {
var useNumberedParams = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
// Names is optional, so shift over all the parameters if not provided

@@ -90,3 +92,3 @@ if (arguments.length < 3) {

}
values[index] = result.value;
if (useNumberedParams) values[index] = result.value;
if (names[index]) {

@@ -121,10 +123,59 @@ values[names[index]] = result.value;

function eventSignature(eventObject) {
var signature = eventObject.name + '(' + utils.getKeys(eventObject.inputs, 'type').join(',') + ')';
return '0x' + utils.keccak256(signature);
}
// decode method data bytecode, from method ABI object
function decodeEvent(eventObject, data) {
var inputNames = utils.getKeys(eventObject.inputs, 'name', true);
var inputTypes = utils.getKeys(eventObject.inputs, 'type');
function decodeEvent(eventObject, data, topics) {
var useNumberedParams = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
return decodeParams(inputNames, inputTypes, utils.hexOrBuffer(data));
var nonIndexed = eventObject.inputs.filter(function (input) {
return !input.indexed;
});
var nonIndexedNames = utils.getKeys(nonIndexed, 'name', true);
var nonIndexedTypes = utils.getKeys(nonIndexed, 'type');
var event = decodeParams(nonIndexedNames, nonIndexedTypes, utils.hexOrBuffer(data), useNumberedParams);
var topicOffset = eventObject.anonymous ? 0 : 1;
eventObject.inputs.filter(function (input) {
return input.indexed;
}).map(function (input, i) {
var topic = new Buffer(topics[i + topicOffset].slice(2), 'hex');
var coder = getParamCoder(input.type);
event[input.name] = coder.decode(topic, 0).value;
});
event._eventName = eventObject.name;
return event;
}
// Decode a specific log item with a specific event abi
function decodeLogItem(eventObject, log) {
var useNumberedParams = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
if (eventObject && log.topics[0] === eventSignature(eventObject)) {
return decodeEvent(eventObject, log.data, log.topics, useNumberedParams);
}
}
// Create a decoder for all events defined in an abi. It returns a function which is called
// on an array of log entries such as received from getLogs or getTransactionReceipt and parses
// any matching log entries
function logDecoder(abi) {
var useNumberedParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var eventMap = {};
abi.filter(function (item) {
return item.type === 'event';
}).map(function (item) {
eventMap[eventSignature(item)] = item;
});
return function (logItems) {
return logItems.map(function (log) {
return decodeLogItem(eventMap[log.topics[0]], log, useNumberedParams);
}).filter(function (i) {
return i;
});
};
}
module.exports = {

@@ -136,3 +187,6 @@ encodeParams: encodeParams,

encodeEvent: encodeEvent,
decodeEvent: decodeEvent
decodeEvent: decodeEvent,
decodeLogItem: decodeLogItem,
logDecoder: logDecoder,
eventSignature: eventSignature
};

@@ -6,4 +6,6 @@ 'use strict';

var contracts = require('./contracts.json');
var BN = require('bn.js');
describe('test basic encoding and decoding functionality', function () {
var interfaceABI = [{ 'constant': false, 'inputs': [{ 'name': '_value', 'type': 'uint256' }], 'name': 'set', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'type': 'function' }, { 'constant': false, 'inputs': [], 'name': 'get', 'outputs': [{ 'name': 'storeValue', 'type': 'uint256' }], 'payable': false, 'type': 'function' }, { 'anonymous': false, 'inputs': [{ 'indexed': false, 'name': '_newValue', 'type': 'uint256' }, { 'indexed': false, 'name': '_sender', 'type': 'address' }], 'name': 'SetComplete', 'type': 'event' }]; // eslint-disable-line
it('should encode and decode contract data nicely', function () {

@@ -13,3 +15,2 @@ var BalanceClaimInterface = JSON.parse(contracts.BalanceClaim['interface']);

assert.equal(encodeBalanceClaimMethod1, '0x30509bca');
var interfaceABI = [{ 'constant': false, 'inputs': [{ 'name': '_value', 'type': 'uint256' }], 'name': 'set', 'outputs': [{ 'name': '', 'type': 'bool' }], 'payable': false, 'type': 'function' }, { 'constant': false, 'inputs': [], 'name': 'get', 'outputs': [{ 'name': 'storeValue', 'type': 'uint256' }], 'payable': false, 'type': 'function' }, { 'anonymous': false, 'inputs': [{ 'indexed': false, 'name': '_newValue', 'type': 'uint256' }, { 'indexed': false, 'name': '_sender', 'type': 'address' }], 'name': 'SetComplete', 'type': 'event' }]; // eslint-disable-line

@@ -23,6 +24,62 @@ var setMethodInputBytecode = abi.encodeMethod(interfaceABI[0], [24000]);

abi.encodeEvent(interfaceABI[2], [24000, '0xca35b7d915458ef540ade6068dfe2f44e8fa733c']);
abi.decodeEvent(interfaceABI[2], '0x0000000000000000000000000000000000000000000000000000000000000d7d000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c');
var event = abi.decodeEvent(interfaceABI[2], '0x0000000000000000000000000000000000000000000000000000000000000d7d000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c');
assert.deepEqual(event, {
0: new BN(3453),
1: '0xca35b7d915458ef540ade6068dfe2f44e8fa733c',
_eventName: 'SetComplete',
_newValue: new BN(3453),
_sender: '0xca35b7d915458ef540ade6068dfe2f44e8fa733c'
});
assert.equal(setMethodInputBytecode, '0x60fe47b10000000000000000000000000000000000000000000000000000000000005dc0');
});
it('should decode event from log', function () {
var eventAbi = {
anonymous: false,
inputs: [{ indexed: true, name: 'userKey', type: 'address' }, { indexed: false, name: 'proxy', type: 'address' }, { indexed: false, name: 'controller', type: 'address' }, { indexed: false, name: 'recoveryKey', type: 'address' }],
name: 'IdentityCreated',
type: 'event'
};
assert.equal(abi.eventSignature(eventAbi), '0xc36800ebd6079fdafc3a7100d0d1172815751804a6d1b7eb365b85f6c9c80e61');
var logs = [{
address: '0xadb4966858672ef5ed70894030526544f9a5acdd',
topics: ['0xc36800ebd6079fdafc3a7100d0d1172815751804a6d1b7eb365b85f6c9c80e61', '0x00000000000000000000000050858f2c7873fac9398ed9c195d185089caa7967'],
data: '0x0000000000000000000000000aa622ec7d114c8a18730a9a6147ffbded11cefa000000000000000000000000cec030978d9e5e8b4ad689b1f509f8e9617efbe300000000000000000000000041f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
blockNumber: 516657,
transactionIndex: 1,
transactionHash: '0x94761202b5fdcf50dfa8cc07abcc10b58744b985470dce6ab97b315a03f7f185',
blockHash: '0x0c8092332fea2f708bcc6e4c105b7a5dc2bdf920e36e7336749c62e307be04e9',
logIndex: 0
}];
var decoded = abi.decodeEvent(eventAbi, logs[0].data, logs[0].topics);
assert.deepEqual(decoded, {
0: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
1: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
2: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
_eventName: 'IdentityCreated',
userKey: '0x50858f2c7873fac9398ed9c195d185089caa7967',
proxy: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
controller: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
recoveryKey: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42'
});
assert.deepEqual(abi.decodeLogItem(eventAbi, logs[0], false), {
_eventName: 'IdentityCreated',
userKey: '0x50858f2c7873fac9398ed9c195d185089caa7967',
proxy: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
controller: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
recoveryKey: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42'
});
var decode = abi.logDecoder([eventAbi].concat(interfaceABI), false);
assert.deepEqual(decode(logs), [{
_eventName: 'IdentityCreated',
userKey: '0x50858f2c7873fac9398ed9c195d185089caa7967',
proxy: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
controller: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
recoveryKey: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42'
}]);
});
});

2

package.json
{
"name": "ethjs-abi",
"version": "0.1.8",
"version": "0.1.9",
"description": "Just the Ethereum encoding and decoding methods from the ethers-io-wallet.",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -18,3 +18,3 @@ /* eslint-disable */

if (types.length !== values.length) {
throw new Error(`[ethjs-abi] while encoding params, types/values mismatch, types length ${types.length} should be ${values.length}`);
throw new Error(`[ethjs-abi] while encoding params, types/values mismatch, Your contract requires ${types.length} types (arguments), and you passed in ${values.length}`);
}

@@ -63,3 +63,3 @@

// decode bytecode data from output names and types
function decodeParams(names, types, data) {
function decodeParams(names, types, data, useNumberedParams = true) {
// Names is optional, so shift over all the parameters if not provided

@@ -86,3 +86,3 @@ if (arguments.length < 3) {

}
values[index] = result.value;
if (useNumberedParams) values[index] = result.value;
if (names[index]) { values[names[index]] = result.value; }

@@ -115,10 +115,44 @@ });

function eventSignature(eventObject) {
const signature = `${eventObject.name}(${utils.getKeys(eventObject.inputs, 'type').join(',')})`;
return `0x${utils.keccak256(signature)}`;
}
// decode method data bytecode, from method ABI object
function decodeEvent(eventObject, data) {
const inputNames = utils.getKeys(eventObject.inputs, 'name', true);
const inputTypes = utils.getKeys(eventObject.inputs, 'type');
function decodeEvent(eventObject, data, topics, useNumberedParams = true) {
const nonIndexed = eventObject.inputs.filter((input) => !input.indexed)
const nonIndexedNames = utils.getKeys(nonIndexed, 'name', true);
const nonIndexedTypes = utils.getKeys(nonIndexed, 'type');
const event = decodeParams(nonIndexedNames, nonIndexedTypes, utils.hexOrBuffer(data), useNumberedParams);
const topicOffset = eventObject.anonymous ? 0 : 1;
eventObject.inputs.filter((input) => input.indexed).map((input, i) => {
const topic = new Buffer(topics[i + topicOffset].slice(2),'hex');
const coder = getParamCoder(input.type);
event[input.name] = coder.decode(topic, 0).value;
})
event._eventName = eventObject.name
return event;
}
return decodeParams(inputNames, inputTypes, utils.hexOrBuffer(data));
// Decode a specific log item with a specific event abi
function decodeLogItem(eventObject, log, useNumberedParams = true) {
if (eventObject && log.topics[0] === eventSignature(eventObject)) {
return decodeEvent(eventObject, log.data, log.topics, useNumberedParams)
}
}
// Create a decoder for all events defined in an abi. It returns a function which is called
// on an array of log entries such as received from getLogs or getTransactionReceipt and parses
// any matching log entries
function logDecoder(abi, useNumberedParams = true) {
const eventMap = {}
abi.filter(item => item.type === 'event').map(item => {
eventMap[eventSignature(item)] = item
})
return function(logItems) {
return logItems.map(log => decodeLogItem(eventMap[log.topics[0]], log, useNumberedParams)).filter(i => i)
}
}
module.exports = {

@@ -131,2 +165,5 @@ encodeParams,

decodeEvent,
decodeLogItem,
logDecoder,
eventSignature
};
const assert = require('chai').assert;
const abi = require('../index.js');
const contracts = require('./contracts.json');
const BN = require('bn.js');
describe('test basic encoding and decoding functionality', () => {
const interfaceABI = [
{'constant':false,'inputs':[{'name':'_value','type':'uint256'}],'name':'set','outputs':[{'name':'','type':'bool'}],'payable':false,'type':'function'}, {'constant':false,'inputs':[],'name':'get','outputs':[{'name':'storeValue','type':'uint256'}],'payable':false,'type':'function'}, {'anonymous':false,'inputs':[{'indexed':false,'name':'_newValue','type':'uint256'},{'indexed':false,'name':'_sender','type':'address'}],'name':'SetComplete','type':'event'}]; // eslint-disable-line
it('should encode and decode contract data nicely', () => {

@@ -10,3 +13,2 @@ const BalanceClaimInterface = JSON.parse(contracts.BalanceClaim.interface);

assert.equal(encodeBalanceClaimMethod1, '0x30509bca');
const interfaceABI = [{'constant':false,'inputs':[{'name':'_value','type':'uint256'}],'name':'set','outputs':[{'name':'','type':'bool'}],'payable':false,'type':'function'},{'constant':false,'inputs':[],'name':'get','outputs':[{'name':'storeValue','type':'uint256'}],'payable':false,'type':'function'},{'anonymous':false,'inputs':[{'indexed':false,'name':'_newValue','type':'uint256'},{'indexed':false,'name':'_sender','type':'address'}],'name':'SetComplete','type':'event'}]; // eslint-disable-line

@@ -20,6 +22,70 @@ const setMethodInputBytecode = abi.encodeMethod(interfaceABI[0], [24000]);

abi.encodeEvent(interfaceABI[2], [24000, '0xca35b7d915458ef540ade6068dfe2f44e8fa733c']);
abi.decodeEvent(interfaceABI[2], '0x0000000000000000000000000000000000000000000000000000000000000d7d000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c');
const event = abi.decodeEvent(interfaceABI[2], '0x0000000000000000000000000000000000000000000000000000000000000d7d000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c');
assert.deepEqual(event, {
0: new BN(3453),
1: '0xca35b7d915458ef540ade6068dfe2f44e8fa733c',
_eventName: 'SetComplete',
_newValue: new BN(3453),
_sender: '0xca35b7d915458ef540ade6068dfe2f44e8fa733c',
});
assert.equal(setMethodInputBytecode, '0x60fe47b10000000000000000000000000000000000000000000000000000000000005dc0');
});
it('should decode event from log', () => {
const eventAbi = {
anonymous: false,
inputs: [
{ indexed: true, name: 'userKey', type: 'address' },
{ indexed: false, name: 'proxy', type: 'address' },
{ indexed: false, name: 'controller', type: 'address' },
{ indexed: false, name: 'recoveryKey', type: 'address' },
],
name: 'IdentityCreated',
type: 'event',
};
assert.equal(abi.eventSignature(eventAbi), '0xc36800ebd6079fdafc3a7100d0d1172815751804a6d1b7eb365b85f6c9c80e61');
const logs = [{
address: '0xadb4966858672ef5ed70894030526544f9a5acdd',
topics: [
'0xc36800ebd6079fdafc3a7100d0d1172815751804a6d1b7eb365b85f6c9c80e61',
'0x00000000000000000000000050858f2c7873fac9398ed9c195d185089caa7967',
],
data: '0x0000000000000000000000000aa622ec7d114c8a18730a9a6147ffbded11cefa000000000000000000000000cec030978d9e5e8b4ad689b1f509f8e9617efbe300000000000000000000000041f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
blockNumber: 516657,
transactionIndex: 1,
transactionHash: '0x94761202b5fdcf50dfa8cc07abcc10b58744b985470dce6ab97b315a03f7f185',
blockHash: '0x0c8092332fea2f708bcc6e4c105b7a5dc2bdf920e36e7336749c62e307be04e9',
logIndex: 0,
}];
const decoded = abi.decodeEvent(eventAbi, logs[0].data, logs[0].topics);
assert.deepEqual(decoded, {
0: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
1: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
2: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
_eventName: 'IdentityCreated',
userKey: '0x50858f2c7873fac9398ed9c195d185089caa7967',
proxy: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
controller: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
recoveryKey: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
});
assert.deepEqual(abi.decodeLogItem(eventAbi, logs[0], false), {
_eventName: 'IdentityCreated',
userKey: '0x50858f2c7873fac9398ed9c195d185089caa7967',
proxy: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
controller: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
recoveryKey: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
});
const decode = abi.logDecoder([eventAbi].concat(interfaceABI), false);
assert.deepEqual(decode(logs), [{
_eventName: 'IdentityCreated',
userKey: '0x50858f2c7873fac9398ed9c195d185089caa7967',
proxy: '0x0aa622ec7d114c8a18730a9a6147ffbded11cefa',
controller: '0xcec030978d9e5e8b4ad689b1f509f8e9617efbe3',
recoveryKey: '0x41f50a40900dc9ac8a6d4cfb4fa5e05ed428de42',
}]);
});
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc