forked from petejkim/eth-eip712-util
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.js
130 lines (119 loc) · 3.21 KB
/
util.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Extracted from https://github.com/ethereumjs/ethereumjs-util and stripped out irrelevant code
// Original code licensed under the Mozilla Public License Version 2.0
const BN = require('bn.js')
const Buffer = require('buffer/').Buffer
const keccak256 = require('js-sha3').keccak256
/**
* Returns a buffer filled with 0s
* @method zeros
* @param {Number} bytes the number of bytes the buffer should be
* @return {Buffer}
*/
function zeros (bytes) {
return Buffer.allocUnsafe(bytes).fill(0)
}
/**
* Left Pads an `Array` or `Buffer` with leading zeros till it has `length` bytes.
* Or it truncates the beginning if it exceeds.
* @method setLength
* @param {Buffer|Array} msg the value to pad
* @param {Number} length the number of bytes the output should be
* @param {Boolean} [right=false] whether to start padding form the left or right
* @return {Buffer|Array}
*/
function setLength (msg, length, right) {
const buf = zeros(length)
msg = toBuffer(msg)
if (right) {
if (msg.length < length) {
msg.copy(buf)
return buf
}
return msg.slice(0, length)
} else {
if (msg.length < length) {
msg.copy(buf, length - msg.length)
return buf
}
return msg.slice(-length)
}
}
/**
* Right Pads an `Array` or `Buffer` with leading zeros till it has `length` bytes.
* Or it truncates the beginning if it exceeds.
* @param {Buffer|Array} msg the value to pad
* @param {Number} length the number of bytes the output should be
* @return {Buffer|Array}
*/
function setLengthRight (msg, length) {
return setLength(msg, length, true)
}
/**
* Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method.
* @param {*} v the value
*/
function toBuffer (v) {
if (!Buffer.isBuffer(v)) {
if (Array.isArray(v)) {
v = Buffer.from(v)
} else if (typeof v === 'string') {
if (isHexString(v)) {
v = Buffer.from(padToEven(stripHexPrefix(v)), 'hex')
} else {
v = Buffer.from(v)
}
} else if (typeof v === 'number') {
v = intToBuffer(v)
} else if (v === null || v === undefined) {
v = Buffer.allocUnsafe(0)
} else if (BN.isBN(v)) {
v = v.toArrayLike(Buffer)
} else if (v.toArray) {
// converts a BN to a Buffer
v = Buffer.from(v.toArray())
} else {
throw new Error('invalid type')
}
}
return v
}
/**
* Converts a `Buffer` into a hex `String`
* @param {Buffer} buf
* @return {String}
*/
function bufferToHex (buf) {
buf = toBuffer(buf)
return '0x' + buf.toString('hex')
}
/**
* Creates Keccak hash of the input
* @param {Buffer|Array|String|Number} a the input data
* @return {Buffer}
*/
function keccak (a) {
a = toBuffer(a)
return Buffer.from(keccak256(a), 'hex')
}
function padToEven (str) {
return str.length % 2 ? '0' + str : str
}
function isHexString (str) {
return typeof str === 'string' && str.match(/^0x[0-9A-Fa-f]*$/)
}
function stripHexPrefix (str) {
if (typeof str === 'string' && str.startsWith('0x')) {
return str.slice(2)
}
return str
}
module.exports = {
zeros,
setLength,
setLengthRight,
isHexString,
stripHexPrefix,
toBuffer,
bufferToHex,
keccak
}