diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 00000000..fd92c294
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: '@ethereumjs/eslint-config-defaults'
+}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9a3a549b..b33cc6ee 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -22,9 +22,11 @@ jobs:
- uses: actions/checkout@v2
- run: npm install
- - run: npm run test
- - name: Upload coverage to Coveralls
- uses: coverallsapp/github-action@master
+ - run: npm run lint
+ - run: npm run coverage
+
+ - uses: codecov/codecov-action@v1
+ if: matrix.node-version == '12.x'
with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
+ file: ./coverage/lcov.info
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9a0e598..4951260e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,9 +6,91 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
(modification: no type change headlines) and this project adheres to
[Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-## [7.0.6] - [UNRELEASED]
+## [7.0.9] - 2021-03-04
-[ ADD REFERENCES TO YOUR WORK HERE UPON PRs. PLEASE ADOPT THE VERSION IF YOUR PR REQUIRES. ]
+This release adds support for very high `chainId` numbers exceeding `MAX_SAFE_INTEGER` (an example is the chain ID `34180983699157880` used for the ephemeral Yolov3 testnet preparing for the `berlin` hardfork, but high chain IDs might be used for things like private test networks and the like as well).
+
+Function signatures for methods in `address` and `signature` are therefore expanded to allow for a `BNLike` input type (`BN | PrefixedHexString | number | Buffer`) for chain ID related parameters.
+
+All function signatures are still taking in a `number` input for backwards-compatibility reasons. If you use one of the following functions to implement generic use cases in your library where the chain ID is not yet known it is recommended to updated to one of the other input types (with plain `Buffer` likely be the most future-proof). Note that on some functions this changes the return value as well.
+
+- `account`: `toChecksumAddresss(hexAddress: string, eip1191ChainId?: number): string`
+ - -> `toChecksumAddress = function(hexAddress: string, eip1191ChainId?: BNLike): string`
+- `account`: `isValidChecksumAddress(hexAddress: string, eip1191ChainId?: number)`
+ - -> `isValidChecksumAddress(hexAddress: string, eip1191ChainId?: BNLike)`
+- `signature`: `ecsign(msgHash: Buffer, privateKey: Buffer, chainId?: number): ECDSASignature`
+ - -> `ecsign(msgHash: Buffer, privateKey: Buffer, chainId?: number): ECDSASignature` (return value stays the same on `number` input)
+ - -> `ecsign(msgHash: Buffer, privateKey: Buffer, chainId: BNLike): ECDSASignatureBuffer` (changed return value for other type inputs)
+- `signature`: `ecrecover(msgHash: Buffer, v: number, r: Buffer, s: Buffer, chainId?: number): Buffer`
+ - -> `ecrecover(msgHash: Buffer, v: BNLike, r: Buffer, s: Buffer, chainId?: BNLike): Buffer`
+- `signature`: `toRpcSig(v: number, r: Buffer, s: Buffer, chainId?: number): string`
+ - -> `toRpcSig(v: BNLike, r: Buffer, s: Buffer, chainId?: BNLike): string`
+- `signature`: `isValidSignature(v: number, r: Buffer, s: Buffer, homesteadOrLater: boolean = true, chainId?: number)`
+ - -> `isValidSignature(v: BNLike, r: Buffer, s: Buffer, homesteadOrLater: boolean = true, chainId?: BNLike)`
+
+[7.0.9]: https://github.com/ethereumjs/ethereumjs-util/compare/v7.0.8...v7.0.9
+
+## [7.0.8] - 2021-02-01
+
+- New `Address.equals(address: Address)` function for easier address equality comparions, PR [#285](https://github.com/ethereumjs/ethereumjs-util/pull/285)
+- Fixed a bug in `fromRpcSig()` in the `signature` module not working correctly for chain IDs greater than 110, PR [#287](https://github.com/ethereumjs/ethereumjs-util/pull/287)
+
+[7.0.8]: https://github.com/ethereumjs/ethereumjs-util/compare/v7.0.7...v7.0.8
+
+## [7.0.7] - 2020-10-15
+
+- Removed `stateRoot` check for `Account.isEmpty()` to make emptiness check `EIP-161` compliant, PR [#279](https://github.com/ethereumjs/ethereumjs-util/pull/279)
+- Added type `AddressLike` and helper `bnToHex()`, PR [#279](https://github.com/ethereumjs/ethereumjs-util/pull/279)
+- Added `account.raw()` which returns a Buffer Array of the raw Buffers for the account in order, PR [#279](https://github.com/ethereumjs/ethereumjs-util/pull/279)
+
+[7.0.7]: https://github.com/ethereumjs/ethereumjs-util/compare/v7.0.6...v7.0.7
+
+## [7.0.6] - 2020-10-07
+
+### New `Account` class
+
+This release adds a new `Account` class intended as a modern replacement for `ethereumjs-account`. It has a shape of `Account(nonce?: BN, balance?: BN, stateRoot?: Buffer, codeHash?: Buffer)`.
+
+**Instantiation**
+
+The static factory methods assist in creating an `Account` object from varying data types: `Object: fromAccountData`, `RLP: fromRlpSerializedAccount`, and `Array: fromValuesArray`.
+
+**Methods**: `isEmpty(): boolean`, `isContract(): boolean`, `serialize(): Buffer`
+
+Example usage:
+
+```typescript
+import { Account, BN } from 'ethereumjs-util'
+
+const account = new Account(
+ new BN(0), // nonce, default: 0
+ new BN(10).pow(new BN(18)), // balance, default: 0
+ undefined, // stateRoot, default: KECCAK256_RLP (hash of RLP of null)
+ undefined, // codeHash, default: KECCAK256_NULL (hash of null)
+)
+```
+
+For more info see the documentation, examples of usage in `test/account.spec.ts` or
+PR [#275](https://github.com/ethereumjs/ethereumjs-util/pull/275).
+
+### New export: TypeScript types
+
+A new file with helpful TypeScript types has been added to the exports of this project,
+see PR [#275](https://github.com/ethereumjs/ethereumjs-util/pull/275).
+
+In this release it contains `BNLike`, `BufferLike`, and `TransformableToBuffer`.
+
+### Address.toBuffer()
+
+The Address class has as a new method `address.toBuffer()` that will give you a copy of the underlying `address.buf`
+(PR [#277](https://github.com/ethereumjs/ethereumjs-util/pull/277)).
+
+### `toBuffer()` now converts TransformableToBuffer
+
+The `toBuffer()` exported function now additionally converts any object with a `toBuffer()` method
+(PR [#277](https://github.com/ethereumjs/ethereumjs-util/pull/277)).
+
+[7.0.6]: https://github.com/ethereumjs/ethereumjs-util/compare/v7.0.5...v7.0.6
## [7.0.5] - 2020-09-09
diff --git a/README.md b/README.md
index 95733ae0..c8f51a87 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,14 @@
+
+
+
+
+
+
# SYNOPSIS
-[](https://www.npmjs.org/package/ethereumjs-util)
-[](https://github.com/ethereumjs/ethereumjs-util/actions)
-[](https://coveralls.io/r/ethereumjs/ethereumjs-util)
+[![NPM Status][npm-badge]][npm-link]
+[![Actions Status][actions-badge]][actions-link]
+[![Coverage Status][coverage-badge]][coverage-link]
[![Discord][discord-badge]][discord-link]
A collection of utility functions for Ethereum. It can be used in Node.js and in the browser with [browserify](http://browserify.org/).
@@ -32,6 +38,7 @@ assert.equal(new BN('dead', 16).add(new BN('101010', 2)), 57047)
### Modules
- [account](docs/modules/_account_.md)
+ - Account class
- Private/public key and address-related functionality (creation, validation, conversion)
- [address](docs/modules/_address_.md)
- Address class and type
@@ -46,6 +53,8 @@ assert.equal(new BN('dead', 16).add(new BN('101010', 2)), 57047)
- Helper function for creating a binary object (`DEPRECATED`)
- [signature](docs/modules/_signature_.md)
- Signing, signature validation, conversion, recovery
+- [types](docs/modules/_types_.md)
+ - Helpful TypeScript types
- [externals](docs/modules/_externals_.md)
- Helper methods from `ethjs-util`
- Re-exports of `BN`, `rlp`
@@ -68,7 +77,7 @@ The following methods are available provided by [ethjs-util](https://github.com/
- toAscii
- getKeys
-Import can be done directly by function name analogous to the build-in function import:
+They can be imported by name:
```js
import { intToHex, stripHexPrefix } from 'ethereumjs-util'
@@ -91,5 +100,11 @@ If you want to join for work or do improvements on the libraries have a look at
MPL-2.0
+[npm-badge]: https://img.shields.io/npm/v/ethereumjs-util.svg
+[npm-link]: https://www.npmjs.org/package/ethereumjs-util
+[actions-badge]: https://github.com/ethereumjs/ethereumjs-util/workflows/Build/badge.svg
+[actions-link]: https://github.com/ethereumjs/ethereumjs-util/actions
+[coverage-badge]: https://codecov.io/gh/ethereumjs/ethereumjs-util/branch/master/graph/badge.svg
+[coverage-link]: https://codecov.io/gh/ethereumjs/ethereumjs-util
[discord-badge]: https://img.shields.io/static/v1?logo=discord&label=discord&message=Join&color=blue
[discord-link]: https://discord.gg/TNwARpR
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 00000000..3bc0db94
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,7 @@
+coverage:
+ status:
+ project:
+ default:
+ target: auto
+ threshold: 2%
+ base: auto
diff --git a/docs/README.md b/docs/README.md
index 9a7b907a..bdfde4cb 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -6,6 +6,7 @@
### Modules
+* ["@types/ethjs-util/index"](modules/__types_ethjs_util_index_.md)
* ["account"](modules/_account_.md)
* ["address"](modules/_address_.md)
* ["bytes"](modules/_bytes_.md)
@@ -15,3 +16,4 @@
* ["helpers"](modules/_helpers_.md)
* ["object"](modules/_object_.md)
* ["signature"](modules/_signature_.md)
+* ["types"](modules/_types_.md)
diff --git a/docs/classes/_account_.account.md b/docs/classes/_account_.account.md
new file mode 100644
index 00000000..8b83bd60
--- /dev/null
+++ b/docs/classes/_account_.account.md
@@ -0,0 +1,169 @@
+[ethereumjs-util](../README.md) › ["account"](../modules/_account_.md) › [Account](_account_.account.md)
+
+# Class: Account
+
+## Hierarchy
+
+* **Account**
+
+## Index
+
+### Constructors
+
+* [constructor](_account_.account.md#constructor)
+
+### Properties
+
+* [balance](_account_.account.md#balance)
+* [codeHash](_account_.account.md#codehash)
+* [nonce](_account_.account.md#nonce)
+* [stateRoot](_account_.account.md#stateroot)
+
+### Methods
+
+* [isContract](_account_.account.md#iscontract)
+* [isEmpty](_account_.account.md#isempty)
+* [serialize](_account_.account.md#serialize)
+* [fromAccountData](_account_.account.md#static-fromaccountdata)
+* [fromRlpSerializedAccount](_account_.account.md#static-fromrlpserializedaccount)
+* [fromValuesArray](_account_.account.md#static-fromvaluesarray)
+
+## Constructors
+
+### constructor
+
+\+ **new Account**(`nonce`: BN‹›, `balance`: BN‹›, `stateRoot`: Buffer‹›, `codeHash`: Buffer‹›): *[Account](_account_.account.md)*
+
+*Defined in [account.ts:61](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L61)*
+
+This constructor assigns and validates the values.
+Use the static factory methods to assist in creating an Account from varying data types.
+
+**Parameters:**
+
+Name | Type | Default |
+------ | ------ | ------ |
+`nonce` | BN‹› | new BN(0) |
+`balance` | BN‹› | new BN(0) |
+`stateRoot` | Buffer‹› | KECCAK256_RLP |
+`codeHash` | Buffer‹› | KECCAK256_NULL |
+
+**Returns:** *[Account](_account_.account.md)*
+
+## Properties
+
+### balance
+
+• **balance**: *BN*
+
+*Defined in [account.ts:27](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L27)*
+
+___
+
+### codeHash
+
+• **codeHash**: *Buffer*
+
+*Defined in [account.ts:29](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L29)*
+
+___
+
+### nonce
+
+• **nonce**: *BN*
+
+*Defined in [account.ts:26](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L26)*
+
+___
+
+### stateRoot
+
+• **stateRoot**: *Buffer*
+
+*Defined in [account.ts:28](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L28)*
+
+## Methods
+
+### isContract
+
+▸ **isContract**(): *boolean*
+
+*Defined in [account.ts:106](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L106)*
+
+Returns a `Boolean` determining if the account is a contract.
+
+**Returns:** *boolean*
+
+___
+
+### isEmpty
+
+▸ **isEmpty**(): *boolean*
+
+*Defined in [account.ts:115](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L115)*
+
+Returns a `Boolean` determining if the account is empty.
+For more details about account emptiness see [EIP-161](https://eips.ethereum.org/EIPS/eip-161).
+Note: The stateRoot is also checked to be empty since in Frontier it was possible to create a contract with no code where nonce remained 0 but some values were written to storage in the constructor (thus stateRoot is not KECCAK256_RLP).
+
+**Returns:** *boolean*
+
+___
+
+### serialize
+
+▸ **serialize**(): *Buffer*
+
+*Defined in [account.ts:99](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L99)*
+
+Returns the RLP serialization of the account as a `Buffer`.
+
+**Returns:** *Buffer*
+
+___
+
+### `Static` fromAccountData
+
+▸ **fromAccountData**(`accountData`: [AccountData](../interfaces/_account_.accountdata.md)): *[Account](_account_.account.md)‹›*
+
+*Defined in [account.ts:31](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L31)*
+
+**Parameters:**
+
+Name | Type |
+------ | ------ |
+`accountData` | [AccountData](../interfaces/_account_.accountdata.md) |
+
+**Returns:** *[Account](_account_.account.md)‹›*
+
+___
+
+### `Static` fromRlpSerializedAccount
+
+▸ **fromRlpSerializedAccount**(`serialized`: Buffer): *[Account](_account_.account.md)‹›*
+
+*Defined in [account.ts:42](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L42)*
+
+**Parameters:**
+
+Name | Type |
+------ | ------ |
+`serialized` | Buffer |
+
+**Returns:** *[Account](_account_.account.md)‹›*
+
+___
+
+### `Static` fromValuesArray
+
+▸ **fromValuesArray**(`values`: Buffer[]): *[Account](_account_.account.md)‹›*
+
+*Defined in [account.ts:52](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L52)*
+
+**Parameters:**
+
+Name | Type |
+------ | ------ |
+`values` | Buffer[] |
+
+**Returns:** *[Account](_account_.account.md)‹›*
diff --git a/docs/classes/_address_.address.md b/docs/classes/_address_.address.md
index 9e367281..9059f8c7 100644
--- a/docs/classes/_address_.address.md
+++ b/docs/classes/_address_.address.md
@@ -19,6 +19,7 @@
### Methods
* [isZero](_address_.address.md#iszero)
+* [toBuffer](_address_.address.md#tobuffer)
* [toString](_address_.address.md#tostring)
* [fromPrivateKey](_address_.address.md#static-fromprivatekey)
* [fromPublicKey](_address_.address.md#static-frompublickey)
@@ -65,6 +66,18 @@ Is address zero.
___
+### toBuffer
+
+▸ **toBuffer**(): *Buffer*
+
+*Defined in [address.ts:95](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/address.ts#L95)*
+
+Returns Buffer representation of address.
+
+**Returns:** *Buffer*
+
+___
+
### toString
▸ **toString**(): *string*
diff --git a/docs/interfaces/_account_.accountdata.md b/docs/interfaces/_account_.accountdata.md
new file mode 100644
index 00000000..126266a0
--- /dev/null
+++ b/docs/interfaces/_account_.accountdata.md
@@ -0,0 +1,48 @@
+[ethereumjs-util](../README.md) › ["account"](../modules/_account_.md) › [AccountData](_account_.accountdata.md)
+
+# Interface: AccountData
+
+## Hierarchy
+
+* **AccountData**
+
+## Index
+
+### Properties
+
+* [balance](_account_.accountdata.md#optional-balance)
+* [codeHash](_account_.accountdata.md#optional-codehash)
+* [nonce](_account_.accountdata.md#optional-nonce)
+* [stateRoot](_account_.accountdata.md#optional-stateroot)
+
+## Properties
+
+### `Optional` balance
+
+• **balance**? : *[BNLike](../modules/_types_.md#bnlike)*
+
+*Defined in [account.ts:20](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L20)*
+
+___
+
+### `Optional` codeHash
+
+• **codeHash**? : *[BufferLike](../modules/_types_.md#bufferlike)*
+
+*Defined in [account.ts:22](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L22)*
+
+___
+
+### `Optional` nonce
+
+• **nonce**? : *[BNLike](../modules/_types_.md#bnlike)*
+
+*Defined in [account.ts:19](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L19)*
+
+___
+
+### `Optional` stateRoot
+
+• **stateRoot**? : *[BufferLike](../modules/_types_.md#bufferlike)*
+
+*Defined in [account.ts:21](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L21)*
diff --git a/docs/interfaces/_types_.transformabletoarray.md b/docs/interfaces/_types_.transformabletoarray.md
new file mode 100644
index 00000000..b89bdcba
--- /dev/null
+++ b/docs/interfaces/_types_.transformabletoarray.md
@@ -0,0 +1,34 @@
+[ethereumjs-util](../README.md) › ["types"](../modules/_types_.md) › [TransformableToArray](_types_.transformabletoarray.md)
+
+# Interface: TransformableToArray
+
+## Hierarchy
+
+* **TransformableToArray**
+
+## Index
+
+### Methods
+
+* [toArray](_types_.transformabletoarray.md#toarray)
+* [toBuffer](_types_.transformabletoarray.md#optional-tobuffer)
+
+## Methods
+
+### toArray
+
+▸ **toArray**(): *Uint8Array*
+
+*Defined in [types.ts:30](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L30)*
+
+**Returns:** *Uint8Array*
+
+___
+
+### `Optional` toBuffer
+
+▸ **toBuffer**(): *Buffer*
+
+*Defined in [types.ts:31](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L31)*
+
+**Returns:** *Buffer*
diff --git a/docs/interfaces/_types_.transformabletobuffer.md b/docs/interfaces/_types_.transformabletobuffer.md
new file mode 100644
index 00000000..3a5d1ac2
--- /dev/null
+++ b/docs/interfaces/_types_.transformabletobuffer.md
@@ -0,0 +1,34 @@
+[ethereumjs-util](../README.md) › ["types"](../modules/_types_.md) › [TransformableToBuffer](_types_.transformabletobuffer.md)
+
+# Interface: TransformableToBuffer
+
+## Hierarchy
+
+* **TransformableToBuffer**
+
+## Index
+
+### Methods
+
+* [toArray](_types_.transformabletobuffer.md#optional-toarray)
+* [toBuffer](_types_.transformabletobuffer.md#tobuffer)
+
+## Methods
+
+### `Optional` toArray
+
+▸ **toArray**(): *Uint8Array*
+
+*Defined in [types.ts:39](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L39)*
+
+**Returns:** *Uint8Array*
+
+___
+
+### toBuffer
+
+▸ **toBuffer**(): *Buffer*
+
+*Defined in [types.ts:38](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L38)*
+
+**Returns:** *Buffer*
diff --git a/docs/modules/__types_ethjs_util_index_.md b/docs/modules/__types_ethjs_util_index_.md
new file mode 100644
index 00000000..45cd1a7f
--- /dev/null
+++ b/docs/modules/__types_ethjs_util_index_.md
@@ -0,0 +1,5 @@
+[ethereumjs-util](../README.md) › ["@types/ethjs-util/index"](__types_ethjs_util_index_.md)
+
+# Module: "@types/ethjs-util/index"
+
+
diff --git a/docs/modules/_account_.md b/docs/modules/_account_.md
index b7a054eb..cc0c3998 100644
--- a/docs/modules/_account_.md
+++ b/docs/modules/_account_.md
@@ -4,6 +4,14 @@
## Index
+### Classes
+
+* [Account](../classes/_account_.account.md)
+
+### Interfaces
+
+* [AccountData](../interfaces/_account_.accountdata.md)
+
### Variables
* [publicToAddress](_account_.md#const-publictoaddress)
@@ -30,7 +38,7 @@
• **publicToAddress**: *pubToAddress* = pubToAddress
-*Defined in [account.ts:160](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L160)*
+*Defined in [account.ts:258](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L258)*
## Functions
@@ -38,7 +46,7 @@
▸ **generateAddress**(`from`: Buffer, `nonce`: Buffer): *Buffer*
-*Defined in [account.ts:82](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L82)*
+*Defined in [account.ts:180](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L180)*
Generates an address of a newly created contract.
@@ -57,7 +65,7 @@ ___
▸ **generateAddress2**(`from`: Buffer, `salt`: Buffer, `initCode`: Buffer): *Buffer*
-*Defined in [account.ts:103](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L103)*
+*Defined in [account.ts:201](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L201)*
Generates an address for a contract created using CREATE2.
@@ -77,7 +85,7 @@ ___
▸ **importPublic**(`publicKey`: Buffer): *Buffer*
-*Defined in [account.ts:183](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L183)*
+*Defined in [account.ts:281](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L281)*
Converts a public key to the Ethereum format.
@@ -95,7 +103,7 @@ ___
▸ **isValidAddress**(`hexAddress`: string): *boolean*
-*Defined in [account.ts:21](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L21)*
+*Defined in [account.ts:128](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L128)*
Checks if the address is a valid. Accepts checksummed addresses too.
@@ -113,7 +121,7 @@ ___
▸ **isValidChecksumAddress**(`hexAddress`: string, `eip1191ChainId?`: undefined | number): *boolean*
-*Defined in [account.ts:70](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L70)*
+*Defined in [account.ts:168](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L168)*
Checks if the address is a valid checksummed address.
@@ -134,7 +142,7 @@ ___
▸ **isValidPrivate**(`privateKey`: Buffer): *boolean*
-*Defined in [account.ts:121](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L121)*
+*Defined in [account.ts:219](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L219)*
Checks if the private key satisfies the rules of the curve secp256k1.
@@ -152,7 +160,7 @@ ___
▸ **isValidPublic**(`publicKey`: Buffer, `sanitize`: boolean): *boolean*
-*Defined in [account.ts:131](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L131)*
+*Defined in [account.ts:229](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L229)*
Checks if the public key satisfies the rules of the curve secp256k1
and the requirements of Ethereum.
@@ -172,9 +180,9 @@ ___
▸ **isZeroAddress**(`hexAddress`: string): *boolean*
-*Defined in [account.ts:29](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L29)*
+*Defined in [account.ts:301](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L301)*
-Checks if a given address is a zero address.
+Checks if a given address is the zero address.
**Parameters:**
@@ -190,7 +198,7 @@ ___
▸ **privateToAddress**(`privateKey`: Buffer): *Buffer*
-*Defined in [account.ts:166](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L166)*
+*Defined in [account.ts:264](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L264)*
Returns the ethereum address of a given private key.
@@ -208,7 +216,7 @@ ___
▸ **privateToPublic**(`privateKey`: Buffer): *Buffer*
-*Defined in [account.ts:174](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L174)*
+*Defined in [account.ts:272](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L272)*
Returns the ethereum public key of a given private key.
@@ -226,7 +234,7 @@ ___
▸ **pubToAddress**(`pubKey`: Buffer, `sanitize`: boolean): *Buffer*
-*Defined in [account.ts:151](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L151)*
+*Defined in [account.ts:249](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L249)*
Returns the ethereum address of a given public key.
Accepts "Ethereum public keys" and SEC1 encoded keys.
@@ -246,13 +254,13 @@ ___
▸ **toChecksumAddress**(`hexAddress`: string, `eip1191ChainId?`: undefined | number): *string*
-*Defined in [account.ts:45](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L45)*
+*Defined in [account.ts:143](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L143)*
Returns a checksummed address.
If a eip1191ChainId is provided, the chainId will be included in the checksum calculation. This
has the effect of checksummed addresses for one chain having invalid checksums for others.
-For more details, consult EIP-1191.
+For more details see [EIP-1191](https://eips.ethereum.org/EIPS/eip-1191).
WARNING: Checksums with and without the chainId will differ. As of 2019-06-26, the most commonly
used variation in Ethereum was without the chainId. This may change in the future.
@@ -272,8 +280,8 @@ ___
▸ **zeroAddress**(): *string*
-*Defined in [account.ts:12](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L12)*
+*Defined in [account.ts:292](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/account.ts#L292)*
-Returns a zero address.
+Returns the zero address.
**Returns:** *string*
diff --git a/docs/modules/_bytes_.md b/docs/modules/_bytes_.md
index 9fb775c1..15cbd175 100644
--- a/docs/modules/_bytes_.md
+++ b/docs/modules/_bytes_.md
@@ -26,7 +26,7 @@
▸ **addHexPrefix**(`str`: string): *string*
-*Defined in [bytes.ts:176](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L176)*
+*Defined in [bytes.ts:204](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L204)*
Adds "0x" to a given `String` if it does not already start with "0x".
@@ -44,7 +44,7 @@ ___
▸ **baToJSON**(`ba`: any): *any*
-*Defined in [bytes.ts:189](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L189)*
+*Defined in [bytes.ts:217](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L217)*
Converts a `Buffer` or `Array` to JSON.
@@ -64,7 +64,7 @@ ___
▸ **bufferToHex**(`buf`: Buffer): *string*
-*Defined in [bytes.ts:152](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L152)*
+*Defined in [bytes.ts:180](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L180)*
Converts a `Buffer` into a `0x`-prefixed hex `String`.
@@ -82,7 +82,7 @@ ___
▸ **bufferToInt**(`buf`: Buffer): *number*
-*Defined in [bytes.ts:144](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L144)*
+*Defined in [bytes.ts:172](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L172)*
Converts a `Buffer` to a `Number`.
@@ -100,7 +100,7 @@ ___
▸ **fromSigned**(`num`: Buffer): *BN*
-*Defined in [bytes.ts:161](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L161)*
+*Defined in [bytes.ts:189](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L189)*
Interprets a `Buffer` as a signed integer and returns a `BN`. Assumes 256-bit numbers.
@@ -118,7 +118,7 @@ ___
▸ **setLengthLeft**(`msg`: Buffer, `length`: number): *Buffer‹›*
-*Defined in [bytes.ts:20](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L20)*
+*Defined in [bytes.ts:21](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L21)*
Left Pads a `Buffer` with leading zeros till it has `length` bytes.
Or it truncates the beginning if it exceeds.
@@ -140,7 +140,7 @@ ___
▸ **setLengthRight**(`msg`: Buffer, `length`: number): *Buffer‹›*
-*Defined in [bytes.ts:32](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L32)*
+*Defined in [bytes.ts:33](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L33)*
Right Pads a `Buffer` with trailing zeros till it has `length` bytes.
it truncates the end if it exceeds.
@@ -160,17 +160,18 @@ ___
### `Const` toBuffer
-▸ **toBuffer**(`v`: any): *Buffer*
+▸ **toBuffer**(`v`: string | number | BN | Buffer | Uint8Array | number[] | [TransformableToArray](../interfaces/_types_.transformabletoarray.md) | [TransformableToBuffer](../interfaces/_types_.transformabletobuffer.md) | null | undefined): *Buffer*
-*Defined in [bytes.ts:111](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L111)*
+*Defined in [bytes.ts:113](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L113)*
-Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method.
+Attempts to turn a value into a `Buffer`.
+Inputs supported: `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` or `toBuffer()` method.
**Parameters:**
Name | Type | Description |
------ | ------ | ------ |
-`v` | any | the value |
+`v` | string | number | BN | Buffer | Uint8Array | number[] | [TransformableToArray](../interfaces/_types_.transformabletoarray.md) | [TransformableToBuffer](../interfaces/_types_.transformabletobuffer.md) | null | undefined | the value |
**Returns:** *Buffer*
@@ -180,7 +181,7 @@ ___
▸ **toUnsigned**(`num`: BN): *Buffer*
-*Defined in [bytes.ts:169](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L169)*
+*Defined in [bytes.ts:197](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L197)*
Converts a `BN` to an unsigned integer and returns it as a `Buffer`. Assumes 256-bit numbers.
@@ -198,7 +199,7 @@ ___
▸ **unpadArray**(`a`: number[]): *number[]*
-*Defined in [bytes.ts:77](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L77)*
+*Defined in [bytes.ts:78](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L78)*
Trims leading zeros from an `Array` (of numbers).
@@ -218,7 +219,7 @@ ___
▸ **unpadBuffer**(`a`: Buffer): *Buffer*
-*Defined in [bytes.ts:67](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L67)*
+*Defined in [bytes.ts:68](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L68)*
Trims leading zeros from a `Buffer`.
@@ -238,7 +239,7 @@ ___
▸ **unpadHexString**(`a`: string): *string*
-*Defined in [bytes.ts:87](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L87)*
+*Defined in [bytes.ts:88](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L88)*
Trims leading zeros from a hex-prefixed `String`.
@@ -258,7 +259,7 @@ ___
▸ **zeros**(`bytes`: number): *Buffer*
-*Defined in [bytes.ts:9](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L9)*
+*Defined in [bytes.ts:10](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/bytes.ts#L10)*
Returns a buffer filled with 0s.
diff --git a/docs/modules/_externals_.md b/docs/modules/_externals_.md
index 2d9a6773..6381f333 100644
--- a/docs/modules/_externals_.md
+++ b/docs/modules/_externals_.md
@@ -3,5 +3,4 @@
# Module: "externals"
Re-exports commonly used modules:
-* Adds [`ethjs-util`](https://github.com/ethjs/ethjs-util) methods.
* Exports [`BN`](https://github.com/indutny/bn.js), [`rlp`](https://github.com/ethereumjs/rlp).
diff --git a/docs/modules/_hash_.md b/docs/modules/_hash_.md
index da56fa04..5f515614 100644
--- a/docs/modules/_hash_.md
+++ b/docs/modules/_hash_.md
@@ -44,7 +44,7 @@ ___
▸ **keccak256**(`a`: Buffer): *Buffer*
-*Defined in [hash.ts:24](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L24)*
+*Defined in [hash.ts:38](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L38)*
Creates Keccak-256 hash of the input, alias for keccak(a, 256).
@@ -62,7 +62,7 @@ ___
▸ **keccakFromArray**(`a`: number[], `bits`: number): *Buffer‹›*
-*Defined in [hash.ts:54](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L54)*
+*Defined in [hash.ts:68](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L68)*
Creates Keccak hash of a number array input
@@ -81,7 +81,7 @@ ___
▸ **keccakFromHexString**(`a`: string, `bits`: number): *Buffer‹›*
-*Defined in [hash.ts:44](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L44)*
+*Defined in [hash.ts:58](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L58)*
Creates Keccak hash of an 0x-prefixed string input
@@ -100,7 +100,7 @@ ___
▸ **keccakFromString**(`a`: string, `bits`: number): *Buffer‹›*
-*Defined in [hash.ts:33](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L33)*
+*Defined in [hash.ts:47](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L47)*
Creates Keccak hash of a utf-8 string input
@@ -119,7 +119,7 @@ ___
▸ **ripemd160**(`a`: Buffer, `padded`: boolean): *Buffer*
-*Defined in [hash.ts:102](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L102)*
+*Defined in [hash.ts:116](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L116)*
Creates RIPEMD160 hash of a Buffer input.
@@ -138,7 +138,7 @@ ___
▸ **ripemd160FromArray**(`a`: number[], `padded`: boolean): *Buffer*
-*Defined in [hash.ts:122](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L122)*
+*Defined in [hash.ts:136](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L136)*
Creates RIPEMD160 hash of a number[] input.
@@ -157,7 +157,7 @@ ___
▸ **ripemd160FromString**(`a`: string, `padded`: boolean): *Buffer*
-*Defined in [hash.ts:112](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L112)*
+*Defined in [hash.ts:126](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L126)*
Creates RIPEMD160 hash of a string input.
@@ -176,7 +176,7 @@ ___
▸ **rlphash**(`a`: rlp.Input): *Buffer*
-*Defined in [hash.ts:148](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L148)*
+*Defined in [hash.ts:162](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L162)*
Creates SHA-3 hash of the RLP encoded version of the input.
@@ -194,7 +194,7 @@ ___
▸ **sha256**(`a`: Buffer): *Buffer*
-*Defined in [hash.ts:63](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L63)*
+*Defined in [hash.ts:77](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L77)*
Creates SHA256 hash of a Buffer input.
@@ -212,7 +212,7 @@ ___
▸ **sha256FromArray**(`a`: number[]): *Buffer*
-*Defined in [hash.ts:81](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L81)*
+*Defined in [hash.ts:95](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L95)*
Creates SHA256 hash of a number[] input.
@@ -230,7 +230,7 @@ ___
▸ **sha256FromString**(`a`: string): *Buffer*
-*Defined in [hash.ts:72](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L72)*
+*Defined in [hash.ts:86](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/hash.ts#L86)*
Creates SHA256 hash of a string input.
diff --git a/docs/modules/_types_.md b/docs/modules/_types_.md
new file mode 100644
index 00000000..8167f51f
--- /dev/null
+++ b/docs/modules/_types_.md
@@ -0,0 +1,62 @@
+[ethereumjs-util](../README.md) › ["types"](_types_.md)
+
+# Module: "types"
+
+## Index
+
+### Interfaces
+
+* [TransformableToArray](../interfaces/_types_.transformabletoarray.md)
+* [TransformableToBuffer](../interfaces/_types_.transformabletobuffer.md)
+
+### Type aliases
+
+* [BNLike](_types_.md#bnlike)
+* [BufferLike](_types_.md#bufferlike)
+* [PrefixedHexString](_types_.md#prefixedhexstring)
+
+### Functions
+
+* [bnToRlp](_types_.md#bntorlp)
+
+## Type aliases
+
+### BNLike
+
+Ƭ **BNLike**: *BN | string | number*
+
+*Defined in [types.ts:7](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L7)*
+
+___
+
+### BufferLike
+
+Ƭ **BufferLike**: *Buffer | Uint8Array | number[] | number | BN | [TransformableToBuffer](../interfaces/_types_.transformabletobuffer.md) | [PrefixedHexString](_types_.md#prefixedhexstring)*
+
+*Defined in [types.ts:12](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L12)*
+
+___
+
+### PrefixedHexString
+
+Ƭ **PrefixedHexString**: *string*
+
+*Defined in [types.ts:24](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L24)*
+
+## Functions
+
+### bnToRlp
+
+▸ **bnToRlp**(`value`: BN): *Buffer*
+
+*Defined in [types.ts:46](https://github.com/ethereumjs/ethereumjs-util/blob/master/src/types.ts#L46)*
+
+Convert value from BN to RLP (unpadded buffer)
+
+**Parameters:**
+
+Name | Type | Description |
+------ | ------ | ------ |
+`value` | BN | value to convert |
+
+**Returns:** *Buffer*
diff --git a/karma.conf.js b/karma.conf.js
index f166a9e5..f9617f27 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -1,24 +1,23 @@
module.exports = function(config) {
config.set({
- frameworks: ['mocha', 'karma-typescript'],
- exclude: ["src/@types/**"], // ref: https://github.com/monounity/karma-typescript/issues/254
+ frameworks: ['tap', 'karma-typescript'],
files: ['src/**/*.ts', 'test/**/*.ts'],
preprocessors: {
- '**/*.ts': ['karma-typescript'],
+ '**/*.ts': ['karma-typescript']
},
- plugins: ['karma-mocha', 'karma-typescript', 'karma-chrome-launcher', 'karma-firefox-launcher'],
karmaTypescriptConfig: {
bundlerOptions: {
- entrypoints: /\.spec\.ts$/,
+ entrypoints: /\.spec\.ts$/
},
+ tsconfig: './tsconfig.json'
},
colors: true,
reporters: ['progress', 'karma-typescript'],
browsers: ['FirefoxHeadless', 'ChromeHeadless'],
singleRun: true,
- concurrency: Infinity,
+ concurrency: 1,
// Fail after timeout
browserDisconnectTimeout: 100000,
- browserNoActivityTimeout: 100000,
+ browserNoActivityTimeout: 100000
})
}
diff --git a/package.json b/package.json
index 2ee6ec6d..93430636 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ethereumjs-util",
- "version": "7.0.5",
+ "version": "7.0.9",
"description": "a collection of utility functions for Ethereum",
"main": "dist/index.js",
"types": "./dist/index.d.ts",
@@ -11,19 +11,16 @@
"dist"
],
"scripts": {
- "build": "ethereumjs-config-build",
+ "build": "ethereumjs-config-ts-build",
"prepublishOnly": "npm run test && npm run build",
+ "coverage": "ethereumjs-config-coverage",
"docs:build": "npx typedoc --options typedoc.js",
- "format": "ethereumjs-config-format",
- "format:fix": "ethereumjs-config-format-fix",
"lint": "ethereumjs-config-lint",
"lint:fix": "ethereumjs-config-lint-fix",
- "test": "npm run lint && npm run test:node && npm run test:browser",
+ "test": "npm run test:node && npm run test:browser",
"test:browser": "karma start karma.conf.js",
- "test:node": "nyc --reporter=lcov mocha 'test/*.spec.ts' -- --require ts-node/register",
- "tsc": "ethereumjs-config-tsc",
- "tslint": "ethereumjs-config-tslint",
- "tslint:fix": "ethereumjs-config-tslint-fix"
+ "test:node": "tape -r ts-node/register test/*.spec.ts",
+ "tsc": "ethereumjs-config-tsc"
},
"husky": {
"hooks": {
@@ -89,7 +86,7 @@
},
"homepage": "https://github.com/ethereumjs/ethereumjs-util",
"dependencies": {
- "@types/bn.js": "^4.11.3",
+ "@types/bn.js": "^5.1.0",
"bn.js": "^5.1.2",
"create-hash": "^1.1.2",
"ethereum-cryptography": "^0.1.3",
@@ -97,26 +94,25 @@
"rlp": "^2.2.4"
},
"devDependencies": {
- "@ethereumjs/config-prettier": "^1.1.0",
- "@ethereumjs/config-tsc": "^1.1.0",
- "@ethereumjs/config-tslint": "^1.1.0",
- "@types/mocha": "^5.2.7",
+ "@ethereumjs/config-coverage": "^2.0.0",
+ "@ethereumjs/config-typescript": "^2.0.0",
+ "@ethereumjs/eslint-config-defaults": "^2.0.0",
+ "@types/assert": "^1.5.4",
"@types/node": "^11.9.0",
"@types/secp256k1": "^4.0.1",
+ "@types/tape": "^4.13.0",
"husky": "^2.1.0",
"karma": "^5.0.2",
"karma-chrome-launcher": "^2.0.0",
"karma-firefox-launcher": "^1.0.0",
- "karma-mocha": "^2.0.0",
+ "karma-tap": "^4.2.0",
"karma-typescript": "^4.1.1",
- "mocha": "^6.0.0",
"nyc": "^15.0.0",
"prettier": "^1.15.3",
+ "tape": "^5.2.2",
"ts-node": "^8.6.2",
- "tslint": "^5.12.0",
"typedoc": "next",
"typedoc-plugin-markdown": "^2.2.16",
- "typescript": "^3.8.3",
- "typestrict": "^1.0.2"
+ "typescript": "^3.8.3"
}
}
diff --git a/prettier.config.js b/prettier.config.js
index 0f2e5b7a..71472721 100644
--- a/prettier.config.js
+++ b/prettier.config.js
@@ -1 +1 @@
-module.exports = require('@ethereumjs/config-prettier')
+module.exports = require('@ethereumjs/eslint-config-defaults/prettier.config.js')
diff --git a/src/account.ts b/src/account.ts
index 125ef2d9..b4893b76 100644
--- a/src/account.ts
+++ b/src/account.ts
@@ -1,23 +1,121 @@
-import * as ethjsUtil from 'ethjs-util'
-const {
+import assert from 'assert'
+import BN from 'bn.js'
+import * as rlp from 'rlp'
+import {
privateKeyVerify,
publicKeyCreate,
publicKeyVerify,
- publicKeyConvert,
-} = require('ethereum-cryptography/secp256k1')
-import * as assert from 'assert'
-import * as BN from 'bn.js'
-import { zeros, bufferToHex } from './bytes'
+ publicKeyConvert
+} from 'ethereum-cryptography/secp256k1'
+import { stripHexPrefix } from 'ethjs-util'
+import { KECCAK256_RLP, KECCAK256_NULL } from './constants'
+import { zeros, bufferToHex, toBuffer } from './bytes'
import { keccak, keccak256, keccakFromString, rlphash } from './hash'
import { assertIsHexString, assertIsBuffer } from './helpers'
+import { BNLike, BufferLike, bnToRlp, toType, TypeOutput } from './types'
-/**
- * Returns a zero address.
- */
-export const zeroAddress = function(): string {
- const addressLength = 20
- const addr = zeros(addressLength)
- return bufferToHex(addr)
+export interface AccountData {
+ nonce?: BNLike
+ balance?: BNLike
+ stateRoot?: BufferLike
+ codeHash?: BufferLike
+}
+
+export class Account {
+ nonce: BN
+ balance: BN
+ stateRoot: Buffer
+ codeHash: Buffer
+
+ static fromAccountData(accountData: AccountData) {
+ const { nonce, balance, stateRoot, codeHash } = accountData
+
+ return new Account(
+ nonce ? new BN(toBuffer(nonce)) : undefined,
+ balance ? new BN(toBuffer(balance)) : undefined,
+ stateRoot ? toBuffer(stateRoot) : undefined,
+ codeHash ? toBuffer(codeHash) : undefined
+ )
+ }
+
+ public static fromRlpSerializedAccount(serialized: Buffer) {
+ const values = rlp.decode(serialized)
+
+ if (!Array.isArray(values)) {
+ throw new Error('Invalid serialized account input. Must be array')
+ }
+
+ return this.fromValuesArray(values)
+ }
+
+ public static fromValuesArray(values: Buffer[]) {
+ const [nonce, balance, stateRoot, codeHash] = values
+
+ return new Account(new BN(nonce), new BN(balance), stateRoot, codeHash)
+ }
+
+ /**
+ * This constructor assigns and validates the values.
+ * Use the static factory methods to assist in creating an Account from varying data types.
+ */
+ constructor(
+ nonce = new BN(0),
+ balance = new BN(0),
+ stateRoot = KECCAK256_RLP,
+ codeHash = KECCAK256_NULL
+ ) {
+ this.nonce = nonce
+ this.balance = balance
+ this.stateRoot = stateRoot
+ this.codeHash = codeHash
+
+ this._validate()
+ }
+
+ private _validate() {
+ if (this.nonce.lt(new BN(0))) {
+ throw new Error('nonce must be greater than zero')
+ }
+ if (this.balance.lt(new BN(0))) {
+ throw new Error('balance must be greater than zero')
+ }
+ if (this.stateRoot.length !== 32) {
+ throw new Error('stateRoot must have a length of 32')
+ }
+ if (this.codeHash.length !== 32) {
+ throw new Error('codeHash must have a length of 32')
+ }
+ }
+
+ /**
+ * Returns a Buffer Array of the raw Buffers for the account, in order.
+ */
+ raw(): Buffer[] {
+ return [bnToRlp(this.nonce), bnToRlp(this.balance), this.stateRoot, this.codeHash]
+ }
+
+ /**
+ * Returns the RLP serialization of the account as a `Buffer`.
+ */
+ serialize(): Buffer {
+ return rlp.encode(this.raw())
+ }
+
+ /**
+ * Returns a `Boolean` determining if the account is a contract.
+ */
+ isContract(): boolean {
+ return !this.codeHash.equals(KECCAK256_NULL)
+ }
+
+ /**
+ * Returns a `Boolean` determining if the account is empty complying to the definition of
+ * account emptiness in [EIP-161](https://eips.ethereum.org/EIPS/eip-161):
+ * "An account is considered empty when it has no code and zero nonce and zero balance."
+ */
+ isEmpty(): boolean {
+ return this.balance.isZero() && this.nonce.isZero() && this.codeHash.equals(KECCAK256_NULL)
+ }
}
/**
@@ -28,30 +126,25 @@ export const isValidAddress = function(hexAddress: string): boolean {
return /^0x[0-9a-fA-F]{40}$/.test(hexAddress)
}
-/**
- * Checks if a given address is a zero address.
- */
-export const isZeroAddress = function(hexAddress: string): boolean {
- assertIsHexString(hexAddress)
- const zeroAddr = zeroAddress()
- return zeroAddr === hexAddress
-}
-
/**
* Returns a checksummed address.
*
* If a eip1191ChainId is provided, the chainId will be included in the checksum calculation. This
* has the effect of checksummed addresses for one chain having invalid checksums for others.
- * For more details, consult EIP-1191.
+ * For more details see [EIP-1191](https://eips.ethereum.org/EIPS/eip-1191).
*
* WARNING: Checksums with and without the chainId will differ. As of 2019-06-26, the most commonly
* used variation in Ethereum was without the chainId. This may change in the future.
*/
-export const toChecksumAddress = function(hexAddress: string, eip1191ChainId?: number): string {
+export const toChecksumAddress = function(hexAddress: string, eip1191ChainId?: BNLike): string {
assertIsHexString(hexAddress)
- const address = ethjsUtil.stripHexPrefix(hexAddress).toLowerCase()
+ const address = stripHexPrefix(hexAddress).toLowerCase()
- const prefix = eip1191ChainId !== undefined ? eip1191ChainId.toString() + '0x' : ''
+ let prefix = ''
+ if (eip1191ChainId) {
+ const chainId = toType(eip1191ChainId, TypeOutput.BN)
+ prefix = chainId.toString() + '0x'
+ }
const hash = keccakFromString(prefix + address).toString('hex')
let ret = '0x'
@@ -74,7 +167,7 @@ export const toChecksumAddress = function(hexAddress: string, eip1191ChainId?: n
*/
export const isValidChecksumAddress = function(
hexAddress: string,
- eip1191ChainId?: number,
+ eip1191ChainId?: BNLike
): boolean {
return isValidAddress(hexAddress) && toChecksumAddress(hexAddress, eip1191ChainId) === hexAddress
}
@@ -114,7 +207,7 @@ export const generateAddress2 = function(from: Buffer, salt: Buffer, initCode: B
assert(salt.length === 32)
const address = keccak256(
- Buffer.concat([Buffer.from('ff', 'hex'), from, salt, keccak256(initCode)]),
+ Buffer.concat([Buffer.from('ff', 'hex'), from, salt, keccak256(initCode)])
)
return address.slice(-20)
@@ -164,14 +257,6 @@ export const pubToAddress = function(pubKey: Buffer, sanitize: boolean = false):
}
export const publicToAddress = pubToAddress
-/**
- * Returns the ethereum address of a given private key.
- * @param privateKey A private key must be 256 bits wide
- */
-export const privateToAddress = function(privateKey: Buffer): Buffer {
- return publicToAddress(privateToPublic(privateKey))
-}
-
/**
* Returns the ethereum public key of a given private key.
* @param privateKey A private key must be 256 bits wide
@@ -182,6 +267,14 @@ export const privateToPublic = function(privateKey: Buffer): Buffer {
return Buffer.from(publicKeyCreate(privateKey, false)).slice(1)
}
+/**
+ * Returns the ethereum address of a given private key.
+ * @param privateKey A private key must be 256 bits wide
+ */
+export const privateToAddress = function(privateKey: Buffer): Buffer {
+ return publicToAddress(privateToPublic(privateKey))
+}
+
/**
* Converts a public key to the Ethereum format.
*/
@@ -192,3 +285,21 @@ export const importPublic = function(publicKey: Buffer): Buffer {
}
return publicKey
}
+
+/**
+ * Returns the zero address.
+ */
+export const zeroAddress = function(): string {
+ const addressLength = 20
+ const addr = zeros(addressLength)
+ return bufferToHex(addr)
+}
+
+/**
+ * Checks if a given address is the zero address.
+ */
+export const isZeroAddress = function(hexAddress: string): boolean {
+ assertIsHexString(hexAddress)
+ const zeroAddr = zeroAddress()
+ return zeroAddr === hexAddress
+}
diff --git a/src/address.ts b/src/address.ts
index d052ce0d..e5ff90ea 100644
--- a/src/address.ts
+++ b/src/address.ts
@@ -1,12 +1,12 @@
-const assert = require('assert')
-import BN = require('bn.js')
+import assert from 'assert'
+import BN from 'bn.js'
import { toBuffer, zeros } from './bytes'
import {
isValidAddress,
pubToAddress,
privateToAddress,
generateAddress,
- generateAddress2,
+ generateAddress2
} from './account'
export class Address {
@@ -75,11 +75,18 @@ export class Address {
return new Address(generateAddress2(from.buf, salt, initCode))
}
+ /**
+ * Is address equal to another.
+ */
+ equals(address: Address): boolean {
+ return this.buf.equals(address.buf)
+ }
+
/**
* Is address zero.
*/
isZero(): boolean {
- return this.buf.equals(Address.zero().buf)
+ return this.equals(Address.zero())
}
/**
@@ -88,4 +95,11 @@ export class Address {
toString(): string {
return '0x' + this.buf.toString('hex')
}
+
+ /**
+ * Returns Buffer representation of address.
+ */
+ toBuffer(): Buffer {
+ return Buffer.from(this.buf)
+ }
}
diff --git a/src/bytes.ts b/src/bytes.ts
index 6e938f06..f2229e3b 100644
--- a/src/bytes.ts
+++ b/src/bytes.ts
@@ -1,5 +1,6 @@
-import * as ethjsUtil from 'ethjs-util'
-import * as BN from 'bn.js'
+import BN from 'bn.js'
+import { intToBuffer, stripHexPrefix, padToEven, isHexString, isHexPrefixed } from 'ethjs-util'
+import { PrefixedHexString, TransformableToArray, TransformableToBuffer } from './types'
import { assertIsBuffer, assertIsArray, assertIsHexString } from './helpers'
/**
@@ -10,6 +11,31 @@ export const zeros = function(bytes: number): Buffer {
return Buffer.allocUnsafe(bytes).fill(0)
}
+/**
+ * Pads a `Buffer` 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)
+ */
+const setLength = function(msg: Buffer, length: number, right: boolean) {
+ const buf = zeros(length)
+ if (right) {
+ if (msg.length < length) {
+ msg.copy(buf)
+ return buf
+ }
+ return msg.slice(0, length)
+ } else {
+ if (msg.length < length) {
+ msg.copy(buf, length - msg.length)
+ return buf
+ }
+ return msg.slice(-length)
+ }
+}
+
/**
* Left Pads a `Buffer` with leading zeros till it has `length` bytes.
* Or it truncates the beginning if it exceeds.
@@ -35,28 +61,17 @@ export const setLengthRight = function(msg: Buffer, length: number) {
}
/**
- * Pads a `Buffer` 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)
+ * Trims leading zeros from a `Buffer`, `String` or `Number[]`.
+ * @param a (Buffer|Array|String)
+ * @return (Buffer|Array|String)
*/
-const setLength = function(msg: Buffer, length: number, right: boolean) {
- const buf = zeros(length)
- if (right) {
- if (msg.length < length) {
- msg.copy(buf)
- return buf
- }
- return msg.slice(0, length)
- } else {
- if (msg.length < length) {
- msg.copy(buf, length - msg.length)
- return buf
- }
- return msg.slice(-length)
+const stripZeros = function(a: any): Buffer | number[] | string {
+ let first = a[0]
+ while (a.length > 0 && first.toString() === '0') {
+ a = a.slice(1)
+ first = a[0]
}
+ return a
}
/**
@@ -86,54 +101,67 @@ export const unpadArray = function(a: number[]): number[] {
*/
export const unpadHexString = function(a: string): string {
assertIsHexString(a)
- a = ethjsUtil.stripHexPrefix(a)
+ a = stripHexPrefix(a)
return stripZeros(a) as string
}
-/**
- * Trims leading zeros from a `Buffer`, `String` or `Number[]`.
- * @param a (Buffer|Array|String)
- * @return (Buffer|Array|String)
- */
-const stripZeros = function(a: any): Buffer | number[] | string {
- let first = a[0]
- while (a.length > 0 && first.toString() === '0') {
- a = a.slice(1)
- first = a[0]
- }
- return a
-}
+export type ToBufferInputTypes =
+ | PrefixedHexString
+ | number
+ | BN
+ | Buffer
+ | Uint8Array
+ | number[]
+ | TransformableToArray
+ | TransformableToBuffer
+ | null
+ | undefined
/**
- * Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method.
+ * Attempts to turn a value into a `Buffer`.
+ * Inputs supported: `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` or `toBuffer()` method.
* @param v the value
*/
-export const toBuffer = function(v: any): Buffer {
- if (!Buffer.isBuffer(v)) {
- if (Array.isArray(v) || v instanceof Uint8Array) {
- v = Buffer.from(v as Uint8Array)
- } else if (typeof v === 'string') {
- if (ethjsUtil.isHexString(v)) {
- v = Buffer.from(ethjsUtil.padToEven(ethjsUtil.stripHexPrefix(v)), 'hex')
- } else {
- throw new Error(
- `Cannot convert string to buffer. toBuffer only supports 0x-prefixed hex strings and this string was given: ${v}`,
- )
- }
- } else if (typeof v === 'number') {
- v = ethjsUtil.intToBuffer(v)
- } else if (v === null || v === undefined) {
- v = Buffer.allocUnsafe(0)
- } else if (BN.isBN(v)) {
- v = v.toArrayLike(Buffer)
- } else if (v.toArray) {
- // converts a BN to a Buffer
- v = Buffer.from(v.toArray())
- } else {
- throw new Error('invalid type')
+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 (BN.isBN(v)) {
+ return v.toArrayLike(Buffer)
}
- return v
+
+ 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')
}
/**
@@ -178,7 +206,7 @@ export const addHexPrefix = function(str: string): string {
return str
}
- return ethjsUtil.isHexPrefixed(str) ? str : '0x' + str
+ return isHexPrefixed(str) ? str : '0x' + str
}
/**
diff --git a/src/constants.ts b/src/constants.ts
index 160284f3..dc0742b6 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,12 +1,12 @@
const Buffer = require('buffer').Buffer
-import * as BN from 'bn.js'
+import BN from 'bn.js'
/**
* The max integer that this VM can handle
*/
export const MAX_INTEGER: BN = new BN(
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
- 16,
+ 16
)
/**
@@ -14,7 +14,7 @@ export const MAX_INTEGER: BN = new BN(
*/
export const TWO_POW256: BN = new BN(
'10000000000000000000000000000000000000000000000000000000000000000',
- 16,
+ 16
)
/**
diff --git a/src/externals.ts b/src/externals.ts
index 22eb12af..17fae578 100644
--- a/src/externals.ts
+++ b/src/externals.ts
@@ -4,11 +4,8 @@
* @packageDocumentation
*/
-// TODO: This can be replaced with a normal ESM import once
-// the new major version of the typescript config package
-// is released and adopted here.
-import BN = require('bn.js')
-import rlp = require('rlp')
+import BN from 'bn.js'
+import * as rlp from 'rlp'
/**
* [`BN`](https://github.com/indutny/bn.js)
diff --git a/src/hash.ts b/src/hash.ts
index 51a30ddc..d6a541de 100644
--- a/src/hash.ts
+++ b/src/hash.ts
@@ -1,6 +1,5 @@
-const { keccak224, keccak384, keccak256: k256, keccak512 } = require('ethereum-cryptography/keccak')
+import { keccak224, keccak384, keccak256 as k256, keccak512 } from 'ethereum-cryptography/keccak'
const createHash = require('create-hash')
-import * as ethjsUtil from 'ethjs-util'
import * as rlp from 'rlp'
import { toBuffer, setLengthLeft } from './bytes'
import { assertIsString, assertIsBuffer, assertIsArray, assertIsHexString } from './helpers'
@@ -70,6 +69,17 @@ export const keccakFromArray = function(a: number[], bits: number = 256) {
return keccak(toBuffer(a), bits)
}
+/**
+ * Creates SHA256 hash of an input.
+ * @param a The input data (Buffer|Array|String)
+ */
+const _sha256 = function(a: any): Buffer {
+ a = toBuffer(a)
+ return createHash('sha256')
+ .update(a)
+ .digest()
+}
+
/**
* Creates SHA256 hash of a Buffer input.
* @param a The input data (Buffer)
@@ -98,14 +108,20 @@ export const sha256FromArray = function(a: number[]): Buffer {
}
/**
- * Creates SHA256 hash of an input.
- * @param a The input data (Buffer|Array|String)
+ * Creates RIPEMD160 hash of the input.
+ * @param a The input data (Buffer|Array|String|Number)
+ * @param padded Whether it should be padded to 256 bits or not
*/
-const _sha256 = function(a: any): Buffer {
+const _ripemd160 = function(a: any, padded: boolean): Buffer {
a = toBuffer(a)
- return createHash('sha256')
+ const hash = createHash('rmd160')
.update(a)
.digest()
+ if (padded === true) {
+ return setLengthLeft(hash, 32)
+ } else {
+ return hash
+ }
}
/**
@@ -138,23 +154,6 @@ export const ripemd160FromArray = function(a: number[], padded: boolean): Buffer
return _ripemd160(a, padded)
}
-/**
- * Creates RIPEMD160 hash of the input.
- * @param a The input data (Buffer|Array|String|Number)
- * @param padded Whether it should be padded to 256 bits or not
- */
-const _ripemd160 = function(a: any, padded: boolean): Buffer {
- a = toBuffer(a)
- const hash = createHash('rmd160')
- .update(a)
- .digest()
- if (padded === true) {
- return setLengthLeft(hash, 32)
- } else {
- return hash
- }
-}
-
/**
* Creates SHA-3 hash of the RLP encoded version of the input.
* @param a The input data
diff --git a/src/helpers.ts b/src/helpers.ts
index 5f48ae39..3fd4eacd 100644
--- a/src/helpers.ts
+++ b/src/helpers.ts
@@ -1,11 +1,11 @@
-import * as ethjsUtil from 'ethjs-util'
+import { isHexString } from 'ethjs-util'
/**
* Throws if a string is not hex prefixed
* @param {string} input string to check hex prefix of
*/
export const assertIsHexString = function(input: string): void {
- if (!ethjsUtil.isHexString(input)) {
+ if (!isHexString(input)) {
const msg = `This method only supports 0x-prefixed hex strings but input was: ${input}`
throw new Error(msg)
}
diff --git a/src/index.ts b/src/index.ts
index bf462b49..848d0c77 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -5,7 +5,7 @@
export * from './constants'
/**
- * Public-key cryptography (secp256k1) and addresses
+ * Account class and helper functions
*/
export * from './account'
@@ -39,6 +39,11 @@ export * from './object'
*/
export * from './externals'
+/**
+ * Helpful TypeScript types
+ */
+export * from './types'
+
/**
* Export ethjs-util methods
*/
diff --git a/src/object.ts b/src/object.ts
index e24991eb..c5c55c6e 100644
--- a/src/object.ts
+++ b/src/object.ts
@@ -1,5 +1,5 @@
+import assert from 'assert'
import * as ethjsUtil from 'ethjs-util'
-import * as assert from 'assert'
import * as rlp from 'rlp'
import { toBuffer, baToJSON, unpadBuffer } from './bytes'
@@ -51,12 +51,12 @@ export const defineProperties = function(self: any, fields: any, data?: any) {
v = unpadBuffer(v)
assert(
field.length >= v.length,
- `The field ${field.name} must not have more ${field.length} bytes`,
+ `The field ${field.name} must not have more ${field.length} bytes`
)
} else if (!(field.allowZero && v.length === 0) && field.length) {
assert(
field.length === v.length,
- `The field ${field.name} must have byte length of ${field.length}`,
+ `The field ${field.name} must have byte length of ${field.length}`
)
}
@@ -67,7 +67,7 @@ export const defineProperties = function(self: any, fields: any, data?: any) {
enumerable: true,
configurable: true,
get: getter,
- set: setter,
+ set: setter
})
if (field.default) {
@@ -80,7 +80,7 @@ export const defineProperties = function(self: any, fields: any, data?: any) {
enumerable: false,
configurable: true,
set: setter,
- get: getter,
+ get: getter
})
}
})
diff --git a/src/signature.ts b/src/signature.ts
index 2a85d50b..31424a36 100644
--- a/src/signature.ts
+++ b/src/signature.ts
@@ -1,8 +1,9 @@
-const { ecdsaSign, ecdsaRecover, publicKeyConvert } = require('ethereum-cryptography/secp256k1')
-import * as BN from 'bn.js'
-import { toBuffer, setLengthLeft, bufferToHex } from './bytes'
+import { ecdsaSign, ecdsaRecover, publicKeyConvert } from 'ethereum-cryptography/secp256k1'
+import BN from 'bn.js'
+import { toBuffer, setLengthLeft, bufferToHex, bufferToInt } from './bytes'
import { keccak } from './hash'
import { assertIsBuffer } from './helpers'
+import { BNLike, toType, TypeOutput } from './types'
export interface ECDSASignature {
v: number
@@ -10,24 +11,55 @@ export interface ECDSASignature {
s: Buffer
}
+export interface ECDSASignatureBuffer {
+ v: Buffer
+ r: Buffer
+ s: Buffer
+}
+
/**
* Returns the ECDSA signature of a message hash.
*/
-export const ecsign = function(
- msgHash: Buffer,
- privateKey: Buffer,
- chainId?: number,
-): ECDSASignature {
- const sig = ecdsaSign(msgHash, privateKey)
- const recovery: number = sig.recid
-
- const ret = {
- r: Buffer.from(sig.signature.slice(0, 32)),
- s: Buffer.from(sig.signature.slice(32, 64)),
- v: chainId ? recovery + (chainId * 2 + 35) : recovery + 27,
+export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId?: number): ECDSASignature
+export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId: BNLike): ECDSASignatureBuffer
+export function ecsign(msgHash: Buffer, privateKey: Buffer, chainId: any): any {
+ const { signature, recid: recovery } = ecdsaSign(msgHash, privateKey)
+
+ const r = Buffer.from(signature.slice(0, 32))
+ const s = Buffer.from(signature.slice(32, 64))
+
+ if (!chainId || typeof chainId === 'number') {
+ // return legacy type ECDSASignature (deprecated in favor of ECDSASignatureBuffer to handle large chainIds)
+ if (chainId && !Number.isSafeInteger(chainId)) {
+ throw new Error(
+ 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
+ )
+ }
+ const v = chainId ? recovery + (chainId * 2 + 35) : recovery + 27
+ return { r, s, v }
+ }
+
+ const chainIdBN = toType(chainId, TypeOutput.BN)
+ const v = chainIdBN
+ .muln(2)
+ .addn(35)
+ .addn(recovery)
+ .toArrayLike(Buffer)
+ return { r, s, v }
+}
+
+function calculateSigRecovery(v: BNLike, chainId?: BNLike): BN {
+ const vBN = toType(v, TypeOutput.BN)
+ if (!chainId) {
+ return vBN.subn(27)
}
+ const chainIdBN = toType(chainId, TypeOutput.BN)
+ return vBN.sub(chainIdBN.muln(2).addn(35))
+}
- return ret
+function isValidSigRecovery(recovery: number | BN): boolean {
+ const rec = new BN(recovery)
+ return rec.eqn(0) || rec.eqn(1)
}
/**
@@ -36,17 +68,17 @@ export const ecsign = function(
*/
export const ecrecover = function(
msgHash: Buffer,
- v: number,
+ v: BNLike,
r: Buffer,
s: Buffer,
- chainId?: number,
+ chainId?: BNLike
): Buffer {
const signature = Buffer.concat([setLengthLeft(r, 32), setLengthLeft(s, 32)], 64)
const recovery = calculateSigRecovery(v, chainId)
if (!isValidSigRecovery(recovery)) {
throw new Error('Invalid signature v value')
}
- const senderPubKey = ecdsaRecover(signature, recovery, msgHash)
+ const senderPubKey = ecdsaRecover(signature, recovery.toNumber(), msgHash)
return Buffer.from(publicKeyConvert(senderPubKey, false).slice(1))
}
@@ -54,7 +86,7 @@ export const ecrecover = function(
* Convert signature parameters into the format of `eth_sign` RPC method.
* @returns Signature
*/
-export const toRpcSig = function(v: number, r: Buffer, s: Buffer, chainId?: number): string {
+export const toRpcSig = function(v: BNLike, r: Buffer, s: Buffer, chainId?: BNLike): string {
const recovery = calculateSigRecovery(v, chainId)
if (!isValidSigRecovery(recovery)) {
throw new Error('Invalid signature v value')
@@ -71,12 +103,11 @@ export const toRpcSig = function(v: number, r: Buffer, s: Buffer, chainId?: numb
export const fromRpcSig = function(sig: string): ECDSASignature {
const buf: Buffer = toBuffer(sig)
- // NOTE: with potential introduction of chainId this might need to be updated
- if (buf.length !== 65) {
+ if (buf.length < 65) {
throw new Error('Invalid signature length')
}
- let v = buf[64]
+ let v = bufferToInt(buf.slice(64))
// support both versions of `eth_sign` responses
if (v < 27) {
v += 27
@@ -85,7 +116,7 @@ export const fromRpcSig = function(sig: string): ECDSASignature {
return {
v: v,
r: buf.slice(0, 32),
- s: buf.slice(32, 64),
+ s: buf.slice(32, 64)
}
}
@@ -94,15 +125,15 @@ export const fromRpcSig = function(sig: string): ECDSASignature {
* @param homesteadOrLater Indicates whether this is being used on either the homestead hardfork or a later one
*/
export const isValidSignature = function(
- v: number,
+ v: BNLike,
r: Buffer,
s: Buffer,
homesteadOrLater: boolean = true,
- chainId?: number,
+ chainId?: BNLike
): boolean {
const SECP256K1_N_DIV_2 = new BN(
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
- 16,
+ 16
)
const SECP256K1_N = new BN('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 16)
@@ -114,8 +145,8 @@ export const isValidSignature = function(
return false
}
- const rBN: BN = new BN(r)
- const sBN: BN = new BN(s)
+ const rBN = new BN(r)
+ const sBN = new BN(s)
if (rBN.isZero() || rBN.gt(SECP256K1_N) || sBN.isZero() || sBN.gt(SECP256K1_N)) {
return false
@@ -138,15 +169,7 @@ export const hashPersonalMessage = function(message: Buffer): Buffer {
assertIsBuffer(message)
const prefix = Buffer.from(
`\u0019Ethereum Signed Message:\n${message.length.toString()}`,
- 'utf-8',
+ 'utf-8'
)
return keccak(Buffer.concat([prefix, message]))
}
-
-function calculateSigRecovery(v: number, chainId?: number): number {
- return chainId ? v - (2 * chainId + 35) : v - 27
-}
-
-function isValidSigRecovery(recovery: number): boolean {
- return recovery === 0 || recovery === 1
-}
diff --git a/src/types.ts b/src/types.ts
new file mode 100644
index 00000000..bdca4baf
--- /dev/null
+++ b/src/types.ts
@@ -0,0 +1,120 @@
+import BN from 'bn.js'
+import { isHexString } from 'ethjs-util'
+import { Address } from './address'
+import { unpadBuffer, toBuffer, ToBufferInputTypes } from './bytes'
+
+/*
+ * A type that represents a BNLike input that can be converted to a BN.
+ */
+export type BNLike = BN | PrefixedHexString | number | Buffer
+
+/*
+ * A type that represents a BufferLike input that can be converted to a Buffer.
+ */
+export type BufferLike =
+ | Buffer
+ | Uint8Array
+ | number[]
+ | number
+ | BN
+ | TransformableToBuffer
+ | PrefixedHexString
+
+/*
+ * A type that represents a `0x`-prefixed hex string.
+ */
+export type PrefixedHexString = string
+
+/**
+ * A type that represents an Address-like value.
+ * To convert to address, use `new Address(toBuffer(value))`
+ */
+export type AddressLike = Address | Buffer | PrefixedHexString
+
+/*
+ * 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
+}
+
+/**
+ * Convert BN to 0x-prefixed hex string.
+ */
+export function bnToHex(value: BN): PrefixedHexString {
+ return `0x${value.toString(16)}`
+}
+
+/**
+ * Convert value from BN to RLP (unpadded buffer)
+ * @param value value to convert
+ */
+export function bnToRlp(value: BN): Buffer {
+ // Using `bn.toArrayLike(Buffer)` instead of `bn.toBuffer()`
+ // for compatibility with browserify and similar tools
+ return unpadBuffer(value.toArrayLike(Buffer))
+}
+
+/**
+ * Type output options
+ */
+export enum TypeOutput {
+ Number,
+ BN,
+ Buffer,
+ PrefixedHexString
+}
+
+export type TypeOutputReturnType = {
+ [TypeOutput.Number]: number
+ [TypeOutput.BN]: BN
+ [TypeOutput.Buffer]: Buffer
+ [TypeOutput.PrefixedHexString]: PrefixedHexString
+}
+
+/**
+ * Convert an input to a specified type
+ * @param input value to convert
+ * @param outputType type to output
+ */
+export function toType(
+ input: ToBufferInputTypes,
+ outputType: T
+): TypeOutputReturnType[T] {
+ if (typeof input === 'string' && !isHexString(input)) {
+ throw new Error(`A string must be provided with a 0x-prefix, given: ${input}`)
+ } else if (typeof input === 'number' && !Number.isSafeInteger(input)) {
+ throw new Error(
+ 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
+ )
+ }
+
+ input = toBuffer(input)
+
+ if (outputType === TypeOutput.Buffer) {
+ return input as any
+ } else if (outputType === TypeOutput.BN) {
+ return new BN(input) as any
+ } else if (outputType === TypeOutput.Number) {
+ const bn = new BN(input)
+ const max = new BN(Number.MAX_SAFE_INTEGER.toString())
+ if (bn.gt(max)) {
+ throw new Error(
+ 'The provided number is greater than MAX_SAFE_INTEGER (please use an alternative output type)'
+ )
+ }
+ return bn.toNumber() as any
+ } else {
+ // outputType === TypeOutput.PrefixedHexString
+ return `0x${input.toString('hex')}` as any
+ }
+}
diff --git a/test/account.spec.ts b/test/account.spec.ts
index 44df2c17..483f88de 100644
--- a/test/account.spec.ts
+++ b/test/account.spec.ts
@@ -1,6 +1,8 @@
-import * as assert from 'assert'
-import * as BN from 'bn.js'
+import tape from 'tape'
+import { encode } from 'rlp'
import {
+ Account,
+ BN,
isValidPrivate,
isValidPublic,
importPublic,
@@ -12,610 +14,668 @@ import {
toBuffer,
isValidChecksumAddress,
isValidAddress,
- toChecksumAddress,
+ toChecksumAddress
} from '../src'
const eip1014Testdata = require('./testdata/eip1014Examples.json')
-describe('isValidPrivate', function() {
- const SECP256K1_N = new BN('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 16)
- it('should fail on short input', function() {
- const tmp = '0011223344'
- assert.throws(function() {
- isValidPrivate(Buffer.from(tmp, 'hex'))
- })
+tape('Account', function(t) {
+ t.test('empty constructor', function(st) {
+ const account = new Account()
+ st.ok(account.nonce.isZero(), 'should have zero nonce')
+ st.ok(account.balance.isZero(), 'should have zero balance')
+ st.equal(
+ account.stateRoot.toString('hex'),
+ '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ 'should have stateRoot equal to KECCAK256_RLP'
+ )
+ st.equal(
+ account.codeHash.toString('hex'),
+ 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'should have codeHash equal to KECCAK256_NULL'
+ )
+ st.end()
})
- it('should fail on too big input', function() {
- const tmp =
- '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
- assert.throws(function() {
- isValidPrivate(Buffer.from(tmp, 'hex'))
- })
+
+ t.test('from Array data', function(st) {
+ const raw = [
+ '0x02', // nonce
+ '0x0384', // balance
+ '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', // stateRoot
+ '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' // codeHash
+ ]
+ const account = Account.fromValuesArray(raw.map(toBuffer))
+ st.ok(account.nonce.eqn(2), 'should have correct nonce')
+ st.ok(account.balance.eqn(900), 'should have correct balance')
+ st.equal(
+ account.stateRoot.toString('hex'),
+ '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ 'should have correct stateRoot'
+ )
+ st.equal(
+ account.codeHash.toString('hex'),
+ 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'should have correct codeHash'
+ )
+ st.end()
})
- it('should fail on wrong input type', function() {
- assert.throws(function() {
- isValidPrivate(('WRONG_INPUT_TYPE') as Buffer)
- })
+
+ t.test('from Object data', function(st) {
+ const raw = {
+ nonce: '0x02',
+ balance: '0x0384',
+ stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
+ }
+ const account = Account.fromAccountData(raw)
+ st.ok(account.nonce.eqn(2), 'should have correct nonce')
+ st.ok(account.balance.eqn(900), 'should have correct balance')
+ st.equal(
+ account.stateRoot.toString('hex'),
+ '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ 'should have correct stateRoot'
+ )
+ st.equal(
+ account.codeHash.toString('hex'),
+ 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'should have correct codeHash'
+ )
+ st.end()
})
- it('should fail on invalid curve (zero)', function() {
- const tmp = '0000000000000000000000000000000000000000000000000000000000000000'
- assert.equal(isValidPrivate(Buffer.from(tmp, 'hex')), false)
+
+ t.test('from RLP data', function(st) {
+ const accountRlp = Buffer.from(
+ 'f84602820384a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'hex'
+ )
+ const account = Account.fromRlpSerializedAccount(accountRlp)
+ st.ok(account.nonce.eqn(2), 'should have correct nonce')
+ st.ok(account.balance.eqn(900), 'should have correct balance')
+ st.equal(
+ account.stateRoot.toString('hex'),
+ '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ 'should have correct stateRoot'
+ )
+ st.equal(
+ account.codeHash.toString('hex'),
+ 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'should have correct codeHash'
+ )
+ st.end()
})
- it('should fail on invalid curve (== N)', function() {
- const tmp = SECP256K1_N.toString(16)
- assert.equal(isValidPrivate(Buffer.from(tmp, 'hex')), false)
+
+ t.test('serialize', function(st) {
+ const raw = {
+ nonce: '0x01',
+ balance: '0x42',
+ stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ codeHash: '0xc5d2461236f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
+ }
+ const account = Account.fromAccountData(raw)
+ const accountRlp = encode([raw.nonce, raw.balance, raw.stateRoot, raw.codeHash])
+ st.ok(account.serialize().equals(accountRlp), 'should serialize correctly')
+ st.end()
})
- it('should fail on invalid curve (>= N)', function() {
- const tmp = SECP256K1_N.addn(1).toString(16)
- assert.equal(isValidPrivate(Buffer.from(tmp, 'hex')), false)
+
+ t.test('isContract', function(st) {
+ const accountRlp = Buffer.from(
+ 'f84602820384a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'hex'
+ )
+ let account = Account.fromRlpSerializedAccount(accountRlp)
+ st.notOk(account.isContract(), 'should return false for a non-contract account')
+
+ const raw = {
+ nonce: '0x01',
+ balance: '0x0042',
+ stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ codeHash: '0xc5d2461236f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
+ }
+ account = Account.fromAccountData(raw)
+ st.ok(account.isContract(), 'should return true for a contract account')
+ st.end()
})
- it('should work otherwise (< N)', function() {
- const tmp = SECP256K1_N.subn(1).toString(16)
- assert.equal(isValidPrivate(Buffer.from(tmp, 'hex')), true)
+
+ t.test('isEmpty', function(st) {
+ let account = new Account()
+ st.ok(account.isEmpty(), 'should return true for an empty account')
+
+ const raw = {
+ nonce: '0x01',
+ balance: '0x0042',
+ stateRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ codeHash: '0xd748bf26ab37599c944babfdbeecf6690801bd61bf2670efb0a34adfc6dca10b'
+ }
+ account = Account.fromAccountData(raw)
+ st.notOk(account.isEmpty(), 'should return false for a non-empty account')
+ st.end()
+ })
+
+ t.test('validation', function(st) {
+ st.throws(() => {
+ new Account(undefined, undefined, Buffer.from('hey'), undefined)
+ }, 'should only accept length 32 buffer for stateRoot')
+
+ st.throws(() => {
+ new Account(undefined, undefined, undefined, Buffer.from('hey'))
+ }, 'should only accept length 32 buffer for codeHash')
+
+ const data = { balance: new BN(5) }
+ st.throws(() => {
+ Account.fromRlpSerializedAccount(data as any)
+ }, 'should only accept an array in fromRlpSerializedAccount')
+
+ st.throws(() => {
+ new Account(new BN(-5))
+ }, 'should not accept nonce less than 0')
+
+ st.throws(() => {
+ new Account(undefined, new BN(-5))
+ }, 'should not accept balance less than 0')
+ st.end()
})
})
-describe('isValidPublic', function() {
- it('should fail on too short input', function() {
- const pubKey = Buffer.from(
- '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744',
- 'hex',
+tape('Utility Functions', function(t) {
+ t.test('isValidPrivate', function(st) {
+ const SECP256K1_N = new BN(
+ 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141',
+ 16
)
- assert.equal(isValidPublic(pubKey), false)
+
+ let tmp = '0011223344'
+ st.throws(function() {
+ isValidPrivate(Buffer.from(tmp, 'hex'))
+ }, 'should fail on short input')
+
+ tmp =
+ '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
+ st.throws(function() {
+ isValidPrivate(Buffer.from(tmp, 'hex'))
+ }, 'should fail on too big input')
+
+ st.throws(function() {
+ isValidPrivate(('WRONG_INPUT_TYPE') as Buffer)
+ }, 'should fail on wrong input type')
+
+ tmp = '0000000000000000000000000000000000000000000000000000000000000000'
+ st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on invalid curve (zero)')
+
+ tmp = SECP256K1_N.toString(16)
+ st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on invalid curve (== N)')
+
+ tmp = SECP256K1_N.addn(1).toString(16)
+ st.notOk(isValidPrivate(Buffer.from(tmp, 'hex')), 'should fail on invalid curve (>= N)')
+
+ tmp = SECP256K1_N.subn(1).toString(16)
+ st.ok(isValidPrivate(Buffer.from(tmp, 'hex')), 'should work otherwise (< N)')
+ st.end()
})
- it('should fail on too big input', function() {
- const pubKey = Buffer.from(
+
+ t.test('isValidPublic', function(st) {
+ let pubKey = Buffer.from(
+ '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744',
+ 'hex'
+ )
+ st.notOk(isValidPublic(pubKey), 'should fail on too short input')
+
+ pubKey = Buffer.from(
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d00',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey), false)
- })
- it('should fail on SEC1 key', function() {
- const pubKey = Buffer.from(
+ st.notOk(isValidPublic(pubKey), 'should fail on too big input')
+
+ pubKey = Buffer.from(
'043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey), false)
- })
- it("shouldn't fail on SEC1 key with sanitize enabled", function() {
- const pubKey = Buffer.from(
+ st.notOk(isValidPublic(pubKey), 'should fail on SEC1 key')
+
+ pubKey = Buffer.from(
'043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey, true), true)
- })
- it('should fail with an invalid SEC1 public key', function() {
- const pubKey = Buffer.from(
+ st.ok(isValidPublic(pubKey, true), "shouldn't fail on SEC1 key wt.testh sant.testize enabled")
+
+ pubKey = Buffer.from(
'023a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey, true), false)
- })
- it('should work with compressed keys with sanitize enabled', function() {
- const pubKey = Buffer.from(
+ st.notOk(isValidPublic(pubKey), 'should fail wt.testh an invalid SEC1 public key')
+
+ pubKey = Buffer.from(
'033a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey, true), true)
- })
- it('should work with sanitize enabled', function() {
- const pubKey = Buffer.from(
+ st.ok(
+ isValidPublic(pubKey, true),
+ 'should work wt.testh compressed keys wt.testh sant.testize enabled'
+ )
+
+ pubKey = Buffer.from(
'043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey, true), true)
- })
- it('should work otherwise', function() {
- const pubKey = Buffer.from(
+ st.ok(isValidPublic(pubKey, true), 'should work wt.testh sant.testize enabled')
+
+ pubKey = Buffer.from(
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- assert.equal(isValidPublic(pubKey), true)
- })
- it('should throw if input is not Buffer', function() {
- const pubKey =
- '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
+ st.ok(isValidPublic(pubKey), 'should work otherwise')
+
+ pubKey = '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' as any
try {
isValidPublic((pubKey) as Buffer)
} catch (err) {
- assert(err.message.includes('This method only supports Buffer'))
+ st.ok(
+ err.message.includes('This method only supports Buffer'),
+ 'should throw if input is not Buffer'
+ )
}
+ st.end()
})
-})
-describe('importPublic', function() {
- const pubKey =
- '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
- it('should work with an Ethereum public key', function() {
- const tmp =
+ t.test('importPublic', function(st) {
+ const pubKey =
+ '3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
+
+ let tmp =
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
- assert.equal(importPublic(Buffer.from(tmp, 'hex')).toString('hex'), pubKey)
- })
- it('should work with uncompressed SEC1 keys', function() {
- const tmp =
+ st.equal(
+ importPublic(Buffer.from(tmp, 'hex')).toString('hex'),
+ pubKey,
+ 'should work wt.testh an Ethereum public key'
+ )
+
+ tmp =
'043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
- assert.equal(importPublic(Buffer.from(tmp, 'hex')).toString('hex'), pubKey)
- })
- it('should work with compressed SEC1 keys', function() {
- const tmp = '033a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a'
- assert.equal(importPublic(Buffer.from(tmp, 'hex')).toString('hex'), pubKey)
- })
- it('should throw if input is not Buffer', function() {
- assert.throws(function() {
+ st.equal(
+ importPublic(Buffer.from(tmp, 'hex')).toString('hex'),
+ pubKey,
+ 'should work wt.testh uncompressed SEC1 keys'
+ )
+
+ tmp = '033a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a'
+ st.equal(
+ importPublic(Buffer.from(tmp, 'hex')).toString('hex'),
+ pubKey,
+ 'should work wt.testh compressed SEC1 keys'
+ )
+
+ st.throws(function() {
importPublic((pubKey) as Buffer)
- })
+ }, 'should throw if input is not Buffer')
+ st.end()
})
-})
-describe('publicToAddress', function() {
- it('should produce an address given a public key', function() {
- const pubKey = Buffer.from(
+ t.test('publicToAddress', function(st) {
+ let pubKey = Buffer.from(
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- const address = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
- const r = publicToAddress(pubKey)
- assert.equal(r.toString('hex'), address)
- })
- it('should produce an address given a SEC1 public key', function() {
- const pubKey = Buffer.from(
+ let address = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
+ let r = publicToAddress(pubKey)
+ st.equal(r.toString('hex'), address, 'should produce an address given a public key')
+
+ pubKey = Buffer.from(
'043a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- const address = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
- const r = publicToAddress(pubKey, true)
- assert.equal(r.toString('hex'), address)
- })
- it("shouldn't produce an address given an invalid SEC1 public key", function() {
- const pubKey = Buffer.from(
+ address = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
+ r = publicToAddress(pubKey, true)
+ st.equal(r.toString('hex'), address, 'should produce an address given a SEC1 public key')
+
+ pubKey = Buffer.from(
'023a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
- assert.throws(function() {
+ st.throws(function() {
publicToAddress(pubKey, true)
- })
- })
- it("shouldn't produce an address given an invalid public key", function() {
- const pubKey = Buffer.from(
+ }, "shouldn't produce an address given an invalid SEC1 public key")
+
+ pubKey = Buffer.from(
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744',
- 'hex',
+ 'hex'
)
- assert.throws(function() {
+ st.throws(function() {
publicToAddress(pubKey)
- })
- })
- it('should throw if input is not a buffer', function() {
- const pubKey: any =
- '0x3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
- assert.throws(function() {
+ }, "shouldn't produce an address given an invalid public key")
+
+ pubKey = '0x3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' as any
+ st.throws(function() {
publicToAddress(pubKey)
- })
+ }, 'should throw if input is not a buffer')
+ st.end()
})
-})
-describe('privateToPublic', function() {
- it('should produce a public key given a private key', function() {
+ t.test('privateToPublic', function(st) {
const pubKey =
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d'
- const privateKey = Buffer.from([
- 234,
- 84,
- 189,
- 197,
- 45,
- 22,
- 63,
- 136,
- 201,
- 58,
- 176,
- 97,
- 87,
- 130,
- 207,
- 113,
- 138,
- 46,
- 251,
- 158,
- 81,
- 167,
- 152,
- 154,
- 171,
- 27,
- 8,
- 6,
- 126,
- 156,
- 28,
- 95,
- ])
- const r: any = privateToPublic(privateKey).toString('hex')
- assert.equal(r.toString('hex'), pubKey)
- })
- it("shouldn't produce a public key given an invalid private key", function() {
- const privateKey1 = Buffer.from([
- 234,
- 84,
- 189,
- 197,
- 45,
- 22,
- 63,
- 136,
- 201,
- 58,
- 176,
- 97,
- 87,
- 130,
- 207,
- 113,
- 138,
- 46,
- 251,
- 158,
- 81,
- 167,
- 152,
- 154,
- 171,
- 27,
- 8,
- 6,
- 126,
- 156,
- 28,
- 95,
- 42,
- ])
- const privateKey2 = Buffer.from([
- 234,
- 84,
- 189,
- 197,
- 45,
- 22,
- 63,
- 136,
- 201,
- 58,
- 176,
- 97,
- 87,
- 130,
- 207,
- 113,
- 138,
- 46,
- 251,
- 158,
- 81,
- 167,
- 152,
- 154,
- 171,
- 27,
- 8,
- 6,
- 126,
- 156,
- 28,
- ])
- assert.throws(function() {
- privateToPublic(privateKey1)
- })
- assert.throws(function() {
- privateToPublic(privateKey2)
- })
- })
+ let privateKey = Buffer.from(
+ 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f',
+ 'hex'
+ )
+ const r = privateToPublic(privateKey)
+ st.equal(r.toString('hex'), pubKey, 'should produce a public key given a private key')
+
+ privateKey = Buffer.from(
+ 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f2a',
+ 'hex'
+ )
+ st.throws(function() {
+ privateToPublic(privateKey)
+ }, "shouldn't produce a public key given an invalid private key")
- it('should throw if private key is not Buffer', function() {
- const privateKey = '0xea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f'
+ privateKey = Buffer.from(
+ 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c',
+ 'hex'
+ )
+ st.throws(function() {
+ privateToPublic(privateKey)
+ }, "shouldn't produce a public key given an invalid private key")
+
+ privateKey = '0xea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f' as any
try {
privateToPublic((privateKey) as Buffer)
} catch (err) {
- assert(err.message.includes('This method only supports Buffer'))
- assert(err.message.includes(privateKey))
+ st.ok(
+ err.message.includes('This method only supports Buffer'),
+ 'should throw if private key is not Buffer'
+ )
+ st.ok(err.message.includes(privateKey), 'should throw if private key is not Buffer')
}
+ st.end()
})
-})
-describe('privateToAddress', function() {
- it('should produce an address given a private key', function() {
+ t.test('privateToAddress', function(st) {
const address = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
// Our private key
- const privateKey = Buffer.from([
- 234,
- 84,
- 189,
- 197,
- 45,
- 22,
- 63,
- 136,
- 201,
- 58,
- 176,
- 97,
- 87,
- 130,
- 207,
- 113,
- 138,
- 46,
- 251,
- 158,
- 81,
- 167,
- 152,
- 154,
- 171,
- 27,
- 8,
- 6,
- 126,
- 156,
- 28,
- 95,
- ])
- const r: any = privateToAddress(privateKey).toString('hex')
- assert.equal(r.toString('hex'), address)
+ const privateKey = Buffer.from(
+ 'ea54bdc52d163f88c93ab0615782cf718a2efb9e51a7989aab1b08067e9c1c5f',
+ 'hex'
+ )
+ const r = privateToAddress(privateKey)
+ st.equal(r.toString('hex'), address, 'should produce an address given a private key')
+ st.end()
})
-})
-describe('generateAddress', function() {
- it('should produce an address given a public key', function() {
- const add: any = generateAddress(
+ t.test('generateAddress', function(st) {
+ const addr = generateAddress(
Buffer.from('990ccf8a0de58091c028d6ff76bb235ee67c1c39', 'utf8'),
- toBuffer(14),
- ).toString('hex')
- assert.equal(add.toString('hex'), '936a4295d8d74e310c0c95f0a63e53737b998d12')
+ toBuffer(14)
+ )
+ st.equal(
+ addr.toString('hex'),
+ '936a4295d8d74e310c0c95f0a63e53737b998d12',
+ 'should produce an address given a public key'
+ )
+ st.end()
})
-})
-describe('generateAddress with hex prefix', function() {
- it('should produce an address given a public key', function() {
- const add: any = generateAddress(
+ t.test('generateAddress wt.testh hex prefix', function(st) {
+ const addr = generateAddress(
toBuffer('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'),
- toBuffer(14),
- ).toString('hex')
- assert.equal(add.toString('hex'), 'd658a4b8247c14868f3c512fa5cbb6e458e4a989')
+ toBuffer(14)
+ )
+ st.equal(
+ addr.toString('hex'),
+ 'd658a4b8247c14868f3c512fa5cbb6e458e4a989',
+ 'should produce an address given a public key'
+ )
+ st.end()
})
-})
-describe('generateAddress with nonce 0 (special case)', function() {
- it('should produce an address given a public key', function() {
- const add: any = generateAddress(
+ t.test('generateAddress wt.testh nonce 0 (special case)', function(st) {
+ const addr = generateAddress(
toBuffer('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'),
- toBuffer(0),
- ).toString('hex')
- assert.equal(add.toString('hex'), 'bfa69ba91385206bfdd2d8b9c1a5d6c10097a85b')
+ toBuffer(0)
+ )
+ st.equal(
+ addr.toString('hex'),
+ 'bfa69ba91385206bfdd2d8b9c1a5d6c10097a85b',
+ 'should produce an address given a public key'
+ )
+ st.end()
})
-})
-describe('generateAddress with non-buffer inputs', function() {
- it('should throw if address is not Buffer', function() {
- assert.throws(function() {
+ t.test('generateAddress wt.testh non-buffer inputs', function(st) {
+ st.throws(function() {
generateAddress(
('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39') as Buffer,
- toBuffer(0),
+ toBuffer(0)
)
- })
- })
- it('should throw if nonce is not Buffer', function() {
- assert.throws(function() {
+ }, 'should throw if address is not Buffer')
+
+ st.throws(function() {
generateAddress(
toBuffer('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39'),
- (0) as Buffer,
+ (0) as Buffer
)
- })
+ }, 'should throw if nonce is not Buffer')
+ st.end()
})
-})
-describe('generateAddress2: EIP-1014 testdata examples', function() {
- for (let i = 0; i <= 6; i++) {
- let e = eip1014Testdata[i]
- it(`${e['comment']}: should generate the addresses provided`, function() {
- let result = generateAddress2(
- toBuffer(e['address']),
- toBuffer(e['salt']),
- toBuffer(e['initCode']),
+ t.test('generateAddress2: EIP-1014 testdata examples', function(st) {
+ for (const testdata of eip1014Testdata) {
+ const { address, comment, result, salt, initCode } = testdata
+ const addr = generateAddress2(toBuffer(address), toBuffer(salt), toBuffer(initCode))
+ st.equal(
+ '0x' + addr.toString('hex'),
+ result,
+ `${comment}: should generate the addresses provided`
)
- assert.equal('0x' + result.toString('hex'), e['result'])
- })
- }
-})
+ }
+ st.end()
+ })
-describe('generateAddress2: non-buffer inputs', function() {
- const e = eip1014Testdata[0]
+ t.test('generateAddress2: non-buffer inputs', function(st) {
+ const { address, salt, initCode } = eip1014Testdata[0]
- it('should throw if address is not Buffer', function() {
- assert.throws(function() {
- generateAddress2(
- (e['address']) as Buffer,
- toBuffer(e['salt']),
- toBuffer(e['initCode']),
- )
- })
- })
- it('should throw if salt is not Buffer', function() {
- assert.throws(function() {
- generateAddress2(
- toBuffer(e['address']),
- (e['salt']) as Buffer,
- toBuffer(e['initCode']),
- )
- })
- })
- it('should throw if initCode is not Buffer', function() {
- assert.throws(function() {
- generateAddress2(
- toBuffer(e['address']),
- toBuffer(e['salt']),
- (e['initCode']) as Buffer,
- )
- })
+ st.throws(function() {
+ generateAddress2((address) as Buffer, toBuffer(salt), toBuffer(initCode))
+ }, 'should throw if address is not Buffer')
+
+ st.throws(function() {
+ generateAddress2(toBuffer(address), (salt) as Buffer, toBuffer(initCode))
+ }, 'should throw if salt is not Buffer')
+
+ st.throws(function() {
+ generateAddress2(toBuffer(address), toBuffer(salt), (initCode) as Buffer)
+ }, 'should throw if initCode is not Buffer')
+ st.end()
})
-})
-const eip55ChecksumAddresses = [
- // All caps
- '0x52908400098527886E0F7030069857D2E4169EE7',
- '0x8617E340B3D01FA5F11F306F4090FD50E238070D',
- // All Lower
- '0xde709f2102306220921060314715629080e2fb77',
- '0x27b1fdb04752bbc536007a920d24acb045561c26',
- // Normal
- '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed',
- '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
- '0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB',
- '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb',
-]
-
-const eip1191ChecksummAddresses = {
- 1: [
- '0x88021160c5C792225E4E5452585947470010289d',
- '0x27b1FdB04752bBc536007a920D24ACB045561c26',
- '0x52908400098527886e0f7030069857D2e4169EE7',
- '0x5aaeB6053f3E94C9b9A09f33669435e7Ef1bEAed',
- '0x8617E340b3d01FA5F11F306f4090FD50E238070d',
- '0xd1220a0CF47C7B9Be7A2E6ba89F429762E7B9Adb',
- '0xdBf03b407c01e7cD3CBea99509d93f8dDDC8C6fB',
- '0xDe709F2102306220921060314715629080E2fb77',
- '0xfb6916095Ca1dF60bB79cE92ce3ea74C37c5D359',
- ],
- 30: [
- '0x6549F4939460DE12611948B3F82B88C3C8975323',
- '0x27b1FdB04752BBc536007A920D24ACB045561c26',
- '0x3599689E6292B81B2D85451025146515070129Bb',
- '0x52908400098527886E0F7030069857D2E4169ee7',
- '0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD',
- '0x8617E340b3D01Fa5f11f306f4090fd50E238070D',
- '0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB',
- '0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB',
- '0xDe709F2102306220921060314715629080e2FB77',
- '0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359',
- ],
- 31: [
- '0x42712D45473476B98452F434E72461577D686318',
- '0x27B1FdB04752BbC536007a920D24acB045561C26',
- '0x3599689e6292b81b2D85451025146515070129Bb',
- '0x52908400098527886E0F7030069857D2e4169EE7',
- '0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd',
- '0x66f9664F97F2b50f62d13eA064982F936DE76657',
- '0x8617e340b3D01fa5F11f306F4090Fd50e238070d',
- '0xDE709F2102306220921060314715629080e2Fb77',
- '0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359',
- '0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB',
- '0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB',
- ],
-}
-
-describe('.toChecksumAddress()', function() {
- describe('EIP55', function() {
- it('should work', function() {
+ const eip55ChecksumAddresses = [
+ // All caps
+ '0x52908400098527886E0F7030069857D2E4169EE7',
+ '0x8617E340B3D01FA5F11F306F4090FD50E238070D',
+ // All Lower
+ '0xde709f2102306220921060314715629080e2fb77',
+ '0x27b1fdb04752bbc536007a920d24acb045561c26',
+ // Normal
+ '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed',
+ '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
+ '0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB',
+ '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb'
+ ]
+
+ const eip1191ChecksummAddresses = {
+ 1: [
+ '0x88021160c5C792225E4E5452585947470010289d',
+ '0x27b1FdB04752bBc536007a920D24ACB045561c26',
+ '0x52908400098527886e0f7030069857D2e4169EE7',
+ '0x5aaeB6053f3E94C9b9A09f33669435e7Ef1bEAed',
+ '0x8617E340b3d01FA5F11F306f4090FD50E238070d',
+ '0xd1220a0CF47C7B9Be7A2E6ba89F429762E7B9Adb',
+ '0xdBf03b407c01e7cD3CBea99509d93f8dDDC8C6fB',
+ '0xDe709F2102306220921060314715629080E2fb77',
+ '0xfb6916095Ca1dF60bB79cE92ce3ea74C37c5D359'
+ ],
+ 30: [
+ '0x6549F4939460DE12611948B3F82B88C3C8975323',
+ '0x27b1FdB04752BBc536007A920D24ACB045561c26',
+ '0x3599689E6292B81B2D85451025146515070129Bb',
+ '0x52908400098527886E0F7030069857D2E4169ee7',
+ '0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD',
+ '0x8617E340b3D01Fa5f11f306f4090fd50E238070D',
+ '0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB',
+ '0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB',
+ '0xDe709F2102306220921060314715629080e2FB77',
+ '0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359'
+ ],
+ 31: [
+ '0x42712D45473476B98452F434E72461577D686318',
+ '0x27B1FdB04752BbC536007a920D24acB045561C26',
+ '0x3599689e6292b81b2D85451025146515070129Bb',
+ '0x52908400098527886E0F7030069857D2e4169EE7',
+ '0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd',
+ '0x66f9664F97F2b50f62d13eA064982F936DE76657',
+ '0x8617e340b3D01fa5F11f306F4090Fd50e238070d',
+ '0xDE709F2102306220921060314715629080e2Fb77',
+ '0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359',
+ '0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB',
+ '0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB'
+ ]
+ }
+
+ t.test('toChecksumAddress()', function(st) {
+ st.test('EIP55', function(st) {
for (let i = 0; i < eip55ChecksumAddresses.length; i++) {
- let tmp = eip55ChecksumAddresses[i]
- assert.equal(toChecksumAddress(tmp.toLowerCase()), tmp)
+ const tmp = eip55ChecksumAddresses[i]
+ st.equal(toChecksumAddress(tmp.toLowerCase()), tmp)
}
+ st.end()
})
- })
- describe('EIP1191', function() {
- it('Should encode the example addresses correctly', function() {
- for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) {
- for (const addr of addresses) {
- assert.equal(toChecksumAddress(addr.toLowerCase(), Number(chainId)), addr)
+ st.test('EIP1191', function(st) {
+ st.test('Should encode the example addresses correctly', function(st) {
+ for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) {
+ for (const addr of addresses) {
+ st.equal(toChecksumAddress(addr.toLowerCase(), Number(chainId)), addr)
+ st.equal(toChecksumAddress(addr.toLowerCase(), Buffer.from([chainId])), addr)
+ st.equal(toChecksumAddress(addr.toLowerCase(), new BN(chainId)), addr)
+ st.equal(
+ toChecksumAddress(addr.toLowerCase(), '0x' + Buffer.from([chainId]).toString('hex')),
+ addr
+ )
+ }
}
- }
+ st.end()
+ })
+ st.test('Should encode large chain ids greater than MAX_INTEGER correctly', function(st) {
+ const addr = '0x88021160C5C792225E4E5452585947470010289D'
+ const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex')
+ st.equal(toChecksumAddress(addr.toLowerCase(), chainIDBuffer), addr)
+ st.equal(toChecksumAddress(addr.toLowerCase(), new BN(chainIDBuffer)), addr)
+ st.equal(toChecksumAddress(addr.toLowerCase(), '0x' + chainIDBuffer.toString('hex')), addr)
+ const chainIDNumber = parseInt(chainIDBuffer.toString('hex'), 16)
+ st.throws(() => {
+ toChecksumAddress(addr.toLowerCase(), chainIDNumber)
+ })
+ st.end()
+ })
+ st.end()
})
- })
- describe('input format', function() {
- it('Should throw when the address is not hex-prefixed', function() {
- assert.throws(function() {
+ st.test('input format', function(st) {
+ st.throws(function() {
toChecksumAddress('52908400098527886E0F7030069857D2E4169EE7'.toLowerCase())
- })
+ }, 'Should throw when the address is not hex-prefixed')
+
+ st.throws(function() {
+ toChecksumAddress('0xde709f2102306220921060314715629080e2fb77', '1234')
+ }, 'Should throw when the chainId is not hex-prefixed')
+ st.end()
})
})
-})
-describe('.isValidChecksumAddress()', function() {
- describe('EIP55', function() {
- it('should return true', function() {
+ t.test('isValidChecksumAddress()', function(st) {
+ st.test('EIP55', function(st) {
for (let i = 0; i < eip55ChecksumAddresses.length; i++) {
- assert.equal(isValidChecksumAddress(eip55ChecksumAddresses[i]), true)
+ st.ok(isValidChecksumAddress(eip55ChecksumAddresses[i]))
}
+ st.notOk(isValidChecksumAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6a'))
+ st.end()
})
- it('should validate', function() {
- assert.equal(isValidChecksumAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6a'), false)
- })
- })
- describe('EIP1191', function() {
- it('Should return true for the example addresses', function() {
- for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) {
- for (const addr of addresses) {
- assert.equal(isValidChecksumAddress(addr, Number(chainId)), true)
+ st.test('EIP1191', function(st) {
+ st.test('Should return true for the example addresses', function(st) {
+ for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) {
+ for (const addr of addresses) {
+ st.ok(isValidChecksumAddress(addr, Number(chainId)))
+ st.ok(isValidChecksumAddress(addr, Buffer.from([chainId])))
+ st.ok(isValidChecksumAddress(addr, new BN(chainId)))
+ st.equal(
+ isValidChecksumAddress(addr, '0x' + Buffer.from([chainId]).toString('hex')),
+ true
+ )
+ }
}
- }
- })
+ st.end()
+ })
- it('Should return false for invalid cases', function() {
- // If we set the chain id, an EIP55 encoded address should be invalid
- for (let i = 0; i < eip55ChecksumAddresses.length; i++) {
- assert.equal(isValidChecksumAddress(eip55ChecksumAddresses[i], 1), false)
- }
+ st.test('Should return false for invalid cases', function(st) {
+ // If we set the chain id, an EIP55 encoded address should be invalid
+ for (let i = 0; i < eip55ChecksumAddresses.length; i++) {
+ st.notOk(isValidChecksumAddress(eip55ChecksumAddresses[i], 1))
+ }
- assert.equal(isValidChecksumAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6a', 1), false)
- })
+ st.notOk(isValidChecksumAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6a', 1))
+ st.end()
+ })
- it('Should return false if the wrong chain id is used', function() {
- for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) {
- for (const addr of addresses) {
- assert.equal(isValidChecksumAddress(addr, Number(chainId) + 1), false)
+ st.test('Should return false if the wrong chain id is used', function(st) {
+ for (const [chainId, addresses] of Object.entries(eip1191ChecksummAddresses)) {
+ for (const addr of addresses) {
+ st.notOk(isValidChecksumAddress(addr, Number(chainId) + 1))
+ }
}
- }
- })
- })
+ st.end()
+ })
- describe('input format', function() {
- it('Should throw when the address is not hex-prefixed', function() {
- assert.throws(function() {
- isValidChecksumAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ st.test('input format', function(st) {
+ st.throws(() => {
+ isValidChecksumAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ }, 'Should throw when the address is not hex-prefixed')
+ st.end()
})
+
+ st.end()
})
})
-})
-describe('.isValidAddress()', function() {
- it('should return true', function() {
- assert.equal(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6a'), true)
- assert.equal(isValidAddress('0x52908400098527886E0F7030069857D2E4169EE7'), true)
- })
- it('should return false', function() {
- assert.equal(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6'), false)
- assert.equal(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6aa'), false)
- })
- it('should throw when input is not hex prefixed', function() {
- assert.throws(function() {
- isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ t.test('isValidAddress()', function(st) {
+ st.test('should return true', function(st) {
+ st.ok(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6a'))
+ st.ok(isValidAddress('0x52908400098527886E0F7030069857D2E4169EE7'))
+ st.end()
})
- assert.throws(function() {
- isValidAddress('x2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ st.test('should return false', function(st) {
+ st.notOk(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6'))
+ st.notOk(isValidAddress('0x2f015c60e0be116b1f0cd534704db9c92118fb6aa'))
+ st.end()
})
- assert.throws(function() {
- isValidAddress('0X52908400098527886E0F7030069857D2E4169EE7')
+ st.test('should throw when input is not hex prefixed', function(st) {
+ st.throws(function() {
+ isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ })
+ st.throws(function() {
+ isValidAddress('x2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ })
+ st.throws(function() {
+ isValidAddress('0X52908400098527886E0F7030069857D2E4169EE7')
+ })
+ st.end()
+ })
+ st.test('error message should have correct format', function(st) {
+ const input = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
+ try {
+ isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
+ } catch (err) {
+ st.ok(err.message.includes('only supports 0x-prefixed hex strings'))
+ st.ok(err.message.includes(input))
+ }
+ st.end()
})
- })
- it('error message should have correct format', function() {
- const input = '2f015c60e0be116b1f0cd534704db9c92118fb6a'
- try {
- isValidAddress('2f015c60e0be116b1f0cd534704db9c92118fb6a')
- } catch (err) {
- assert(err.message.includes('only supports 0x-prefixed hex strings'))
- assert(err.message.includes(input))
- }
})
})
diff --git a/test/address.spec.ts b/test/address.spec.ts
index ede4bbda..804084b9 100644
--- a/test/address.spec.ts
+++ b/test/address.spec.ts
@@ -1,79 +1,115 @@
-import * as assert from 'assert'
-import { BN, toBuffer } from '../src'
-import { Address } from '../src'
+import tape from 'tape'
+import { Address, BN, toBuffer } from '../src'
const eip1014Testdata = require('./testdata/eip1014Examples.json')
-describe('Address', () => {
+tape('Address', t => {
const ZERO_ADDR_S = '0x0000000000000000000000000000000000000000'
- it('should validate address length', () => {
+ t.test('should validate address length', st => {
const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a11'
- assert.throws(() => Address.fromString(str))
+ st.throws(() => Address.fromString(str))
const shortStr = '0x2f015c60e0be116b1f0cd534704db9c92118fb'
- assert.throws(() => Address.fromString(shortStr))
+ st.throws(() => Address.fromString(shortStr))
const buf = toBuffer(str)
- assert.throws(() => new Address(buf))
+ st.throws(() => new Address(buf))
+ st.end()
})
- it('should generate a zero address', () => {
+ t.test('should generate a zero address', st => {
const addr = Address.zero()
- assert.deepEqual(addr.buf, toBuffer(ZERO_ADDR_S))
- assert.equal(addr.toString(), ZERO_ADDR_S)
+ st.deepEqual(addr.buf, toBuffer(ZERO_ADDR_S))
+ st.equal(addr.toString(), ZERO_ADDR_S)
+ st.end()
})
- it('should instantiate address from zero address string', () => {
+ t.test('should instantiate address from zero address string', st => {
const addr = Address.fromString(ZERO_ADDR_S)
- assert.deepEqual(addr.toString(), ZERO_ADDR_S)
- assert.equal(addr.isZero(), true)
+ st.deepEqual(addr.toString(), ZERO_ADDR_S)
+ st.ok(addr.isZero())
+ st.end()
})
- it('should detect non-zero address', () => {
+ t.test('should detect non-zero address', st => {
const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
const addr = Address.fromString(str)
- assert.equal(addr.isZero(), false)
+ st.notOk(addr.isZero())
+ st.end()
})
- it('should instantiate from public key', () => {
+ t.test('should instantiate from public key', st => {
const pubKey = Buffer.from(
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d',
- 'hex',
+ 'hex'
)
const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
const addr = Address.fromPublicKey(pubKey)
- assert.equal(addr.toString(), str)
+ st.equal(addr.toString(), str)
+ st.end()
})
- it('should fail to instantiate from invalid public key', () => {
+ t.test('should fail to instantiate from invalid public key', st => {
const pubKey = Buffer.from(
'3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae744',
- 'hex',
+ 'hex'
)
- assert.throws(() => Address.fromPublicKey(pubKey))
+ st.throws(() => Address.fromPublicKey(pubKey))
+ st.end()
})
- it('should instantiate from private key', () => {
+ t.test('should instantiate from private key', st => {
// prettier-ignore
const privateKey = Buffer.from([234, 84, 189, 197, 45, 22, 63, 136, 201, 58, 176, 97, 87, 130, 207, 113, 138, 46, 251, 158, 81, 167, 152, 154, 171, 27, 8, 6, 126, 156, 28, 95])
const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
const addr = Address.fromPrivateKey(privateKey)
- assert.equal(addr.toString(), str)
+ st.equal(addr.toString(), str)
+ st.end()
})
- it('should generate address for created contract', () => {
+ t.test('should generate address for created contract', st => {
const from = Address.fromString('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39')
const addr = Address.generate(from, new BN(14))
- assert.equal(addr.toString(), '0xd658a4b8247c14868f3c512fa5cbb6e458e4a989')
+ st.equal(addr.toString(), '0xd658a4b8247c14868f3c512fa5cbb6e458e4a989')
const addr2 = Address.generate(from, new BN(0))
- assert.equal(addr2.toString(), '0xbfa69ba91385206bfdd2d8b9c1a5d6c10097a85b')
+ st.equal(addr2.toString(), '0xbfa69ba91385206bfdd2d8b9c1a5d6c10097a85b')
+ st.end()
})
- it('should generate address for CREATE2', () => {
+ t.test('should generate address for CREATE2', st => {
for (const testdata of eip1014Testdata) {
const { address, salt, initCode, result } = testdata
const from = Address.fromString(address)
const addr = Address.generate2(from, toBuffer(salt), toBuffer(initCode))
- assert.equal(addr.toString(), result)
+ st.equal(addr.toString(), result)
}
+ st.end()
+ })
+
+ t.test('should provide a buffer that does not mutate the original address', st => {
+ const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
+ const address = Address.fromString(str)
+ const addressBuf = address.toBuffer()
+ addressBuf.fill(0)
+ st.equal(address.toString(), str)
+ st.end()
+ })
+
+ t.test('should compare equality properly', st => {
+ const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
+ const address1 = Address.fromString(str)
+ const address2 = new Address(Buffer.from(str.slice(2), 'hex'))
+ st.ok(address1.equals(address2))
+ st.ok(address1.buf.equals(address2.buf))
+
+ const str2 = '0xcd4EC7b66fbc029C116BA9Ffb3e59351c20B5B06'
+ const address3 = Address.fromString(str2)
+ st.ok(!address1.equals(address3))
+
+ const address3LowerCase = Address.fromString(str2.toLowerCase())
+ st.ok(address3.equals(address3LowerCase))
+
+ const address4 = Address.zero()
+ st.ok(!address1.equals(address4))
+ st.end()
})
})
diff --git a/test/bytes.spec.ts b/test/bytes.spec.ts
index 78617b85..7ee5cf8e 100644
--- a/test/bytes.spec.ts
+++ b/test/bytes.spec.ts
@@ -1,6 +1,7 @@
-import * as assert from 'assert'
-import * as BN from 'bn.js'
+import tape from 'tape'
import {
+ Address,
+ BN,
zeros,
zeroAddress,
isZeroAddress,
@@ -15,232 +16,274 @@ import {
toUnsigned,
addHexPrefix,
toBuffer,
- baToJSON,
+ baToJSON
} from '../src'
-describe('zeros function', function() {
- it('should produce lots of 0s', function() {
+tape('zeros function', function(t) {
+ t.test('should produce lots of 0s', function(st) {
const z60 = zeros(30)
const zs60 = '000000000000000000000000000000000000000000000000000000000000'
- assert.equal(z60.toString('hex'), zs60)
+ st.equal(z60.toString('hex'), zs60)
+ st.end()
})
})
-describe('zero address', function() {
- it('should generate a zero address', function() {
- assert.equal(zeroAddress(), '0x0000000000000000000000000000000000000000')
+tape('zero address', function(t) {
+ t.test('should generate a zero address', function(st) {
+ st.equal(zeroAddress(), '0x0000000000000000000000000000000000000000')
+ st.end()
})
})
-describe('is zero address', function() {
- it('should return true when a zero address is passed', function() {
- assert.equal(isZeroAddress('0x0000000000000000000000000000000000000000'), true)
+tape('is zero address', function(t) {
+ t.test('should return true when a zero address is passed', function(st) {
+ st.equal(isZeroAddress('0x0000000000000000000000000000000000000000'), true)
+ st.end()
})
- it('should return false when the address is not equal to zero', function() {
+ t.test('should return false when the address is not equal to zero', function(st) {
const nonZeroAddress = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
- assert.equal(isZeroAddress(nonZeroAddress), false)
+ st.equal(isZeroAddress(nonZeroAddress), false)
+ st.end()
})
- it('should throw when address is not hex-prefixed', function() {
- assert.throws(function() {
+ t.test('should throw when address is not hex-prefixed', function(st) {
+ st.throws(function() {
isZeroAddress('0000000000000000000000000000000000000000')
})
+ st.end()
})
})
-describe('unpadBuffer', function() {
- it('should unpad a Buffer', function() {
+tape('unpadBuffer', function(t) {
+ t.test('should unpad a Buffer', function(st) {
const buf = toBuffer('0x0000000006600')
const r = unpadBuffer(buf)
- assert.deepEqual(r, toBuffer('0x6600'))
+ st.ok(r.equals(toBuffer('0x6600')))
+ st.end()
})
- it('should throw if input is not a Buffer', function() {
- assert.throws(function() {
+ t.test('should throw if input is not a Buffer', function(st) {
+ st.throws(function() {
unpadBuffer(('0000000006600') as Buffer)
})
+ st.end()
})
})
-describe('unpadArray', function() {
- it('should unpad an Array', function() {
+tape('unpadArray', function(t) {
+ t.test('should unpad an Array', function(st) {
const arr = [0, 0, 0, 1]
const r = unpadArray(arr)
- assert.deepEqual(r, [1])
+ st.deepEqual(r, [1])
+ st.end()
})
- it('should throw if input is not an Array', function() {
- assert.throws(function() {
+ t.test('should throw if input is not an Array', function(st) {
+ st.throws(function() {
unpadArray((toBuffer([0, 0, 0, 1])) as number[])
})
+ st.end()
})
})
-describe('unpadHexString', function() {
- it('should unpad a hex prefixed string', function() {
+tape('unpadHexString', function(t) {
+ t.test('should unpad a hex prefixed string', function(st) {
const str = '0x0000000006600'
const r = unpadHexString(str)
- assert.equal(r, '6600')
+ st.equal(r, '6600')
+ st.end()
})
- it('should throw if input is not hex-prefixed', function() {
- assert.throws(function() {
+ t.test('should throw if input is not hex-prefixed', function(st) {
+ st.throws(function() {
unpadHexString('0000000006600')
})
+ st.end()
})
})
-describe('setLengthLeft', function() {
- it('should left pad a Buffer', function() {
+tape('setLengthLeft', function(t) {
+ t.test('should left pad a Buffer', function(st) {
const buf = Buffer.from([9, 9])
const padded = setLengthLeft(buf, 3)
- assert.equal(padded.toString('hex'), '000909')
+ st.equal(padded.toString('hex'), '000909')
+ st.end()
})
- it('should left truncate a Buffer', function() {
+ t.test('should left truncate a Buffer', function(st) {
const buf = Buffer.from([9, 0, 9])
const padded = setLengthLeft(buf, 2)
- assert.equal(padded.toString('hex'), '0009')
+ st.equal(padded.toString('hex'), '0009')
+ st.end()
})
- it('should throw if input is not a Buffer', function() {
- assert.throws(function() {
+ t.test('should throw if input is not a Buffer', function(st) {
+ st.throws(function() {
setLengthLeft(([9, 9]) as Buffer, 3)
})
+ st.end()
})
})
-describe('setLengthRight', function() {
- it('should right pad a Buffer', function() {
+tape('setLengthRight', function(t) {
+ t.test('should right pad a Buffer', function(st) {
const buf = Buffer.from([9, 9])
const padded = setLengthRight(buf, 3)
- assert.equal(padded.toString('hex'), '090900')
+ st.equal(padded.toString('hex'), '090900')
+ st.end()
})
- it('should right truncate a Buffer', function() {
+ t.test('should right truncate a Buffer', function(st) {
const buf = Buffer.from([9, 0, 9])
const padded = setLengthRight(buf, 2)
- assert.equal(padded.toString('hex'), '0900')
+ st.equal(padded.toString('hex'), '0900')
+ st.end()
})
- it('should throw if input is not a Buffer', function() {
- assert.throws(function() {
+ t.test('should throw if input is not a Buffer', function(st) {
+ st.throws(function() {
setLengthRight(([9, 9]) as Buffer, 3)
})
+ st.end()
})
})
-describe('bufferToHex', function() {
- it('should convert a buffer to hex', function() {
+tape('bufferToHex', function(t) {
+ t.test('should convert a buffer to hex', function(st) {
const buf = Buffer.from('5b9ac8', 'hex')
const hex = bufferToHex(buf)
- assert.equal(hex, '0x5b9ac8')
+ st.equal(hex, '0x5b9ac8')
+ st.end()
})
- it('empty buffer', function() {
+ t.test('empty buffer', function(st) {
const buf = Buffer.alloc(0)
const hex = bufferToHex(buf)
- assert.strictEqual(hex, '0x')
+ st.strictEqual(hex, '0x')
+ st.end()
})
})
-describe('bufferToInt', function() {
- it('should convert a int to hex', function() {
+tape('bufferToInt', function(t) {
+ t.test('should convert an int to hex', function(st) {
const buf = Buffer.from('5b9ac8', 'hex')
const i = bufferToInt(buf)
- assert.equal(i, 6003400)
- assert.equal(bufferToInt(Buffer.allocUnsafe(0)), 0)
+ st.equal(i, 6003400)
+ st.equal(bufferToInt(Buffer.allocUnsafe(0)), 0)
+ st.end()
})
- it('should convert empty input to 0', function() {
- assert.equal(bufferToInt(Buffer.allocUnsafe(0)), 0)
+ t.test('should convert empty input to 0', function(st) {
+ st.equal(bufferToInt(Buffer.allocUnsafe(0)), 0)
+ st.end()
})
})
-describe('fromSigned', function() {
- it('should convert an unsigned (negative) buffer to a singed number', function() {
+tape('fromSigned', function(t) {
+ t.test('should convert an unsigned (negative) buffer to a signed number', function(st) {
const neg = '-452312848583266388373324160190187140051835877600158453279131187530910662656'
const buf = Buffer.allocUnsafe(32).fill(0)
buf[0] = 255
- assert.equal(fromSigned(buf), neg)
+ st.equal(fromSigned(buf).toString(), neg)
+ st.end()
})
- it('should convert an unsigned (positive) buffer to a singed number', function() {
+ t.test('should convert an unsigned (positive) buffer to a signed number', function(st) {
const neg = '452312848583266388373324160190187140051835877600158453279131187530910662656'
const buf = Buffer.allocUnsafe(32).fill(0)
buf[0] = 1
- assert.equal(fromSigned(buf), neg)
+ st.equal(fromSigned(buf).toString(), neg)
+ st.end()
})
})
-describe('toUnsigned', function() {
- it('should convert a signed (negative) number to unsigned', function() {
+tape('toUnsigned', function(t) {
+ t.test('should convert a signed (negative) number to unsigned', function(st) {
const neg = '-452312848583266388373324160190187140051835877600158453279131187530910662656'
const hex = 'ff00000000000000000000000000000000000000000000000000000000000000'
const num = new BN(neg)
- assert.equal(toUnsigned(num).toString('hex'), hex)
+ st.equal(toUnsigned(num).toString('hex'), hex)
+ st.end()
})
- it('should convert a signed (positive) number to unsigned', function() {
+ t.test('should convert a signed (positive) number to unsigned', function(st) {
const neg = '452312848583266388373324160190187140051835877600158453279131187530910662656'
const hex = '0100000000000000000000000000000000000000000000000000000000000000'
const num = new BN(neg)
- assert.equal(toUnsigned(num).toString('hex'), hex)
+ st.equal(toUnsigned(num).toString('hex'), hex)
+ st.end()
})
})
-describe('hex prefix', function() {
+tape('hex prefix', function(t) {
const string = 'd658a4b8247c14868f3c512fa5cbb6e458e4a989'
- it('should add', function() {
- assert.equal(addHexPrefix(string), '0x' + string)
+ t.test('should add', function(st) {
+ st.equal(addHexPrefix(string), '0x' + string)
+ st.end()
})
- it('should return on non-string input', function() {
- assert.equal(addHexPrefix(1 as any), 1)
+ t.test('should return on non-string input', function(st) {
+ st.equal(addHexPrefix(1 as any), 1)
+ st.end()
})
})
-describe('toBuffer', function() {
- it('should work', function() {
+tape('toBuffer', function(t) {
+ t.test('should work', function(st) {
// Buffer
- assert.deepEqual(toBuffer(Buffer.allocUnsafe(0)), Buffer.allocUnsafe(0))
+ st.ok(toBuffer(Buffer.allocUnsafe(0)).equals(Buffer.allocUnsafe(0)))
// Array
- assert.deepEqual(toBuffer([]), Buffer.allocUnsafe(0))
+ st.ok(toBuffer([]).equals(Buffer.allocUnsafe(0)))
// String
- assert.deepEqual(toBuffer('0x11'), Buffer.from([17]))
- assert.deepEqual(toBuffer('0x1234').toString('hex'), '1234')
- assert.deepEqual(toBuffer('0x'), Buffer.from([]))
+ st.ok(toBuffer('0x11').equals(Buffer.from([17])))
+ st.equal(toBuffer('0x1234').toString('hex'), '1234')
+ st.ok(toBuffer('0x').equals(Buffer.from([])))
// Number
- assert.deepEqual(toBuffer(1), Buffer.from([1]))
+ st.ok(toBuffer(1).equals(Buffer.from([1])))
// null
- assert.deepEqual(toBuffer(null), Buffer.allocUnsafe(0))
+ st.ok(toBuffer(null).equals(Buffer.allocUnsafe(0)))
// undefined
- assert.deepEqual(toBuffer(undefined), Buffer.allocUnsafe(0))
+ st.ok(toBuffer(undefined).equals(Buffer.allocUnsafe(0)))
// 'toBN'
- assert.deepEqual(toBuffer(new BN(1)), Buffer.from([1]))
+ st.ok(toBuffer(new BN(1)).equals(Buffer.from([1])))
// 'toArray'
- assert.deepEqual(
+ st.ok(
toBuffer({
- toArray: function() {
+ toArray: function(): any {
return [1]
- },
- }),
- Buffer.from([1]),
+ }
+ }).equals(Buffer.from([1]))
)
+ st.end()
})
- it('should fail', function() {
- assert.throws(function() {
- toBuffer({ test: 1 })
+ t.test('should fail', function(st) {
+ st.throws(function() {
+ toBuffer({ test: 1 } as any)
})
+ st.end()
})
- it('should fail with non 0x-prefixed hex strings', function() {
- assert.throws(() => toBuffer('11'), '11')
- assert.throws(() => toBuffer(''))
- assert.throws(() => toBuffer('0xR'), '0xR')
+ t.test('should fail with non 0x-prefixed hex strings', function(st) {
+ st.throws(() => toBuffer('11'), '11')
+ st.throws(() => toBuffer(''))
+ st.throws(() => toBuffer('0xR'), '0xR')
+ st.end()
})
+
+ t.test(
+ 'should convert a TransformableToBuffer like the Address class (i.e. provides a toBuffer method)',
+ function(st) {
+ const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a'
+ const address = Address.fromString(str)
+ const addressBuf = toBuffer(address)
+ st.ok(addressBuf.equals(address.toBuffer()))
+ st.end()
+ }
+ )
})
-describe('baToJSON', function() {
- it('should turn a array of buffers into a pure json object', function() {
+tape('baToJSON', function(t) {
+ t.test('should turn a array of buffers into a pure json object', function(st) {
const ba = [Buffer.from([0]), Buffer.from([1]), [Buffer.from([2])]]
- assert.deepEqual(baToJSON(ba), ['0x00', '0x01', ['0x02']])
+ st.deepEqual(baToJSON(ba), ['0x00', '0x01', ['0x02']])
+ st.end()
})
- it('should turn a buffers into string', function() {
- assert.deepEqual(baToJSON(Buffer.from([0])), '0x00')
+ t.test('should turn a buffers into string', function(st) {
+ st.deepEqual(baToJSON(Buffer.from([0])), '0x00')
+ st.end()
})
})
diff --git a/test/constants.spec.ts b/test/constants.spec.ts
index 79cdf188..c8dd28b7 100644
--- a/test/constants.spec.ts
+++ b/test/constants.spec.ts
@@ -1,4 +1,4 @@
-import * as assert from 'assert'
+import tape from 'tape'
import {
MAX_INTEGER,
TWO_POW256,
@@ -7,49 +7,45 @@ import {
KECCAK256_RLP_ARRAY_S,
KECCAK256_RLP_ARRAY,
KECCAK256_RLP_S,
- KECCAK256_RLP,
+ KECCAK256_RLP
} from '../src'
-describe('constants', function() {
- it('should match constants', function() {
- assert.equal(
+tape('constants', function(t) {
+ t.test('should match constants', function(st) {
+ st.equal(
MAX_INTEGER.toString('hex'),
- 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
)
- assert.equal(
+ st.equal(
TWO_POW256.toString('hex'),
- '10000000000000000000000000000000000000000000000000000000000000000',
+ '10000000000000000000000000000000000000000000000000000000000000000'
)
- assert.equal(
- KECCAK256_NULL_S,
- 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
- )
+ st.equal(KECCAK256_NULL_S, 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470')
- assert.equal(
+ st.equal(
KECCAK256_NULL.toString('hex'),
- 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470',
+ 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
)
- assert.equal(
+ st.equal(
KECCAK256_RLP_ARRAY_S,
- '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
+ '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'
)
- assert.equal(
+ st.equal(
KECCAK256_RLP_ARRAY.toString('hex'),
- '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
+ '1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'
)
- assert.equal(
- KECCAK256_RLP_S,
- '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
- )
+ st.equal(KECCAK256_RLP_S, '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')
- assert.equal(
+ st.equal(
KECCAK256_RLP.toString('hex'),
- '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
+ '56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'
)
+
+ st.end()
})
})
diff --git a/test/externals.spec.ts b/test/externals.spec.ts
index 4292d4fa..37fbad46 100644
--- a/test/externals.spec.ts
+++ b/test/externals.spec.ts
@@ -1,81 +1,93 @@
-import * as assert from 'assert'
-
-import * as BN_export from 'bn.js'
+import tape from 'tape'
+import BN_export from 'bn.js'
import * as rlp_export from 'rlp'
-
import * as src from '../src'
-describe('External BN export', () => {
- it('should export `BN`', () => {
- assert.equal(src.BN, BN_export)
+tape('External BN export', t => {
+ t.test('should export `BN`', st => {
+ st.equal(src.BN, BN_export)
+ st.end()
})
- it('should use a BN function correctly', () => {
+ t.test('should use a BN function correctly', st => {
const a = new src.BN('dead', 16)
const b = new src.BN('101010', 2)
const result = a.add(b)
- assert.equal(result.toString(10), 57047)
+ st.equal(result.toString(10), '57047')
+ st.end()
})
- it('should throw on exceptions', () => {
+ t.test('should throw on exceptions', st => {
// should not allow 0 input
- assert.throws(() => {
+ st.throws(() => {
new src.BN(1).egcd(new src.BN('0'))
}, /^Error: Assertion failed$/)
+ st.end()
})
- // should not accept an unsafe integer
- const num = Math.pow(2, 53)
- assert.throws(() => {
- return new src.BN(num, 10)
- }, /^Error: Assertion failed$/)
+ t.test('should not accept an unsafe integer', st => {
+ const num = Math.pow(2, 53)
+ st.throws(() => {
+ return new src.BN(num, 10)
+ }, /^Error: Assertion failed$/)
+ st.end()
+ })
- // should throw error with num eq 0x4000000
- assert.throws(function() {
- new src.BN(0).iaddn(0x4000000)
- }, /^Error: Assertion failed$/)
+ t.test('should throw error with num eq 0x4000000', st => {
+ st.throws(function() {
+ new src.BN(0).iaddn(0x4000000)
+ }, /^Error: Assertion failed$/)
+ st.end()
+ })
})
-describe('External rlp export', () => {
- it('should export `rlp`', () => {
- assert.equal(src.rlp, rlp_export)
+tape('External rlp export', t => {
+ t.test('should export `rlp`', st => {
+ st.equal(src.rlp, rlp_export)
+ st.end()
})
- it('should use a rlp function correctly', () => {
+ t.test('should use a rlp function correctly', st => {
const nestedList = [[], [[]], [[], [[]]]]
- var encoded = src.rlp.encode(nestedList)
- var decoded = src.rlp.decode(encoded)
- assert.deepEqual(nestedList, decoded)
+ const encoded = src.rlp.encode(nestedList)
+ const decoded = src.rlp.decode(encoded)
+ st.deepEqual(nestedList, decoded)
+ st.end()
})
- it('should throw on exceptions', () => {
+ t.test('should throw on exceptions', st => {
// bad values: wrong encoded a zero
const val = Buffer.from(
'f9005f030182520894b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3',
- 'hex',
+ 'hex'
)
let result
try {
result = src.rlp.decode(val)
- } catch (e) {}
- assert.equal(result, undefined)
+ } catch (e) {
+ // pass
+ }
+ st.equal(result, undefined)
// bad values: invalid length
const a = Buffer.from(
'f86081000182520894b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3',
- 'hex',
+ 'hex'
)
let res
try {
result = src.rlp.decode(a)
- } catch (e) {}
- assert.equal(res, undefined)
+ } catch (e) {
+ // pass
+ }
+ st.equal(res, undefined)
+ st.end()
})
})
-describe('External ethjsUtil export', () => {
- it('should have all ethjsUtil methods', () => {
+tape('External ethjsUtil export', t => {
+ t.test('should have all ethjsUtil methods', st => {
const expected = [
'arrayContainsArray',
'toBuffer',
@@ -90,34 +102,37 @@ describe('External ethjsUtil export', () => {
'toAscii',
'getKeys',
'isHexString',
- 'toUtf8',
+ 'toUtf8'
]
expected.forEach(prop => {
- assert.ok(src.hasOwnProperty(prop))
+ st.ok(prop in src)
})
+ st.end()
})
- it('should use ethjsUtil functions correctly', () => {
+ t.test('should use ethjsUtil functions correctly', st => {
// should convert intToHex
- assert.equal(src.intToHex(new src.BN(0).toNumber()), '0x0')
+ st.equal(src.intToHex(new src.BN(0).toNumber()), '0x0')
// should convert intToHex
const i = 6003400
const hex = src.intToHex(i)
- assert.equal(hex, '0x5b9ac8')
+ st.equal(hex, '0x5b9ac8')
// should convert a int to a buffer
const j = 6003400
const buf = src.intToBuffer(j)
- assert.equal(buf.toString('hex'), '5b9ac8')
+ st.equal(buf.toString('hex'), '5b9ac8')
+ st.end()
})
- it('should handle exceptions and invalid inputs', () => {
+ t.test('should handle exceptions and invalid inputs', st => {
// should throw when invalid abi
- assert.throws(() => src.getKeys([], (3289) as string), Error)
+ st.throws(() => src.getKeys([], (3289) as string), Error)
// should detect invalid length hex string
- assert.equal(src.isHexString('0x0', 2), false)
+ st.equal(src.isHexString('0x0', 2), false)
+ st.end()
})
})
diff --git a/test/hash.spec.ts b/test/hash.spec.ts
index bb01089d..9e28cb78 100644
--- a/test/hash.spec.ts
+++ b/test/hash.spec.ts
@@ -1,4 +1,4 @@
-import * as assert from 'assert'
+import tape from 'tape'
import {
keccak,
keccak256,
@@ -12,239 +12,270 @@ import {
ripemd160FromString,
ripemd160FromArray,
rlphash,
- toBuffer,
+ toBuffer
} from '../src'
-describe('keccak', function() {
- it('should produce a keccak224 hash', function() {
+tape('keccak', function(t) {
+ t.test('should produce a keccak224 hash', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '9e66938bd8f32c8610444bb524630db496bd58b689f9733182df63ba'
const hash = keccak(toBuffer(msg), 224)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should produce a keccak256 hash', function() {
+ t.test('should produce a keccak256 hash', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28'
const hash = keccak(toBuffer(msg))
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should produce a keccak384 hash', function() {
+ t.test('should produce a keccak384 hash', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r =
'923e0f6a1c324a698139c3f3abbe88ac70bf2e7c02b26192c6124732555a32cef18e81ac91d5d97ce969745409c5bbc6'
const hash = keccak(toBuffer(msg), 384)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should produce a keccak512 hash', function() {
+ t.test('should produce a keccak512 hash', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r =
'36fdacd0339307068e9ed191773a6f11f6f9f99016bd50f87fd529ab7c87e1385f2b7ef1ac257cc78a12dcb3e5804254c6a7b404a6484966b831eadc721c3d24'
const hash = keccak(toBuffer(msg), 512)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not Buffer', function() {
+ t.test('should error if input is not Buffer', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
keccak((msg) as Buffer)
})
+ st.end()
})
- it('should error if provided incorrect bits', function() {
+ t.test('should error if provided incorrect bits', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
keccak(toBuffer(msg), 1024)
})
+ st.end()
})
})
-describe('keccak256', function() {
- it('should produce a hash (keccak(a, 256) alias)', function() {
+tape('keccak256', function(t) {
+ t.test('should produce a hash (keccak(a, 256) alias)', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28'
const hash = keccak256(toBuffer(msg))
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
})
-describe('keccakFromString', function() {
- it('should produce a hash', function() {
+tape('keccakFromString', function(t) {
+ t.test('should produce a hash', function(st) {
const msg = '3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '22ae1937ff93ec72c4d46ff3e854661e3363440acd6f6e4adf8f1a8978382251'
const hash = keccakFromString(msg)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should throw if input is not a string', function() {
+ t.test('should throw if input is not a string', function(st) {
const buf = toBuffer('0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1')
- assert.throws(function() {
+ st.throws(function() {
keccakFromString((buf) as string)
})
+ st.end()
})
})
-describe('keccakFromHexString', function() {
- it('should produce a hash', function() {
+tape('keccakFromHexString', function(t) {
+ t.test('should produce a hash', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28'
const hash = keccakFromHexString(msg)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should throw if input is not hex-prefixed', function() {
+ t.test('should throw if input is not hex-prefixed', function(st) {
const msg = '3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
keccakFromHexString(msg)
})
+ st.end()
})
- it('should throw if input is not a string', function() {
+ t.test('should throw if input is not a string', function(st) {
const buf = toBuffer('0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1')
- assert.throws(function() {
+ st.throws(function() {
keccakFromHexString((buf) as string)
})
+ st.end()
})
})
-describe('keccakFromArray', function() {
- it('should produce a hash', function() {
+tape('keccakFromArray', function(t) {
+ t.test('should produce a hash', function(st) {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0]
const r = 'fba8669bd39e3257e64752758f3a0d3218865a15757c6b0bc48b8ef95bc8bfd5'
const hash = keccakFromArray(arr)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should throw if input is not an array', function() {
+ t.test('should throw if input is not an array', function(st) {
const buf = toBuffer([0, 1, 2, 3, 4, 5, 6, 7, 8, 0])
- assert.throws(function() {
+ st.throws(function() {
keccakFromArray((buf) as number[])
})
+ st.end()
})
})
-describe('keccak-512', function() {
- it('should produce a hash', function() {
+tape('keccak-512', function(t) {
+ t.test('should produce a hash', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r =
'36fdacd0339307068e9ed191773a6f11f6f9f99016bd50f87fd529ab7c87e1385f2b7ef1ac257cc78a12dcb3e5804254c6a7b404a6484966b831eadc721c3d24'
const hash = keccak(toBuffer(msg), 512)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
})
-describe('sha256', function() {
- it('should produce a sha256', function() {
+tape('sha256', function(t) {
+ t.test('should produce a sha256', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '58bbda5e10bc11a32d808e40f9da2161a64f00b5557762a161626afe19137445'
const hash = sha256(toBuffer(msg))
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not Buffer', function() {
+ t.test('should error if input is not Buffer', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
sha256((msg) as Buffer)
})
+ st.end()
})
})
-describe('sha256FromString', function() {
- it('should produce a sha256', function() {
+tape('sha256FromString', function(t) {
+ t.test('should produce a sha256', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '58bbda5e10bc11a32d808e40f9da2161a64f00b5557762a161626afe19137445'
const hash = sha256FromString(msg)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not Buffer', function() {
+ t.test('should error if input is not Buffer', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
sha256FromString((toBuffer(msg)) as string)
})
+ st.end()
})
})
-describe('sha256FromArray', function() {
- it('should produce a sha256', function() {
+tape('sha256FromArray', function(t) {
+ t.test('should produce a sha256', function(st) {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0]
const r = '5443c487d45d01c56150d91e7a071c69a97939b1c57874b73989a9ff7875e86b'
const hash = sha256FromArray(arr)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not Buffer', function() {
+ t.test('should error if input is not Buffer', function(st) {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0]
- assert.throws(function() {
+ st.throws(function() {
sha256FromArray((toBuffer(arr)) as number[])
})
+ st.end()
})
})
-describe('ripemd160', function() {
- it('should produce a ripemd160', function() {
+tape('ripemd160', function(t) {
+ t.test('should produce a ripemd160', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '4bb0246cbfdfddbe605a374f1187204c896fabfd'
const hash = ripemd160(toBuffer(msg), false)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should produce a padded ripemd160', function() {
+ t.test('should produce a padded ripemd160', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '0000000000000000000000004bb0246cbfdfddbe605a374f1187204c896fabfd'
const hash = ripemd160(toBuffer(msg), true)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not Buffer', function() {
+ t.test('should error if input is not Buffer', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
ripemd160((msg) as Buffer, false)
})
+ st.end()
})
})
-describe('ripemd160FromString', function() {
- it('should produce a ripemd160', function() {
+tape('ripemd160FromString', function(t) {
+ t.test('should produce a ripemd160', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '4bb0246cbfdfddbe605a374f1187204c896fabfd'
const hash = ripemd160FromString(msg, false)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should produce a padded ripemd160', function() {
+ t.test('should produce a padded ripemd160', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '0000000000000000000000004bb0246cbfdfddbe605a374f1187204c896fabfd'
const hash = ripemd160FromString(msg, true)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not a string', function() {
+ t.test('should error if input is not a string', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
- assert.throws(function() {
+ st.throws(function() {
ripemd160FromString((toBuffer(msg)) as string, false)
})
+ st.end()
})
})
-describe('ripemd160FromArray', function() {
- it('should produce a ripemd160', function() {
+tape('ripemd160FromArray', function(t) {
+ t.test('should produce a ripemd160', function(st) {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0]
const r = 'ddbb5062318b209e3dbfc389fe61840363050071'
const hash = ripemd160FromArray(arr, false)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should produce a padded ripemd160', function() {
+ t.test('should produce a padded ripemd160', function(st) {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0]
const r = '000000000000000000000000ddbb5062318b209e3dbfc389fe61840363050071'
const hash = ripemd160FromArray(arr, true)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
- it('should error if input is not an array', function() {
+ t.test('should error if input is not an array', function(st) {
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0]
- assert.throws(function() {
+ st.throws(function() {
ripemd160FromArray((toBuffer(arr)) as number[], false)
})
+ st.end()
})
})
-describe('rlphash', function() {
- it('should produce a keccak-256 hash of the rlp data', function() {
+tape('rlphash', function(t) {
+ t.test('should produce a keccak-256 hash of the rlp data', function(st) {
const msg = '0x3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1'
const r = '33f491f24abdbdbf175e812b94e7ede338d1c7f01efb68574acd279a15a39cbe'
const hash = rlphash(msg)
- assert.equal(hash.toString('hex'), r)
+ st.equal(hash.toString('hex'), r)
+ st.end()
})
})
diff --git a/test/object.spec.ts b/test/object.spec.ts
index e0b5004e..e99ad11b 100644
--- a/test/object.spec.ts
+++ b/test/object.spec.ts
@@ -1,134 +1,140 @@
-import * as assert from 'assert'
+import tape from 'tape'
import { zeros, defineProperties } from '../src'
-describe('define', function() {
+tape('define', function(t) {
const fields = [
{
name: 'aword',
alias: 'blah',
word: true,
- default: Buffer.allocUnsafe(0),
+ default: Buffer.allocUnsafe(0)
},
{
name: 'empty',
allowZero: true,
length: 20,
- default: Buffer.allocUnsafe(0),
+ default: Buffer.allocUnsafe(0)
},
{
name: 'cannotBeZero',
allowZero: false,
- default: Buffer.from([0]),
+ default: Buffer.from([0])
},
{
name: 'value',
- default: Buffer.allocUnsafe(0),
+ default: Buffer.allocUnsafe(0)
},
{
name: 'r',
length: 32,
allowLess: true,
- default: zeros(32),
- },
+ default: zeros(32)
+ }
]
- it('should trim zeros', function() {
- var someOb: any = {}
+ t.test('should trim zeros', function(st) {
+ const someOb: any = {}
defineProperties(someOb, fields)
// Define Properties
someOb.r = '0x00004'
- assert.equal(someOb.r.toString('hex'), '04')
+ st.equal(someOb.r.toString('hex'), '04')
someOb.r = Buffer.from([0, 0, 0, 0, 4])
- assert.equal(someOb.r.toString('hex'), '04')
+ st.equal(someOb.r.toString('hex'), '04')
+ st.end()
})
- it("shouldn't allow wrong size for exact size requirements", function() {
- var someOb = {}
+ t.test("shouldn't allow wrong size for exact size requirements", function(st) {
+ const someOb = {}
defineProperties(someOb, fields)
- assert.throws(function() {
+ st.throws(function() {
const tmp = [
{
name: 'mustBeExactSize',
allowZero: false,
length: 20,
- default: Buffer.from([1, 2, 3, 4]),
- },
+ default: Buffer.from([1, 2, 3, 4])
+ }
]
defineProperties(someOb, tmp)
})
+ st.end()
})
- it('it should accept rlp encoded intial data', function() {
- var someOb: any = {}
- var data = {
+ t.test('it should accept rlp encoded intial data', function(st) {
+ const someOb: any = {}
+ const data = {
aword: '0x01',
cannotBeZero: '0x02',
value: '0x03',
- r: '0x04',
+ r: '0x04'
}
- var expected = {
+ const expected = {
aword: '0x01',
empty: '0x',
cannotBeZero: '0x02',
value: '0x03',
- r: '0x04',
+ r: '0x04'
}
- var expectedArray = ['0x01', '0x', '0x02', '0x03', '0x04']
+ const expectedArray = ['0x01', '0x', '0x02', '0x03', '0x04']
defineProperties(someOb, fields, data)
- assert.deepEqual(someOb.toJSON(true), expected, 'should produce the correctly labeled object')
+ st.deepEqual(someOb.toJSON(true), expected, 'should produce the correctly labeled object')
- var someOb2: any = {}
- var rlpEncoded = someOb.serialize().toString('hex')
+ const someOb2: any = {}
+ const rlpEncoded = someOb.serialize().toString('hex')
defineProperties(someOb2, fields, rlpEncoded)
- assert.equal(
+ st.equal(
someOb2.serialize().toString('hex'),
rlpEncoded,
- 'the constuctor should accept rlp encoded buffers',
+ 'the constuctor should accept rlp encoded buffers'
)
- var someOb3 = {}
+ const someOb3 = {}
defineProperties(someOb3, fields, expectedArray)
- assert.deepEqual(someOb.toJSON(), expectedArray, 'should produce the correctly object')
+ st.deepEqual(someOb.toJSON(), expectedArray, 'should produce the correctly object')
+ st.end()
})
- it('it should not accept invalid values in the constuctor', function() {
- var someOb = {}
- assert.throws(function() {
+ t.test('it should not accept invalid values in the constuctor', function(st) {
+ const someOb = {}
+ st.throws(function() {
defineProperties(someOb, fields, 5)
}, 'should throw on nonsensical data')
- assert.throws(function() {
+ st.throws(function() {
defineProperties(someOb, fields, Array(6))
}, 'should throw on invalid arrays')
+ st.end()
})
- it('alias should work ', function() {
- var someOb: any = {}
- var data = {
+ t.test('alias should work ', function(st) {
+ const someOb: any = {}
+ const data = {
aword: '0x01',
cannotBeZero: '0x02',
value: '0x03',
- r: '0x04',
+ r: '0x04'
}
defineProperties(someOb, fields, data)
- assert.equal(someOb.blah.toString('hex'), '01')
+ st.equal(someOb.blah.toString('hex'), '01')
someOb.blah = '0x09'
- assert.equal(someOb.blah.toString('hex'), '09')
- assert.equal(someOb.aword.toString('hex'), '09')
+ st.equal(someOb.blah.toString('hex'), '09')
+ st.equal(someOb.aword.toString('hex'), '09')
+ st.end()
})
- it('alias should work #2', function() {
- var someOb: any = {}
- var data = { blah: '0x1' }
+ t.test('alias should work #2', function(st) {
+ const someOb: any = {}
+ const data = { blah: '0x1' }
defineProperties(someOb, fields, data)
- assert.equal(someOb.blah.toString('hex'), '01')
- assert.equal(someOb.aword.toString('hex'), '01')
+ st.equal(someOb.blah.toString('hex'), '01')
+ st.equal(someOb.aword.toString('hex'), '01')
+ st.end()
})
})
diff --git a/test/signature.spec.ts b/test/signature.spec.ts
index 2969ce7b..302d0097 100644
--- a/test/signature.spec.ts
+++ b/test/signature.spec.ts
@@ -1,6 +1,6 @@
-import * as assert from 'assert'
-import * as BN from 'bn.js'
+import tape from 'tape'
import {
+ BN,
ecsign,
ecrecover,
privateToPublic,
@@ -8,213 +8,453 @@ import {
isValidSignature,
fromRpcSig,
toRpcSig,
+ intToBuffer
} from '../src'
const echash = Buffer.from(
'82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28',
- 'hex',
+ 'hex'
)
const ecprivkey = Buffer.from(
'3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1',
- 'hex',
+ 'hex'
)
const chainId = 3 // ropsten
-describe('ecsign', function() {
- it('should produce a signature', function() {
+tape('ecsign', function(t) {
+ t.test('should produce a signature', function(st) {
const sig = ecsign(echash, ecprivkey)
- assert.deepEqual(
- sig.r,
- Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex'),
+ st.ok(
+ sig.r.equals(
+ Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
+ )
)
- assert.deepEqual(
- sig.s,
- Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex'),
+ st.ok(
+ sig.s.equals(
+ Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
+ )
)
- assert.equal(sig.v, 27)
+ st.equal(sig.v, 27)
+ st.end()
})
- it('should produce a signature for Ropsten testnet', function() {
+ t.test('should produce a signature for Ropsten testnet', function(st) {
const sig = ecsign(echash, ecprivkey, chainId)
- assert.deepEqual(
- sig.r,
- Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex'),
+ st.ok(
+ sig.r.equals(
+ Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
+ )
)
- assert.deepEqual(
- sig.s,
- Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex'),
+ st.ok(
+ sig.s.equals(
+ Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
+ )
)
- assert.equal(sig.v, 41)
+ st.equal(sig.v, 41)
+ st.end()
})
+
+ t.test('should produce a signature for chainId=150', function(st) {
+ const expectedSigR = Buffer.from(
+ '99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9',
+ 'hex'
+ )
+ const expectedSigS = Buffer.from(
+ '129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66',
+ 'hex'
+ )
+ const expectedSigV = Buffer.from('014f', 'hex')
+
+ const sig = ecsign(echash, ecprivkey, 150)
+ st.ok(sig.r.equals(expectedSigR))
+ st.ok(sig.s.equals(expectedSigS))
+ st.equal(sig.v, 150 * 2 + 35)
+
+ let sigBuffer = ecsign(echash, ecprivkey, new BN(150))
+ st.ok(sigBuffer.r.equals(expectedSigR))
+ st.ok(sigBuffer.s.equals(expectedSigS))
+ st.ok(sigBuffer.v.equals(expectedSigV))
+
+ sigBuffer = ecsign(echash, ecprivkey, Buffer.from([150]))
+ st.ok(sigBuffer.v.equals(expectedSigV))
+
+ sigBuffer = ecsign(echash, ecprivkey, '0x96')
+ st.ok(sigBuffer.v.equals(expectedSigV))
+
+ st.throws(function() {
+ ecsign(echash, ecprivkey, '96')
+ })
+ st.end()
+ })
+
+ t.test(
+ 'should produce a signature for a high number chainId greater than MAX_SAFE_INTEGER',
+ function(st) {
+ const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex')
+ const expectedSigR = Buffer.from(
+ '99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9',
+ 'hex'
+ )
+ const expectedSigS = Buffer.from(
+ '129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66',
+ 'hex'
+ )
+ const expectedSigV = Buffer.from('f2ded8deec6713', 'hex')
+
+ let sigBuffer = ecsign(echash, ecprivkey, new BN(chainIDBuffer))
+ st.ok(sigBuffer.r.equals(expectedSigR))
+ st.ok(sigBuffer.s.equals(expectedSigS))
+ st.ok(sigBuffer.v.equals(expectedSigV))
+
+ sigBuffer = ecsign(echash, ecprivkey, chainIDBuffer)
+ st.ok(sigBuffer.v.equals(expectedSigV))
+
+ sigBuffer = ecsign(echash, ecprivkey, '0x' + chainIDBuffer.toString('hex'))
+ st.ok(sigBuffer.v.equals(expectedSigV))
+
+ const chainIDNumber = parseInt(chainIDBuffer.toString('hex'), 16)
+ st.throws(() => {
+ // If we would use a number for the `chainId` parameter then it should throw.
+ // (The numbers are too high to perform arithmetic on)
+ ecsign(echash, ecprivkey, chainIDNumber)
+ })
+ st.end()
+ }
+ )
})
-describe('ecrecover', function() {
- it('should recover a public key', function() {
+tape('ecrecover', function(t) {
+ t.test('should recover a public key', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
const v = 27
const pubkey = ecrecover(echash, v, r, s)
- assert.deepEqual(pubkey, privateToPublic(ecprivkey))
+ st.ok(pubkey.equals(privateToPublic(ecprivkey)))
+ st.end()
})
- it('should recover a public key (chainId = 3)', function() {
+ t.test('should recover a public key (chainId = 3)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
const v = 41
const pubkey = ecrecover(echash, v, r, s, chainId)
- assert.deepEqual(pubkey, privateToPublic(ecprivkey))
+ st.ok(pubkey.equals(privateToPublic(ecprivkey)))
+ st.end()
+ })
+ t.test('should recover a public key (chainId = 150)', function(st) {
+ const chainId = 150
+ const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
+ const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
+ const v = chainId * 2 + 35
+ const pubkey = ecrecover(echash, v, r, s, chainId)
+ st.ok(pubkey.equals(privateToPublic(ecprivkey)))
+ st.end()
})
- it('should fail on an invalid signature (v = 21)', function() {
+ t.test('should fail on an invalid signature (v = 21)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- assert.throws(function() {
+ st.throws(function() {
ecrecover(echash, 21, r, s)
})
+ st.end()
})
- it('should fail on an invalid signature (v = 29)', function() {
+ t.test('should fail on an invalid signature (v = 29)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- assert.throws(function() {
+ st.throws(function() {
ecrecover(echash, 29, r, s)
})
+ st.end()
})
- it('should fail on an invalid signature (swapped points)', function() {
+ t.test('should fail on an invalid signature (swapped points)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- assert.throws(function() {
+ st.throws(function() {
ecrecover(echash, 27, s, r)
})
+ st.end()
+ })
+ t.test('should return the right sender when using very high chain id / v values', function(st) {
+ // This data is from a transaction of the YoloV3 network, block 77, txhash c6121a23ca17b8ff70d4706c7d134920c1da43c8329444c96b4c63a55af1c760
+ /*
+ {
+ nonce: '0x8',
+ gasPrice: '0x3b9aca00',
+ gasLimit: '0x1a965',
+ to: undefined,
+ value: '0x0',
+ data: '0x608060405234801561001057600080fd5b50610101806100206000396000f3fe608060405260043610601f5760003560e01c8063776d1a0114603b576020565b5b6000543660008037600080366000845af43d6000803e3d6000f35b348015604657600080fd5b50608660048036036020811015605b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506088565b005b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea26469706673582212206d3160e3f009c6ebac579877e529c0a1ca8313678f08fe311659d440067d26ea64736f6c63430007040033',
+ v: '0xf2ded8deec6714',
+ r: '0xec212841e0b7aaffc3b3e33a08adf32fa07159e856ef23db85175a4f6d71dc0f',
+ s: '0x4b8e02b96b94064a5aa2f8d72bd0040616ba8e482a5dd96422e38c9a4611f8d5'
+ }
+ */
+ const senderPubKey = Buffer.from(
+ '78988201fbceed086cfca7b64e382d08d0bd776898731443d2907c097745b7324c54f522087f5964412cddba019f192de0fd57a0ffa63f098c2b200e53594b15',
+ 'hex'
+ )
+ const msgHash = Buffer.from(
+ '8ae8cb685a7a9f29494b07b287c3f6a103b73fa178419d10d1184861a40f6afe',
+ 'hex'
+ )
+
+ const r = Buffer.from('ec212841e0b7aaffc3b3e33a08adf32fa07159e856ef23db85175a4f6d71dc0f', 'hex')
+ const s = Buffer.from('4b8e02b96b94064a5aa2f8d72bd0040616ba8e482a5dd96422e38c9a4611f8d5', 'hex')
+
+ const vBuffer = Buffer.from('f2ded8deec6714', 'hex')
+ const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex')
+ let sender = ecrecover(msgHash, vBuffer, r, s, chainIDBuffer)
+ st.ok(sender.equals(senderPubKey), 'sender pubkey correct (Buffer)')
+
+ const vBN = new BN(vBuffer)
+ const chainIDBN = new BN(chainIDBuffer)
+ sender = ecrecover(msgHash, vBN, r, s, chainIDBN)
+ st.ok(sender.equals(senderPubKey), 'sender pubkey correct (BN)')
+
+ const vHexString = '0xf2ded8deec6714'
+ const chainIDHexString = '0x796f6c6f763378'
+ sender = ecrecover(msgHash, vHexString, r, s, chainIDHexString)
+ st.ok(sender.equals(senderPubKey), 'sender pubkey correct (HexString)')
+
+ st.throws(function() {
+ ecrecover(msgHash, 'f2ded8deec6714', r, s, chainIDHexString)
+ })
+ st.throws(function() {
+ ecrecover(msgHash, vHexString, r, s, '796f6c6f763378')
+ })
+
+ const chainIDNumber = parseInt(chainIDBuffer.toString('hex'), 16)
+ const vNumber = parseInt(vBuffer.toString('hex'), 16)
+ st.throws(() => {
+ // If we would use numbers for the `v` and `chainId` parameters, then it should throw.
+ // (The numbers are too high to perform arithmetic on)
+ ecrecover(msgHash, vNumber, r, s, chainIDNumber)
+ })
+ st.end()
})
})
-describe('hashPersonalMessage', function() {
- it('should produce a deterministic hash', function() {
+tape('hashPersonalMessage', function(t) {
+ t.test('should produce a deterministic hash', function(st) {
const h = hashPersonalMessage(Buffer.from('Hello world'))
- assert.deepEqual(
- h,
- Buffer.from('8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', 'hex'),
+ st.ok(
+ h.equals(
+ Buffer.from('8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', 'hex')
+ )
)
+ st.end()
})
- it('should throw if input is not a buffer', function() {
+ t.test('should throw if input is not a buffer', function(st) {
try {
hashPersonalMessage(([0, 1, 2, 3, 4]) as Buffer)
} catch (err) {
- assert(err.message.includes('This method only supports Buffer'))
+ st.ok(err.message.includes('This method only supports Buffer'))
}
+ st.end()
})
})
-describe('isValidSignature', function() {
- it('should fail on an invalid signature (shorter r))', function() {
+tape('isValidSignature', function(t) {
+ t.test('should fail on an invalid signature (shorter r))', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1ab', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- assert.equal(isValidSignature(27, r, s), false)
+ st.notOk(isValidSignature(27, r, s))
+ st.end()
})
- it('should fail on an invalid signature (shorter s))', function() {
+ t.test('should fail on an invalid signature (shorter s))', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca', 'hex')
- assert.equal(isValidSignature(27, r, s), false)
+ st.notOk(isValidSignature(27, r, s))
+ st.end()
})
- it('should fail on an invalid signature (v = 21)', function() {
+ t.test('should fail on an invalid signature (v = 21)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- assert.equal(isValidSignature(21, r, s), false)
+ st.notOk(isValidSignature(21, r, s))
+ st.end()
})
- it('should fail on an invalid signature (v = 29)', function() {
+ t.test('should fail on an invalid signature (v = 29)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- assert.equal(isValidSignature(29, r, s), false)
+ st.notOk(isValidSignature(29, r, s))
+ st.end()
})
- it('should fail when on homestead and s > secp256k1n/2', function() {
+ t.test('should fail when on homestead and s > secp256k1n/2', function(st) {
const SECP256K1_N_DIV_2 = new BN(
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
- 16,
+ 16
)
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from(SECP256K1_N_DIV_2.add(new BN('1', 16)).toString(16), 'hex')
const v = 27
- assert.equal(isValidSignature(v, r, s, true), false)
+ st.notOk(isValidSignature(v, r, s, true))
+ st.end()
})
- it('should not fail when not on homestead but s > secp256k1n/2', function() {
+ t.test('should not fail when not on homestead but s > secp256k1n/2', function(st) {
const SECP256K1_N_DIV_2 = new BN(
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0',
- 16,
+ 16
)
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from(SECP256K1_N_DIV_2.add(new BN('1', 16)).toString(16), 'hex')
const v = 27
- assert.equal(isValidSignature(v, r, s, false), true)
+ st.ok(isValidSignature(v, r, s, false))
+ st.end()
})
- it('should work otherwise', function() {
+ t.test('should work otherwise', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
const v = 27
- assert.equal(isValidSignature(v, r, s), true)
+ st.ok(isValidSignature(v, r, s))
+ st.end()
})
- it('should work otherwise(chainId=3)', function() {
+ t.test('should work otherwise (chainId=3)', function(st) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
const v = 41
- assert.equal(isValidSignature(v, r, s, false, chainId), true)
+ st.ok(isValidSignature(v, r, s, false, chainId))
+ st.end()
+ })
+ t.test('should work otherwise (chainId=150)', function(st) {
+ const chainId = 150
+ const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
+ const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
+ const v = chainId * 2 + 35
+ st.ok(isValidSignature(v, r, s, false, chainId))
+ st.ok(isValidSignature(intToBuffer(v), r, s, false, intToBuffer(chainId)))
+ st.ok(isValidSignature(new BN(v), r, s, false, new BN(chainId)))
+ st.ok(
+ isValidSignature(
+ '0x' + intToBuffer(v).toString('hex'),
+ r,
+ s,
+ false,
+ '0x' + intToBuffer(chainId).toString('hex')
+ )
+ )
+ st.end()
+ })
+ t.test('should work otherwise (chainId larger than MAX_INTEGER)', function(st) {
+ const r = Buffer.from('ec212841e0b7aaffc3b3e33a08adf32fa07159e856ef23db85175a4f6d71dc0f', 'hex')
+ const s = Buffer.from('4b8e02b96b94064a5aa2f8d72bd0040616ba8e482a5dd96422e38c9a4611f8d5', 'hex')
+
+ const vBuffer = Buffer.from('f2ded8deec6714', 'hex')
+ const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex')
+ st.ok(isValidSignature(vBuffer, r, s, false, chainIDBuffer))
+ st.ok(isValidSignature(new BN(vBuffer), r, s, false, new BN(chainIDBuffer)))
+ st.ok(
+ isValidSignature(
+ '0x' + vBuffer.toString('hex'),
+ r,
+ s,
+ false,
+ '0x' + chainIDBuffer.toString('hex')
+ )
+ )
+
+ const chainIDNumber = parseInt(chainIDBuffer.toString('hex'), 16)
+ const vNumber = parseInt(vBuffer.toString('hex'), 16)
+ st.throws(() => {
+ // If we would use numbers for the `v` and `chainId` parameters, then it should throw.
+ // (The numbers are too high to perform arithmetic on)
+ isValidSignature(vNumber, r, s, false, chainIDNumber)
+ })
+ st.end()
})
// FIXME: add homestead test
})
-describe('message sig', function() {
+tape('message sig', function(t) {
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
- it('should return hex strings that the RPC can use', function() {
- assert.equal(
- toRpcSig(27, r, s),
- '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca661b',
- )
- assert.deepEqual(
- fromRpcSig(
- '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca661b',
- ),
- {
- v: 27,
- r: r,
- s: s,
- },
- )
- assert.deepEqual(
- fromRpcSig(
- '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca6600',
+ t.test('should return hex strings that the RPC can use', function(st) {
+ const sig =
+ '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca661b'
+ st.equal(toRpcSig(27, r, s), sig)
+ st.deepEqual(fromRpcSig(sig), {
+ v: 27,
+ r,
+ s
+ })
+ st.end()
+ })
+
+ t.test('should return hex strings that the RPC can use (chainId=150)', function(st) {
+ const sig =
+ '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66014f'
+ const chainId = 150
+ const v = chainId * 2 + 35
+ st.equal(toRpcSig(v, r, s, chainId), sig)
+ st.equal(toRpcSig(intToBuffer(v), r, s, intToBuffer(chainId)), sig)
+ st.equal(toRpcSig(new BN(v), r, s, new BN(chainId)), sig)
+ st.equal(
+ toRpcSig(
+ '0x' + intToBuffer(v).toString('hex'),
+ r,
+ s,
+ '0x' + intToBuffer(chainId).toString('hex')
),
- {
- v: 27,
- r: r,
- s: s,
- },
+ sig
)
+ st.deepEqual(fromRpcSig(sig), {
+ v,
+ r,
+ s
+ })
+ st.end()
})
- it('should throw on invalid length', function() {
- assert.throws(function() {
+ t.test(
+ 'should return hex strings that the RPC can use (chainId larger than MAX_SAFE_INTEGER)',
+ function(st) {
+ const sig =
+ '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66f2ded8deec6714'
+ const chainIDBuffer = Buffer.from('796f6c6f763378', 'hex')
+ const vBuffer = Buffer.from('f2ded8deec6714', 'hex')
+ st.equal(toRpcSig(vBuffer, r, s, chainIDBuffer), sig)
+ st.equal(toRpcSig(new BN(vBuffer), r, s, new BN(chainIDBuffer)), sig)
+ st.equal(
+ toRpcSig('0x' + vBuffer.toString('hex'), r, s, '0x' + chainIDBuffer.toString('hex')),
+ sig
+ )
+
+ const chainIDNumber = parseInt(chainIDBuffer.toString('hex'), 16)
+ const vNumber = parseInt(vBuffer.toString('hex'), 16)
+ st.throws(function() {
+ toRpcSig(vNumber, r, s, chainIDNumber)
+ })
+ st.end()
+ }
+ )
+
+ t.test('should throw on shorter length', function(st) {
+ st.throws(function() {
fromRpcSig('')
})
- assert.throws(function() {
+ st.throws(function() {
fromRpcSig(
- '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca660042',
+ '0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca'
)
})
+ st.end()
})
- it('pad short r and s values', function() {
- assert.equal(
+ t.test('pad short r and s values', function(st) {
+ st.equal(
toRpcSig(27, r.slice(20), s.slice(20)),
- '0x00000000000000000000000000000000000000004a1579cf389ef88b20a1abe90000000000000000000000000000000000000000326fa689f228040429e3ca661b',
+ '0x00000000000000000000000000000000000000004a1579cf389ef88b20a1abe90000000000000000000000000000000000000000326fa689f228040429e3ca661b'
)
+ st.end()
})
- it('should throw on invalid v value', function() {
- assert.throws(function() {
+ t.test('should throw on invalid v value', function(st) {
+ st.throws(function() {
toRpcSig(1, r, s)
})
+ st.end()
})
})
diff --git a/test/types.spec.ts b/test/types.spec.ts
new file mode 100644
index 00000000..0b2322ed
--- /dev/null
+++ b/test/types.spec.ts
@@ -0,0 +1,124 @@
+import tape from 'tape'
+import {
+ BN,
+ toType,
+ TypeOutput,
+ intToBuffer,
+ bufferToHex,
+ intToHex,
+ bnToHex,
+ toBuffer
+} from '../src'
+
+tape('toType', function(t) {
+ t.test('from Number', function(st) {
+ const num = 1000
+ st.test('should convert to Number', function(st) {
+ const result = toType(num, TypeOutput.Number)
+ st.strictEqual(result, num)
+ st.end()
+ })
+ st.test('should convert to BN', function(st) {
+ const result = toType(num, TypeOutput.BN)
+ st.ok(result.eq(new BN(num)))
+ st.end()
+ })
+ st.test('should convert to Buffer', function(st) {
+ const result = toType(num, TypeOutput.Buffer)
+ st.ok(result.equals(intToBuffer(num)))
+ st.end()
+ })
+ st.test('should convert to PrefixedHexString', function(st) {
+ const result = toType(num, TypeOutput.PrefixedHexString)
+ st.strictEqual(result, bufferToHex(new BN(num).toArrayLike(Buffer)))
+ st.end()
+ })
+ st.test('should throw an error if greater than MAX_SAFE_INTEGER', function(st) {
+ st.throws(() => {
+ const num = Number.MAX_SAFE_INTEGER + 1
+ toType(num, TypeOutput.BN)
+ }, /^Error: The provided number is greater than MAX_SAFE_INTEGER \(please use an alternative input type\)$/)
+ st.end()
+ })
+ })
+ t.test('from BN', function(st) {
+ const num = new BN(1000)
+ st.test('should convert to Number', function(st) {
+ const result = toType(num, TypeOutput.Number)
+ st.strictEqual(result, num.toNumber())
+ st.end()
+ })
+ st.test('should convert to BN', function(st) {
+ const result = toType(num, TypeOutput.BN)
+ st.ok(result.eq(num))
+ st.end()
+ })
+ st.test('should convert to Buffer', function(st) {
+ const result = toType(num, TypeOutput.Buffer)
+ st.ok(result.equals(num.toArrayLike(Buffer)))
+ st.end()
+ })
+ st.test('should convert to PrefixedHexString', function(st) {
+ const result = toType(num, TypeOutput.PrefixedHexString)
+ st.strictEqual(result, bufferToHex(num.toArrayLike(Buffer)))
+ st.end()
+ })
+ st.test(
+ 'should throw an error if converting to Number and greater than MAX_SAFE_INTEGER',
+ function(st) {
+ const num = new BN(Number.MAX_SAFE_INTEGER).addn(1)
+ st.throws(() => {
+ toType(num, TypeOutput.Number)
+ }, /^Error: The provided number is greater than MAX_SAFE_INTEGER \(please use an alternative output type\)$/)
+ st.end()
+ }
+ )
+ })
+ t.test('from Buffer', function(st) {
+ const num = intToBuffer(1000)
+ st.test('should convert to Number', function(st) {
+ const result = toType(num, TypeOutput.Number)
+ st.ok(intToBuffer(result).equals(num))
+ st.end()
+ })
+ st.test('should convert to BN', function(st) {
+ const result = toType(num, TypeOutput.BN)
+ st.ok(result.eq(new BN(num)))
+ st.end()
+ })
+ st.test('should convert to Buffer', function(st) {
+ const result = toType(num, TypeOutput.Buffer)
+ st.ok(result.equals(num))
+ st.end()
+ })
+ st.test('should convert to PrefixedHexString', function(st) {
+ const result = toType(num, TypeOutput.PrefixedHexString)
+ st.strictEqual(result, bufferToHex(num))
+ st.end()
+ })
+ })
+ t.test('from HexPrefixedString', function(st) {
+ const num = intToHex(1000)
+ st.test('should convert to Number', function(st) {
+ const result = toType(num, TypeOutput.Number)
+ st.strictEqual(intToHex(result), num)
+ st.end()
+ })
+ st.test('should convert to BN', function(st) {
+ const result = toType(num, TypeOutput.BN)
+ st.strictEqual(bnToHex(result), num)
+ st.end()
+ })
+ st.test('should convert to Buffer', function(st) {
+ const result = toType(num, TypeOutput.Buffer)
+ st.ok(result.equals(toBuffer(num)))
+ st.end()
+ })
+ st.test('should throw an error if is not 0x-prefixed', function(st) {
+ st.throws(() => {
+ toType('1', TypeOutput.Number)
+ }, /^Error: A string must be provided with a 0x-prefix, given: 1$/)
+ st.end()
+ })
+ })
+})
diff --git a/tsconfig.json b/tsconfig.json
index ddbd8a97..ed3b4809 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,4 +1,4 @@
{
- "extends": "@ethereumjs/config-tsc",
+ "extends": "@ethereumjs/config-typescript",
"include": ["src/**/*.ts", "test/**/*.ts"]
}
diff --git a/tsconfig.prod.json b/tsconfig.prod.json
index 37770820..31187a41 100644
--- a/tsconfig.prod.json
+++ b/tsconfig.prod.json
@@ -1,7 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
- "outDir": "./dist"
+ "outDir": "./dist",
},
"include": ["src/**/*.ts"]
}
diff --git a/tslint.json b/tslint.json
deleted file mode 100644
index 2ba21c41..00000000
--- a/tslint.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": "@ethereumjs/config-tslint"
-}
diff --git a/typedoc.js b/typedoc.js
index 3bf7fa03..c8e893a9 100644
--- a/typedoc.js
+++ b/typedoc.js
@@ -5,8 +5,8 @@ module.exports = {
plugin: 'typedoc-plugin-markdown',
readme: 'none',
gitRevision: 'master',
- exclude: '**/*+(index|.spec|.e2e).ts',
+ exclude: ['src/index.ts', 'test/*.ts'],
excludeNotExported: true,
- // excludePrivate: true,
- // excludeProtected: true,
+ excludePrivate: true,
+ excludeProtected: true,
}
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy