Socket
Socket
Sign inDemoInstall

@nomicfoundation/ethereumjs-util

Package Overview
Dependencies
Maintainers
4
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nomicfoundation/ethereumjs-util - npm Package Compare versions

Comparing version 9.0.3 to 9.0.4

dist/cjs/account.d.ts

34

package.json
{
"name": "@nomicfoundation/ethereumjs-util",
"version": "9.0.3",
"version": "9.0.4",
"description": "A collection of utility functions for Ethereum",

@@ -64,4 +64,5 @@ "keywords": [

],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "commonjs",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"files": [

@@ -74,25 +75,30 @@ "dist",

"clean": "../../config/cli/clean-package.sh",
"coverage": "../../config/cli/coverage.sh",
"docs:build": "npx typedoc --options typedoc.js",
"coverage": "DEBUG=ethjs npx vitest run --coverage.enabled --coverage.reporter=lcov",
"docs:build": "npx typedoc --options typedoc.cjs",
"examples": "tsx ../../scripts/examples-runner.ts -- util",
"examples:build": "npx embedme README.md",
"lint": "../../config/cli/lint.sh",
"lint:diff": "../../config/cli/lint-diff.sh",
"lint:fix": "../../config/cli/lint-fix.sh",
"tape": "tape -r ts-node/register",
"test": "npm run test:node && npm run test:browser",
"test:browser": "karma start karma.conf.js",
"test:node": "npm run tape -- test/*.spec.ts",
"test:browser": "npx vitest run --config=./vitest.config.browser.ts --browser.name=chrome --browser.headless",
"test:node": "npx vitest run",
"tsc": "../../config/cli/ts-compile.sh"
},
"dependencies": {
"@chainsafe/ssz": "^0.10.0",
"@nomicfoundation/ethereumjs-rlp": "5.0.3",
"@nomicfoundation/ethereumjs-rlp": "5.0.4",
"ethereum-cryptography": "0.1.3"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
"@types/secp256k1": "^4.0.1"
"devDependencies": {},
"peerDependencies": {
"c-kzg": "^2.1.2"
},
"peerDependenciesMeta": {
"c-kzg": {
"optional": true
}
},
"engines": {
"node": ">=14"
"node": ">=18"
}
}

@@ -9,3 +9,4 @@ # @ethereumjs/util

A collection of utility functions for Ethereum. It can be used in Node.js and in the browser with [browserify](http://browserify.org/).
| A collection of utility functions for Ethereum. |
| ----------------------------------------------- |

@@ -22,11 +23,161 @@ ## Installation

```js
import assert from 'assert'
import { isValidChecksumAddress, unpadBuffer } from '@ethereumjs/util'
This package contains the following modules providing respective helper methods, classes and commonly re-used constants.
assert.ok(isValidChecksumAddress('0x2F015C60E0be116B1f0CD534704Db9c92118FB6A'))
All helpers are re-exported from the root level and deep imports are not necessary. So an import can be done like this:
assert.ok(unpadBuffer(Buffer.from('000000006600', 'hex')).equals(Buffer.from('6600', 'hex')))
```ts
import { hexToBytes, isValidChecksumAddress } from '@ethereumjs/util'
```
### Module: [account](src/account.ts)
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
With the breaking release round in Summer 2023 we have added hybrid ESM/CJS builds for all our libraries (see section below) and have eliminated many of the caveats which had previously prevented a frictionless browser usage.
It is now easily possible to run a browser build of one of the EthereumJS libraries within a modern browser using the provided ESM build. For a setup example see [./examples/browser.html](./examples/browser.html).
## API

@@ -38,28 +189,65 @@

### Modules
### Upgrade Helpers in bytes-Module
- [account](src/account.ts)
- Account class
- Private/public key and address-related functionality (creation, validation, conversion)
- [address](src/address.ts)
- Address class and type
- [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
- hash
- This module has been removed with `v8`, please use [ethereum-cryptography](https://github.com/ethereum/js-ethereum-cryptography) directly instead
- [signature](src/signature.ts)
- Signing, signature validation, conversion, recovery
- [types](src/types.ts)
- Helpful TypeScript types
- [internal](src/internal.ts)
- Internalized helper methods
- [withdrawal](src/withdrawal.ts)
- Withdrawal class (EIP-4895)
Depending on the extend of `Buffer` usage within your own libraries and other planning considerations, there are the two upgrade options to do the switch to `Uint8Array` yourself or keep `Buffer` and do transitions for input and output values.
We have updated the `@ethereumjs/util` `bytes` module with helpers for the most common conversions:
```ts
Buffer.alloc(97) // Allocate a Buffer with length 97
new Uint8Array(97) // Allocate a Uint8Array with length 97
Buffer.from('342770c0', 'hex') // Convert a hex string to a Buffer
hexToBytes('0x342770c0') // Convert a prefixed hex string to a Uint8Array, Util.hexToBytes()
`0x${myBuffer.toString('hex')}` // Convert a Buffer to a prefixed hex string
bytesToHex(myUint8Array) // Convert a Uint8Array to a prefixed hex string
intToBuffer(9) // Convert an integer to a Buffer, old (removed)
intToBytes(9) // Convert an integer to a Uint8Array, Util.intToBytes()
bytesToInt(myUint8Array) // Convert a Uint8Array to an integer, Util.bytesToInt()
bigIntToBytes(myBigInt) // Convert a BigInt to a Uint8Array, Util.bigIntToBytes()
bytesToBigInt(myUint8Array) // Convert a Uint8Array to a BigInt, Util.bytesToInt()
utf8ToBytes(myUtf8String) // Converts a UTF-8 string to a Uint8Array, Util.utf8ToBytes()
bytesToUtf8(myUint8Array) // Converts a Uint8Array to a UTF-8 string, Util.bytesToUtf8()
toBuffer(v: ToBufferInputTypes) // Converts various byte compatible types to Buffer, old (removed)
toBytes(v: ToBytesInputTypes) // Converts various byte compatible types to Uint8Array, Util.toBytes()
```
Helper methods can be imported like this:
```ts
import { hexToBytes } from '@ethereumjs/util'
```
### Hybrid CJS/ESM Builds
With the breaking releases from Summer 2023 we have started to ship our libraries with both CommonJS (`cjs` folder) and ESM builds (`esm` folder), see `package.json` for the detailed setup.
If you use an ES6-style `import` in your code files from the ESM build will be used:
```ts
import { EthereumJSClass } from '@ethereumjs/[PACKAGE_NAME]'
```
If you use Node.js specific `require`, the CJS build will be used:
```ts
const { EthereumJSClass } = require('@ethereumjs/[PACKAGE_NAME]')
```
Using ESM will give you additional advantages over CJS beyond browser usage like static code analysis / Tree Shaking which CJS can not provide.
### Buffer -> Uint8Array
With the breaking releases from Summer 2023 we have removed all Node.js specific `Buffer` usages from our libraries and replace these with [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) representations, which are available both in Node.js and the browser (`Buffer` is a subclass of `Uint8Array`).
We have converted existing Buffer conversion methods to Uint8Array conversion methods in the [@ethereumjs/util](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/util) `bytes` module, see the respective README section for guidance.
### BigInt Support
Starting with v8 the usage of [BN.js](https://github.com/indutny/bn.js/) for big numbers has been removed from the library and replaced with the usage of the native JS [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) data type (introduced in `ES2020`).
Starting with Util v8 the usage of [BN.js](https://github.com/indutny/bn.js/) for big numbers has been removed from the library and replaced with the usage of the native JS [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) data type (introduced in `ES2020`).

@@ -86,3 +274,3 @@ Please note that number-related API signatures have changed along with this version update and the minimal build target has been updated to `ES2020`.

```typescript
```ts
import { stripHexPrefix } from '@ethereumjs/util'

@@ -89,0 +277,0 @@ ```

import { RLP } from '@nomicfoundation/ethereumjs-rlp'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import {

@@ -11,26 +11,26 @@ privateKeyVerify,

import {
arrToBufArr,
bigIntToUnpaddedBuffer,
bufArrToArr,
bufferToBigInt,
bufferToHex,
toBuffer,
bigIntToUnpaddedBytes,
bytesToBigInt,
bytesToHex,
concatBytes,
equalsBytes,
hexToBytes,
toBytes,
utf8ToBytes,
zeros,
} from './bytes'
import { KECCAK256_NULL, KECCAK256_RLP } from './constants'
import { assertIsBuffer, assertIsHexString, assertIsString } from './helpers'
import { stripHexPrefix } from './internal'
} from './bytes.js'
import { BIGINT_0, KECCAK256_NULL, KECCAK256_RLP } from './constants.js'
import { assertIsBytes, assertIsHexString, assertIsString } from './helpers.js'
import { stripHexPrefix } from './internal.js'
import type { BigIntLike, BufferLike } from './types'
import type { BigIntLike, BytesLike } from './types.js'
const _0n = BigInt(0)
export interface AccountData {
nonce?: BigIntLike
balance?: BigIntLike
storageRoot?: BufferLike
codeHash?: BufferLike
storageRoot?: BytesLike
codeHash?: BytesLike
}
export type AccountBodyBuffer = [Buffer, Buffer, Buffer | Uint8Array, Buffer | Uint8Array]
export type AccountBodyBytes = [Uint8Array, Uint8Array, Uint8Array, Uint8Array]

@@ -40,4 +40,4 @@ export class Account {

balance: bigint
storageRoot: Buffer
codeHash: Buffer
storageRoot: Uint8Array
codeHash: Uint8Array

@@ -48,11 +48,11 @@ static fromAccountData(accountData: AccountData) {

return new Account(
nonce !== undefined ? bufferToBigInt(toBuffer(nonce)) : undefined,
balance !== undefined ? bufferToBigInt(toBuffer(balance)) : undefined,
storageRoot !== undefined ? toBuffer(storageRoot) : undefined,
codeHash !== undefined ? toBuffer(codeHash) : undefined
nonce !== undefined ? bytesToBigInt(toBytes(nonce)) : undefined,
balance !== undefined ? bytesToBigInt(toBytes(balance)) : undefined,
storageRoot !== undefined ? toBytes(storageRoot) : undefined,
codeHash !== undefined ? toBytes(codeHash) : undefined
)
}
public static fromRlpSerializedAccount(serialized: Buffer) {
const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized)) as Uint8Array[]) as Buffer[]
public static fromRlpSerializedAccount(serialized: Uint8Array) {
const values = RLP.decode(serialized) as Uint8Array[]

@@ -66,6 +66,6 @@ if (!Array.isArray(values)) {

public static fromValuesArray(values: Buffer[]) {
public static fromValuesArray(values: Uint8Array[]) {
const [nonce, balance, storageRoot, codeHash] = values
return new Account(bufferToBigInt(nonce), bufferToBigInt(balance), storageRoot, codeHash)
return new Account(bytesToBigInt(nonce), bytesToBigInt(balance), storageRoot, codeHash)
}

@@ -77,3 +77,8 @@

*/
constructor(nonce = _0n, balance = _0n, storageRoot = KECCAK256_RLP, codeHash = KECCAK256_NULL) {
constructor(
nonce = BIGINT_0,
balance = BIGINT_0,
storageRoot = KECCAK256_RLP,
codeHash = KECCAK256_NULL
) {
this.nonce = nonce

@@ -88,6 +93,6 @@ this.balance = balance

private _validate() {
if (this.nonce < _0n) {
if (this.nonce < BIGINT_0) {
throw new Error('nonce must be greater than zero')
}
if (this.balance < _0n) {
if (this.balance < BIGINT_0) {
throw new Error('balance must be greater than zero')

@@ -104,8 +109,8 @@ }

/**
* Returns a Buffer Array of the raw Buffers for the account, in order.
* Returns an array of Uint8Arrays of the raw bytes for the account, in order.
*/
raw(): Buffer[] {
raw(): Uint8Array[] {
return [
bigIntToUnpaddedBuffer(this.nonce),
bigIntToUnpaddedBuffer(this.balance),
bigIntToUnpaddedBytes(this.nonce),
bigIntToUnpaddedBytes(this.balance),
this.storageRoot,

@@ -117,6 +122,6 @@ this.codeHash,

/**
* Returns the RLP serialization of the account as a `Buffer`.
* Returns the RLP serialization of the account as a `Uint8Array`.
*/
serialize(): Buffer {
return Buffer.from(RLP.encode(bufArrToArr(this.raw())))
serialize(): Uint8Array {
return RLP.encode(this.raw())
}

@@ -128,3 +133,3 @@

isContract(): boolean {
return !this.codeHash.equals(KECCAK256_NULL)
return !equalsBytes(this.codeHash, KECCAK256_NULL)
}

@@ -138,3 +143,7 @@

isEmpty(): boolean {
return this.balance === _0n && this.nonce === _0n && this.codeHash.equals(KECCAK256_NULL)
return (
this.balance === BIGINT_0 &&
this.nonce === BIGINT_0 &&
equalsBytes(this.codeHash, KECCAK256_NULL)
)
}

@@ -177,8 +186,8 @@ }

if (eip1191ChainId !== undefined) {
const chainId = bufferToBigInt(toBuffer(eip1191ChainId))
const chainId = bytesToBigInt(toBytes(eip1191ChainId))
prefix = chainId.toString() + '0x'
}
const buf = Buffer.from(prefix + address, 'utf8')
const hash = keccak256(buf).toString('hex')
const bytes = utf8ToBytes(prefix + address)
const hash = bytesToHex(keccak256(Buffer.from(bytes))).slice(2)
let ret = '0x'

@@ -214,16 +223,14 @@

*/
export const generateAddress = function (from: Buffer, nonce: Buffer): Buffer {
assertIsBuffer(from)
assertIsBuffer(nonce)
export const generateAddress = function (from: Uint8Array, nonce: Uint8Array): Uint8Array {
assertIsBytes(from)
assertIsBytes(nonce)
if (bufferToBigInt(nonce) === BigInt(0)) {
if (bytesToBigInt(nonce) === BIGINT_0) {
// in RLP we want to encode null in the case of zero nonce
// read the RLP documentation for an answer if you dare
return Buffer.from(keccak256(arrToBufArr(RLP.encode(bufArrToArr([from, null] as any))))).slice(
-20
)
return keccak256(Buffer.from(RLP.encode([from, Uint8Array.from([])]))).subarray(-20)
}
// Only take the lower 160bits of the hash
return Buffer.from(keccak256(arrToBufArr(RLP.encode(bufArrToArr([from, nonce]))))).slice(-20)
return keccak256(Buffer.from(RLP.encode([from, nonce]))).subarray(-20)
}

@@ -237,6 +244,10 @@

*/
export const generateAddress2 = function (from: Buffer, salt: Buffer, initCode: Buffer): Buffer {
assertIsBuffer(from)
assertIsBuffer(salt)
assertIsBuffer(initCode)
export const generateAddress2 = function (
from: Uint8Array,
salt: Uint8Array,
initCode: Uint8Array
): Uint8Array {
assertIsBytes(from)
assertIsBytes(salt)
assertIsBytes(initCode)

@@ -251,6 +262,6 @@ if (from.length !== 20) {

const address = keccak256(
Buffer.concat([Buffer.from('ff', 'hex'), from, salt, keccak256(initCode)])
Buffer.from(concatBytes(hexToBytes('0xff'), from, salt, keccak256(Buffer.from(initCode))))
)
return toBuffer(address).slice(-20)
return address.subarray(-20)
}

@@ -261,3 +272,3 @@

*/
export const isValidPrivate = function (privateKey: Buffer): boolean {
export const isValidPrivate = function (privateKey: Uint8Array): boolean {
try {

@@ -276,4 +287,4 @@ return privateKeyVerify(privateKey)

*/
export const isValidPublic = function (publicKey: Buffer, sanitize: boolean = false): boolean {
assertIsBuffer(publicKey)
export const isValidPublic = function (publicKey: Uint8Array, sanitize: boolean = false): boolean {
assertIsBytes(publicKey)
if (publicKey.length === 64) {

@@ -297,4 +308,4 @@ // Convert to SEC1 for secp256k1

*/
export const pubToAddress = function (pubKey: Buffer, sanitize: boolean = false): Buffer {
assertIsBuffer(pubKey)
export const pubToAddress = function (pubKey: Uint8Array, sanitize: boolean = false): Uint8Array {
assertIsBytes(pubKey)
if (sanitize && pubKey.length !== 64) {

@@ -307,3 +318,3 @@ pubKey = Buffer.from(publicKeyConvert(pubKey, false).slice(1))

// Only take the lower 160bits of the hash
return Buffer.from(keccak256(pubKey)).slice(-20)
return Buffer.from(keccak256(Buffer.from(pubKey))).slice(-20)
}

@@ -316,4 +327,4 @@ export const publicToAddress = pubToAddress

*/
export const privateToPublic = function (privateKey: Buffer): Buffer {
assertIsBuffer(privateKey)
export const privateToPublic = function (privateKey: Uint8Array): Uint8Array {
assertIsBytes(privateKey)
// skip the type flag and use the X, Y points

@@ -327,3 +338,3 @@ return Buffer.from(publicKeyCreate(privateKey, false)).slice(1)

*/
export const privateToAddress = function (privateKey: Buffer): Buffer {
export const privateToAddress = function (privateKey: Uint8Array): Uint8Array {
return publicToAddress(privateToPublic(privateKey))

@@ -335,4 +346,4 @@ }

*/
export const importPublic = function (publicKey: Buffer): Buffer {
assertIsBuffer(publicKey)
export const importPublic = function (publicKey: Uint8Array): Uint8Array {
assertIsBytes(publicKey)
if (publicKey.length !== 64) {

@@ -350,3 +361,3 @@ publicKey = Buffer.from(publicKeyConvert(publicKey, false).slice(1))

const addr = zeros(addressLength)
return bufferToHex(addr)
return bytesToHex(addr)
}

@@ -368,3 +379,3 @@

export function accountBodyFromSlim(body: AccountBodyBuffer) {
export function accountBodyFromSlim(body: AccountBodyBytes) {
const [nonce, balance, storageRoot, codeHash] = body

@@ -374,4 +385,4 @@ return [

balance,
arrToBufArr(storageRoot).length === 0 ? KECCAK256_RLP : storageRoot,
arrToBufArr(codeHash).length === 0 ? KECCAK256_NULL : codeHash,
storageRoot.length === 0 ? KECCAK256_RLP : storageRoot,
codeHash.length === 0 ? KECCAK256_NULL : codeHash,
]

@@ -381,3 +392,3 @@ }

const emptyUint8Arr = new Uint8Array(0)
export function accountBodyToSlim(body: AccountBodyBuffer) {
export function accountBodyToSlim(body: AccountBodyBytes) {
const [nonce, balance, storageRoot, codeHash] = body

@@ -387,4 +398,4 @@ return [

balance,
arrToBufArr(storageRoot).equals(KECCAK256_RLP) ? emptyUint8Arr : storageRoot,
arrToBufArr(codeHash).equals(KECCAK256_NULL) ? emptyUint8Arr : codeHash,
equalsBytes(storageRoot, KECCAK256_RLP) ? emptyUint8Arr : storageRoot,
equalsBytes(codeHash, KECCAK256_NULL) ? emptyUint8Arr : codeHash,
]

@@ -395,8 +406,8 @@ }

* Converts a slim account (per snap protocol spec) to the RLP encoded version of the account
* @param body Array of 4 Buffer-like items to represent the account
* @param body Array of 4 Uint8Array-like items to represent the account
* @returns RLP encoded version of the account
*/
export function accountBodyToRLP(body: AccountBodyBuffer, couldBeSlim = true) {
export function accountBodyToRLP(body: AccountBodyBytes, couldBeSlim = true) {
const accountBody = couldBeSlim ? accountBodyFromSlim(body) : body
return arrToBufArr(RLP.encode(accountBody))
return RLP.encode(accountBody)
}

@@ -7,4 +7,5 @@ import {

pubToAddress,
} from './account'
import { bigIntToBuffer, bufferToBigInt, toBuffer, zeros } from './bytes'
} from './account.js'
import { bigIntToBytes, bytesToBigInt, bytesToHex, equalsBytes, toBytes, zeros } from './bytes.js'
import { BIGINT_0 } from './constants.js'

@@ -15,9 +16,9 @@ /**

export class Address {
public readonly buf: Buffer
public readonly bytes: Uint8Array
constructor(buf: Buffer) {
if (buf.length !== 20) {
constructor(bytes: Uint8Array) {
if (bytes.length !== 20) {
throw new Error('Invalid address length')
}
this.buf = buf
this.bytes = bytes
}

@@ -40,3 +41,3 @@

}
return new Address(toBuffer(str))
return new Address(toBytes(str))
}

@@ -48,8 +49,8 @@

*/
static fromPublicKey(pubKey: Buffer): Address {
if (!Buffer.isBuffer(pubKey)) {
throw new Error('Public key should be Buffer')
static fromPublicKey(pubKey: Uint8Array): Address {
if (!(pubKey instanceof Uint8Array)) {
throw new Error('Public key should be Uint8Array')
}
const buf = pubToAddress(pubKey)
return new Address(buf)
const bytes = pubToAddress(pubKey)
return new Address(bytes)
}

@@ -61,8 +62,8 @@

*/
static fromPrivateKey(privateKey: Buffer): Address {
if (!Buffer.isBuffer(privateKey)) {
throw new Error('Private key should be Buffer')
static fromPrivateKey(privateKey: Uint8Array): Address {
if (!(privateKey instanceof Uint8Array)) {
throw new Error('Private key should be Uint8Array')
}
const buf = privateToAddress(privateKey)
return new Address(buf)
const bytes = privateToAddress(privateKey)
return new Address(bytes)
}

@@ -79,3 +80,3 @@

}
return new Address(generateAddress(from.buf, bigIntToBuffer(nonce)))
return new Address(generateAddress(from.bytes, bigIntToBytes(nonce)))
}

@@ -89,10 +90,10 @@

*/
static generate2(from: Address, salt: Buffer, initCode: Buffer): Address {
if (!Buffer.isBuffer(salt)) {
throw new Error('Expected salt to be a Buffer')
static generate2(from: Address, salt: Uint8Array, initCode: Uint8Array): Address {
if (!(salt instanceof Uint8Array)) {
throw new Error('Expected salt to be a Uint8Array')
}
if (!Buffer.isBuffer(initCode)) {
throw new Error('Expected initCode to be a Buffer')
if (!(initCode instanceof Uint8Array)) {
throw new Error('Expected initCode to be a Uint8Array')
}
return new Address(generateAddress2(from.buf, salt, initCode))
return new Address(generateAddress2(from.bytes, salt, initCode))
}

@@ -104,3 +105,3 @@

equals(address: Address): boolean {
return this.buf.equals(address.buf)
return equalsBytes(this.bytes, address.bytes)
}

@@ -120,4 +121,4 @@

isPrecompileOrSystemAddress(): boolean {
const address = bufferToBigInt(this.buf)
const rangeMin = BigInt(0)
const address = bytesToBigInt(this.bytes)
const rangeMin = BIGINT_0
const rangeMax = BigInt('0xffff')

@@ -131,11 +132,11 @@ return address >= rangeMin && address <= rangeMax

toString(): string {
return '0x' + this.buf.toString('hex')
return bytesToHex(this.bytes)
}
/**
* Returns Buffer representation of address.
* Returns a new Uint8Array representation of address.
*/
toBuffer(): Buffer {
return Buffer.from(this.buf)
toBytes(): Uint8Array {
return new Uint8Array(this.bytes)
}
}

@@ -1,19 +0,153 @@

import { assertIsArray, assertIsBuffer, assertIsHexString } from './helpers'
import { isHexPrefixed, isHexString, padToEven, stripHexPrefix } from './internal'
import { getRandomBytesSync } from 'ethereum-cryptography/random.js'
import type {
NestedBufferArray,
NestedUint8Array,
PrefixedHexString,
TransformableToArray,
TransformableToBuffer,
TransformabletoBytes,
} from './types'
import { assertIsArray, assertIsBytes, assertIsHexString } from './helpers.js'
import { isHexPrefixed, isHexString, padToEven, stripHexPrefix } from './internal.js'
import type { PrefixedHexString, TransformabletoBytes } from './types.js'
const BIGINT_0 = BigInt(0)
function isBytes(a: unknown): a is Uint8Array {
return (
a instanceof Uint8Array ||
// eslint-disable-next-line eqeqeq
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')
)
}
const hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'))
export function _bytesToUnprefixedHex(bytes: Uint8Array): string {
if (!isBytes(bytes)) throw new Error('Uint8Array expected')
// pre-caching improves the speed 6x
let hex = ''
for (let i = 0; i < bytes.length; i++) {
hex += hexes[bytes[i]]
}
return hex
}
/**
* Converts a `Number` into a hex `String`
* @param {Number} i
* @return {String}
* @deprecated
*/
export const intToHex = function (i: number) {
export const bytesToUnprefixedHex = _bytesToUnprefixedHex
// 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) => {
if (inp.slice(0, 2) === '0x') {
throw new Error('hex string is prefixed with 0x, should be unprefixed')
} else {
return _unprefixedHexToBytes(padToEven(inp))
}
}
/**************** Borrowed from @chainsafe/ssz */
// Caching this info costs about ~1000 bytes and speeds up toHexString() by x6
const hexByByte = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'))
export const bytesToHex = (bytes: Uint8Array): string => {
let hex = '0x'
if (bytes === undefined || bytes.length === 0) return hex
for (const byte of bytes) {
hex += hexByByte[byte]
}
return hex
}
// BigInt cache for the numbers 0 - 256*256-1 (two-byte bytes)
const BIGINT_CACHE: bigint[] = []
for (let i = 0; i <= 256 * 256 - 1; i++) {
BIGINT_CACHE[i] = BigInt(i)
}
/**
* Converts a {@link Uint8Array} to a {@link bigint}
* @param {Uint8Array} bytes the bytes to convert
* @returns {bigint}
*/
export const bytesToBigInt = (bytes: Uint8Array, littleEndian = false): bigint => {
if (littleEndian) {
bytes.reverse()
}
const hex = bytesToHex(bytes)
if (hex === '0x') {
return BIGINT_0
}
if (hex.length === 4) {
// If the byte length is 1 (this is faster than checking `bytes.length === 1`)
return BIGINT_CACHE[bytes[0]]
}
if (hex.length === 6) {
return BIGINT_CACHE[bytes[0] * 256 + bytes[1]]
}
return BigInt(hex)
}
/**
* Converts a {@link Uint8Array} to a {@link number}.
* @param {Uint8Array} bytes the bytes to convert
* @return {number}
* @throws If the input number exceeds 53 bits.
*/
export const bytesToInt = (bytes: Uint8Array): number => {
const res = Number(bytesToBigInt(bytes))
if (!Number.isSafeInteger(res)) throw new Error('Number exceeds 53 bits')
return res
}
export const hexToBytes = (hex: string): Uint8Array => {
if (typeof hex !== 'string') {
throw new Error(`hex argument type ${typeof hex} must be of type string`)
}
if (!/^0x[0-9a-fA-F]*$/.test(hex)) {
throw new Error(`Input must be a 0x-prefixed hexadecimal string, got ${hex}`)
}
hex = hex.slice(2)
if (hex.length % 2 !== 0) {
hex = padToEven(hex)
}
return _unprefixedHexToBytes(hex)
}
/******************************************/
/**
* Converts a {@link number} into a {@link PrefixedHexString}
* @param {number} i
* @return {PrefixedHexString}
*/
export const intToHex = (i: number): PrefixedHexString => {
if (!Number.isSafeInteger(i) || i < 0) {

@@ -26,9 +160,9 @@ throw new Error(`Received an invalid integer type: ${i}`)

/**
* Converts an `Number` to a `Buffer`
* Converts an {@link number} to a {@link Uint8Array}
* @param {Number} i
* @return {Buffer}
* @return {Uint8Array}
*/
export const intToBuffer = function (i: number) {
export const intToBytes = (i: number): Uint8Array => {
const hex = intToHex(i)
return Buffer.from(padToEven(hex.slice(2)), 'hex')
return hexToBytes(hex)
}

@@ -41,37 +175,37 @@

*/
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
}
/**
* Returns a buffer filled with 0s.
* @param bytes the number of bytes the buffer should be
* Returns a Uint8Array filled with 0s.
* @param {number} bytes the number of bytes of the Uint8Array
* @return {Uint8Array}
*/
export const zeros = function (bytes: number): Buffer {
return Buffer.allocUnsafe(bytes).fill(0)
export const zeros = (bytes: number): Uint8Array => {
return new Uint8Array(bytes)
}
/**
* Pads a `Buffer` with zeros till it has `length` bytes.
* Pads a `Uint8Array` with zeros till it has `length` bytes.
* Truncates the beginning or end of input if its length exceeds `length`.
* @param msg the value to pad (Buffer)
* @param length the number of bytes the output should be
* @param right whether to start padding form the left or right
* @return (Buffer)
* @param {Uint8Array} msg the value to pad
* @param {number} length the number of bytes the output should be
* @param {boolean} right whether to start padding form the left or right
* @return {Uint8Array}
*/
const setLength = function (msg: Buffer, length: number, right: boolean) {
const buf = zeros(length)
const setLength = (msg: Uint8Array, length: number, right: boolean): Uint8Array => {
if (right) {
if (msg.length < length) {
msg.copy(buf)
return buf
return new Uint8Array([...msg, ...zeros(length - msg.length)])
}
return msg.slice(0, length)
return msg.subarray(0, length)
} else {
if (msg.length < length) {
msg.copy(buf, length - msg.length)
return buf
return new Uint8Array([...zeros(length - msg.length), ...msg])
}
return msg.slice(-length)
return msg.subarray(-length)
}

@@ -81,10 +215,10 @@ }

/**
* Left Pads a `Buffer` with leading zeros till it has `length` bytes.
* Left Pads a `Uint8Array` with leading zeros till it has `length` bytes.
* Or it truncates the beginning if it exceeds.
* @param msg the value to pad (Buffer)
* @param length the number of bytes the output should be
* @return (Buffer)
* @param {Uint8Array} msg the value to pad
* @param {number} length the number of bytes the output should be
* @return {Uint8Array}
*/
export const setLengthLeft = function (msg: Buffer, length: number) {
assertIsBuffer(msg)
export const setLengthLeft = (msg: Uint8Array, length: number): Uint8Array => {
assertIsBytes(msg)
return setLength(msg, length, false)

@@ -94,10 +228,10 @@ }

/**
* Right Pads a `Buffer` with trailing zeros till it has `length` bytes.
* Right Pads a `Uint8Array` with trailing zeros till it has `length` bytes.
* it truncates the end if it exceeds.
* @param msg the value to pad (Buffer)
* @param length the number of bytes the output should be
* @return (Buffer)
* @param {Uint8Array} msg the value to pad
* @param {number} length the number of bytes the output should be
* @return {Uint8Array}
*/
export const setLengthRight = function (msg: Buffer, length: number) {
assertIsBuffer(msg)
export const setLengthRight = (msg: Uint8Array, length: number): Uint8Array => {
assertIsBytes(msg)
return setLength(msg, length, true)

@@ -107,10 +241,14 @@ }

/**
* Trims leading zeros from a `Buffer`, `String` or `Number[]`.
* @param a (Buffer|Array|String)
* @return (Buffer|Array|String)
* Trims leading zeros from a `Uint8Array`, `number[]` or PrefixedHexString`.
* @param {Uint8Array|number[]|PrefixedHexString} a
* @return {Uint8Array|number[]|PrefixedHexString}
*/
const stripZeros = function (a: any): Buffer | number[] | string {
const stripZeros = <
T extends Uint8Array | number[] | PrefixedHexString = Uint8Array | number[] | PrefixedHexString
>(
a: T
): T => {
let first = a[0]
while (a.length > 0 && first.toString() === '0') {
a = a.slice(1)
a = a.slice(1) as T
first = a[0]

@@ -122,9 +260,9 @@ }

/**
* Trims leading zeros from a `Buffer`.
* @param a (Buffer)
* @return (Buffer)
* Trims leading zeros from a `Uint8Array`.
* @param {Uint8Array} a
* @return {Uint8Array}
*/
export const unpadBuffer = function (a: Buffer): Buffer {
assertIsBuffer(a)
return stripZeros(a) as Buffer
export const unpadBytes = (a: Uint8Array): Uint8Array => {
assertIsBytes(a)
return stripZeros(a)
}

@@ -134,183 +272,21 @@

* Trims leading zeros from an `Array` (of numbers).
* @param a (number[])
* @return (number[])
* @param {number[]} a
* @return {number[]}
*/
export const unpadArray = function (a: number[]): number[] {
export const unpadArray = (a: number[]): number[] => {
assertIsArray(a)
return stripZeros(a) as number[]
return stripZeros(a)
}
/**
* Trims leading zeros from a hex-prefixed `String`.
* @param a (String)
* @return (String)
* Trims leading zeros from a `PrefixedHexString`.
* @param {PrefixedHexString} a
* @return {PrefixedHexString}
*/
export const unpadHexString = function (a: string): string {
export const unpadHex = (a: string): PrefixedHexString => {
assertIsHexString(a)
a = stripHexPrefix(a)
return ('0x' + stripZeros(a)) as string
return '0x' + stripZeros(a)
}
export type ToBufferInputTypes =
| PrefixedHexString
| number
| bigint
| Buffer
| Uint8Array
| number[]
| TransformableToArray
| TransformableToBuffer
| null
| undefined
/**
* Attempts to turn a value into a `Buffer`.
* Inputs supported: `Buffer`, `String` (hex-prefixed), `Number`, null/undefined, `BigInt` and other objects
* with a `toArray()` or `toBuffer()` method.
* @param v the value
*/
export const toBuffer = function (v: ToBufferInputTypes): Buffer {
if (v === null || v === undefined) {
return Buffer.allocUnsafe(0)
}
if (Buffer.isBuffer(v)) {
return Buffer.from(v)
}
if (Array.isArray(v) || v instanceof Uint8Array) {
return Buffer.from(v as Uint8Array)
}
if (typeof v === 'string') {
if (!isHexString(v)) {
throw new Error(
`Cannot convert string to buffer. toBuffer only supports 0x-prefixed hex strings and this string was given: ${v}`
)
}
return Buffer.from(padToEven(stripHexPrefix(v)), 'hex')
}
if (typeof v === 'number') {
return intToBuffer(v)
}
if (typeof v === 'bigint') {
if (v < BigInt(0)) {
throw new Error(`Cannot convert negative bigint to buffer. Given: ${v}`)
}
let n = v.toString(16)
if (n.length % 2) n = '0' + n
return Buffer.from(n, 'hex')
}
if (v.toArray) {
// converts a BN to a Buffer
return Buffer.from(v.toArray())
}
if (v.toBuffer) {
return Buffer.from(v.toBuffer())
}
throw new Error('invalid type')
}
/**
* Converts a `Buffer` into a `0x`-prefixed hex `String`.
* @param buf `Buffer` object to convert
*/
export const bufferToHex = function (buf: Buffer): string {
buf = toBuffer(buf)
return '0x' + buf.toString('hex')
}
/**
* Converts a {@link Buffer} to a {@link bigint}
*/
export function bufferToBigInt(buf: Buffer) {
const hex = bufferToHex(buf)
if (hex === '0x') {
return BigInt(0)
}
return BigInt(hex)
}
/**
* Converts a {@link bigint} to a {@link Buffer}
*/
export function bigIntToBuffer(num: bigint) {
return toBuffer('0x' + num.toString(16))
}
/**
* Converts a `Buffer` to a `Number`.
* @param buf `Buffer` object to convert
* @throws If the input number exceeds 53 bits.
*/
export const bufferToInt = function (buf: Buffer): number {
const res = Number(bufferToBigInt(buf))
if (!Number.isSafeInteger(res)) throw new Error('Number exceeds 53 bits')
return res
}
export const hexToBytes = (hex: string): Uint8Array => {
if (typeof hex !== 'string') {
throw new Error(`hex argument type ${typeof hex} must be of type string`)
}
if (!hex.startsWith('0x')) {
throw new Error(`prefixed hex input should start with 0x, got ${hex.substring(0, 2)}`)
}
hex = hex.slice(2)
if (hex.length % 2 !== 0) {
hex = padToEven(hex)
}
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
}
/**
* Converts an {@link number} to a {@link Uint8Array}
* @param {Number} i
* @return {Uint8Array}
*/
export const intToBytes = (i: number): Uint8Array => {
const hex = intToHex(i)
return hexToBytes(hex)
}
const _unprefixedHexToBytes = (data: string) => {
const hex = data.startsWith('0x') ? data.substring(2) : data
if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex)
const len = hex.length
if (len % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + len)
const array = new Uint8Array(len / 2)
for (let i = 0; i < array.length; i++) {
const j = i * 2
const hexByte = hex.slice(j, j + 2)
const byte = Number.parseInt(hexByte, 16)
if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence')
array[i] = byte
}
return array
}
export const unprefixedHexToBytes = (inp: string) => {
if (inp.slice(0, 2) === '0x') {
throw new Error('hex string is prefixed with 0x, should be unprefixed')
} else {
return _unprefixedHexToBytes(padToEven(inp))
}
}
export type ToBytesInputTypes =

@@ -333,2 +309,3 @@ | PrefixedHexString

*/
export const toBytes = (v: ToBytesInputTypes): Uint8Array => {

@@ -357,3 +334,3 @@ if (v === null || v === undefined) {

if (typeof v === 'bigint') {
if (v < BigInt(0)) {
if (v < BIGINT_0) {
throw new Error(`Cannot convert negative bigint to Uint8Array. Given: ${v}`)

@@ -375,21 +352,25 @@ }

/**
* Interprets a `Buffer` as a signed integer and returns a `BigInt`. Assumes 256-bit numbers.
* @param num Signed integer value
* Interprets a `Uint8Array` as a signed integer and returns a `BigInt`. Assumes 256-bit numbers.
* @param {Uint8Array} num Signed integer value
* @returns {bigint}
*/
export const fromSigned = function (num: Buffer): bigint {
return BigInt.asIntN(256, bufferToBigInt(num))
export const fromSigned = (num: Uint8Array): bigint => {
return BigInt.asIntN(256, bytesToBigInt(num))
}
/**
* Converts a `BigInt` to an unsigned integer and returns it as a `Buffer`. Assumes 256-bit numbers.
* @param num
* Converts a `BigInt` to an unsigned integer and returns it as a `Uint8Array`. Assumes 256-bit numbers.
* @param {bigint} num
* @returns {Uint8Array}
*/
export const toUnsigned = function (num: bigint): Buffer {
return bigIntToBuffer(BigInt.asUintN(256, num))
export const toUnsigned = (num: bigint): Uint8Array => {
return bigIntToBytes(BigInt.asUintN(256, num))
}
/**
* Adds "0x" to a given `String` if it does not already start with "0x".
* Adds "0x" to a given `string` if it does not already start with "0x".
* @param {string} str
* @return {PrefixedHexString}
*/
export const addHexPrefix = function (str: string): string {
export const addHexPrefix = (str: string): PrefixedHexString => {
if (typeof str !== 'string') {

@@ -403,3 +384,3 @@ return str

/**
* Shortens a string or buffer's hex string representation to maxLength (default 50).
* Shortens a string or Uint8Array's hex string representation to maxLength (default 50).
*

@@ -410,142 +391,188 @@ * Examples:

* Output: '657468657265756d0000000000000000000000000000000000…'
* @param {Uint8Array | string} bytes
* @param {number} maxLength
* @return {string}
*/
export function short(buffer: Buffer | string, maxLength: number = 50): string {
const bufferStr = Buffer.isBuffer(buffer) ? buffer.toString('hex') : buffer
if (bufferStr.length <= maxLength) {
return bufferStr
export const short = (bytes: Uint8Array | string, maxLength: number = 50): string => {
const byteStr = bytes instanceof Uint8Array ? bytesToHex(bytes) : bytes
const len = byteStr.slice(0, 2) === '0x' ? maxLength + 2 : maxLength
if (byteStr.length <= len) {
return byteStr
}
return bufferStr.slice(0, maxLength) + '…'
return byteStr.slice(0, len) + '…'
}
/**
* Returns the utf8 string representation from a hex string.
* Checks provided Uint8Array for leading zeroes and throws if found.
*
* Examples:
*
* Input 1: '657468657265756d000000000000000000000000000000000000000000000000'
* Input 2: '657468657265756d'
* Input 3: '000000000000000000000000000000000000000000000000657468657265756d'
* Valid values: 0x1, 0x, 0x01, 0x1234
* Invalid values: 0x0, 0x00, 0x001, 0x0001
*
* Output (all 3 input variants): 'ethereum'
*
* Note that this method is not intended to be used with hex strings
* representing quantities in both big endian or little endian notation.
*
* @param string Hex string, should be `0x` prefixed
* @return Utf8 string
* Note: This method is useful for validating that RLP encoded integers comply with the rule that all
* integer values encoded to RLP must be in the most compact form and contain no leading zero bytes
* @param values An object containing string keys and Uint8Array values
* @throws if any provided value is found to have leading zero bytes
*/
export const toUtf8 = function (hex: string): string {
const zerosRegexp = /^(00)+|(00)+$/g
hex = stripHexPrefix(hex)
if (hex.length % 2 !== 0) {
throw new Error('Invalid non-even hex string input for toUtf8() provided')
export const validateNoLeadingZeroes = (values: { [key: string]: Uint8Array | undefined }) => {
for (const [k, v] of Object.entries(values)) {
if (v !== undefined && v.length > 0 && v[0] === 0) {
throw new Error(`${k} cannot have leading zeroes, received: ${bytesToHex(v)}`)
}
}
const bufferVal = Buffer.from(hex.replace(zerosRegexp, ''), 'hex')
}
return bufferVal.toString('utf8')
/**
* Converts a {@link bigint} to a `0x` prefixed hex string
* @param {bigint} num the bigint to convert
* @returns {PrefixedHexString}
*/
export const bigIntToHex = (num: bigint): PrefixedHexString => {
return '0x' + num.toString(16)
}
/**
* Converts a `Buffer` or `Array` to JSON.
* @param ba (Buffer|Array)
* @return (Array|String|null)
* Convert value from bigint to an unpadded Uint8Array
* (useful for RLP transport)
* @param {bigint} value the bigint to convert
* @returns {Uint8Array}
*/
export const baToJSON = function (ba: any): any {
if (Buffer.isBuffer(ba)) {
return `0x${ba.toString('hex')}`
} else if (ba instanceof Array) {
const array = []
for (let i = 0; i < ba.length; i++) {
array.push(baToJSON(ba[i]))
}
return array
}
export const bigIntToUnpaddedBytes = (value: bigint): Uint8Array => {
return unpadBytes(bigIntToBytes(value))
}
/**
* Checks provided Buffers for leading zeroes and throws if found.
* Convert value from number to an unpadded Uint8Array
* (useful for RLP transport)
* @param {number} value the bigint to convert
* @returns {Uint8Array}
*/
export const intToUnpaddedBytes = (value: number): Uint8Array => {
return unpadBytes(intToBytes(value))
}
/**
* Compares two Uint8Arrays and returns a number indicating their order in a sorted array.
*
* Examples:
* @param {Uint8Array} value1 - The first Uint8Array to compare.
* @param {Uint8Array} value2 - The second Uint8Array to compare.
* @returns {number} A positive number if value1 is larger than value2,
* A negative number if value1 is smaller than value2,
* or 0 if value1 and value2 are equal.
*/
export const compareBytes = (value1: Uint8Array, value2: Uint8Array): number => {
const bigIntValue1 = bytesToBigInt(value1)
const bigIntValue2 = bytesToBigInt(value2)
return bigIntValue1 > bigIntValue2 ? 1 : bigIntValue1 < bigIntValue2 ? -1 : 0
}
/**
* Generates a Uint8Array of random bytes of specified length.
*
* Valid values: 0x1, 0x, 0x01, 0x1234
* Invalid values: 0x0, 0x00, 0x001, 0x0001
*
* Note: This method is useful for validating that RLP encoded integers comply with the rule that all
* integer values encoded to RLP must be in the most compact form and contain no leading zero bytes
* @param values An object containing string keys and Buffer values
* @throws if any provided value is found to have leading zero bytes
* @param {number} length - The length of the Uint8Array.
* @returns {Uint8Array} A Uint8Array of random bytes of specified length.
*/
export const validateNoLeadingZeroes = function (values: { [key: string]: Buffer | undefined }) {
for (const [k, v] of Object.entries(values)) {
if (v !== undefined && v.length > 0 && v[0] === 0) {
throw new Error(`${k} cannot have leading zeroes, received: ${v.toString('hex')}`)
}
}
export const randomBytes = (length: number): Uint8Array => {
return getRandomBytesSync(length)
}
/**
* Converts a {@link Uint8Array} or {@link NestedUint8Array} to {@link Buffer} or {@link NestedBufferArray}
* This mirrors the functionality of the `ethereum-cryptography` export except
* it skips the check to validate that every element of `arrays` is indead a `uint8Array`
* Can give small performance gains on large arrays
* @param {Uint8Array[]} arrays an array of Uint8Arrays
* @returns {Uint8Array} one Uint8Array with all the elements of the original set
* works like `Buffer.concat`
*/
export function arrToBufArr(arr: Uint8Array): Buffer
export function arrToBufArr(arr: NestedUint8Array): NestedBufferArray
export function arrToBufArr(arr: Uint8Array | NestedUint8Array): Buffer | NestedBufferArray
export function arrToBufArr(arr: Uint8Array | NestedUint8Array): Buffer | NestedBufferArray {
if (!Array.isArray(arr)) {
return Buffer.from(arr)
export const concatBytes = (...arrays: Uint8Array[]): Uint8Array => {
if (arrays.length === 1) return arrays[0]
const length = arrays.reduce((a, arr) => a + arr.length, 0)
const result = new Uint8Array(length)
for (let i = 0, pad = 0; i < arrays.length; i++) {
const arr = arrays[i]
result.set(arr, pad)
pad += arr.length
}
return arr.map((a) => arrToBufArr(a))
return result
}
/**
* Converts a {@link Buffer} or {@link NestedBufferArray} to {@link Uint8Array} or {@link NestedUint8Array}
* @notice Convert a Uint8Array to a 32-bit integer
* @param {Uint8Array} bytes The input Uint8Array from which to read the 32-bit integer.
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian.
* @return {number} The 32-bit integer read from the input Uint8Array.
*/
export function bufArrToArr(arr: Buffer): Uint8Array
export function bufArrToArr(arr: NestedBufferArray): NestedUint8Array
export function bufArrToArr(arr: Buffer | NestedBufferArray): Uint8Array | NestedUint8Array
export function bufArrToArr(arr: Buffer | NestedBufferArray): Uint8Array | NestedUint8Array {
if (!Array.isArray(arr)) {
return Uint8Array.from(arr ?? [])
export function bytesToInt32(bytes: Uint8Array, littleEndian: boolean = false): number {
if (bytes.length < 4) {
bytes = setLength(bytes, 4, littleEndian)
}
return arr.map((a) => bufArrToArr(a))
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
return dataView.getUint32(0, littleEndian)
}
/**
* Converts a {@link bigint} to a `0x` prefixed hex string
* @notice Convert a Uint8Array to a 64-bit bigint
* @param {Uint8Array} bytes The input Uint8Array from which to read the 64-bit bigint.
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian.
* @return {bigint} The 64-bit bigint read from the input Uint8Array.
*/
export const bigIntToHex = (num: bigint) => {
return '0x' + num.toString(16)
export function bytesToBigInt64(bytes: Uint8Array, littleEndian: boolean = false): bigint {
if (bytes.length < 8) {
bytes = setLength(bytes, 8, littleEndian)
}
const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
return dataView.getBigUint64(0, littleEndian)
}
/**
* Convert value from bigint to an unpadded Buffer
* (useful for RLP transport)
* @param value value to convert
* @notice Convert a 32-bit integer to a Uint8Array.
* @param {number} value The 32-bit integer to convert.
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian.
* @return {Uint8Array} A Uint8Array of length 4 containing the integer.
*/
export function bigIntToUnpaddedBuffer(value: bigint): Buffer {
return unpadBuffer(bigIntToBuffer(value))
export function int32ToBytes(value: number, littleEndian: boolean = false): Uint8Array {
const buffer = new ArrayBuffer(4)
const dataView = new DataView(buffer)
dataView.setUint32(0, value, littleEndian)
return new Uint8Array(buffer)
}
export function intToUnpaddedBuffer(value: number): Buffer {
return unpadBuffer(intToBuffer(value))
/**
* @notice Convert a 64-bit bigint to a Uint8Array.
* @param {bigint} value The 64-bit bigint to convert.
* @param {boolean} littleEndian True for little-endian, undefined or false for big-endian.
* @return {Uint8Array} A Uint8Array of length 8 containing the bigint.
*/
export function bigInt64ToBytes(value: bigint, littleEndian: boolean = false): Uint8Array {
const buffer = new ArrayBuffer(8)
const dataView = new DataView(buffer)
dataView.setBigUint64(0, value, littleEndian)
return new Uint8Array(buffer)
}
/**************** Borrowed from @chainsafe/ssz */
// Caching this info costs about ~1000 bytes and speeds up toHexString() by x6
const hexByByte = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0'))
export function equalsBytes(a: Uint8Array, b: Uint8Array): boolean {
if (a.length !== b.length) {
return false
}
export const bytesToHex = (bytes: Uint8Array): string => {
let hex = '0x'
if (bytes === undefined || bytes.length === 0) return hex
for (const byte of bytes) {
hex += hexByByte[byte]
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false
}
}
return hex
return true
}
export const bytesToBigInt = (bytes: Uint8Array): bigint => {
const hex = bytesToHex(bytes)
if (hex === '0x') {
return BigInt(0)
export function bytesToUtf8(data: Uint8Array): string {
if (!(data instanceof Uint8Array)) {
throw new TypeError(`bytesToUtf8 expected Uint8Array, got ${typeof data}`)
}
return BigInt(hex)
return new TextDecoder().decode(data)
}
export function utf8ToBytes(str: string): Uint8Array {
if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`)
return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809
}

@@ -1,2 +0,2 @@

import { Buffer } from 'buffer'
import { hexToBytes } from './bytes.js'

@@ -39,3 +39,3 @@ /**

*/
export const KECCAK256_NULL_S = 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
export const KECCAK256_NULL_S = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'

@@ -45,3 +45,3 @@ /**

*/
export const KECCAK256_NULL = Buffer.from(KECCAK256_NULL_S, 'hex')
export const KECCAK256_NULL = hexToBytes(KECCAK256_NULL_S)

@@ -52,3 +52,3 @@ /**

export const KECCAK256_RLP_ARRAY_S =
'1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'
'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'

@@ -58,3 +58,3 @@ /**

*/
export const KECCAK256_RLP_ARRAY = Buffer.from(KECCAK256_RLP_ARRAY_S, 'hex')
export const KECCAK256_RLP_ARRAY = hexToBytes(KECCAK256_RLP_ARRAY_S)

@@ -64,3 +64,3 @@ /**

*/
export const KECCAK256_RLP_S = '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'
export const KECCAK256_RLP_S = '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'

@@ -70,3 +70,3 @@ /**

*/
export const KECCAK256_RLP = Buffer.from(KECCAK256_RLP_S, 'hex')
export const KECCAK256_RLP = hexToBytes(KECCAK256_RLP_S)

@@ -76,4 +76,39 @@ /**

*/
export const RLP_EMPTY_STRING = Buffer.from([0x80])
export const RLP_EMPTY_STRING = Uint8Array.from([0x80])
export const MAX_WITHDRAWALS_PER_PAYLOAD = 16
export const RIPEMD160_ADDRESS_STRING = '0000000000000000000000000000000000000003'
/**
* BigInt constants
*/
export const BIGINT_NEG1 = BigInt(-1)
export const BIGINT_0 = BigInt(0)
export const BIGINT_1 = BigInt(1)
export const BIGINT_2 = BigInt(2)
export const BIGINT_3 = BigInt(3)
export const BIGINT_7 = BigInt(7)
export const BIGINT_8 = BigInt(8)
export const BIGINT_27 = BigInt(27)
export const BIGINT_28 = BigInt(28)
export const BIGINT_31 = BigInt(31)
export const BIGINT_32 = BigInt(32)
export const BIGINT_64 = BigInt(64)
export const BIGINT_128 = BigInt(128)
export const BIGINT_255 = BigInt(255)
export const BIGINT_256 = BigInt(256)
export const BIGINT_96 = BigInt(96)
export const BIGINT_100 = BigInt(100)
export const BIGINT_160 = BigInt(160)
export const BIGINT_224 = BigInt(224)
export const BIGINT_2EXP96 = BigInt(79228162514264337593543950336)
export const BIGINT_2EXP160 = BigInt(1461501637330902918203684832716283019655932542976)
export const BIGINT_2EXP224 =
BigInt(26959946667150639794667015087019630673637144422540572481103610249216)
export const BIGINT_2EXP256 = BIGINT_2 ** BIGINT_256

@@ -1,2 +0,2 @@

import { isHexString } from './internal'
import { isHexString } from './internal.js'

@@ -18,5 +18,5 @@ /**

*/
export const assertIsBuffer = function (input: Buffer): void {
if (!Buffer.isBuffer(input)) {
const msg = `This method only supports Buffer but input was: ${input}`
export const assertIsBytes = function (input: Uint8Array): void {
if (!(input instanceof Uint8Array)) {
const msg = `This method only supports Uint8Array but input was: ${input}`
throw new Error(msg)

@@ -23,0 +23,0 @@ }

/**
* Constants
*/
export * from './constants'
export * from './constants.js'

@@ -9,3 +9,3 @@ /**

*/
export * from './units'
export * from './units.js'

@@ -15,3 +15,3 @@ /**

*/
export * from './account'
export * from './account.js'

@@ -21,23 +21,23 @@ /**

*/
export * from './address'
export * from './address.js'
/**
* Withdrawal type
* DB type
*/
export * from './withdrawal'
export * from './db.js'
/**
* ECDSA signature
* Withdrawal type
*/
export * from './signature'
export * from './withdrawal.js'
/**
* Utilities for manipulating Buffers, byte arrays, etc.
* ECDSA signature
*/
export * from './bytes'
export * from './signature.js'
/**
* SSZ containers
* Utilities for manipulating bytes, Uint8Arrays, etc.
*/
export * as ssz from './ssz'
export * from './bytes.js'

@@ -47,3 +47,3 @@ /**

*/
export * from './types'
export * from './types.js'

@@ -53,3 +53,5 @@ /**

*/
export * from './asyncEventEmitter'
export * from './asyncEventEmitter.js'
export * from './blobs.js'
export * from './genesis.js'
export {

@@ -66,3 +68,6 @@ arrayContainsArray,

toAscii,
} from './internal'
export * from './lock'
} from './internal.js'
export * from './kzg.js'
export * from './lock.js'
export * from './mapDB.js'
export * from './provider.js'

@@ -25,2 +25,4 @@ /*

import { bytesToUnprefixedHex, utf8ToBytes } from './bytes.js'
/**

@@ -79,3 +81,3 @@ * Returns a `Boolean` on whether or not the a `String` starts with '0x'

return Buffer.byteLength(str, 'utf8')
return utf8ToBytes(str).byteLength
}

@@ -132,3 +134,4 @@

/**
* Should be called to get hex representation (prefixed by 0x) of utf8 string
* Should be called to get hex representation (prefixed by 0x) of utf8 string.
* Strips leading and trailing 0's.
*

@@ -140,5 +143,5 @@ * @param string

export function fromUtf8(stringValue: string) {
const str = Buffer.from(stringValue, 'utf8')
const str = utf8ToBytes(stringValue)
return `0x${padToEven(str.toString('hex')).replace(/^0+|0+$/g, '')}`
return `0x${padToEven(bytesToUnprefixedHex(str)).replace(/^0+|0+$/g, '')}`
}

@@ -145,0 +148,0 @@

@@ -1,12 +0,26 @@

import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { ecdsaRecover, ecdsaSign, publicKeyConvert } from 'ethereum-cryptography/secp256k1'
import { bufferToBigInt, bufferToHex, bufferToInt, setLengthLeft, toBuffer } from './bytes'
import { SECP256K1_ORDER, SECP256K1_ORDER_DIV_2 } from './constants'
import { assertIsBuffer } from './helpers'
import {
bytesToBigInt,
bytesToHex,
bytesToInt,
concatBytes,
setLengthLeft,
toBytes,
} from './bytes.js'
import {
BIGINT_0,
BIGINT_1,
BIGINT_2,
BIGINT_27,
SECP256K1_ORDER,
SECP256K1_ORDER_DIV_2,
} from './constants.js'
import { assertIsBytes } from './helpers.js'
export interface ECDSASignature {
v: bigint
r: Buffer
s: Buffer
r: Uint8Array
s: Uint8Array
}

@@ -20,3 +34,7 @@

*/
export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId?: bigint): ECDSASignature {
export function ecsign(
msgHash: Uint8Array,
privateKey: Uint8Array,
chainId?: bigint
): ECDSASignature {
const { signature, recid: recovery } = ecdsaSign(msgHash, privateKey)

@@ -35,13 +53,13 @@

function calculateSigRecovery(v: bigint, chainId?: bigint): bigint {
if (v === BigInt(0) || v === BigInt(1)) return v
export function calculateSigRecovery(v: bigint, chainId?: bigint): bigint {
if (v === BIGINT_0 || v === BIGINT_1) return v
if (chainId === undefined) {
return v - BigInt(27)
return v - BIGINT_27
}
return v - (chainId * BigInt(2) + BigInt(35))
return v - (chainId * BIGINT_2 + BigInt(35))
}
function isValidSigRecovery(recovery: bigint): boolean {
return recovery === BigInt(0) || recovery === BigInt(1)
return recovery === BIGINT_0 || recovery === BIGINT_1
}

@@ -55,9 +73,9 @@

export const ecrecover = function (
msgHash: Buffer,
msgHash: Uint8Array,
v: bigint,
r: Buffer,
s: Buffer,
r: Uint8Array,
s: Uint8Array,
chainId?: bigint
): Buffer {
const signature = Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32)], 64)
): Uint8Array {
const signature = concatBytes(setLengthLeft(r, 32), setLengthLeft(s, 32))
const recovery = calculateSigRecovery(v, chainId)

@@ -77,3 +95,8 @@ if (!isValidSigRecovery(recovery)) {

*/
export const toRpcSig = function (v: bigint, r: Buffer, s: Buffer, chainId?: bigint): string {
export const toRpcSig = function (
v: bigint,
r: Uint8Array,
s: Uint8Array,
chainId?: bigint
): string {
const recovery = calculateSigRecovery(v, chainId)

@@ -85,3 +108,4 @@ if (!isValidSigRecovery(recovery)) {

// geth (and the RPC eth_sign method) uses the 65 byte format used by Bitcoin
return bufferToHex(Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32), toBuffer(v)]))
return bytesToHex(concatBytes(setLengthLeft(r, 32), setLengthLeft(s, 32), toBytes(v)))
}

@@ -94,3 +118,8 @@

*/
export const toCompactSig = function (v: bigint, r: Buffer, s: Buffer, chainId?: bigint): string {
export const toCompactSig = function (
v: bigint,
r: Uint8Array,
s: Uint8Array,
chainId?: bigint
): string {
const recovery = calculateSigRecovery(v, chainId)

@@ -101,9 +130,8 @@ if (!isValidSigRecovery(recovery)) {

let ss = s
if ((v > BigInt(28) && v % BigInt(2) === BigInt(1)) || v === BigInt(1) || v === BigInt(28)) {
ss = Buffer.from(s)
const ss = Uint8Array.from([...s])
if ((v > BigInt(28) && v % BIGINT_2 === BIGINT_1) || v === BIGINT_1 || v === BigInt(28)) {
ss[0] |= 0x80
}
return bufferToHex(Buffer.concat([setLengthLeft(r, 32), setLengthLeft(ss, 32)]))
return bytesToHex(concatBytes(setLengthLeft(r, 32), setLengthLeft(ss, 32)))
}

@@ -120,16 +148,16 @@

export const fromRpcSig = function (sig: string): ECDSASignature {
const buf: Buffer = toBuffer(sig)
const bytes: Uint8Array = toBytes(sig)
let r: Buffer
let s: Buffer
let r: Uint8Array
let s: Uint8Array
let v: bigint
if (buf.length >= 65) {
r = buf.slice(0, 32)
s = buf.slice(32, 64)
v = bufferToBigInt(buf.slice(64))
} else if (buf.length === 64) {
if (bytes.length >= 65) {
r = bytes.subarray(0, 32)
s = bytes.subarray(32, 64)
v = bytesToBigInt(bytes.subarray(64))
} else if (bytes.length === 64) {
// Compact Signature Representation (https://eips.ethereum.org/EIPS/eip-2098)
r = buf.slice(0, 32)
s = buf.slice(32, 64)
v = BigInt(bufferToInt(buf.slice(32, 33)) >> 7)
r = bytes.subarray(0, 32)
s = bytes.subarray(32, 64)
v = BigInt(bytesToInt(bytes.subarray(32, 33)) >> 7)
s[0] &= 0x7f

@@ -142,3 +170,3 @@ } else {

if (v < 27) {
v = v + BigInt(27)
v = v + BIGINT_27
}

@@ -160,4 +188,4 @@

v: bigint,
r: Buffer,
s: Buffer,
r: Uint8Array,
s: Uint8Array,
homesteadOrLater: boolean = true,

@@ -174,9 +202,9 @@ chainId?: bigint

const rBigInt = bufferToBigInt(r)
const sBigInt = bufferToBigInt(s)
const rBigInt = bytesToBigInt(r)
const sBigInt = bytesToBigInt(s)
if (
rBigInt === BigInt(0) ||
rBigInt === BIGINT_0 ||
rBigInt >= SECP256K1_ORDER ||
sBigInt === BigInt(0) ||
sBigInt === BIGINT_0 ||
sBigInt >= SECP256K1_ORDER

@@ -200,6 +228,6 @@ ) {

*/
export const hashPersonalMessage = function (message: Buffer): Buffer {
assertIsBuffer(message)
export const hashPersonalMessage = function (message: Uint8Array): Uint8Array {
assertIsBytes(message)
const prefix = Buffer.from(`\u0019Ethereum Signed Message:\n${message.length}`, 'utf-8')
return Buffer.from(keccak256(Buffer.concat([prefix, message])))
}

@@ -1,6 +0,6 @@

import { bufferToBigInt, bufferToHex, toBuffer } from './bytes'
import { isHexString } from './internal'
import { bytesToBigInt, bytesToHex, toBytes } from './bytes.js'
import { isHexString } from './internal.js'
import type { Address } from './address'
import type { ToBufferInputTypes } from './bytes'
import type { Address } from './address.js'
import type { ToBytesInputTypes } from './bytes.js'

@@ -10,9 +10,8 @@ /*

*/
export type BigIntLike = bigint | PrefixedHexString | number | Buffer
export type BigIntLike = bigint | PrefixedHexString | number | Uint8Array
/*
* A type that represents an input that can be converted to a Buffer.
* A type that represents an input that can be converted to a Uint8Array.
*/
export type BufferLike =
| Buffer
export type BytesLike =
| Uint8Array

@@ -22,3 +21,3 @@ | number[]

| bigint
| TransformableToBuffer
| TransformabletoBytes
| PrefixedHexString

@@ -34,3 +33,3 @@

*/
export type AddressLike = Address | Buffer | PrefixedHexString
export type AddressLike = Address | Uint8Array | PrefixedHexString

@@ -41,20 +40,3 @@ export interface TransformabletoBytes {

/*
* A type that represents an object that has a `toArray()` method.
*/
export interface TransformableToArray {
toArray(): Uint8Array
toBuffer?(): Buffer
}
/*
* A type that represents an object that has a `toBuffer()` method.
*/
export interface TransformableToBuffer {
toBuffer(): Buffer
toArray?(): Uint8Array
}
export type NestedUint8Array = Array<Uint8Array | NestedUint8Array>
export type NestedBufferArray = Array<Buffer | NestedBufferArray>

@@ -67,3 +49,3 @@ /**

BigInt,
Buffer,
Uint8Array,
PrefixedHexString,

@@ -75,3 +57,3 @@ }

[TypeOutput.BigInt]: bigint
[TypeOutput.Buffer]: Buffer
[TypeOutput.Uint8Array]: Uint8Array
[TypeOutput.PrefixedHexString]: PrefixedHexString

@@ -89,7 +71,7 @@ }

export function toType<T extends TypeOutput>(
input: ToBufferInputTypes,
input: ToBytesInputTypes,
outputType: T
): TypeOutputReturnType[T]
export function toType<T extends TypeOutput>(
input: ToBufferInputTypes,
input: ToBytesInputTypes,
outputType: T

@@ -112,11 +94,11 @@ ): TypeOutputReturnType[T] | undefined | null {

const output = toBuffer(input)
const output = toBytes(input)
switch (outputType) {
case TypeOutput.Buffer:
case TypeOutput.Uint8Array:
return output as TypeOutputReturnType[T]
case TypeOutput.BigInt:
return bufferToBigInt(output) as TypeOutputReturnType[T]
return bytesToBigInt(output) as TypeOutputReturnType[T]
case TypeOutput.Number: {
const bigInt = bufferToBigInt(output)
const bigInt = bytesToBigInt(output)
if (bigInt > BigInt(Number.MAX_SAFE_INTEGER)) {

@@ -130,3 +112,3 @@ throw new Error(

case TypeOutput.PrefixedHexString:
return bufferToHex(output) as TypeOutputReturnType[T]
return bytesToHex(output) as TypeOutputReturnType[T]
default:

@@ -133,0 +115,0 @@ throw new Error('unknown outputType')

@@ -0,2 +1,20 @@

import { BIGINT_0, BIGINT_1 } from './constants.js'
/** Easy conversion from Gwei to wei */
export const GWEI_TO_WEI = BigInt(1000000000)
export function formatBigDecimal(
numerator: bigint,
denominator: bigint,
maxDecimalFactor: bigint
): string {
if (denominator === BIGINT_0) {
denominator = BIGINT_1
}
const full = numerator / denominator
const fraction = ((numerator - full * denominator) * maxDecimalFactor) / denominator
// zeros to be added post decimal are number of zeros in maxDecimalFactor - number of digits in fraction
const zerosPostDecimal = String(maxDecimalFactor).length - 1 - String(fraction).length
return `${full}.${'0'.repeat(zerosPostDecimal)}${fraction}`
}

@@ -1,6 +0,7 @@

import { Address } from './address'
import { bigIntToHex } from './bytes'
import { TypeOutput, toType } from './types'
import { Address } from './address.js'
import { bigIntToHex, bytesToHex, toBytes } from './bytes.js'
import { BIGINT_0 } from './constants.js'
import { TypeOutput, toType } from './types.js'
import type { AddressLike, BigIntLike } from './types'
import type { AddressLike, BigIntLike } from './types.js'

@@ -29,3 +30,3 @@ /**

export type WithdrawalBuffer = [Buffer, Buffer, Buffer, Buffer]
export type WithdrawalBytes = [Uint8Array, Uint8Array, Uint8Array, Uint8Array]

@@ -60,3 +61,3 @@ /**

const validatorIndex = toType(validatorIndexData, TypeOutput.BigInt)
const address = new Address(toType(addressData, TypeOutput.Buffer))
const address = addressData instanceof Address ? addressData : new Address(toBytes(addressData))
const amount = toType(amountData, TypeOutput.BigInt)

@@ -67,3 +68,3 @@

public static fromValuesArray(withdrawalArray: WithdrawalBuffer) {
public static fromValuesArray(withdrawalArray: WithdrawalBytes) {
if (withdrawalArray.length !== 4) {

@@ -81,28 +82,25 @@ throw Error(`Invalid withdrawalArray length expected=4 actual=${withdrawalArray.length}`)

*/
public static toBufferArray(withdrawal: Withdrawal | WithdrawalData): WithdrawalBuffer {
public static toBytesArray(withdrawal: Withdrawal | WithdrawalData): WithdrawalBytes {
const { index, validatorIndex, address, amount } = withdrawal
const indexBuffer =
toType(index, TypeOutput.BigInt) === BigInt(0)
? Buffer.alloc(0)
: toType(index, TypeOutput.Buffer)
const validatorIndexBuffer =
toType(validatorIndex, TypeOutput.BigInt) === BigInt(0)
? Buffer.alloc(0)
: toType(validatorIndex, TypeOutput.Buffer)
let addressBuffer
if (address instanceof Address) {
addressBuffer = (<Address>address).buf
} else {
addressBuffer = toType(address, TypeOutput.Buffer)
}
const amountBuffer =
toType(amount, TypeOutput.BigInt) === BigInt(0)
? Buffer.alloc(0)
: toType(amount, TypeOutput.Buffer)
const indexBytes =
toType(index, TypeOutput.BigInt) === BIGINT_0
? new Uint8Array()
: toType(index, TypeOutput.Uint8Array)
const validatorIndexBytes =
toType(validatorIndex, TypeOutput.BigInt) === BIGINT_0
? new Uint8Array()
: toType(validatorIndex, TypeOutput.Uint8Array)
const addressBytes =
address instanceof Address ? (<Address>address).bytes : toType(address, TypeOutput.Uint8Array)
return [indexBuffer, validatorIndexBuffer, addressBuffer, amountBuffer]
const amountBytes =
toType(amount, TypeOutput.BigInt) === BIGINT_0
? new Uint8Array()
: toType(amount, TypeOutput.Uint8Array)
return [indexBytes, validatorIndexBytes, addressBytes, amountBytes]
}
raw() {
return Withdrawal.toBufferArray(this)
return Withdrawal.toBytesArray(this)
}

@@ -114,3 +112,3 @@

validatorIndex: this.validatorIndex,
address: this.address.buf,
address: this.address.bytes,
amount: this.amount,

@@ -124,3 +122,3 @@ }

validatorIndex: bigIntToHex(this.validatorIndex),
address: '0x' + this.address.buf.toString('hex'),
address: bytesToHex(this.address.bytes),
amount: bigIntToHex(this.amount),

@@ -127,0 +125,0 @@ }

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc