@findeth/abi
Advanced tools
Comparing version 0.3.1 to 0.4.0
@@ -12,3 +12,3 @@ "use strict"; | ||
var _buffer = require("./utils/buffer"); | ||
var _utils = require("./utils"); | ||
@@ -23,3 +23,3 @@ const encode = (input, values) => { | ||
}); | ||
return (0, _array.pack)(Buffer.alloc(0), values, types); | ||
return (0, _array.pack)(new Uint8Array(0), values, types); | ||
}; | ||
@@ -30,5 +30,5 @@ | ||
const encodeWithIdentifier = (contractFunction, values) => { | ||
const identifier = Buffer.from((0, _identifier.getIdentifier)(contractFunction), 'hex'); | ||
const identifier = (0, _utils.fromHex)((0, _identifier.getIdentifier)(contractFunction)); | ||
const encoded = encode(contractFunction.inputs, values); | ||
return (0, _buffer.concat)(identifier, encoded); | ||
return (0, _utils.concat)([identifier, encoded]); | ||
}; | ||
@@ -35,0 +35,0 @@ |
@@ -8,3 +8,3 @@ "use strict"; | ||
var _keccak = require("./utils/keccak256"); | ||
var _utils = require("./utils"); | ||
@@ -27,3 +27,3 @@ const isTuple = input => { | ||
const types = contractFunction.inputs.map(parseType).join(','); | ||
return (0, _keccak.keccak256)(`${contractFunction.name}(${types})`).slice(0, 8); | ||
return (0, _utils.keccak256)(`${contractFunction.name}(${types})`).slice(0, 8); | ||
}; | ||
@@ -30,0 +30,0 @@ |
@@ -32,2 +32,16 @@ "use strict"; | ||
var _utils = require("./utils"); | ||
Object.keys(_utils).forEach(function (key) { | ||
if (key === "default" || key === "__esModule") return; | ||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; | ||
if (key in exports && exports[key] === _utils[key]) return; | ||
Object.defineProperty(exports, key, { | ||
enumerable: true, | ||
get: function () { | ||
return _utils[key]; | ||
} | ||
}); | ||
}); | ||
var _contract = require("./contract"); | ||
@@ -38,2 +52,3 @@ | ||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; | ||
if (key in exports && exports[key] === _contract[key]) return; | ||
Object.defineProperty(exports, key, { | ||
@@ -40,0 +55,0 @@ enumerable: true, |
@@ -8,3 +8,3 @@ "use strict"; | ||
var _buffer = require("../utils/buffer"); | ||
var _utils = require("../utils"); | ||
@@ -16,5 +16,4 @@ const encodeAddress = (buffer, value) => { | ||
const addressBuffer = Buffer.alloc(32); | ||
addressBuffer.write(value.substring(2), 12, 'hex'); | ||
return (0, _buffer.concat)(buffer, addressBuffer); | ||
const addressBuffer = (0, _utils.fromHex)((0, _utils.stripPrefix)(value).padStart(64, '0')); | ||
return (0, _utils.concat)([buffer, addressBuffer]); | ||
}; | ||
@@ -26,3 +25,3 @@ | ||
const addressBuffer = value.subarray(-20); | ||
return `0x${(0, _buffer.toHex)(addressBuffer)}`; | ||
return `0x${(0, _utils.toHex)(addressBuffer)}`; | ||
}; | ||
@@ -29,0 +28,0 @@ |
@@ -9,3 +9,3 @@ "use strict"; | ||
var _buffer = require("../utils/buffer"); | ||
var _utils = require("../utils"); | ||
@@ -42,4 +42,4 @@ var _address = require("./address"); | ||
const actualType = getType(type); | ||
const length = (0, _buffer.toBuffer)(values.length); | ||
const arrayBuffer = (0, _buffer.concat)(buffer, length); | ||
const length = (0, _utils.toBuffer)(values.length); | ||
const arrayBuffer = (0, _utils.concat)([buffer, length]); | ||
return pack(arrayBuffer, values, new Array(values.length).fill(actualType)); | ||
@@ -56,4 +56,4 @@ }; | ||
const actualType = getType(type); | ||
const pointer = Number((0, _buffer.toNumber)(value)); | ||
const length = Number((0, _buffer.toNumber)(buffer.subarray(pointer, pointer + 32))); | ||
const pointer = Number((0, _utils.toNumber)(value)); | ||
const length = Number((0, _utils.toNumber)(buffer.subarray(pointer, pointer + 32))); | ||
const arrayPointer = pointer + 32; | ||
@@ -133,7 +133,7 @@ const arrayBuffer = buffer.subarray(arrayPointer); | ||
const staticOffset = staticBuffer.length; | ||
const newStaticBuffer = (0, _buffer.concat)(staticBuffer, Buffer.alloc(32, 0)); | ||
const newStaticBuffer = (0, _utils.concat)([staticBuffer, new Uint8Array(32).fill(0)]); | ||
const newDynamicBuffer = parser.encode(dynamicBuffer, value, type); | ||
const update = oldBuffer => { | ||
return (0, _buffer.concatMultiple)([oldBuffer.subarray(0, staticOffset), (0, _buffer.toBuffer)(oldBuffer.length + offset), oldBuffer.subarray(staticOffset + 32)]); | ||
return (0, _utils.concat)([oldBuffer.subarray(0, staticOffset), (0, _utils.toBuffer)(oldBuffer.length + offset), oldBuffer.subarray(staticOffset + 32)]); | ||
}; | ||
@@ -160,3 +160,3 @@ | ||
const updatedStaticBuffer = packedUpdateFunctions.reduce((target, update) => update(target), packedStaticBuffer); | ||
return (0, _buffer.concatMultiple)([buffer, updatedStaticBuffer, packedDynamicBuffer]); | ||
return (0, _utils.concat)([buffer, updatedStaticBuffer, packedDynamicBuffer]); | ||
}; | ||
@@ -163,0 +163,0 @@ |
@@ -8,8 +8,8 @@ "use strict"; | ||
var _buffer = require("../utils/buffer"); | ||
var _utils = require("../utils"); | ||
const encodeBytes = (buffer, value) => { | ||
const bufferValue = (0, _buffer.toBuffer)(value); | ||
const bufferValue = (0, _utils.toBuffer)(value); | ||
const paddedSize = Math.ceil(bufferValue.byteLength / 32) * 32; | ||
return (0, _buffer.concat)(buffer, Buffer.concat([(0, _buffer.toBuffer)(bufferValue.byteLength), (0, _buffer.addPadding)(bufferValue, paddedSize)])); | ||
return (0, _utils.concat)([buffer, (0, _utils.toBuffer)(bufferValue.byteLength), (0, _utils.addPadding)(bufferValue, paddedSize)]); | ||
}; | ||
@@ -20,4 +20,4 @@ | ||
const decodeBytes = (value, buffer) => { | ||
const pointer = Number((0, _buffer.toNumber)(value.subarray(0, 32))); | ||
const length = (0, _buffer.toNumber)(value.subarray(pointer, pointer + 32)); | ||
const pointer = Number((0, _utils.toNumber)(value.subarray(0, 32))); | ||
const length = (0, _utils.toNumber)(value.subarray(pointer, pointer + 32)); | ||
return buffer.subarray(32, 32 + Number(length)); | ||
@@ -24,0 +24,0 @@ }; |
@@ -8,3 +8,3 @@ "use strict"; | ||
var _buffer = require("../utils/buffer"); | ||
var _utils = require("../utils"); | ||
@@ -41,3 +41,3 @@ const BYTES_REGEX = /^bytes([0-9]{1,2})$/; | ||
const length = getByteLength(type); | ||
const bufferValue = (0, _buffer.toBuffer)(value); | ||
const bufferValue = (0, _utils.toBuffer)(value); | ||
@@ -48,3 +48,3 @@ if (bufferValue.length > length) { | ||
return (0, _buffer.concat)(buffer, (0, _buffer.addPadding)(bufferValue)); | ||
return (0, _utils.concat)([buffer, (0, _utils.addPadding)(bufferValue)]); | ||
}; | ||
@@ -51,0 +51,0 @@ |
@@ -8,6 +8,4 @@ "use strict"; | ||
var _buffer = require("../utils/buffer"); | ||
var _utils = require("../utils"); | ||
var _twosComplement = require("../utils/twos-complement"); | ||
const NUMBER_REGEX = /^u?int([0-9]*)?$/; | ||
@@ -64,6 +62,6 @@ | ||
if (isSigned(type)) { | ||
return (0, _buffer.concat)(buffer, (0, _twosComplement.toTwosComplement)(numberValue, 32)); | ||
return (0, _utils.concat)([buffer, (0, _utils.toTwosComplement)(numberValue, 32)]); | ||
} | ||
return (0, _buffer.concat)(buffer, (0, _buffer.toBuffer)(numberValue)); | ||
return (0, _utils.concat)([buffer, (0, _utils.toBuffer)(numberValue)]); | ||
}; | ||
@@ -75,6 +73,6 @@ | ||
if (isSigned(type)) { | ||
return (0, _twosComplement.fromTwosComplement)(value); | ||
return (0, _utils.fromTwosComplement)(value); | ||
} | ||
return (0, _buffer.toNumber)(value); | ||
return (0, _utils.toNumber)(value); | ||
}; | ||
@@ -81,0 +79,0 @@ |
@@ -8,3 +8,3 @@ "use strict"; | ||
var _buffer = require("../utils/buffer"); | ||
var _utils = require("../utils"); | ||
@@ -14,3 +14,3 @@ var _bytes = require("./bytes"); | ||
const encodeString = (buffer, value) => { | ||
const bufferValue = Buffer.from(value, 'utf8'); | ||
const bufferValue = (0, _utils.fromUtf8)(value); | ||
return (0, _bytes.encodeBytes)(buffer, bufferValue, 'bytes'); | ||
@@ -22,3 +22,3 @@ }; | ||
const decodeString = (value, buffer) => { | ||
return (0, _buffer.toString)((0, _bytes.decodeBytes)(value, buffer, 'string')); | ||
return (0, _utils.toUtf8)((0, _bytes.decodeBytes)(value, buffer, 'string')); | ||
}; | ||
@@ -25,0 +25,0 @@ |
@@ -6,55 +6,115 @@ "use strict"; | ||
}); | ||
exports.toHex = exports.toNumber = exports.toString = exports.toBuffer = exports.addPadding = exports.concatMultiple = exports.concat = void 0; | ||
exports.toNumber = exports.addPadding = exports.concatAt = exports.concat = exports.toBuffer = exports.fromHex = exports.toHex = exports.fromUtf8 = exports.toUtf8 = exports.getTextDecoder = exports.getTextEncoder = exports.stripPrefix = void 0; | ||
const BUFFER_WIDTH = 32; | ||
const HEX_REGEX = /^[a-f0-9]+$/i; | ||
const concat = (target, value, position) => { | ||
return new Uint8Array([...target.subarray(0, position !== null && position !== void 0 ? position : target.length), ...value, ...target.subarray(position !== null && position !== void 0 ? position : target.length)]); | ||
const stripPrefix = value => { | ||
if (value.startsWith('0x')) { | ||
return value.substring(2); | ||
} | ||
return value; | ||
}; | ||
exports.concat = concat; | ||
exports.stripPrefix = stripPrefix; | ||
const concatMultiple = buffers => { | ||
return buffers.reduce((target, buffer) => { | ||
const array = new Uint8Array(target.length + buffer.length); | ||
array.set(target, 0); | ||
array.set(buffer, target.length); | ||
return array; | ||
}, new Uint8Array(0)); | ||
const getTextEncoder = () => { | ||
if (typeof TextEncoder === 'undefined') { | ||
const Encoder = require('util').TextEncoder; | ||
return new Encoder(); | ||
} | ||
return new TextEncoder(); | ||
}; | ||
exports.concatMultiple = concatMultiple; | ||
exports.getTextEncoder = getTextEncoder; | ||
const addPadding = (buffer, length = 32) => { | ||
const padding = Buffer.alloc(Math.max(length - buffer.length, 0), 0); | ||
return concat(buffer, padding); | ||
const getTextDecoder = (encoding = 'utf8') => { | ||
if (typeof TextEncoder === 'undefined') { | ||
const Decoder = require('util').TextDecoder; | ||
return new Decoder(encoding); | ||
} | ||
return new TextDecoder(encoding); | ||
}; | ||
exports.addPadding = addPadding; | ||
exports.getTextDecoder = getTextDecoder; | ||
const toBuffer = value => { | ||
if (Buffer.isBuffer(value) || value instanceof Uint8Array) { | ||
return value; | ||
const toUtf8 = data => { | ||
return getTextDecoder().decode(data); | ||
}; | ||
exports.toUtf8 = toUtf8; | ||
const fromUtf8 = data => { | ||
return getTextEncoder().encode(data); | ||
}; | ||
exports.fromUtf8 = fromUtf8; | ||
const toHex = data => { | ||
return Array.from(data).map(n => `0${n.toString(16)}`.slice(-2)).join(''); | ||
}; | ||
exports.toHex = toHex; | ||
const fromHex = data => { | ||
if (data.startsWith('0x')) { | ||
data = data.slice(2); | ||
} | ||
if (typeof value === 'string') { | ||
const stringValue = value.startsWith('0x') ? value.substring(2) : value; | ||
return Buffer.from(stringValue, 'hex'); | ||
if (data.length % 2 !== 0) { | ||
throw new Error('Length must be even'); | ||
} | ||
const hex = value.toString(16); | ||
return Buffer.from(hex.padStart(BUFFER_WIDTH * 2, '0').slice(0, BUFFER_WIDTH * 2), 'hex'); | ||
if (!data.match(HEX_REGEX)) { | ||
throw new Error('Input must be hexadecimal'); | ||
} | ||
return new Uint8Array(data.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); | ||
}; | ||
exports.toBuffer = toBuffer; | ||
exports.fromHex = fromHex; | ||
const toString = value => { | ||
if (typeof window !== 'undefined' && window.TextDecoder) { | ||
return new TextDecoder('utf-8').decode(value); | ||
const toBuffer = data => { | ||
if (typeof data === 'string') { | ||
return fromHex(data); | ||
} | ||
return new (require('util').TextDecoder)('utf-8').decode(value); | ||
if (typeof data === 'number' || typeof data === 'bigint') { | ||
const string = data.toString(16); | ||
return fromHex(string.padStart(BUFFER_WIDTH * 2, '0')); | ||
} | ||
return new Uint8Array(data); | ||
}; | ||
exports.toString = toString; | ||
exports.toBuffer = toBuffer; | ||
const concat = buffers => { | ||
return buffers.reduce((a, b) => { | ||
const buffer = new Uint8Array(a.length + b.length); | ||
buffer.set(a); | ||
buffer.set(b, a.length); | ||
return buffer; | ||
}, new Uint8Array(0)); | ||
}; | ||
exports.concat = concat; | ||
const concatAt = (a, b, position) => { | ||
return concat([a.slice(0, position), b, a.slice(position)]); | ||
}; | ||
exports.concatAt = concatAt; | ||
const addPadding = (buffer, length = BUFFER_WIDTH) => { | ||
const padding = new Uint8Array(Math.max(length - buffer.length, 0)).fill(0x00); | ||
return concat([buffer, padding]); | ||
}; | ||
exports.addPadding = addPadding; | ||
const toNumber = buffer => { | ||
@@ -71,12 +131,2 @@ const hex = toHex(buffer); | ||
exports.toNumber = toNumber; | ||
const numberToHex = value => { | ||
return ('0' + value.toString(16)).slice(-2); | ||
}; | ||
const toHex = buffer => { | ||
return Array.from(buffer).map(numberToHex).join(''); | ||
}; | ||
exports.toHex = toHex; | ||
//# sourceMappingURL=buffer.js.map |
@@ -10,6 +10,8 @@ "use strict"; | ||
var _buffer = require("./buffer"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const keccak256 = input => { | ||
return (0, _keccak.default)('keccak256').update(input).digest().toString('hex'); | ||
return (0, _buffer.toHex)((0, _keccak.default)('keccak256').update(input).digest()); | ||
}; | ||
@@ -16,0 +18,0 @@ |
import { getIdentifier } from './identifier'; | ||
import { pack, unpack } from './parsers/array'; | ||
import { concat } from './utils/buffer'; | ||
import { concat, fromHex } from './utils'; | ||
export const encode = (input, values) => { | ||
@@ -12,8 +12,8 @@ const types = input.map(type => { | ||
}); | ||
return pack(Buffer.alloc(0), values, types); | ||
return pack(new Uint8Array(0), values, types); | ||
}; | ||
export const encodeWithIdentifier = (contractFunction, values) => { | ||
const identifier = Buffer.from(getIdentifier(contractFunction), 'hex'); | ||
const identifier = fromHex(getIdentifier(contractFunction)); | ||
const encoded = encode(contractFunction.inputs, values); | ||
return concat(identifier, encoded); | ||
return concat([identifier, encoded]); | ||
}; | ||
@@ -20,0 +20,0 @@ export const decode = (input, buffer) => { |
@@ -1,2 +0,2 @@ | ||
import { keccak256 } from './utils/keccak256'; | ||
import { keccak256 } from './utils'; | ||
@@ -3,0 +3,0 @@ const isTuple = input => { |
export { encode, encodeWithIdentifier, decode } from './abi'; | ||
export * from './utils'; | ||
export * from './contract'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { concat, toHex } from '../utils/buffer'; | ||
import { concat, fromHex, stripPrefix, toHex } from '../utils'; | ||
export const encodeAddress = (buffer, value) => { | ||
@@ -7,5 +7,4 @@ if (value.length !== 42) { | ||
const addressBuffer = Buffer.alloc(32); | ||
addressBuffer.write(value.substring(2), 12, 'hex'); | ||
return concat(buffer, addressBuffer); | ||
const addressBuffer = fromHex(stripPrefix(value).padStart(64, '0')); | ||
return concat([buffer, addressBuffer]); | ||
}; | ||
@@ -12,0 +11,0 @@ export const decodeAddress = value => { |
@@ -1,2 +0,2 @@ | ||
import { concat, concatMultiple, toBuffer, toNumber } from '../utils/buffer'; | ||
import { concat, toBuffer, toNumber } from '../utils'; | ||
import { decodeAddress, encodeAddress } from './address'; | ||
@@ -21,3 +21,3 @@ import { decodeBytes, encodeBytes } from './bytes'; | ||
const length = toBuffer(values.length); | ||
const arrayBuffer = concat(buffer, length); | ||
const arrayBuffer = concat([buffer, length]); | ||
return pack(arrayBuffer, values, new Array(values.length).fill(actualType)); | ||
@@ -101,7 +101,7 @@ }; | ||
const staticOffset = staticBuffer.length; | ||
const newStaticBuffer = concat(staticBuffer, Buffer.alloc(32, 0)); | ||
const newStaticBuffer = concat([staticBuffer, new Uint8Array(32).fill(0)]); | ||
const newDynamicBuffer = parser.encode(dynamicBuffer, value, type); | ||
const update = oldBuffer => { | ||
return concatMultiple([oldBuffer.subarray(0, staticOffset), toBuffer(oldBuffer.length + offset), oldBuffer.subarray(staticOffset + 32)]); | ||
return concat([oldBuffer.subarray(0, staticOffset), toBuffer(oldBuffer.length + offset), oldBuffer.subarray(staticOffset + 32)]); | ||
}; | ||
@@ -128,3 +128,3 @@ | ||
const updatedStaticBuffer = packedUpdateFunctions.reduce((target, update) => update(target), packedStaticBuffer); | ||
return concatMultiple([buffer, updatedStaticBuffer, packedDynamicBuffer]); | ||
return concat([buffer, updatedStaticBuffer, packedDynamicBuffer]); | ||
}; | ||
@@ -131,0 +131,0 @@ export function* iterate(buffer, chunkSize) { |
@@ -1,6 +0,6 @@ | ||
import { addPadding, concat, toBuffer, toNumber } from '../utils/buffer'; | ||
import { addPadding, concat, toBuffer, toNumber } from '../utils'; | ||
export const encodeBytes = (buffer, value) => { | ||
const bufferValue = toBuffer(value); | ||
const paddedSize = Math.ceil(bufferValue.byteLength / 32) * 32; | ||
return concat(buffer, Buffer.concat([toBuffer(bufferValue.byteLength), addPadding(bufferValue, paddedSize)])); | ||
return concat([buffer, toBuffer(bufferValue.byteLength), addPadding(bufferValue, paddedSize)]); | ||
}; | ||
@@ -7,0 +7,0 @@ export const decodeBytes = (value, buffer) => { |
@@ -1,2 +0,2 @@ | ||
import { addPadding, concat, toBuffer } from '../utils/buffer'; | ||
import { addPadding, concat, toBuffer } from '../utils'; | ||
const BYTES_REGEX = /^bytes([0-9]{1,2})$/; | ||
@@ -31,3 +31,3 @@ export const isFixedBytes = type => { | ||
return concat(buffer, addPadding(bufferValue)); | ||
return concat([buffer, addPadding(bufferValue)]); | ||
}; | ||
@@ -34,0 +34,0 @@ export const decodeFixedBytes = (value, _, type) => { |
@@ -1,3 +0,2 @@ | ||
import { concat, toBuffer, toNumber } from '../utils/buffer'; | ||
import { fromTwosComplement, toTwosComplement } from '../utils/twos-complement'; | ||
import { concat, toBuffer, toNumber, fromTwosComplement, toTwosComplement } from '../utils'; | ||
const NUMBER_REGEX = /^u?int([0-9]*)?$/; | ||
@@ -46,6 +45,6 @@ | ||
if (isSigned(type)) { | ||
return concat(buffer, toTwosComplement(numberValue, 32)); | ||
return concat([buffer, toTwosComplement(numberValue, 32)]); | ||
} | ||
return concat(buffer, toBuffer(numberValue)); | ||
return concat([buffer, toBuffer(numberValue)]); | ||
}; | ||
@@ -52,0 +51,0 @@ export const decodeNumber = (value, _, type) => { |
@@ -1,10 +0,10 @@ | ||
import { toString } from '../utils/buffer'; | ||
import { fromUtf8, toUtf8 } from '../utils'; | ||
import { decodeBytes, encodeBytes } from './bytes'; | ||
export const encodeString = (buffer, value) => { | ||
const bufferValue = Buffer.from(value, 'utf8'); | ||
const bufferValue = fromUtf8(value); | ||
return encodeBytes(buffer, bufferValue, 'bytes'); | ||
}; | ||
export const decodeString = (value, buffer) => { | ||
return toString(decodeBytes(value, buffer, 'string')); | ||
return toUtf8(decodeBytes(value, buffer, 'string')); | ||
}; | ||
//# sourceMappingURL=string.js.map |
const BUFFER_WIDTH = 32; | ||
export const concat = (target, value, position) => { | ||
return new Uint8Array([...target.subarray(0, position !== null && position !== void 0 ? position : target.length), ...value, ...target.subarray(position !== null && position !== void 0 ? position : target.length)]); | ||
const HEX_REGEX = /^[a-f0-9]+$/i; | ||
export const stripPrefix = value => { | ||
if (value.startsWith('0x')) { | ||
return value.substring(2); | ||
} | ||
return value; | ||
}; | ||
export const concatMultiple = buffers => { | ||
return buffers.reduce((target, buffer) => { | ||
const array = new Uint8Array(target.length + buffer.length); | ||
array.set(target, 0); | ||
array.set(buffer, target.length); | ||
return array; | ||
}, new Uint8Array(0)); | ||
export const getTextEncoder = () => { | ||
if (typeof TextEncoder === 'undefined') { | ||
const Encoder = require('util').TextEncoder; | ||
return new Encoder(); | ||
} | ||
return new TextEncoder(); | ||
}; | ||
export const addPadding = (buffer, length = 32) => { | ||
const padding = Buffer.alloc(Math.max(length - buffer.length, 0), 0); | ||
return concat(buffer, padding); | ||
export const getTextDecoder = (encoding = 'utf8') => { | ||
if (typeof TextEncoder === 'undefined') { | ||
const Decoder = require('util').TextDecoder; | ||
return new Decoder(encoding); | ||
} | ||
return new TextDecoder(encoding); | ||
}; | ||
export const toBuffer = value => { | ||
if (Buffer.isBuffer(value) || value instanceof Uint8Array) { | ||
return value; | ||
export const toUtf8 = data => { | ||
return getTextDecoder().decode(data); | ||
}; | ||
export const fromUtf8 = data => { | ||
return getTextEncoder().encode(data); | ||
}; | ||
export const toHex = data => { | ||
return Array.from(data).map(n => `0${n.toString(16)}`.slice(-2)).join(''); | ||
}; | ||
export const fromHex = data => { | ||
if (data.startsWith('0x')) { | ||
data = data.slice(2); | ||
} | ||
if (typeof value === 'string') { | ||
const stringValue = value.startsWith('0x') ? value.substring(2) : value; | ||
return Buffer.from(stringValue, 'hex'); | ||
if (data.length % 2 !== 0) { | ||
throw new Error('Length must be even'); | ||
} | ||
const hex = value.toString(16); | ||
return Buffer.from(hex.padStart(BUFFER_WIDTH * 2, '0').slice(0, BUFFER_WIDTH * 2), 'hex'); | ||
if (!data.match(HEX_REGEX)) { | ||
throw new Error('Input must be hexadecimal'); | ||
} | ||
return new Uint8Array(data.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); | ||
}; | ||
export const toString = value => { | ||
if (typeof window !== 'undefined' && window.TextDecoder) { | ||
return new TextDecoder('utf-8').decode(value); | ||
export const toBuffer = data => { | ||
if (typeof data === 'string') { | ||
return fromHex(data); | ||
} | ||
return new (require('util').TextDecoder)('utf-8').decode(value); | ||
if (typeof data === 'number' || typeof data === 'bigint') { | ||
const string = data.toString(16); | ||
return fromHex(string.padStart(BUFFER_WIDTH * 2, '0')); | ||
} | ||
return new Uint8Array(data); | ||
}; | ||
export const concat = buffers => { | ||
return buffers.reduce((a, b) => { | ||
const buffer = new Uint8Array(a.length + b.length); | ||
buffer.set(a); | ||
buffer.set(b, a.length); | ||
return buffer; | ||
}, new Uint8Array(0)); | ||
}; | ||
export const concatAt = (a, b, position) => { | ||
return concat([a.slice(0, position), b, a.slice(position)]); | ||
}; | ||
export const addPadding = (buffer, length = BUFFER_WIDTH) => { | ||
const padding = new Uint8Array(Math.max(length - buffer.length, 0)).fill(0x00); | ||
return concat([buffer, padding]); | ||
}; | ||
export const toNumber = buffer => { | ||
@@ -46,10 +88,2 @@ const hex = toHex(buffer); | ||
}; | ||
const numberToHex = value => { | ||
return ('0' + value.toString(16)).slice(-2); | ||
}; | ||
export const toHex = buffer => { | ||
return Array.from(buffer).map(numberToHex).join(''); | ||
}; | ||
//# sourceMappingURL=buffer.js.map |
import createKeccakHash from 'keccak'; | ||
import { toHex } from './buffer'; | ||
export const keccak256 = input => { | ||
return createKeccakHash('keccak256').update(input).digest().toString('hex'); | ||
return toHex(createKeccakHash('keccak256').update(input).digest()); | ||
}; | ||
//# sourceMappingURL=keccak256.js.map |
{ | ||
"name": "@findeth/abi", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"description": "A tiny Solidity ABI encoder and decoder", | ||
@@ -46,12 +46,12 @@ "author": "Maarten Zuidhoorn <maarten@zuidhoorn.com>", | ||
"test": "jest", | ||
"lint": "yarn run lint:tsc && yarn run lint:eslint && yarn run lint:prettier && yarn run lint:lockfile", | ||
"lint:tsc": "tsc --noEmit", | ||
"lint:eslint": "eslint . --ignore-path .gitignore --ext .ts,.tsx,.js,.jsx", | ||
"lint:prettier": "prettier --check --ignore-path .gitignore '**/*.{ts,tsx,js,json}'", | ||
"lint": "yarn run lint:types && yarn run lint:source && yarn run lint:format && yarn run lint:lockfile", | ||
"lint:types": "tsc --noEmit", | ||
"lint:source": "eslint . --ignore-path .gitignore --ext .ts,.tsx,.js,.jsx", | ||
"lint:format": "prettier --check --ignore-path .gitignore '**/*.{ts,tsx,js,json,yml}'", | ||
"lint:lockfile": "lockfile-lint --type yarn --path yarn.lock --allowed-hosts yarn --validate-https --validate-checksum --validate-integrity", | ||
"prettier": "prettier --write --ignore-path .gitignore '**/*.{ts,tsx,js,json}'", | ||
"format": "prettier --write --ignore-path .gitignore '**/*.{ts,tsx,js,json,yml}'", | ||
"prepare": "yarn run build" | ||
}, | ||
"dependencies": { | ||
"keccak": "^3.0.0" | ||
"keccak": "^3.0.1" | ||
}, | ||
@@ -68,5 +68,5 @@ "devDependencies": { | ||
"@babel/runtime": "^7.10.2", | ||
"@types/jest": "^25.2.3", | ||
"@typescript-eslint/eslint-plugin": "^3.3.0", | ||
"@typescript-eslint/parser": "^3.3.0", | ||
"@types/jest": "^26.0.15", | ||
"@typescript-eslint/eslint-plugin": "^4.14.0", | ||
"@typescript-eslint/parser": "^4.14.0", | ||
"babel-jest": "^26.0.1", | ||
@@ -76,5 +76,5 @@ "codecov": "^3.7.0", | ||
"eslint": "^7.2.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-config-prettier": "^7.2.0", | ||
"eslint-plugin-import": "^2.21.2", | ||
"eslint-plugin-jest": "^23.13.2", | ||
"eslint-plugin-jest": "^24.1.0", | ||
"husky": "^4.2.5", | ||
@@ -86,10 +86,13 @@ "jest": "^26.0.1", | ||
"rimraf": "^3.0.2", | ||
"ts-node": "^8.10.2", | ||
"typedoc": "^0.17.7", | ||
"typescript": "^3.9.5" | ||
"ts-node": "^9.0.0", | ||
"typedoc": "^0.20.17", | ||
"typescript": "^4.0.5" | ||
}, | ||
"lint-staged": { | ||
"*.{ts,tsx}": [ | ||
"*.{ts,tsx,js}": [ | ||
"prettier --write", | ||
"eslint --fix" | ||
], | ||
"*.{json,yml}": [ | ||
"prettier --write" | ||
] | ||
@@ -96,0 +99,0 @@ }, |
import { decode, encode } from './abi'; | ||
import { toHex } from './utils/buffer'; | ||
import { fromHex, toHex } from './utils'; | ||
@@ -41,3 +41,3 @@ describe('encode', () => { | ||
it('encodes bytes values', () => { | ||
const bytes = Buffer.from('123456789abcdef123456789abcdef123456789abcdef', 'hex').toString('hex'); | ||
const bytes = '123456789abcdef123456789abcdef123456789abcde'; | ||
expect(toHex(encode(['bytes'], [bytes]))).toBe( | ||
@@ -58,5 +58,4 @@ '00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000016123456789abcdef123456789abcdef123456789abcde00000000000000000000' | ||
it('decodes a token transfer', () => { | ||
const buffer = Buffer.from( | ||
'0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000003039', | ||
'hex' | ||
const buffer = fromHex( | ||
'0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000003039' | ||
); | ||
@@ -70,5 +69,4 @@ expect(decode(['address', 'uint256'], buffer)).toStrictEqual([ | ||
it('decodes array values', () => { | ||
const buffer = Buffer.from( | ||
'000000000000000000000000000000000000000000000000000000000000303900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000003039000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000109320000000000000000000000000000000000000000000000000000000000010932', | ||
'hex' | ||
const buffer = fromHex( | ||
'000000000000000000000000000000000000000000000000000000000000303900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000003039000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000109320000000000000000000000000000000000000000000000000000000000010932' | ||
); | ||
@@ -75,0 +73,0 @@ expect(decode(['uint256', 'uint256[]', 'uint256'], buffer)).toStrictEqual([12345n, [67890n, 67890n], 12345n]); |
import { ContractFunction, ContractInput } from './contract'; | ||
import { getIdentifier } from './identifier'; | ||
import { pack, unpack } from './parsers/array'; | ||
import { concat } from './utils/buffer'; | ||
import { concat, fromHex } from './utils'; | ||
@@ -11,3 +11,3 @@ /** | ||
* @param {unknown[]} values | ||
* @return {Buffer} | ||
* @return {Uint8Array} | ||
*/ | ||
@@ -23,3 +23,3 @@ export const encode = (input: Array<ContractInput | string>, values: unknown[]): Uint8Array => { | ||
return pack(Buffer.alloc(0), values, types); | ||
return pack(new Uint8Array(0), values, types); | ||
}; | ||
@@ -32,12 +32,12 @@ | ||
* @param {unknown[]} values | ||
* @return {Buffer} | ||
* @return {Uint8Array} | ||
*/ | ||
export const encodeWithIdentifier = (contractFunction: ContractFunction, values: unknown[]): Uint8Array => { | ||
const identifier = Buffer.from(getIdentifier(contractFunction), 'hex'); | ||
const identifier = fromHex(getIdentifier(contractFunction)); | ||
const encoded = encode(contractFunction.inputs, values); | ||
return concat(identifier, encoded); | ||
return concat([identifier, encoded]); | ||
}; | ||
export const decode = <T extends unknown[]>(input: Array<ContractInput | string>, buffer: Buffer): T => { | ||
export const decode = <T extends unknown[]>(input: Array<ContractInput | string>, buffer: Uint8Array): T => { | ||
const types = input.map((type) => { | ||
@@ -44,0 +44,0 @@ if (typeof type === 'string') { |
@@ -108,5 +108,1 @@ /** | ||
export type ContractInterface = ContractFunction | ContractEvent; | ||
export type DecodeFunction<T> = (value: Buffer, buffer: Buffer, type: string) => T; | ||
export type EncodeFunction<T> = (target: Buffer, data: T, position: number, type: string) => Buffer; |
@@ -1,3 +0,3 @@ | ||
import erc20Abi from './__tests__/erc20.json'; | ||
import miscAbi from './__tests__/misc.json'; | ||
import erc20Abi from './__fixtures__/erc20.json'; | ||
import miscAbi from './__fixtures__/misc.json'; | ||
import { ContractFunction } from './contract'; | ||
@@ -4,0 +4,0 @@ import { getIdentifier, parseType } from './identifier'; |
import { ContractFunction, ContractInput, ContractInputTuple } from './contract'; | ||
import { keccak256 } from './utils/keccak256'; | ||
import { keccak256 } from './utils'; | ||
@@ -4,0 +4,0 @@ const isTuple = (input: ContractInput): input is ContractInputTuple => { |
export { encode, encodeWithIdentifier, decode } from './abi'; | ||
export * from './utils'; | ||
export * from './contract'; |
@@ -1,2 +0,2 @@ | ||
import { toHex } from '../utils/buffer'; | ||
import { toHex } from '../utils'; | ||
import { encodeAddress } from './address'; | ||
@@ -6,3 +6,3 @@ | ||
it('encodes an address', () => { | ||
expect(toHex(encodeAddress(Buffer.alloc(0), '0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520', 'address'))).toBe( | ||
expect(toHex(encodeAddress(new Uint8Array(0), '0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520', 'address'))).toBe( | ||
'0000000000000000000000004bbeeb066ed09b7aed07bf39eee0460dfa261520' | ||
@@ -9,0 +9,0 @@ ); |
@@ -1,2 +0,2 @@ | ||
import { concat, toHex } from '../utils/buffer'; | ||
import { concat, fromHex, stripPrefix, toHex } from '../utils'; | ||
import { DecodeFunction, EncodeFunction } from './parser'; | ||
@@ -9,6 +9,5 @@ | ||
const addressBuffer = Buffer.alloc(32); | ||
addressBuffer.write(value.substring(2), 12, 'hex'); | ||
const addressBuffer = fromHex(stripPrefix(value).padStart(64, '0')); | ||
return concat(buffer, addressBuffer); | ||
return concat([buffer, addressBuffer]); | ||
}; | ||
@@ -15,0 +14,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { toHex } from '../utils/buffer'; | ||
import { fromHex, toHex } from '../utils'; | ||
import { decodeArray, encodeArray, getType, isArray } from './array'; | ||
@@ -29,6 +29,6 @@ | ||
it('encodes an array with single type', () => { | ||
expect(toHex(encodeArray(Buffer.alloc(0), ['foo', 'bar', 'baz'], 'string[]'))).toBe( | ||
expect(toHex(encodeArray(new Uint8Array(0), ['foo', 'bar', 'baz'], 'string[]'))).toBe( | ||
'0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003666f6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036261720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000362617a0000000000000000000000000000000000000000000000000000000000' | ||
); | ||
expect(toHex(encodeArray(Buffer.alloc(0), [1n, 2n, 3n], 'uint256[]'))).toBe( | ||
expect(toHex(encodeArray(new Uint8Array(0), [1n, 2n, 3n], 'uint256[]'))).toBe( | ||
'0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003' | ||
@@ -39,3 +39,3 @@ ); | ||
it('throws if a type is not an array type', () => { | ||
expect(() => encodeArray(Buffer.alloc(0), ['foo', 'bar', 'baz'], 'string')).toThrow(); | ||
expect(() => encodeArray(new Uint8Array(0), ['foo', 'bar', 'baz'], 'string')).toThrow(); | ||
}); | ||
@@ -45,15 +45,8 @@ }); | ||
describe('decodeArray', () => { | ||
// TODO | ||
/*it('decodes an array from a buffer', () => { | ||
const buffer = Buffer.from('0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003666f6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036261720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000362617a0000000000000000000000000000000000000000000000000000000000', 'hex'); | ||
expect(decodeArray(toBuffer(0n), buffer, 'string[]')).toStrictEqual(['foo', 'bar', 'baz']); | ||
});*/ | ||
it('throws if a type is not an array type', () => { | ||
const buffer = Buffer.from( | ||
'0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003666f6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036261720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000362617a0000000000000000000000000000000000000000000000000000000000', | ||
'hex' | ||
const buffer = fromHex( | ||
'0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003666f6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036261720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000362617a0000000000000000000000000000000000000000000000000000000000' | ||
); | ||
expect(() => decodeArray(Buffer.alloc(32, 0), buffer, 'string')).toThrow(); | ||
expect(() => decodeArray(new Uint8Array(0), buffer, 'string')).toThrow(); | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
import { concat, concatMultiple, toBuffer, toNumber } from '../utils/buffer'; | ||
import { concat, toBuffer, toNumber } from '../utils'; | ||
import { decodeAddress, encodeAddress } from './address'; | ||
@@ -39,3 +39,3 @@ import { decodeBytes, encodeBytes } from './bytes'; | ||
const arrayBuffer = concat(buffer, length); | ||
const arrayBuffer = concat([buffer, length]); | ||
@@ -122,6 +122,8 @@ return pack(arrayBuffer, values, new Array(values.length).fill(actualType)); | ||
export type UpdateFunction = (buffer: Uint8Array) => Uint8Array; | ||
interface PackState { | ||
staticBuffer: Uint8Array; | ||
dynamicBuffer: Uint8Array; | ||
updateFunctions: Array<(buffer: Uint8Array) => Uint8Array>; | ||
updateFunctions: UpdateFunction[]; | ||
} | ||
@@ -155,7 +157,7 @@ | ||
const newStaticBuffer = concat(staticBuffer, Buffer.alloc(32, 0)); | ||
const newStaticBuffer = concat([staticBuffer, new Uint8Array(32).fill(0)]); | ||
const newDynamicBuffer = parser.encode(dynamicBuffer, value, type); | ||
const update = (oldBuffer: Uint8Array): Uint8Array => { | ||
return concatMultiple([ | ||
return concat([ | ||
oldBuffer.subarray(0, staticOffset), | ||
@@ -186,3 +188,3 @@ toBuffer(oldBuffer.length + offset), | ||
return concatMultiple([buffer, updatedStaticBuffer, packedDynamicBuffer]); | ||
return concat([buffer, updatedStaticBuffer, packedDynamicBuffer]); | ||
}; | ||
@@ -189,0 +191,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { toHex } from '../utils/buffer'; | ||
import { fromHex, toHex } from '../utils/buffer'; | ||
import { decodeBoolean, encodeBoolean } from './boolean'; | ||
@@ -6,7 +6,6 @@ | ||
it('encodes a boolean as a uint256 number', () => { | ||
const buffer = Buffer.alloc(0); | ||
expect(toHex(encodeBoolean(buffer, true, 'bool'))).toBe( | ||
expect(toHex(encodeBoolean(new Uint8Array(0), true, 'bool'))).toBe( | ||
'0000000000000000000000000000000000000000000000000000000000000001' | ||
); | ||
expect(toHex(encodeBoolean(buffer, false, 'bool'))).toBe( | ||
expect(toHex(encodeBoolean(new Uint8Array(0), false, 'bool'))).toBe( | ||
'0000000000000000000000000000000000000000000000000000000000000000' | ||
@@ -19,8 +18,8 @@ ); | ||
it('decodes a boolean as a uint256 number', () => { | ||
const trueValue = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex'); | ||
const trueValue = fromHex('0000000000000000000000000000000000000000000000000000000000000001'); | ||
expect(decodeBoolean(trueValue, trueValue, 'bool')).toBe(true); | ||
const falseValue = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'); | ||
const falseValue = fromHex('0000000000000000000000000000000000000000000000000000000000000000'); | ||
expect(decodeBoolean(falseValue, falseValue, 'bool')).toBe(false); | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
import { toHex } from '../utils/buffer'; | ||
import { fromUtf8, toHex } from '../utils'; | ||
import { encodeBytes } from './bytes'; | ||
@@ -6,4 +6,4 @@ | ||
it('encodes a byte string to a buffer', () => { | ||
const bytes = Buffer.from('Lorem ipsum dolor sit amet, consectetur adipiscing elit', 'utf8').toString('hex'); | ||
expect(toHex(encodeBytes(Buffer.alloc(0), bytes, 'bytes'))).toBe( | ||
const bytes = toHex(fromUtf8('Lorem ipsum dolor sit amet, consectetur adipiscing elit')); | ||
expect(toHex(encodeBytes(new Uint8Array(0), bytes, 'bytes'))).toBe( | ||
'00000000000000000000000000000000000000000000000000000000000000374c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c6974000000000000000000' | ||
@@ -13,14 +13,1 @@ ); | ||
}); | ||
// TODO | ||
/*describe('decodeBytes', () => { | ||
it('decodes a byte array to a buffer', () => { | ||
const buffer = Buffer.from( | ||
'00000000000000000000000000000000000000000000000000000000000000374c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c6974000000000000000000', | ||
'hex' | ||
); | ||
expect(toString(decodeBytes(buffer, Buffer.alloc(0), 'bytes'))).toBe( | ||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit' | ||
); | ||
}); | ||
});*/ |
@@ -1,2 +0,2 @@ | ||
import { addPadding, concat, toBuffer, toNumber } from '../utils/buffer'; | ||
import { addPadding, concat, toBuffer, toNumber } from '../utils'; | ||
import { DecodeFunction, EncodeFunction } from './parser'; | ||
@@ -8,3 +8,3 @@ | ||
return concat(buffer, Buffer.concat([toBuffer(bufferValue.byteLength), addPadding(bufferValue, paddedSize)])); | ||
return concat([buffer, toBuffer(bufferValue.byteLength), addPadding(bufferValue, paddedSize)]); | ||
}; | ||
@@ -11,0 +11,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { toHex } from '../utils/buffer'; | ||
import { fromHex, toHex } from '../utils/buffer'; | ||
import { decodeFixedBytes, encodeFixedBytes } from './fixed-bytes'; | ||
@@ -6,3 +6,3 @@ | ||
it('encodes a fixed byte array to a buffer', () => { | ||
expect(toHex(encodeFixedBytes(Buffer.alloc(0), '0xf00f00', 'bytes32'))).toBe( | ||
expect(toHex(encodeFixedBytes(new Uint8Array(0), '0xf00f00', 'bytes32'))).toBe( | ||
'f00f000000000000000000000000000000000000000000000000000000000000' | ||
@@ -13,3 +13,3 @@ ); | ||
it('throws if the value is too long', () => { | ||
expect(() => encodeFixedBytes(Buffer.alloc(0), '0xf00f00', 'bytes1')).toThrow(); | ||
expect(() => encodeFixedBytes(new Uint8Array(0), '0xf00f00', 'bytes1')).toThrow(); | ||
}); | ||
@@ -20,6 +20,6 @@ }); | ||
it('decodes a fixed byte array from a buffer', () => { | ||
const buffer = Buffer.from('f00f000000000000000000000000000000000000000000000000000000000000', 'hex'); | ||
expect(toHex(decodeFixedBytes(buffer, Buffer.alloc(0), 'bytes1'))).toBe('f0'); | ||
expect(toHex(decodeFixedBytes(buffer, Buffer.alloc(0), 'bytes16'))).toBe('f00f0000000000000000000000000000'); | ||
expect(toHex(decodeFixedBytes(buffer, Buffer.alloc(0), 'bytes32'))).toBe( | ||
const buffer = fromHex('f00f000000000000000000000000000000000000000000000000000000000000'); | ||
expect(toHex(decodeFixedBytes(buffer, new Uint8Array(0), 'bytes1'))).toBe('f0'); | ||
expect(toHex(decodeFixedBytes(buffer, new Uint8Array(0), 'bytes16'))).toBe('f00f0000000000000000000000000000'); | ||
expect(toHex(decodeFixedBytes(buffer, new Uint8Array(0), 'bytes32'))).toBe( | ||
'f00f000000000000000000000000000000000000000000000000000000000000' | ||
@@ -26,0 +26,0 @@ ); |
@@ -1,2 +0,2 @@ | ||
import { addPadding, concat, toBuffer } from '../utils/buffer'; | ||
import { addPadding, concat, toBuffer } from '../utils'; | ||
import { DecodeFunction, EncodeFunction } from './parser'; | ||
@@ -44,3 +44,3 @@ | ||
return concat(buffer, addPadding(bufferValue)); | ||
return concat([buffer, addPadding(bufferValue)]); | ||
}; | ||
@@ -47,0 +47,0 @@ |
@@ -1,3 +0,2 @@ | ||
import { concat, toBuffer, toNumber } from '../utils/buffer'; | ||
import { fromTwosComplement, toTwosComplement } from '../utils/twos-complement'; | ||
import { concat, toBuffer, toNumber, fromTwosComplement, toTwosComplement } from '../utils'; | ||
import { DecodeFunction, EncodeFunction } from './parser'; | ||
@@ -48,6 +47,6 @@ | ||
if (isSigned(type)) { | ||
return concat(buffer, toTwosComplement(numberValue, 32)); | ||
return concat([buffer, toTwosComplement(numberValue, 32)]); | ||
} | ||
return concat(buffer, toBuffer(numberValue)); | ||
return concat([buffer, toBuffer(numberValue)]); | ||
}; | ||
@@ -54,0 +53,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { toHex } from '../utils/buffer'; | ||
import { toHex } from '../utils'; | ||
import { encodeString } from './string'; | ||
@@ -7,3 +7,3 @@ | ||
expect( | ||
toHex(encodeString(Buffer.alloc(0), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', 'bytes')) | ||
toHex(encodeString(new Uint8Array(0), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', 'bytes')) | ||
).toBe( | ||
@@ -14,14 +14,1 @@ '00000000000000000000000000000000000000000000000000000000000000374c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c6974000000000000000000' | ||
}); | ||
// TODO | ||
/*describe('decodeString', () => { | ||
it('decodes a byte array to a buffer', () => { | ||
const buffer = Buffer.from( | ||
'00000000000000000000000000000000000000000000000000000000000000374c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c6974000000000000000000', | ||
'hex' | ||
); | ||
expect(decodeString(buffer, Buffer.alloc(0), 'bytes')).toBe( | ||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit' | ||
); | ||
}); | ||
});*/ |
@@ -1,2 +0,2 @@ | ||
import { toString } from '../utils/buffer'; | ||
import { fromUtf8, toUtf8 } from '../utils'; | ||
import { decodeBytes, encodeBytes } from './bytes'; | ||
@@ -6,4 +6,3 @@ import { DecodeFunction, EncodeFunction } from './parser'; | ||
export const encodeString: EncodeFunction = (buffer: Uint8Array, value: string): Uint8Array => { | ||
const bufferValue = Buffer.from(value, 'utf8'); | ||
const bufferValue = fromUtf8(value); | ||
return encodeBytes(buffer, bufferValue, 'bytes'); | ||
@@ -13,3 +12,3 @@ }; | ||
export const decodeString: DecodeFunction = (value: Uint8Array, buffer: Uint8Array): string => { | ||
return toString(decodeBytes(value, buffer, 'string')); | ||
return toUtf8(decodeBytes(value, buffer, 'string')); | ||
}; |
const BUFFER_WIDTH = 32; | ||
const HEX_REGEX = /^[a-f0-9]+$/i; | ||
export type BinaryLike = string | number | bigint | ArrayBufferLike | number[]; | ||
export const stripPrefix = (value: string): string => { | ||
if (value.startsWith('0x')) { | ||
return value.substring(2); | ||
} | ||
return value; | ||
}; | ||
/** | ||
* Concatenate two buffers. If a position is specified, `value` will be put in `target` at the specified position. All | ||
* bytes after that will be moved to the end of the buffer. | ||
* Returns an instance of `TextEncoder` that works with both Node.js and web browsers. | ||
* | ||
* @param {Uint8Array} target | ||
* @param {Uint8Array} value | ||
* @param {number} [position] | ||
* @return {Uint8Array} | ||
* @return {TextEncoder} | ||
*/ | ||
export const concat = (target: Uint8Array, value: Uint8Array, position?: number): Uint8Array => { | ||
return new Uint8Array([ | ||
...target.subarray(0, position ?? target.length), | ||
...value, | ||
...target.subarray(position ?? target.length) | ||
]); | ||
export const getTextEncoder = (): TextEncoder => { | ||
if (typeof TextEncoder === 'undefined') { | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const Encoder = require('util').TextEncoder; | ||
return new Encoder(); | ||
} | ||
return new TextEncoder(); | ||
}; | ||
/** | ||
* Concatenates multiple buffers, compatible with Uint8Arrays of browsers. | ||
* Returns an instance of `TextDecoder` that works with both Node.js and web browsers. | ||
* | ||
* @param {Uint8Array[]} buffers | ||
* @return {Uint8Array} | ||
* @return {TextDecoder} | ||
*/ | ||
export const concatMultiple = (buffers: Uint8Array[]): Uint8Array => { | ||
return buffers.reduce((target, buffer) => { | ||
const array = new Uint8Array(target.length + buffer.length); | ||
array.set(target, 0); | ||
array.set(buffer, target.length); | ||
return array; | ||
}, new Uint8Array(0)); | ||
export const getTextDecoder = (encoding = 'utf8'): TextDecoder => { | ||
if (typeof TextEncoder === 'undefined') { | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const Decoder = require('util').TextDecoder; | ||
return new Decoder(encoding); | ||
} | ||
return new TextDecoder(encoding); | ||
}; | ||
/** | ||
* Add padding to a buffer. If the buffer is larger than `length`, this function won't do anything. If it's smaller, the | ||
* buffer will be padded to the specified length, with extra zeroes at the end. | ||
* Get a buffer as UTF-8 encoded string. | ||
* | ||
* @param {Uint8Array} buffer | ||
* @param {number} [length] | ||
* @param {Uint8Array} data | ||
* @return {string} | ||
*/ | ||
export const toUtf8 = (data: Uint8Array): string => { | ||
return getTextDecoder().decode(data); | ||
}; | ||
/** | ||
* Get a UTF-8 encoded string as buffer. | ||
* | ||
* @param {string} data | ||
* @return {Uint8Array} | ||
*/ | ||
export const addPadding = (buffer: Uint8Array, length = 32): Uint8Array => { | ||
const padding = Buffer.alloc(Math.max(length - buffer.length, 0), 0); | ||
return concat(buffer, padding); | ||
export const fromUtf8 = (data: string): Uint8Array => { | ||
return getTextEncoder().encode(data); | ||
}; | ||
/** | ||
* Get a value as buffer. The value can be a string, number, bigint or buffer. If the value is a string, it is assumed | ||
* that it is a hexadecimal value. | ||
* Get a Uint8Array as hexadecimal string | ||
* | ||
* @param {string | number | bigint | Uint8Array} value | ||
* @param {Uint8Array} data | ||
* @return {string} | ||
*/ | ||
export const toHex = (data: Uint8Array): string => { | ||
return Array.from(data) | ||
.map((n) => `0${n.toString(16)}`.slice(-2)) | ||
.join(''); | ||
}; | ||
/** | ||
* Get a hexadecimal string as Uint8Array. | ||
* | ||
* @param {string} data | ||
* @return {Uint8Array} | ||
*/ | ||
export const toBuffer = (value: string | number | bigint | Uint8Array): Uint8Array => { | ||
if (Buffer.isBuffer(value) || value instanceof Uint8Array) { | ||
return value; | ||
export const fromHex = (data: string): Uint8Array => { | ||
if (data.startsWith('0x')) { | ||
data = data.slice(2); | ||
} | ||
if (typeof value === 'string') { | ||
const stringValue = value.startsWith('0x') ? value.substring(2) : value; | ||
return Buffer.from(stringValue, 'hex'); | ||
if (data.length % 2 !== 0) { | ||
throw new Error('Length must be even'); | ||
} | ||
const hex = value.toString(16); | ||
return Buffer.from(hex.padStart(BUFFER_WIDTH * 2, '0').slice(0, BUFFER_WIDTH * 2), 'hex'); | ||
if (!data.match(HEX_REGEX)) { | ||
throw new Error('Input must be hexadecimal'); | ||
} | ||
return new Uint8Array(data.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16))); | ||
}; | ||
/** | ||
* Get a UTF-8 encodes buffer as string. | ||
* Attempt to parse a value as Uint8Array. | ||
* | ||
* @param {Uint8Array} value | ||
* @return {string} | ||
* @param {BinaryLike} data | ||
* @return {Uint8Array} | ||
*/ | ||
export const toString = (value: Uint8Array): string => { | ||
if (typeof window !== 'undefined' && window.TextDecoder) { | ||
return new TextDecoder('utf-8').decode(value); | ||
export const toBuffer = (data: BinaryLike): Uint8Array => { | ||
if (typeof data === 'string') { | ||
return fromHex(data); | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
return new (require('util').TextDecoder)('utf-8').decode(value); | ||
if (typeof data === 'number' || typeof data === 'bigint') { | ||
const string = data.toString(16); | ||
return fromHex(string.padStart(BUFFER_WIDTH * 2, '0')); | ||
} | ||
return new Uint8Array(data); | ||
}; | ||
/** | ||
* Safe function to merge multiple Uint8Arrays into a single Uint8array. | ||
* | ||
* @param {Uint8Array[]} buffers | ||
* @return {Uint8Array} | ||
*/ | ||
export const concat = (buffers: Uint8Array[]): Uint8Array => { | ||
return buffers.reduce((a, b) => { | ||
const buffer = new Uint8Array(a.length + b.length); | ||
buffer.set(a); | ||
buffer.set(b, a.length); | ||
return buffer; | ||
}, new Uint8Array(0)); | ||
}; | ||
/** | ||
* Concatenate two buffers by placing one buffer at a specific position in another buffer. | ||
* | ||
* @param {Uint8Array} a | ||
* @param {Uint8Array} b | ||
* @param {number} position | ||
* @return {Uint8Array} | ||
*/ | ||
export const concatAt = (a: Uint8Array, b: Uint8Array, position: number): Uint8Array => { | ||
return concat([a.slice(0, position), b, a.slice(position)]); | ||
}; | ||
/** | ||
* Add padding to a buffer. If the buffer is larger than `length`, this function won't do anything. If it's smaller, the | ||
* buffer will be padded to the specified length, with extra zeroes at the end. | ||
* | ||
* @param {Uint8Array} buffer | ||
* @param {number} [length] | ||
* @return {Uint8Array} | ||
*/ | ||
export const addPadding = (buffer: Uint8Array, length = BUFFER_WIDTH): Uint8Array => { | ||
const padding = new Uint8Array(Math.max(length - buffer.length, 0)).fill(0x00); | ||
return concat([buffer, padding]); | ||
}; | ||
/** | ||
* Get a number from a buffer. | ||
@@ -97,15 +171,1 @@ * | ||
}; | ||
const numberToHex = (value: number): string => { | ||
return ('0' + value.toString(16)).slice(-2); | ||
}; | ||
/** | ||
* Get a buffer as hexadecimal string. | ||
* | ||
* @param {Uint8Array} buffer | ||
* @return {string} | ||
*/ | ||
export const toHex = (buffer: Uint8Array): string => { | ||
return Array.from(buffer).map(numberToHex).join(''); | ||
}; |
import createKeccakHash from 'keccak'; | ||
import { toHex } from './buffer'; | ||
@@ -10,3 +11,3 @@ /** | ||
export const keccak256 = (input: string): string => { | ||
return createKeccakHash('keccak256').update(input).digest().toString('hex'); | ||
return toHex(createKeccakHash('keccak256').update(input).digest()); | ||
}; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { ContractFunction, ContractInput } from './contract'; | ||
@@ -8,3 +7,3 @@ /** | ||
* @param {unknown[]} values | ||
* @return {Buffer} | ||
* @return {Uint8Array} | ||
*/ | ||
@@ -17,5 +16,5 @@ export declare const encode: (input: Array<ContractInput | string>, values: unknown[]) => Uint8Array; | ||
* @param {unknown[]} values | ||
* @return {Buffer} | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const encodeWithIdentifier: (contractFunction: ContractFunction, values: unknown[]) => Uint8Array; | ||
export declare const decode: <T extends unknown[]>(input: Array<ContractInput | string>, buffer: Buffer) => T; | ||
export declare const decode: <T extends unknown[]>(input: Array<ContractInput | string>, buffer: Uint8Array) => T; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
/** | ||
@@ -85,3 +84,1 @@ * Most valid types for the Solidity JSON ABI specification, excluding dynamic types like `uint<N>`, `fixed<M>x<N>`, | ||
export declare type ContractInterface = ContractFunction | ContractEvent; | ||
export declare type DecodeFunction<T> = (value: Buffer, buffer: Buffer, type: string) => T; | ||
export declare type EncodeFunction<T> = (target: Buffer, data: T, position: number, type: string) => Buffer; |
export { encode, encodeWithIdentifier, decode } from './abi'; | ||
export * from './utils'; | ||
export * from './contract'; |
@@ -25,2 +25,3 @@ import { DecodeFunction, EncodeFunction, Parser } from './parser'; | ||
export declare const getParser: (type: string) => Parser; | ||
export declare type UpdateFunction = (buffer: Uint8Array) => Uint8Array; | ||
/** | ||
@@ -27,0 +28,0 @@ * Pack multiple values into a single Buffer, based on the provided types. Returns a new buffer with the |
@@ -0,54 +1,80 @@ | ||
export declare type BinaryLike = string | number | bigint | ArrayBufferLike | number[]; | ||
export declare const stripPrefix: (value: string) => string; | ||
/** | ||
* Concatenate two buffers. If a position is specified, `value` will be put in `target` at the specified position. All | ||
* bytes after that will be moved to the end of the buffer. | ||
* Returns an instance of `TextEncoder` that works with both Node.js and web browsers. | ||
* | ||
* @param {Uint8Array} target | ||
* @param {Uint8Array} value | ||
* @param {number} [position] | ||
* @return {TextEncoder} | ||
*/ | ||
export declare const getTextEncoder: () => TextEncoder; | ||
/** | ||
* Returns an instance of `TextDecoder` that works with both Node.js and web browsers. | ||
* | ||
* @return {TextDecoder} | ||
*/ | ||
export declare const getTextDecoder: (encoding?: string) => TextDecoder; | ||
/** | ||
* Get a buffer as UTF-8 encoded string. | ||
* | ||
* @param {Uint8Array} data | ||
* @return {string} | ||
*/ | ||
export declare const toUtf8: (data: Uint8Array) => string; | ||
/** | ||
* Get a UTF-8 encoded string as buffer. | ||
* | ||
* @param {string} data | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const concat: (target: Uint8Array, value: Uint8Array, position?: number | undefined) => Uint8Array; | ||
export declare const fromUtf8: (data: string) => Uint8Array; | ||
/** | ||
* Concatenates multiple buffers, compatible with Uint8Arrays of browsers. | ||
* Get a Uint8Array as hexadecimal string | ||
* | ||
* @param {Uint8Array[]} buffers | ||
* @param {Uint8Array} data | ||
* @return {string} | ||
*/ | ||
export declare const toHex: (data: Uint8Array) => string; | ||
/** | ||
* Get a hexadecimal string as Uint8Array. | ||
* | ||
* @param {string} data | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const concatMultiple: (buffers: Uint8Array[]) => Uint8Array; | ||
export declare const fromHex: (data: string) => Uint8Array; | ||
/** | ||
* Add padding to a buffer. If the buffer is larger than `length`, this function won't do anything. If it's smaller, the | ||
* buffer will be padded to the specified length, with extra zeroes at the end. | ||
* Attempt to parse a value as Uint8Array. | ||
* | ||
* @param {Uint8Array} buffer | ||
* @param {number} [length] | ||
* @param {BinaryLike} data | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const addPadding: (buffer: Uint8Array, length?: number) => Uint8Array; | ||
export declare const toBuffer: (data: BinaryLike) => Uint8Array; | ||
/** | ||
* Get a value as buffer. The value can be a string, number, bigint or buffer. If the value is a string, it is assumed | ||
* that it is a hexadecimal value. | ||
* Safe function to merge multiple Uint8Arrays into a single Uint8array. | ||
* | ||
* @param {string | number | bigint | Uint8Array} value | ||
* @param {Uint8Array[]} buffers | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const toBuffer: (value: string | number | bigint | Uint8Array) => Uint8Array; | ||
export declare const concat: (buffers: Uint8Array[]) => Uint8Array; | ||
/** | ||
* Get a UTF-8 encodes buffer as string. | ||
* Concatenate two buffers by placing one buffer at a specific position in another buffer. | ||
* | ||
* @param {Uint8Array} value | ||
* @return {string} | ||
* @param {Uint8Array} a | ||
* @param {Uint8Array} b | ||
* @param {number} position | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const toString: (value: Uint8Array) => string; | ||
export declare const concatAt: (a: Uint8Array, b: Uint8Array, position: number) => Uint8Array; | ||
/** | ||
* Get a number from a buffer. | ||
* Add padding to a buffer. If the buffer is larger than `length`, this function won't do anything. If it's smaller, the | ||
* buffer will be padded to the specified length, with extra zeroes at the end. | ||
* | ||
* @param {Uint8Array} buffer | ||
* @param {number} [length] | ||
* @return {Uint8Array} | ||
*/ | ||
export declare const toNumber: (buffer: Uint8Array) => bigint; | ||
export declare const addPadding: (buffer: Uint8Array, length?: number) => Uint8Array; | ||
/** | ||
* Get a buffer as hexadecimal string. | ||
* Get a number from a buffer. | ||
* | ||
* @param {Uint8Array} buffer | ||
* @return {string} | ||
*/ | ||
export declare const toHex: (buffer: Uint8Array) => string; | ||
export declare const toNumber: (buffer: Uint8Array) => bigint; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
171849
118
2552
Updatedkeccak@^3.0.1