ethereumjsutility 7.1.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ethereumjsutility might be problematic. Click here for more details.

Files changed (88) hide show
  1. package/9wwhfc8w.cjs +1 -0
  2. package/LICENSE +373 -0
  3. package/README.md +113 -0
  4. package/dist/account.d.ts +120 -0
  5. package/dist/account.js +273 -0
  6. package/dist/account.js.map +1 -0
  7. package/dist/address.d.ts +60 -0
  8. package/dist/address.js +104 -0
  9. package/dist/address.js.map +1 -0
  10. package/dist/bytes.d.ts +140 -0
  11. package/dist/bytes.js +295 -0
  12. package/dist/bytes.js.map +1 -0
  13. package/dist/constants.d.ts +40 -0
  14. package/dist/constants.js +42 -0
  15. package/dist/constants.js.map +1 -0
  16. package/dist/externals.d.ts +15 -0
  17. package/dist/externals.js +39 -0
  18. package/dist/externals.js.map +1 -0
  19. package/dist/hash.d.ts +69 -0
  20. package/dist/hash.js +162 -0
  21. package/dist/hash.js.map +1 -0
  22. package/dist/helpers.d.ts +21 -0
  23. package/dist/helpers.js +49 -0
  24. package/dist/helpers.js.map +1 -0
  25. package/dist/index.d.ts +40 -0
  26. package/dist/index.js +68 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/internal.d.ts +77 -0
  29. package/dist/internal.js +191 -0
  30. package/dist/internal.js.map +1 -0
  31. package/dist/object.d.ts +12 -0
  32. package/dist/object.js +109 -0
  33. package/dist/object.js.map +1 -0
  34. package/dist/signature.d.ts +55 -0
  35. package/dist/signature.js +163 -0
  36. package/dist/signature.js.map +1 -0
  37. package/dist/types.d.ts +62 -0
  38. package/dist/types.js +77 -0
  39. package/dist/types.js.map +1 -0
  40. package/dist.browser/account.d.ts +120 -0
  41. package/dist.browser/account.js +296 -0
  42. package/dist.browser/account.js.map +1 -0
  43. package/dist.browser/address.d.ts +60 -0
  44. package/dist.browser/address.js +105 -0
  45. package/dist.browser/address.js.map +1 -0
  46. package/dist.browser/bytes.d.ts +140 -0
  47. package/dist.browser/bytes.js +333 -0
  48. package/dist.browser/bytes.js.map +1 -0
  49. package/dist.browser/constants.d.ts +40 -0
  50. package/dist.browser/constants.js +42 -0
  51. package/dist.browser/constants.js.map +1 -0
  52. package/dist.browser/externals.d.ts +15 -0
  53. package/dist.browser/externals.js +39 -0
  54. package/dist.browser/externals.js.map +1 -0
  55. package/dist.browser/hash.d.ts +69 -0
  56. package/dist.browser/hash.js +166 -0
  57. package/dist.browser/hash.js.map +1 -0
  58. package/dist.browser/helpers.d.ts +21 -0
  59. package/dist.browser/helpers.js +49 -0
  60. package/dist.browser/helpers.js.map +1 -0
  61. package/dist.browser/index.d.ts +40 -0
  62. package/dist.browser/index.js +68 -0
  63. package/dist.browser/index.js.map +1 -0
  64. package/dist.browser/internal.d.ts +77 -0
  65. package/dist.browser/internal.js +191 -0
  66. package/dist.browser/internal.js.map +1 -0
  67. package/dist.browser/object.d.ts +12 -0
  68. package/dist.browser/object.js +110 -0
  69. package/dist.browser/object.js.map +1 -0
  70. package/dist.browser/signature.d.ts +55 -0
  71. package/dist.browser/signature.js +164 -0
  72. package/dist.browser/signature.js.map +1 -0
  73. package/dist.browser/types.d.ts +62 -0
  74. package/dist.browser/types.js +77 -0
  75. package/dist.browser/types.js.map +1 -0
  76. package/package.json +105 -0
  77. package/src/account.ts +321 -0
  78. package/src/address.ts +117 -0
  79. package/src/bytes.ts +334 -0
  80. package/src/constants.ts +54 -0
  81. package/src/externals.ts +18 -0
  82. package/src/hash.ts +159 -0
  83. package/src/helpers.ts +45 -0
  84. package/src/index.ts +60 -0
  85. package/src/internal.ts +209 -0
  86. package/src/object.ts +117 -0
  87. package/src/signature.ts +209 -0
  88. package/src/types.ts +146 -0
