@ethereumjs/util
Advanced tools
Comparing version 9.0.1 to 9.0.2
@@ -17,3 +17,3 @@ import { bytesToHex as _bytesToUnprefixedHex } from 'ethereum-cryptography/utils.js'; | ||
*/ | ||
export declare const bytesToBigInt: (bytes: Uint8Array) => bigint; | ||
export declare const bytesToBigInt: (bytes: Uint8Array, littleEndian?: boolean) => bigint; | ||
/** | ||
@@ -45,3 +45,3 @@ * Converts a {@link Uint8Array} to a {@link number}. | ||
*/ | ||
export declare const bigIntToBytes: (num: bigint) => Uint8Array; | ||
export declare const bigIntToBytes: (num: bigint, littleEndian?: boolean) => Uint8Array; | ||
/** | ||
@@ -192,3 +192,2 @@ * Returns a Uint8Array filled with 0s. | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 4. | ||
* @return {number} The 32-bit integer read from the input Uint8Array. | ||
@@ -201,3 +200,2 @@ */ | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 8. | ||
* @return {bigint} The 64-bit bigint read from the input Uint8Array. | ||
@@ -204,0 +202,0 @@ */ |
@@ -14,5 +14,30 @@ "use strict"; | ||
exports.bytesToUnprefixedHex = utils_js_1.bytesToHex; | ||
// hexToBytes cache | ||
const hexToBytesMapFirstKey = {}; | ||
const hexToBytesMapSecondKey = {}; | ||
for (let i = 0; i < 16; i++) { | ||
const vSecondKey = i; | ||
const vFirstKey = i * 16; | ||
const key = i.toString(16).toLowerCase(); | ||
hexToBytesMapSecondKey[key] = vSecondKey; | ||
hexToBytesMapSecondKey[key.toUpperCase()] = vSecondKey; | ||
hexToBytesMapFirstKey[key] = vFirstKey; | ||
hexToBytesMapFirstKey[key.toUpperCase()] = vFirstKey; | ||
} | ||
/** | ||
* NOTE: only use this function if the string is even, and only consists of hex characters | ||
* If this is not the case, this function could return weird results | ||
* @deprecated | ||
*/ | ||
function _unprefixedHexToBytes(hex) { | ||
const byteLen = hex.length; | ||
const bytes = new Uint8Array(byteLen / 2); | ||
for (let i = 0; i < byteLen; i += 2) { | ||
bytes[i / 2] = hexToBytesMapFirstKey[hex[i]] + hexToBytesMapSecondKey[hex[i + 1]]; | ||
} | ||
return bytes; | ||
} | ||
/** | ||
* @deprecated | ||
*/ | ||
const unprefixedHexToBytes = (inp) => { | ||
@@ -23,3 +48,3 @@ if (inp.slice(0, 2) === '0x') { | ||
else { | ||
return (0, utils_js_1.hexToBytes)((0, internal_js_1.padToEven)(inp)); | ||
return _unprefixedHexToBytes((0, internal_js_1.padToEven)(inp)); | ||
} | ||
@@ -51,3 +76,6 @@ }; | ||
*/ | ||
const bytesToBigInt = (bytes) => { | ||
const bytesToBigInt = (bytes, littleEndian = false) => { | ||
if (littleEndian) { | ||
bytes.reverse(); | ||
} | ||
const hex = (0, exports.bytesToHex)(bytes); | ||
@@ -84,4 +112,4 @@ if (hex === '0x') { | ||
} | ||
if (!hex.startsWith('0x')) { | ||
throw new Error(`prefixed hex input should start with 0x, got ${hex.substring(0, 2)}`); | ||
if (!/^0x[0-9a-fA-F]*$/.test(hex)) { | ||
throw new Error(`Input must be a 0x-prefixed hexadecimal string, got ${hex}`); | ||
} | ||
@@ -92,9 +120,3 @@ hex = hex.slice(2); | ||
} | ||
const byteLen = hex.length / 2; | ||
const bytes = new Uint8Array(byteLen); | ||
for (let i = 0; i < byteLen; i++) { | ||
const byte = parseInt(hex.slice(i * 2, (i + 1) * 2), 16); | ||
bytes[i] = byte; | ||
} | ||
return bytes; | ||
return _unprefixedHexToBytes(hex); | ||
}; | ||
@@ -130,5 +152,6 @@ exports.hexToBytes = hexToBytes; | ||
*/ | ||
const bigIntToBytes = (num) => { | ||
const bigIntToBytes = (num, littleEndian = false) => { | ||
// eslint-disable-next-line @typescript-eslint/no-use-before-define | ||
return (0, exports.toBytes)('0x' + (0, internal_js_1.padToEven)(num.toString(16))); | ||
const bytes = (0, exports.toBytes)('0x' + (0, internal_js_1.padToEven)(num.toString(16))); | ||
return littleEndian ? bytes.reverse() : bytes; | ||
}; | ||
@@ -424,3 +447,2 @@ exports.bigIntToBytes = bigIntToBytes; | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 4. | ||
* @return {number} The 32-bit integer read from the input Uint8Array. | ||
@@ -430,6 +452,6 @@ */ | ||
if (bytes.length < 4) { | ||
throw new Error('The input Uint8Array must have at least 4 bytes.'); | ||
bytes = setLength(bytes, 4, littleEndian); | ||
} | ||
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); | ||
return dataView.getInt32(0, littleEndian); | ||
return dataView.getUint32(0, littleEndian); | ||
} | ||
@@ -441,3 +463,2 @@ exports.bytesToInt32 = bytesToInt32; | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 8. | ||
* @return {bigint} The 64-bit bigint read from the input Uint8Array. | ||
@@ -447,6 +468,6 @@ */ | ||
if (bytes.length < 8) { | ||
throw new Error('The input Uint8Array must have at least 8 bytes.'); | ||
bytes = setLength(bytes, 8, littleEndian); | ||
} | ||
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); | ||
return dataView.getBigInt64(0, littleEndian); | ||
return dataView.getBigUint64(0, littleEndian); | ||
} | ||
@@ -463,3 +484,3 @@ exports.bytesToBigInt64 = bytesToBigInt64; | ||
const dataView = new DataView(buffer); | ||
dataView.setInt32(0, value, littleEndian); | ||
dataView.setUint32(0, value, littleEndian); | ||
return new Uint8Array(buffer); | ||
@@ -477,3 +498,3 @@ } | ||
const dataView = new DataView(buffer); | ||
dataView.setBigInt64(0, value, littleEndian); | ||
dataView.setBigUint64(0, value, littleEndian); | ||
return new Uint8Array(buffer); | ||
@@ -480,0 +501,0 @@ } |
@@ -13,2 +13,10 @@ declare type rpcParams = { | ||
* @returns the `result` field from the JSON-RPC response | ||
* @example | ||
* ```ts | ||
* const provider = 'https://mainnet.infura.io/v3/...' | ||
* const params = { | ||
* method: 'eth_getBlockByNumber', | ||
* params: ['latest', false], | ||
* } | ||
* const block = await fetchFromProvider(provider, params) | ||
*/ | ||
@@ -15,0 +23,0 @@ export declare const fetchFromProvider: (url: string, params: rpcParams) => Promise<any>; |
@@ -12,2 +12,10 @@ "use strict"; | ||
* @returns the `result` field from the JSON-RPC response | ||
* @example | ||
* ```ts | ||
* const provider = 'https://mainnet.infura.io/v3/...' | ||
* const params = { | ||
* method: 'eth_getBlockByNumber', | ||
* params: ['latest', false], | ||
* } | ||
* const block = await fetchFromProvider(provider, params) | ||
*/ | ||
@@ -28,3 +36,13 @@ const fetchFromProvider = async (url, params) => { | ||
}); | ||
if (!res.ok) { | ||
throw new Error(`JSONRpcError: ${JSON.stringify({ | ||
method: params.method, | ||
status: res.status, | ||
message: await res.text().catch(() => { | ||
return 'Could not parse error message likely because of a network error'; | ||
}), | ||
}, null, 2)}`); | ||
} | ||
const json = await res.json(); | ||
// TODO we should check json.error here | ||
return json.result; | ||
@@ -31,0 +49,0 @@ }; |
@@ -13,2 +13,3 @@ export interface ECDSASignature { | ||
export declare function ecsign(msgHash: Uint8Array, privateKey: Uint8Array, chainId?: bigint): ECDSASignature; | ||
export declare function calculateSigRecovery(v: bigint, chainId?: bigint): bigint; | ||
/** | ||
@@ -15,0 +16,0 @@ * ECDSA public key recovery from signature. |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.hashPersonalMessage = exports.isValidSignature = exports.fromRpcSig = exports.toCompactSig = exports.toRpcSig = exports.ecrecover = exports.ecsign = void 0; | ||
exports.hashPersonalMessage = exports.isValidSignature = exports.fromRpcSig = exports.toCompactSig = exports.toRpcSig = exports.ecrecover = exports.calculateSigRecovery = exports.ecsign = void 0; | ||
const keccak_js_1 = require("ethereum-cryptography/keccak.js"); | ||
@@ -34,2 +34,3 @@ const secp256k1_js_1 = require("ethereum-cryptography/secp256k1.js"); | ||
} | ||
exports.calculateSigRecovery = calculateSigRecovery; | ||
function isValidSigRecovery(recovery) { | ||
@@ -36,0 +37,0 @@ return recovery === constants_js_1.BIGINT_0 || recovery === constants_js_1.BIGINT_1; |
@@ -17,3 +17,3 @@ import { bytesToHex as _bytesToUnprefixedHex } from 'ethereum-cryptography/utils.js'; | ||
*/ | ||
export declare const bytesToBigInt: (bytes: Uint8Array) => bigint; | ||
export declare const bytesToBigInt: (bytes: Uint8Array, littleEndian?: boolean) => bigint; | ||
/** | ||
@@ -45,3 +45,3 @@ * Converts a {@link Uint8Array} to a {@link number}. | ||
*/ | ||
export declare const bigIntToBytes: (num: bigint) => Uint8Array; | ||
export declare const bigIntToBytes: (num: bigint, littleEndian?: boolean) => Uint8Array; | ||
/** | ||
@@ -192,3 +192,2 @@ * Returns a Uint8Array filled with 0s. | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 4. | ||
* @return {number} The 32-bit integer read from the input Uint8Array. | ||
@@ -201,3 +200,2 @@ */ | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 8. | ||
* @return {bigint} The 64-bit bigint read from the input Uint8Array. | ||
@@ -204,0 +202,0 @@ */ |
import { getRandomBytesSync } from 'ethereum-cryptography/random.js'; | ||
// eslint-disable-next-line no-restricted-imports | ||
import { bytesToHex as _bytesToUnprefixedHex, hexToBytes as _unprefixedHexToBytes, } from 'ethereum-cryptography/utils.js'; | ||
import { bytesToHex as _bytesToUnprefixedHex } from 'ethereum-cryptography/utils.js'; | ||
import { assertIsArray, assertIsBytes, assertIsHexString } from './helpers.js'; | ||
@@ -11,5 +11,30 @@ import { isHexPrefixed, isHexString, padToEven, stripHexPrefix } from './internal.js'; | ||
export const bytesToUnprefixedHex = _bytesToUnprefixedHex; | ||
// hexToBytes cache | ||
const hexToBytesMapFirstKey = {}; | ||
const hexToBytesMapSecondKey = {}; | ||
for (let i = 0; i < 16; i++) { | ||
const vSecondKey = i; | ||
const vFirstKey = i * 16; | ||
const key = i.toString(16).toLowerCase(); | ||
hexToBytesMapSecondKey[key] = vSecondKey; | ||
hexToBytesMapSecondKey[key.toUpperCase()] = vSecondKey; | ||
hexToBytesMapFirstKey[key] = vFirstKey; | ||
hexToBytesMapFirstKey[key.toUpperCase()] = vFirstKey; | ||
} | ||
/** | ||
* NOTE: only use this function if the string is even, and only consists of hex characters | ||
* If this is not the case, this function could return weird results | ||
* @deprecated | ||
*/ | ||
function _unprefixedHexToBytes(hex) { | ||
const byteLen = hex.length; | ||
const bytes = new Uint8Array(byteLen / 2); | ||
for (let i = 0; i < byteLen; i += 2) { | ||
bytes[i / 2] = hexToBytesMapFirstKey[hex[i]] + hexToBytesMapSecondKey[hex[i + 1]]; | ||
} | ||
return bytes; | ||
} | ||
/** | ||
* @deprecated | ||
*/ | ||
export const unprefixedHexToBytes = (inp) => { | ||
@@ -45,3 +70,6 @@ if (inp.slice(0, 2) === '0x') { | ||
*/ | ||
export const bytesToBigInt = (bytes) => { | ||
export const bytesToBigInt = (bytes, littleEndian = false) => { | ||
if (littleEndian) { | ||
bytes.reverse(); | ||
} | ||
const hex = bytesToHex(bytes); | ||
@@ -76,4 +104,4 @@ if (hex === '0x') { | ||
} | ||
if (!hex.startsWith('0x')) { | ||
throw new Error(`prefixed hex input should start with 0x, got ${hex.substring(0, 2)}`); | ||
if (!/^0x[0-9a-fA-F]*$/.test(hex)) { | ||
throw new Error(`Input must be a 0x-prefixed hexadecimal string, got ${hex}`); | ||
} | ||
@@ -84,9 +112,3 @@ hex = hex.slice(2); | ||
} | ||
const byteLen = hex.length / 2; | ||
const bytes = new Uint8Array(byteLen); | ||
for (let i = 0; i < byteLen; i++) { | ||
const byte = parseInt(hex.slice(i * 2, (i + 1) * 2), 16); | ||
bytes[i] = byte; | ||
} | ||
return bytes; | ||
return _unprefixedHexToBytes(hex); | ||
}; | ||
@@ -119,5 +141,6 @@ /******************************************/ | ||
*/ | ||
export const bigIntToBytes = (num) => { | ||
export const bigIntToBytes = (num, littleEndian = false) => { | ||
// eslint-disable-next-line @typescript-eslint/no-use-before-define | ||
return toBytes('0x' + padToEven(num.toString(16))); | ||
const bytes = toBytes('0x' + padToEven(num.toString(16))); | ||
return littleEndian ? bytes.reverse() : bytes; | ||
}; | ||
@@ -394,3 +417,2 @@ /** | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 4. | ||
* @return {number} The 32-bit integer read from the input Uint8Array. | ||
@@ -400,6 +422,6 @@ */ | ||
if (bytes.length < 4) { | ||
throw new Error('The input Uint8Array must have at least 4 bytes.'); | ||
bytes = setLength(bytes, 4, littleEndian); | ||
} | ||
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); | ||
return dataView.getInt32(0, littleEndian); | ||
return dataView.getUint32(0, littleEndian); | ||
} | ||
@@ -410,3 +432,2 @@ /** | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 8. | ||
* @return {bigint} The 64-bit bigint read from the input Uint8Array. | ||
@@ -416,6 +437,6 @@ */ | ||
if (bytes.length < 8) { | ||
throw new Error('The input Uint8Array must have at least 8 bytes.'); | ||
bytes = setLength(bytes, 8, littleEndian); | ||
} | ||
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); | ||
return dataView.getBigInt64(0, littleEndian); | ||
return dataView.getBigUint64(0, littleEndian); | ||
} | ||
@@ -431,3 +452,3 @@ /** | ||
const dataView = new DataView(buffer); | ||
dataView.setInt32(0, value, littleEndian); | ||
dataView.setUint32(0, value, littleEndian); | ||
return new Uint8Array(buffer); | ||
@@ -444,3 +465,3 @@ } | ||
const dataView = new DataView(buffer); | ||
dataView.setBigInt64(0, value, littleEndian); | ||
dataView.setBigUint64(0, value, littleEndian); | ||
return new Uint8Array(buffer); | ||
@@ -447,0 +468,0 @@ } |
@@ -13,2 +13,10 @@ declare type rpcParams = { | ||
* @returns the `result` field from the JSON-RPC response | ||
* @example | ||
* ```ts | ||
* const provider = 'https://mainnet.infura.io/v3/...' | ||
* const params = { | ||
* method: 'eth_getBlockByNumber', | ||
* params: ['latest', false], | ||
* } | ||
* const block = await fetchFromProvider(provider, params) | ||
*/ | ||
@@ -15,0 +23,0 @@ export declare const fetchFromProvider: (url: string, params: rpcParams) => Promise<any>; |
@@ -9,2 +9,10 @@ /** | ||
* @returns the `result` field from the JSON-RPC response | ||
* @example | ||
* ```ts | ||
* const provider = 'https://mainnet.infura.io/v3/...' | ||
* const params = { | ||
* method: 'eth_getBlockByNumber', | ||
* params: ['latest', false], | ||
* } | ||
* const block = await fetchFromProvider(provider, params) | ||
*/ | ||
@@ -25,3 +33,13 @@ export const fetchFromProvider = async (url, params) => { | ||
}); | ||
if (!res.ok) { | ||
throw new Error(`JSONRpcError: ${JSON.stringify({ | ||
method: params.method, | ||
status: res.status, | ||
message: await res.text().catch(() => { | ||
return 'Could not parse error message likely because of a network error'; | ||
}), | ||
}, null, 2)}`); | ||
} | ||
const json = await res.json(); | ||
// TODO we should check json.error here | ||
return json.result; | ||
@@ -28,0 +46,0 @@ }; |
@@ -13,2 +13,3 @@ export interface ECDSASignature { | ||
export declare function ecsign(msgHash: Uint8Array, privateKey: Uint8Array, chainId?: bigint): ECDSASignature; | ||
export declare function calculateSigRecovery(v: bigint, chainId?: bigint): bigint; | ||
/** | ||
@@ -15,0 +16,0 @@ * ECDSA public key recovery from signature. |
@@ -22,3 +22,3 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js'; | ||
} | ||
function calculateSigRecovery(v, chainId) { | ||
export function calculateSigRecovery(v, chainId) { | ||
if (v === BIGINT_0 || v === BIGINT_1) | ||
@@ -25,0 +25,0 @@ return v; |
{ | ||
"name": "@ethereumjs/util", | ||
"version": "9.0.1", | ||
"version": "9.0.2", | ||
"description": "A collection of utility functions for Ethereum", | ||
@@ -82,3 +82,4 @@ "keywords": [ | ||
"docs:build": "npx typedoc --options typedoc.cjs", | ||
"examples": "ts-node ../../scripts/examples-runner.ts -- util", | ||
"examples": "tsx ../../scripts/examples-runner.ts -- util", | ||
"examples:build": "npx embedme README.md", | ||
"lint": "../../config/cli/lint.sh", | ||
@@ -94,4 +95,4 @@ "lint:diff": "../../config/cli/lint-diff.sh", | ||
"dependencies": { | ||
"@ethereumjs/rlp": "^5.0.1", | ||
"ethereum-cryptography": "^2.1.2" | ||
"@ethereumjs/rlp": "^5.0.2", | ||
"ethereum-cryptography": "^2.1.3" | ||
}, | ||
@@ -98,0 +99,0 @@ "devDependencies": {}, |
191
README.md
@@ -22,10 +22,155 @@ # @ethereumjs/util | ||
```js | ||
This package contains the following modules providing respective helper methods, classes and commonly re-used constants. | ||
All helpers are re-exported from the root level and deep imports are not necessary. So an import can be done like this: | ||
```ts | ||
import { hexToBytes, isValidChecksumAddress } from '@ethereumjs/util' | ||
``` | ||
isValidChecksumAddress('0x2F015C60E0be116B1f0CD534704Db9c92118FB6A') // true | ||
### Module: [account](src/account.ts) | ||
hexToBytes('0x342770c0') | ||
Class representing an `Account` and providing private/public key and address-related functionality (creation, validation, conversion). | ||
```ts | ||
// ./examples/account.ts | ||
import { Account } from '@ethereumjs/util' | ||
const account = Account.fromAccountData({ | ||
nonce: '0x02', | ||
balance: '0x0384', | ||
storageRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', | ||
codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', | ||
}) | ||
console.log(`Account with nonce=${account.nonce} and balance=${account.balance} created`) | ||
``` | ||
### Module: [address](src/address.ts) | ||
Class representing an Ethereum `Address` with instantiation helpers and validation methods. | ||
```ts | ||
// ./examples/address.ts | ||
import { Address } from '@ethereumjs/util' | ||
const address = Address.fromString('0x2f015c60e0be116b1f0cd534704db9c92118fb6a') | ||
console.log(`Ethereum address ${address.toString()} created`) | ||
``` | ||
### Module: [blobs](src/blobs.ts) | ||
Module providing helpers for 4844 blobs and versioned hashes. | ||
```ts | ||
// ./examples/blobs.ts | ||
import { bytesToHex, computeVersionedHash, getBlobs } from '@ethereumjs/util' | ||
const blobs = getBlobs('test input') | ||
console.log('Created the following blobs:') | ||
console.log(blobs) | ||
const commitment = new Uint8Array([1, 2, 3]) | ||
const blobCommitmentVersion = 0x01 | ||
const versionedHash = computeVersionedHash(commitment, blobCommitmentVersion) | ||
console.log(`Versioned hash ${bytesToHex(versionedHash)} computed`) | ||
``` | ||
### Module: [bytes](src/bytes.ts) | ||
Byte-related helper and conversion functions. | ||
```ts | ||
// ./examples/bytes.ts | ||
import { bytesToBigInt } from '@ethereumjs/util' | ||
const bytesValue = new Uint8Array([97]) | ||
const bigIntValue = bytesToBigInt(bytesValue) | ||
console.log(`Converted value: ${bigIntValue}`) | ||
``` | ||
### Module: [constants](src/constants.ts) | ||
Exposed constants (e.g. `KECCAK256_NULL_S` for string representation of Keccak-256 hash of null) | ||
```ts | ||
// ./examples/constants.ts | ||
import { BIGINT_2EXP96, KECCAK256_NULL_S } from '@ethereumjs/util' | ||
console.log(`The keccak-256 hash of null: ${KECCAK256_NULL_S}`) | ||
console.log(`BigInt constants (performance), e.g. BIGINT_2EXP96: ${BIGINT_2EXP96}`) | ||
``` | ||
### Module: [db](src/db.ts) | ||
DB interface for database abstraction (Blockchain, Trie), see e.g. [@ethereumjs/trie recipes](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/trie/recipes/level.ts)) for usage. | ||
### Module: [genesis](src/genesis.ts) | ||
Genesis related interfaces and helpers. | ||
### Module: [internal](src/internal.ts) | ||
Internalized simple helper methods like `isHexPrefixed`. Note that methods from this module might get deprectared in the future. | ||
### Module: [kzg](src/kzg.ts) | ||
KZG interface (used for 4844 blob txs), see [@ethereumjs/tx](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx/README.md#kzg-setup) README for main usage instructions. | ||
### Module: [mapDB](src/mapDB.ts) | ||
Simple map DB implementation using the `DB` interface (see above). | ||
### Module: [signature](src/signature.ts) | ||
Functionality for signing, signature validation, conversion, recovery. | ||
```ts | ||
// ./examples/signature.ts | ||
import { bytesToHex, ecrecover, hexToBytes } from '@ethereumjs/util' | ||
const chainId = BigInt(3) // Ropsten | ||
const echash = hexToBytes('0x82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28') | ||
const r = hexToBytes('0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9') | ||
const s = hexToBytes('0x129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66') | ||
const v = BigInt(41) | ||
const pubkey = ecrecover(echash, v, r, s, chainId) | ||
console.log(`Recovered public key ${bytesToHex(pubkey)} from valid signature values`) | ||
``` | ||
### Module: [types](src/types.ts) | ||
Various TypeScript types. Direct usage is not recommended, type structure might change in the future. | ||
### Module: [withdrawal](src/withdrawal.ts) | ||
Class representing an `EIP-4895` `Withdrawal` with different constructors as well as conversion and output helpers. | ||
```ts | ||
// ./examples/withdrawal.ts | ||
import { Withdrawal } from '@ethereumjs/util' | ||
const withdrawal = Withdrawal.fromWithdrawalData({ | ||
index: 0n, | ||
validatorIndex: 65535n, | ||
address: '0x0000000000000000000000000000000000000000', | ||
amount: 0n, | ||
}) | ||
console.log('Withdrawal object created:') | ||
console.log(withdrawal.toJSON()) | ||
``` | ||
## Browser | ||
@@ -43,32 +188,2 @@ | ||
### Modules | ||
- [account](src/account.ts) | ||
- Account class | ||
- Private/public key and address-related functionality (creation, validation, conversion) | ||
- [address](src/address.ts) | ||
- Address class and type | ||
- [blobs](src/blobs.ts) | ||
- Helpers for 4844 blobs and versioned hashes | ||
- [bytes](src/bytes.ts) | ||
- Byte-related helper and conversion functions | ||
- [constants](src/constants.ts) | ||
- Exposed constants (e.g. `KECCAK256_NULL_S` for string representation of Keccak-256 hash of null) | ||
- [db](src/db.ts) | ||
- DB interface for database abstraction (Blockchain, Trie) | ||
- [genesis](src/genesis.ts) | ||
- Genesis related interfaces and helpers | ||
- [internal](src/internal.ts) | ||
- Internalized helper methods | ||
- [kzg](src/kzg.ts) | ||
- KZG interface (used for 4844 blob txs) | ||
- [mapDB](src/mapDB.ts) | ||
- Simple map DB implementation using the `DB` interface | ||
- [signature](src/signature.ts) | ||
- Signing, signature validation, conversion, recovery | ||
- [types](src/types.ts) | ||
- Helpful TypeScript types | ||
- [withdrawal](src/withdrawal.ts) | ||
- Withdrawal class (EIP-4895) | ||
### Upgrade Helpers in bytes-Module | ||
@@ -80,3 +195,3 @@ | ||
```typescript | ||
```ts | ||
Buffer.alloc(97) // Allocate a Buffer with length 97 | ||
@@ -107,3 +222,3 @@ new Uint8Array(97) // Allocate a Uint8Array with length 97 | ||
```typescript | ||
```ts | ||
import { hexToBytes } from '@ethereumjs/util' | ||
@@ -118,3 +233,3 @@ ``` | ||
```typescript | ||
```ts | ||
import { EthereumJSClass } from '@ethereumjs/[PACKAGE_NAME]' | ||
@@ -125,3 +240,3 @@ ``` | ||
```typescript | ||
```ts | ||
const { EthereumJSClass } = require('@ethereumjs/[PACKAGE_NAME]') | ||
@@ -162,3 +277,3 @@ ``` | ||
```typescript | ||
```ts | ||
import { stripHexPrefix } from '@ethereumjs/util' | ||
@@ -165,0 +280,0 @@ ``` |
import { getRandomBytesSync } from 'ethereum-cryptography/random.js' | ||
// eslint-disable-next-line no-restricted-imports | ||
import { | ||
bytesToHex as _bytesToUnprefixedHex, | ||
hexToBytes as _unprefixedHexToBytes, | ||
} from 'ethereum-cryptography/utils.js' | ||
import { bytesToHex as _bytesToUnprefixedHex } from 'ethereum-cryptography/utils.js' | ||
@@ -20,5 +17,33 @@ import { assertIsArray, assertIsBytes, assertIsHexString } from './helpers.js' | ||
// hexToBytes cache | ||
const hexToBytesMapFirstKey: { [key: string]: number } = {} | ||
const hexToBytesMapSecondKey: { [key: string]: number } = {} | ||
for (let i = 0; i < 16; i++) { | ||
const vSecondKey = i | ||
const vFirstKey = i * 16 | ||
const key = i.toString(16).toLowerCase() | ||
hexToBytesMapSecondKey[key] = vSecondKey | ||
hexToBytesMapSecondKey[key.toUpperCase()] = vSecondKey | ||
hexToBytesMapFirstKey[key] = vFirstKey | ||
hexToBytesMapFirstKey[key.toUpperCase()] = vFirstKey | ||
} | ||
/** | ||
* NOTE: only use this function if the string is even, and only consists of hex characters | ||
* If this is not the case, this function could return weird results | ||
* @deprecated | ||
*/ | ||
function _unprefixedHexToBytes(hex: string): Uint8Array { | ||
const byteLen = hex.length | ||
const bytes = new Uint8Array(byteLen / 2) | ||
for (let i = 0; i < byteLen; i += 2) { | ||
bytes[i / 2] = hexToBytesMapFirstKey[hex[i]] + hexToBytesMapSecondKey[hex[i + 1]] | ||
} | ||
return bytes | ||
} | ||
/** | ||
* @deprecated | ||
*/ | ||
export const unprefixedHexToBytes = (inp: string) => { | ||
@@ -56,3 +81,6 @@ if (inp.slice(0, 2) === '0x') { | ||
*/ | ||
export const bytesToBigInt = (bytes: Uint8Array): bigint => { | ||
export const bytesToBigInt = (bytes: Uint8Array, littleEndian = false): bigint => { | ||
if (littleEndian) { | ||
bytes.reverse() | ||
} | ||
const hex = bytesToHex(bytes) | ||
@@ -89,4 +117,4 @@ if (hex === '0x') { | ||
if (!hex.startsWith('0x')) { | ||
throw new Error(`prefixed hex input should start with 0x, got ${hex.substring(0, 2)}`) | ||
if (!/^0x[0-9a-fA-F]*$/.test(hex)) { | ||
throw new Error(`Input must be a 0x-prefixed hexadecimal string, got ${hex}`) | ||
} | ||
@@ -99,10 +127,3 @@ | ||
} | ||
const byteLen = hex.length / 2 | ||
const bytes = new Uint8Array(byteLen) | ||
for (let i = 0; i < byteLen; i++) { | ||
const byte = parseInt(hex.slice(i * 2, (i + 1) * 2), 16) | ||
bytes[i] = byte | ||
} | ||
return bytes | ||
return _unprefixedHexToBytes(hex) | ||
} | ||
@@ -139,5 +160,7 @@ | ||
*/ | ||
export const bigIntToBytes = (num: bigint): Uint8Array => { | ||
export const bigIntToBytes = (num: bigint, littleEndian = false): Uint8Array => { | ||
// eslint-disable-next-line @typescript-eslint/no-use-before-define | ||
return toBytes('0x' + padToEven(num.toString(16))) | ||
const bytes = toBytes('0x' + padToEven(num.toString(16))) | ||
return littleEndian ? bytes.reverse() : bytes | ||
} | ||
@@ -456,3 +479,2 @@ | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 4. | ||
* @return {number} The 32-bit integer read from the input Uint8Array. | ||
@@ -462,6 +484,6 @@ */ | ||
if (bytes.length < 4) { | ||
throw new Error('The input Uint8Array must have at least 4 bytes.') | ||
bytes = setLength(bytes, 4, littleEndian) | ||
} | ||
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength) | ||
return dataView.getInt32(0, littleEndian) | ||
return dataView.getUint32(0, littleEndian) | ||
} | ||
@@ -473,3 +495,2 @@ | ||
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian. | ||
* @throws {Error} If the input Uint8Array has a length less than 8. | ||
* @return {bigint} The 64-bit bigint read from the input Uint8Array. | ||
@@ -479,6 +500,6 @@ */ | ||
if (bytes.length < 8) { | ||
throw new Error('The input Uint8Array must have at least 8 bytes.') | ||
bytes = setLength(bytes, 8, littleEndian) | ||
} | ||
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength) | ||
return dataView.getBigInt64(0, littleEndian) | ||
return dataView.getBigUint64(0, littleEndian) | ||
} | ||
@@ -495,3 +516,3 @@ | ||
const dataView = new DataView(buffer) | ||
dataView.setInt32(0, value, littleEndian) | ||
dataView.setUint32(0, value, littleEndian) | ||
return new Uint8Array(buffer) | ||
@@ -509,3 +530,3 @@ } | ||
const dataView = new DataView(buffer) | ||
dataView.setBigInt64(0, value, littleEndian) | ||
dataView.setBigUint64(0, value, littleEndian) | ||
return new Uint8Array(buffer) | ||
@@ -512,0 +533,0 @@ } |
@@ -14,2 +14,10 @@ type rpcParams = { | ||
* @returns the `result` field from the JSON-RPC response | ||
* @example | ||
* ```ts | ||
* const provider = 'https://mainnet.infura.io/v3/...' | ||
* const params = { | ||
* method: 'eth_getBlockByNumber', | ||
* params: ['latest', false], | ||
* } | ||
* const block = await fetchFromProvider(provider, params) | ||
*/ | ||
@@ -31,3 +39,19 @@ export const fetchFromProvider = async (url: string, params: rpcParams) => { | ||
}) | ||
if (!res.ok) { | ||
throw new Error( | ||
`JSONRpcError: ${JSON.stringify( | ||
{ | ||
method: params.method, | ||
status: res.status, | ||
message: await res.text().catch(() => { | ||
return 'Could not parse error message likely because of a network error' | ||
}), | ||
}, | ||
null, | ||
2 | ||
)}` | ||
) | ||
} | ||
const json = await res.json() | ||
// TODO we should check json.error here | ||
return json.result | ||
@@ -34,0 +58,0 @@ } |
@@ -53,3 +53,3 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js' | ||
function calculateSigRecovery(v: bigint, chainId?: bigint): bigint { | ||
export function calculateSigRecovery(v: bigint, chainId?: bigint): bigint { | ||
if (v === BIGINT_0 || v === BIGINT_1) return v | ||
@@ -56,0 +56,0 @@ |
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
551688
8370
293
Updated@ethereumjs/rlp@^5.0.2
Updatedethereum-cryptography@^2.1.3