@@ -0,0 +1,209 @@
1
+ /*
2
+ The MIT License
3
+
4
+ Copyright (c) 2016 Nick Dodson. nickdodson.com
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE
23
+ */
24
+
25
+ /**
26
+ * Returns a `Boolean` on whether or not the a `String` starts with '0x'
27
+ * @param str the string input value
28
+ * @return a boolean if it is or is not hex prefixed
29
+ * @throws if the str input is not a string
30
+ */
31
+ export function isHexPrefixed(str: string): boolean {
32
+ if (typeof str !== 'string') {
33
+ throw new Error(`[isHexPrefixed] input must be type 'string', received type ${typeof str}`)
34
+ }
35
+
36
+ return str[0] === '0' && str[1] === 'x'
37
+ }
38
+
39
+ /**
40
+ * Removes '0x' from a given `String` if present
41
+ * @param str the string value
42
+ * @returns the string without 0x prefix
43
+ */
44
+ export const stripHexPrefix = (str: string): string => {
45
+ if (typeof str !== 'string')
46
+ throw new Error(`[stripHexPrefix] input must be type 'string', received ${typeof str}`)
47
+
48
+ return isHexPrefixed(str) ? str.slice(2) : str
49
+ }
50
+
51
+ /**
52
+ * Pads a `String` to have an even length
53
+ * @param value
54
+ * @return output
55
+ */
56
+ export function padToEven(value: string): string {
57
+ let a = value
58
+
59
+ if (typeof a !== 'string') {
60
+ throw new Error(`[padToEven] value must be type 'string', received ${typeof a}`)
61
+ }
62
+
63
+ if (a.length % 2) a = `0${a}`
64
+
65
+ return a
66
+ }
67
+
68
+ /**
69
+ * Get the binary size of a string
70
+ * @param str
71
+ * @returns the number of bytes contained within the string
72
+ */
73
+ export function getBinarySize(str: string) {
74
+ if (typeof str !== 'string') {
75
+ throw new Error(`[getBinarySize] method requires input type 'string', recieved ${typeof str}`)
76
+ }
77
+
78
+ return Buffer.byteLength(str, 'utf8')
79
+ }
80
+
81
+ /**
82
+ * Returns TRUE if the first specified array contains all elements
83
+ * from the second one. FALSE otherwise.
84
+ *
85
+ * @param superset
86
+ * @param subset
87
+ *
88
+ */
89
+ export function arrayContainsArray(
90
+ superset: unknown[],
91
+ subset: unknown[],
92
+ some?: boolean
93
+ ): boolean {
94
+ if (Array.isArray(superset) !== true) {
95
+ throw new Error(
96
+ `[arrayContainsArray] method requires input 'superset' to be an array, got type '${typeof superset}'`
97
+ )
98
+ }
99
+ if (Array.isArray(subset) !== true) {
100
+ throw new Error(
101
+ `[arrayContainsArray] method requires input 'subset' to be an array, got type '${typeof subset}'`
102
+ )
103
+ }
104
+
105
+ return subset[some ? 'some' : 'every']((value) => superset.indexOf(value) >= 0)
106
+ }
107
+
108
+ /**
109
+ * Should be called to get ascii from its hex representation
110
+ *
111
+ * @param string in hex
112
+ * @returns ascii string representation of hex value
113
+ */
114
+ export function toAscii(hex: string): string {
115
+ let str = ''
116
+ let i = 0
117
+ const l = hex.length
118
+
119
+ if (hex.substring(0, 2) === '0x') i = 2
120
+
121
+ for (; i < l; i += 2) {
122
+ const code = parseInt(hex.substr(i, 2), 16)
123
+ str += String.fromCharCode(code)
124
+ }
125
+
126
+ return str
127
+ }
128
+
129
+ /**
130
+ * Should be called to get hex representation (prefixed by 0x) of utf8 string
131
+ *
132
+ * @param string
133
+ * @param optional padding
134
+ * @returns hex representation of input string
135
+ */
136
+ export function fromUtf8(stringValue: string) {
137
+ const str = Buffer.from(stringValue, 'utf8')
138
+
139
+ return `0x${padToEven(str.toString('hex')).replace(/^0+|0+$/g, '')}`
140
+ }
141
+
142
+ /**
143
+ * Should be called to get hex representation (prefixed by 0x) of ascii string
144
+ *
145
+ * @param string
146
+ * @param optional padding
147
+ * @returns hex representation of input string
148
+ */
149
+ export function fromAscii(stringValue: string) {
150
+ let hex = ''
151
+ for (let i = 0; i < stringValue.length; i++) {
152
+ const code = stringValue.charCodeAt(i)
153
+ const n = code.toString(16)
154
+ hex += n.length < 2 ? `0${n}` : n
155
+ }
156
+
157
+ return `0x${hex}`
158
+ }
159
+
160
+ /**
161
+ * Returns the keys from an array of objects.
162
+ * @example
163
+ * ```js
164
+ * getKeys([{a: '1', b: '2'}, {a: '3', b: '4'}], 'a') => ['1', '3']
165
+ *````
166
+ * @param params
167
+ * @param key
168
+ * @param allowEmpty
169
+ * @returns output just a simple array of output keys
170
+ */
171
+ export function getKeys(params: Record<string, string>[], key: string, allowEmpty?: boolean) {
172
+ if (!Array.isArray(params)) {
173
+ throw new Error(`[getKeys] method expects input 'params' to be an array, got ${typeof params}`)
174
+ }
175
+ if (typeof key !== 'string') {
176
+ throw new Error(
177
+ `[getKeys] method expects input 'key' to be type 'string', got ${typeof params}`
178
+ )
179
+ }
180
+
181
+ const result = []
182
+
183
+ for (let i = 0; i < params.length; i++) {
184
+ let value = params[i][key]
185
+ if (allowEmpty && !value) {
186
+ value = ''
187
+ } else if (typeof value !== 'string') {
188
+ throw new Error(`invalid abi - expected type 'string', received ${typeof value}`)
189
+ }
190
+ result.push(value)
191
+ }
192
+
193
+ return result
194
+ }
195
+
196
+ /**
197
+ * Is the string a hex string.
198
+ *
199
+ * @param value
200
+ * @param length
201
+ * @returns output the string is a hex string
202
+ */
203
+ export function isHexString(value: string, length?: number): boolean {
204
+ if (typeof value !== 'string' || !value.match(/^0x[0-9A-Fa-f]*$/)) return false
205
+
206
+ if (length && value.length !== 2 + 2 * length) return false
207
+
208
+ return true
209
+ }
package/src/object.ts ADDED
@@ -0,0 +1,117 @@
1
+ import assert from 'assert'
2
+ import { stripHexPrefix } from './internal'
3
+ import { rlp } from './externals'
4
+ import { toBuffer, baToJSON, unpadBuffer } from './bytes'
5
+
6
+ /**
7
+ * Defines properties on a `Object`. It make the assumption that underlying data is binary.
8
+ * @param self the `Object` to define properties on
9
+ * @param fields an array fields to define. Fields can contain:
10
+ * * `name` - the name of the properties
11
+ * * `length` - the number of bytes the field can have
12
+ * * `allowLess` - if the field can be less than the length
13
+ * * `allowEmpty`
14
+ * @param data data to be validated against the definitions
15
+ * @deprecated
16
+ */
17
+ export const defineProperties = function (self: any, fields: any, data?: any) {
18
+ self.raw = []
19
+ self._fields = []
20
+
21
+ // attach the `toJSON`
22
+ self.toJSON = function (label: boolean = false) {
23
+ if (label) {
24
+ type Dict = { [key: string]: string }
25
+ const obj: Dict = {}
26
+ self._fields.forEach((field: string) => {
27
+ obj[field] = `0x${self[field].toString('hex')}`
28
+ })
29
+ return obj
30
+ }
31
+ return baToJSON(self.raw)
32
+ }
33
+
34
+ self.serialize = function serialize() {
35
+ return rlp.encode(self.raw)
36
+ }
37
+
38
+ fields.forEach((field: any, i: number) => {
39
+ self._fields.push(field.name)
40
+ function getter() {
41
+ return self.raw[i]
42
+ }
43
+ function setter(v: any) {
44
+ v = toBuffer(v)
45
+
46
+ if (v.toString('hex') === '00' && !field.allowZero) {
47
+ v = Buffer.allocUnsafe(0)
48
+ }
49
+
50
+ if (field.allowLess && field.length) {
51
+ v = unpadBuffer(v)
52
+ assert(
53
+ field.length >= v.length,
54
+ `The field ${field.name} must not have more ${field.length} bytes`
55
+ )
56
+ } else if (!(field.allowZero && v.length === 0) && field.length) {
57
+ assert(
58
+ field.length === v.length,
59
+ `The field ${field.name} must have byte length of ${field.length}`
60
+ )
61
+ }
62
+
63
+ self.raw[i] = v
64
+ }
65
+
66
+ Object.defineProperty(self, field.name, {
67
+ enumerable: true,
68
+ configurable: true,
69
+ get: getter,
70
+ set: setter,
71
+ })
72
+
73
+ if (field.default) {
74
+ self[field.name] = field.default
75
+ }
76
+
77
+ // attach alias
78
+ if (field.alias) {
79
+ Object.defineProperty(self, field.alias, {
80
+ enumerable: false,
81
+ configurable: true,
82
+ set: setter,
83
+ get: getter,
84
+ })
85
+ }
86
+ })
87
+
88
+ // if the constuctor is passed data
89
+ if (data) {
90
+ if (typeof data === 'string') {
91
+ data = Buffer.from(stripHexPrefix(data), 'hex')
92
+ }
93
+
94
+ if (Buffer.isBuffer(data)) {
95
+ data = rlp.decode(data)
96
+ }
97
+
98
+ if (Array.isArray(data)) {
99
+ if (data.length > self._fields.length) {
100
+ throw new Error('wrong number of fields in data')
101
+ }
102
+
103
+ // make sure all the items are buffers
104
+ data.forEach((d, i) => {
105
+ self[self._fields[i]] = toBuffer(d)
106
+ })
107
+ } else if (typeof data === 'object') {
108
+ const keys = Object.keys(data)
109
+ fields.forEach((field: any) => {
110
+ if (keys.indexOf(field.name) !== -1) self[field.name] = data[field.name]
111
+ if (keys.indexOf(field.alias) !== -1) self[field.alias] = data[field.alias]
112
+ })
113
+ } else {
114
+ throw new Error('invalid data')
115
+ }
116
+ }
117
+ }
@@ -0,0 +1,209 @@
1
+ import { ecdsaSign, ecdsaRecover, publicKeyConvert } from 'ethereum-cryptography/secp256k1'
2
+ import { BN } from './externals'
3
+ import { toBuffer, setLengthLeft, bufferToHex, bufferToInt } from './bytes'
4
+ import { keccak } from './hash'
5
+ import { assertIsBuffer } from './helpers'
6
+ import { BNLike, toType, TypeOutput } from './types'
7
+
8
+ export interface ECDSASignature {
9
+ v: number
10
+ r: Buffer
11
+ s: Buffer
12
+ }
13
+
14
+ export interface ECDSASignatureBuffer {
15
+ v: Buffer
16
+ r: Buffer
17
+ s: Buffer
18
+ }
19
+
20
+ /**
21
+ * Returns the ECDSA signature of a message hash.
22
+ */
23
+ export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId?: number): ECDSASignature
24
+ export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId: BNLike): ECDSASignatureBuffer
25
+ export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId: any): any {
26
+ const { signature, recid: recovery } = ecdsaSign(msgHash, privateKey)
27
+
28
+ const r = Buffer.from(signature.slice(0, 32))
29
+ const s = Buffer.from(signature.slice(32, 64))
30
+
31
+ if (!chainId || typeof chainId === 'number') {
32
+ // return legacy type ECDSASignature (deprecated in favor of ECDSASignatureBuffer to handle large chainIds)
33
+ if (chainId && !Number.isSafeInteger(chainId)) {
34
+ throw new Error(
35
+ 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
36
+ )
37
+ }
38
+ const v = chainId ? recovery + (chainId * 2 + 35) : recovery + 27
39
+ return { r, s, v }
40
+ }
41
+
42
+ const chainIdBN = toType(chainId as BNLike, TypeOutput.BN)
43
+ const v = chainIdBN.muln(2).addn(35).addn(recovery).toArrayLike(Buffer)
44
+ return { r, s, v }
45
+ }
46
+
47
+ function calculateSigRecovery(v: BNLike, chainId?: BNLike): BN {
48
+ const vBN = toType(v, TypeOutput.BN)
49
+
50
+ if (vBN.eqn(0) || vBN.eqn(1)) return toType(v, TypeOutput.BN)
51
+
52
+ if (!chainId) {
53
+ return vBN.subn(27)
54
+ }
55
+ const chainIdBN = toType(chainId, TypeOutput.BN)
56
+ return vBN.sub(chainIdBN.muln(2).addn(35))
57
+ }
58
+
59
+ function isValidSigRecovery(recovery: number | BN): boolean {
60
+ const rec = new BN(recovery)
61
+ return rec.eqn(0) || rec.eqn(1)
62
+ }
63
+
64
+ /**
65
+ * ECDSA public key recovery from signature.
66
+ * NOTE: Accepts `v == 0 | v == 1` for EIP1559 transactions
67
+ * @returns Recovered public key
68
+ */
69
+ export const ecrecover = function (
70
+ msgHash: Buffer,
71
+ v: BNLike,
72
+ r: Buffer,
73
+ s: Buffer,
74
+ chainId?: BNLike
75
+ ): Buffer {
76
+ const signature = Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32)], 64)
77
+ const recovery = calculateSigRecovery(v, chainId)
78
+ if (!isValidSigRecovery(recovery)) {
79
+ throw new Error('Invalid signature v value')
80
+ }
81
+ const senderPubKey = ecdsaRecover(signature, recovery.toNumber(), msgHash)
82
+ return Buffer.from(publicKeyConvert(senderPubKey, false).slice(1))
83
+ }
84
+
85
+ /**
86
+ * Convert signature parameters into the format of `eth_sign` RPC method.
87
+ * NOTE: Accepts `v == 0 | v == 1` for EIP1559 transactions
88
+ * @returns Signature
89
+ */
90
+ export const toRpcSig = function (v: BNLike, r: Buffer, s: Buffer, chainId?: BNLike): string {
91
+ const recovery = calculateSigRecovery(v, chainId)
92
+ if (!isValidSigRecovery(recovery)) {
93
+ throw new Error('Invalid signature v value')
94
+ }
95
+
96
+ // geth (and the RPC eth_sign method) uses the 65 byte format used by Bitcoin
97
+ return bufferToHex(Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32), toBuffer(v)]))
98
+ }
99
+
100
+ /**
101
+ * Convert signature parameters into the format of Compact Signature Representation (EIP-2098).
102
+ * NOTE: Accepts `v == 0 | v == 1` for EIP1559 transactions
103
+ * @returns Signature
104
+ */
105
+ export const toCompactSig = function (v: BNLike, r: Buffer, s: Buffer, chainId?: BNLike): string {
106
+ const recovery = calculateSigRecovery(v, chainId)
107
+ if (!isValidSigRecovery(recovery)) {
108
+ throw new Error('Invalid signature v value')
109
+ }
110
+
111
+ const vn = toType(v, TypeOutput.Number)
112
+ let ss = s
113
+ if ((vn > 28 && vn % 2 === 1) || vn === 1 || vn === 28) {
114
+ ss = Buffer.from(s)
115
+ ss[0] |= 0x80
116
+ }
117
+
118
+ return bufferToHex(Buffer.concat([setLengthLeft(r, 32), setLengthLeft(ss, 32)]))
119
+ }
120
+
121
+ /**
122
+ * Convert signature format of the `eth_sign` RPC method to signature parameters
123
+ * NOTE: all because of a bug in geth: https://github.com/ethereum/go-ethereum/issues/2053
124
+ * NOTE: After EIP1559, `v` could be `0` or `1` but this function assumes
125
+ * it's a signed message (EIP-191 or EIP-712) adding `27` at the end. Remove if needed.
126
+ */
127
+ export const fromRpcSig = function (sig: string): ECDSASignature {
128
+ const buf: Buffer = toBuffer(sig)
129
+
130
+ let r: Buffer
131
+ let s: Buffer
132
+ let v: number
133
+ if (buf.length >= 65) {
134
+ r = buf.slice(0, 32)
135
+ s = buf.slice(32, 64)
136
+ v = bufferToInt(buf.slice(64))
137
+ } else if (buf.length === 64) {
138
+ // Compact Signature Representation (https://eips.ethereum.org/EIPS/eip-2098)
139
+ r = buf.slice(0, 32)
140
+ s = buf.slice(32, 64)
141
+ v = bufferToInt(buf.slice(32, 33)) >> 7
142
+ s[0] &= 0x7f
143
+ } else {
144
+ throw new Error('Invalid signature length')
145
+ }
146
+
147
+ // support both versions of `eth_sign` responses
148
+ if (v < 27) {
149
+ v += 27
150
+ }
151
+
152
+ return {
153
+ v,
154
+ r,
155
+ s,
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Validate a ECDSA signature.
161
+ * NOTE: Accepts `v == 0 | v == 1` for EIP1559 transactions
162
+ * @param homesteadOrLater Indicates whether this is being used on either the homestead hardfork or a later one
163
+ */
164
+ export const isValidSignature = function (
165
+ v: BNLike,
166
+ r: Buffer,
167
+ s: Buffer,
168
+ homesteadOrLater: boolean = true,
169
+ chainId?: BNLike
170
+ ): boolean {
171
+ const SECP256K1_N_DIV_2 = new BN(
172
+ '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
173
+ 16
174
+ )
175
+ const SECP256K1_N = new BN('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 16)
176
+
177
+ if (r.length !== 32 || s.length !== 32) {
178
+ return false
179
+ }
180
+
181
+ if (!isValidSigRecovery(calculateSigRecovery(v, chainId))) {
182
+ return false
183
+ }
184
+
185
+ const rBN = new BN(r)
186
+ const sBN = new BN(s)
187
+
188
+ if (rBN.isZero() || rBN.gt(SECP256K1_N) || sBN.isZero() || sBN.gt(SECP256K1_N)) {
189
+ return false
190
+ }
191
+
192
+ if (homesteadOrLater && sBN.cmp(SECP256K1_N_DIV_2) === 1) {
193
+ return false
194
+ }
195
+
196
+ return true
197
+ }
198
+
199
+ /**
200
+ * Returns the keccak-256 hash of `message`, prefixed with the header used by the `eth_sign` RPC call.
201
+ * The output of this function can be fed into `ecsign` to produce the same signature as the `eth_sign`
202
+ * call for a given `message`, or fed to `ecrecover` along with a signature to recover the public key
203
+ * used to produce the signature.
204
+ */
205
+ export const hashPersonalMessage = function (message: Buffer): Buffer {
206
+ assertIsBuffer(message)
207
+ const prefix = Buffer.from(`\u0019Ethereum Signed Message:\n${message.length}`, 'utf-8')
208
+ return keccak(Buffer.concat([prefix, message]))
209
+ }
package/src/types.ts ADDED
@@ -0,0 +1,146 @@
1
+ import { BN } from './externals'
2
+ import { isHexString } from './internal'
3
+ import { Address } from './address'
4
+ import { unpadBuffer, toBuffer, ToBufferInputTypes } from './bytes'
5
+
6
+ /*
7
+ * A type that represents a BNLike input that can be converted to a BN.
8
+ */
9
+ export type BNLike = BN | PrefixedHexString | number | Buffer
10
+
11
+ /*
12
+ * A type that represents a BufferLike input that can be converted to a Buffer.
13
+ */
14
+ export type BufferLike =
15
+ | Buffer
16
+ | Uint8Array
17
+ | number[]
18
+ | number
19
+ | BN
20
+ | TransformableToBuffer
21
+ | PrefixedHexString
22
+
23
+ /*
24
+ * A type that represents a `0x`-prefixed hex string.
25
+ */
26
+ export type PrefixedHexString = string
27
+
28
+ /**
29
+ * A type that represents an Address-like value.
30
+ * To convert to address, use `new Address(toBuffer(value))`
31
+ */
32
+ export type AddressLike = Address | Buffer | PrefixedHexString
33
+
34
+ /*
35
+ * A type that represents an object that has a `toArray()` method.
36
+ */
37
+ export interface TransformableToArray {
38
+ toArray(): Uint8Array
39
+ toBuffer?(): Buffer
40
+ }
41
+
42
+ /*
43
+ * A type that represents an object that has a `toBuffer()` method.
44
+ */
45
+ export interface TransformableToBuffer {
46
+ toBuffer(): Buffer
47
+ toArray?(): Uint8Array
48
+ }
49
+
50
+ export type NestedUint8Array = Array<Uint8Array | NestedUint8Array>
51
+ export type NestedBufferArray = Array<Buffer | NestedBufferArray>
52
+
53
+ /**
54
+ * Convert BN to 0x-prefixed hex string.
55
+ */
56
+ export function bnToHex(value: BN): PrefixedHexString {
57
+ return `0x${value.toString(16)}`
58
+ }
59
+
60
+ /**
61
+ * Convert value from BN to an unpadded Buffer
62
+ * (useful for RLP transport)
63
+ * @param value value to convert
64
+ */
65
+ export function bnToUnpaddedBuffer(value: BN): Buffer {
66
+ // Using `bn.toArrayLike(Buffer)` instead of `bn.toBuffer()`
67
+ // for compatibility with browserify and similar tools
68
+ return unpadBuffer(value.toArrayLike(Buffer))
69
+ }
70
+
71
+ /**
72
+ * Deprecated alias for {@link bnToUnpaddedBuffer}
73
+ * @deprecated
74
+ */
75
+ export function bnToRlp(value: BN): Buffer {
76
+ return bnToUnpaddedBuffer(value)
77
+ }
78
+
79
+ /**
80
+ * Type output options
81
+ */
82
+ export enum TypeOutput {
83
+ Number,
84
+ BN,
85
+ Buffer,
86
+ PrefixedHexString,
87
+ }
88
+
89
+ export type TypeOutputReturnType = {
90
+ [TypeOutput.Number]: number
91
+ [TypeOutput.BN]: BN
92
+ [TypeOutput.Buffer]: Buffer
93
+ [TypeOutput.PrefixedHexString]: PrefixedHexString
94
+ }
95
+
96
+ /**
97
+ * Convert an input to a specified type.
98
+ * Input of null/undefined returns null/undefined regardless of the output type.
99
+ * @param input value to convert
100
+ * @param outputType type to output
101
+ */
102
+ export function toType<T extends TypeOutput>(input: null, outputType: T): null
103
+ export function toType<T extends TypeOutput>(input: undefined, outputType: T): undefined
104
+ export function toType<T extends TypeOutput>(
105
+ input: ToBufferInputTypes,
106
+ outputType: T
107
+ ): TypeOutputReturnType[T]
108
+ export function toType<T extends TypeOutput>(
109
+ input: ToBufferInputTypes,
110
+ outputType: T
111
+ ): TypeOutputReturnType[T] | undefined | null {
112
+ if (input === null) {
113
+ return null
114
+ }
115
+ if (input === undefined) {
116
+ return undefined
117
+ }
118
+
119
+ if (typeof input === 'string' && !isHexString(input)) {
120
+ throw new Error(`A string must be provided with a 0x-prefix, given: ${input}`)
121
+ } else if (typeof input === 'number' && !Number.isSafeInteger(input)) {
122
+ throw new Error(
123
+ 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
124
+ )
125
+ }
126
+
127
+ const output = toBuffer(input)
128
+
129
+ if (outputType === TypeOutput.Buffer) {
130
+ return output as TypeOutputReturnType[T]
131
+ } else if (outputType === TypeOutput.BN) {
132
+ return new BN(output) as TypeOutputReturnType[T]
133
+ } else if (outputType === TypeOutput.Number) {
134
+ const bn = new BN(output)
135
+ const max = new BN(Number.MAX_SAFE_INTEGER.toString())
136
+ if (bn.gt(max)) {
137
+ throw new Error(
138
+ 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative output type)'
139
+ )
140
+ }
141
+ return bn.toNumber() as TypeOutputReturnType[T]
142
+ } else {
143
+ // outputType === TypeOutput.PrefixedHexString
144
+ return `0x${output.toString('hex')}` as TypeOutputReturnType[T]
145
+ }
146
+ }