From 4fb927f4245fe167cb158ef61ada354359919ab1 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Thu, 31 Aug 2023 09:32:34 +0200
Subject: [PATCH 01/16] implement `EventEmitter` compatible with browsers
---
packages/web3-core/src/web3_event_emitter.ts | 2 +-
.../web3-eth-accounts/src/common/common.ts | 3 +-
.../test/unit/__mocks__/isomorphic-ws.ts | 2 +-
packages/web3-utils/src/event_emitter.ts | 104 ++++++++++++++++++
packages/web3-utils/src/index.ts | 1 +
.../test/unit/socket_provider.test.ts | 2 +-
6 files changed, 109 insertions(+), 5 deletions(-)
create mode 100644 packages/web3-utils/src/event_emitter.ts
diff --git a/packages/web3-core/src/web3_event_emitter.ts b/packages/web3-core/src/web3_event_emitter.ts
index 1a0e6016953..36180c51df3 100644
--- a/packages/web3-core/src/web3_event_emitter.ts
+++ b/packages/web3-core/src/web3_event_emitter.ts
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-import { EventEmitter } from 'events';
+import { EventEmitter } from 'web3-utils';
export type Web3EventMap = Record;
export type Web3EventKey = string & keyof T;
diff --git a/packages/web3-eth-accounts/src/common/common.ts b/packages/web3-eth-accounts/src/common/common.ts
index 0c668c01579..e941338763a 100644
--- a/packages/web3-eth-accounts/src/common/common.ts
+++ b/packages/web3-eth-accounts/src/common/common.ts
@@ -15,9 +15,8 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
import pkg from 'crc-32';
-import { EventEmitter } from 'events';
+import { EventEmitter, bytesToHex, hexToBytes, uint8ArrayConcat } from 'web3-utils';
import type { Numbers } from 'web3-types';
-import { bytesToHex, hexToBytes, uint8ArrayConcat } from 'web3-utils';
import { TypeOutput } from './types.js';
import { intToUint8Array, toType, parseGethGenesis } from './utils.js';
import goerli from './chains/goerli.js';
diff --git a/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts b/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts
index bf3bd4cf1dd..42a0cdf4871 100644
--- a/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts
+++ b/packages/web3-providers-ws/test/unit/__mocks__/isomorphic-ws.ts
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-import { EventEmitter } from 'events';
+import { EventEmitter } from 'web3-utils';
export default class WebSocket extends EventEmitter {
public readyState: number;
diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts
new file mode 100644
index 00000000000..a80989d521b
--- /dev/null
+++ b/packages/web3-utils/src/event_emitter.ts
@@ -0,0 +1,104 @@
+/*
+This file is part of web3.js.
+
+web3.js is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+web3.js is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with web3.js. If not, see .
+*/
+
+import { EventEmitter as NodeEventEmitter } from 'events';
+
+type Callback = (params: any) => void | Promise;
+
+export class InBrowserEventEmitter extends EventTarget {
+ private _listeners: Record = {};
+ private maxListeners = Number.MAX_SAFE_INTEGER;
+
+ public on(eventName: string, fn: Callback) {
+ super.addEventListener(eventName, fn as EventListener);
+ this._addToListeners(eventName, fn);
+ return this;
+ }
+
+ public once(eventName: string, fn: Callback) {
+ const onceCallback = async (params: unknown) => {
+ await fn(params);
+ this.off(eventName, onceCallback);
+ };
+ return this.on(eventName, onceCallback);
+ }
+
+ public off(eventName: string, fn: Callback) {
+ super.removeEventListener(eventName, fn as EventListener);
+ this._removeFromListeners(eventName, fn);
+ return this;
+ }
+
+ public emit(eventName: string, params: unknown) {
+ const event = new CustomEvent(eventName, { detail: params });
+ return super.dispatchEvent(event);
+ }
+
+ public listenerCount(eventName: string): number {
+ const eventListeners = this._listeners[eventName];
+ return eventListeners ? eventListeners.length : 0;
+ }
+
+ public listeners(eventName: string): Callback[] {
+ return this._listeners[eventName] || [];
+ }
+
+ public eventNames(): string[] {
+ return Object.keys(this._listeners);
+ }
+
+ public removeAllListeners() {
+ this._listeners = {};
+ return this;
+ }
+
+ public setMaxListeners(maxListeners: number) {
+ this.maxListeners = maxListeners;
+ return this;
+ }
+
+ public getMaxListeners(): number {
+ return this.maxListeners;
+ }
+
+ private _addToListeners(eventName: string, fn: Callback) {
+ if (!this._listeners[eventName]) {
+ this._listeners[eventName] = [];
+ }
+ this._listeners[eventName].push(fn);
+ }
+
+ private _removeFromListeners(eventName: string, fn: Callback) {
+ const eventListeners = this._listeners[eventName];
+ if (eventListeners) {
+ const index = eventListeners.indexOf(fn);
+ if (index !== -1) {
+ eventListeners.splice(index, 1);
+ }
+ }
+ }
+}
+
+// eslint-disable-next-line import/no-mutable-exports
+export let EventEmitter: typeof NodeEventEmitter;
+// Check if the code is running in a Node.js environment
+if (typeof window === 'undefined') {
+ EventEmitter = NodeEventEmitter;
+} else {
+ // Fallback for the browser environment
+ EventEmitter = InBrowserEventEmitter as unknown as typeof NodeEventEmitter;
+}
diff --git a/packages/web3-utils/src/index.ts b/packages/web3-utils/src/index.ts
index 3990d0a6b0a..52bb219692b 100644
--- a/packages/web3-utils/src/index.ts
+++ b/packages/web3-utils/src/index.ts
@@ -16,6 +16,7 @@ along with web3.js. If not, see .
*/
export * from './converters.js';
+export * from './event_emitter.js';
export * from './validation.js';
export * from './formatter.js';
export * from './hash.js';
diff --git a/packages/web3-utils/test/unit/socket_provider.test.ts b/packages/web3-utils/test/unit/socket_provider.test.ts
index 054e11691e7..d50f9aaffac 100644
--- a/packages/web3-utils/test/unit/socket_provider.test.ts
+++ b/packages/web3-utils/test/unit/socket_provider.test.ts
@@ -15,8 +15,8 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-import { EventEmitter } from 'stream';
import { Web3APIPayload, EthExecutionAPI, JsonRpcResponse, Web3ProviderStatus } from 'web3-types';
+import { EventEmitter } from '../../src/event_emitter';
// eslint-disable-next-line import/no-relative-packages
import { sleep } from '../../../../fixtures/utils';
import { SocketProvider } from '../../src/socket_provider';
From 0e9ce5d11d054abc1ccb399981aa42560cb0c393 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Mon, 4 Sep 2023 11:35:42 +0200
Subject: [PATCH 02/16] some fixes at InBrowserEventEmitter
---
packages/web3-utils/src/event_emitter.ts | 35 ++++++++++++++++--------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts
index a80989d521b..2a9e19b7437 100644
--- a/packages/web3-utils/src/event_emitter.ts
+++ b/packages/web3-utils/src/event_emitter.ts
@@ -17,20 +17,31 @@ along with web3.js. If not, see .
import { EventEmitter as NodeEventEmitter } from 'events';
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Callback = (params: any) => void | Promise;
+type EventTargetCallback = (params: CustomEvent) => void;
+
+const wrapFunction =
+ (fn: Callback): EventTargetCallback =>
+ (params: CustomEvent) =>
+ fn(params.detail);
+
+/**
+ * This class copy the behavior of Node.js EventEmitter class.
+ * It is used to provide the same interface for the browser environment.
+ */
export class InBrowserEventEmitter extends EventTarget {
- private _listeners: Record = {};
+ private _listeners: Record = {};
private maxListeners = Number.MAX_SAFE_INTEGER;
public on(eventName: string, fn: Callback) {
- super.addEventListener(eventName, fn as EventListener);
- this._addToListeners(eventName, fn);
+ this.addEventListener(eventName, fn);
return this;
}
public once(eventName: string, fn: Callback) {
- const onceCallback = async (params: unknown) => {
+ const onceCallback = async (params: Callback) => {
await fn(params);
this.off(eventName, onceCallback);
};
@@ -38,8 +49,7 @@ export class InBrowserEventEmitter extends EventTarget {
}
public off(eventName: string, fn: Callback) {
- super.removeEventListener(eventName, fn as EventListener);
- this._removeFromListeners(eventName, fn);
+ this.removeEventListener(eventName, fn);
return this;
}
@@ -54,7 +64,7 @@ export class InBrowserEventEmitter extends EventTarget {
}
public listeners(eventName: string): Callback[] {
- return this._listeners[eventName] || [];
+ return this._listeners[eventName].map(value => value[0]) || [];
}
public eventNames(): string[] {
@@ -75,18 +85,21 @@ export class InBrowserEventEmitter extends EventTarget {
return this.maxListeners;
}
- private _addToListeners(eventName: string, fn: Callback) {
+ public addEventListener(eventName: string, fn: Callback) {
+ const wrappedFn = wrapFunction(fn);
+ super.addEventListener(eventName, wrappedFn as EventListener);
if (!this._listeners[eventName]) {
this._listeners[eventName] = [];
}
- this._listeners[eventName].push(fn);
+ this._listeners[eventName].push([fn, wrappedFn]);
}
- private _removeFromListeners(eventName: string, fn: Callback) {
+ public removeEventListener(eventName: string, fn: Callback) {
const eventListeners = this._listeners[eventName];
if (eventListeners) {
- const index = eventListeners.indexOf(fn);
+ const index = eventListeners.findIndex(item => item[0] === fn);
if (index !== -1) {
+ super.removeEventListener(eventName, eventListeners[index][1] as EventListener);
eventListeners.splice(index, 1);
}
}
From 28ba5dc1f078158f878310b76409c6400feab505 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Mon, 4 Sep 2023 16:38:13 +0200
Subject: [PATCH 03/16] some renaming inside event_emitter.ts
---
packages/web3-utils/src/event_emitter.ts | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts
index 2a9e19b7437..6d2a6e298e8 100644
--- a/packages/web3-utils/src/event_emitter.ts
+++ b/packages/web3-utils/src/event_emitter.ts
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-import { EventEmitter as NodeEventEmitter } from 'events';
+import { EventEmitter as EventEmitterAtNode } from 'events';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Callback = (params: any) => void | Promise;
@@ -31,7 +31,7 @@ const wrapFunction =
* This class copy the behavior of Node.js EventEmitter class.
* It is used to provide the same interface for the browser environment.
*/
-export class InBrowserEventEmitter extends EventTarget {
+export class EventEmitterAtBrowser extends EventTarget {
private _listeners: Record = {};
private maxListeners = Number.MAX_SAFE_INTEGER;
@@ -107,11 +107,11 @@ export class InBrowserEventEmitter extends EventTarget {
}
// eslint-disable-next-line import/no-mutable-exports
-export let EventEmitter: typeof NodeEventEmitter;
+export let EventEmitter: typeof EventEmitterAtNode;
// Check if the code is running in a Node.js environment
if (typeof window === 'undefined') {
- EventEmitter = NodeEventEmitter;
+ EventEmitter = EventEmitterAtNode;
} else {
// Fallback for the browser environment
- EventEmitter = InBrowserEventEmitter as unknown as typeof NodeEventEmitter;
+ EventEmitter = EventEmitterAtBrowser as unknown as typeof EventEmitterAtNode;
}
From 195463d433e43c3ac730e83bc3113da4318d95ef Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 4 Oct 2023 11:25:22 +0200
Subject: [PATCH 04/16] export EventEmitter as a class
---
packages/web3-utils/src/event_emitter.ts | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts
index 6d2a6e298e8..5254c49e668 100644
--- a/packages/web3-utils/src/event_emitter.ts
+++ b/packages/web3-utils/src/event_emitter.ts
@@ -107,11 +107,13 @@ export class EventEmitterAtBrowser extends EventTarget {
}
// eslint-disable-next-line import/no-mutable-exports
-export let EventEmitter: typeof EventEmitterAtNode;
+let EventEmitterType: typeof EventEmitterAtNode;
// Check if the code is running in a Node.js environment
if (typeof window === 'undefined') {
- EventEmitter = EventEmitterAtNode;
+ EventEmitterType = EventEmitterAtNode;
} else {
// Fallback for the browser environment
- EventEmitter = EventEmitterAtBrowser as unknown as typeof EventEmitterAtNode;
+ EventEmitterType = EventEmitterAtBrowser as unknown as typeof EventEmitterAtNode;
}
+
+export class EventEmitter extends EventEmitterType {}
\ No newline at end of file
From 180805813b10401068407d7db37833e8c90e731b Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 4 Oct 2023 11:25:57 +0200
Subject: [PATCH 05/16] add unit tests for EventEmitter
---
.../test/unit/event_emitter.test.ts | 124 ++++++++++++++++++
1 file changed, 124 insertions(+)
create mode 100644 packages/web3-utils/test/unit/event_emitter.test.ts
diff --git a/packages/web3-utils/test/unit/event_emitter.test.ts b/packages/web3-utils/test/unit/event_emitter.test.ts
new file mode 100644
index 00000000000..d3bdeb7a623
--- /dev/null
+++ b/packages/web3-utils/test/unit/event_emitter.test.ts
@@ -0,0 +1,124 @@
+/*
+This file is part of web3.js.
+
+web3.js is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+web3.js is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with web3.js. If not, see .
+*/
+
+// this file will contain the unit test for the event emitter
+
+import { EventEmitter } from '../../src/event_emitter';
+
+describe('EventEmitter', () => {
+ // let emitter = new EventEmitter();
+ let emitter: EventEmitter;
+
+ beforeEach(() => {
+ emitter = new EventEmitter();
+
+ //emitter.removeAllListeners('test');
+ });
+
+ describe('on', () => {
+ it('should add a listener for the specified event', () => {
+ const callback = jest.fn();
+ emitter.on('test', callback);
+ emitter.emit('test', 'hello');
+ expect(callback).toHaveBeenCalledWith('hello');
+ });
+ });
+
+ describe('once', () => {
+ it('should add a listener for the specified event that is only called once', () => {
+ const callback = jest.fn();
+ emitter.once('test', callback);
+ emitter.emit('test', 'hello');
+ emitter.emit('test', 'world');
+ expect(callback).toHaveBeenCalledTimes(1);
+ expect(callback).toHaveBeenCalledWith('hello');
+ });
+ });
+
+ describe('off', () => {
+ it('should remove a listener for the specified event', () => {
+ const callback = jest.fn();
+ emitter.on('test', callback);
+ emitter.off('test', callback);
+ emitter.emit('test', 'hello');
+ expect(callback).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('emit', () => {
+ it('should call all listeners for the specified event', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test', callback1);
+ emitter.on('test', callback2);
+ emitter.emit('test', 'hello');
+ expect(callback1).toHaveBeenCalledWith('hello');
+ expect(callback2).toHaveBeenCalledWith('hello');
+ });
+ });
+
+ describe('listenerCount', () => {
+ it('should return the number of listeners for the specified event', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test', callback1);
+ emitter.on('test', callback2);
+ expect(emitter.listenerCount('test')).toBe(2);
+ });
+ });
+
+ describe('listeners', () => {
+ it('should return an array of listeners for the specified event', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test', callback1);
+ emitter.on('test', callback2);
+ expect(emitter.listeners('test')).toEqual([callback1, callback2]);
+ });
+ });
+
+ describe('eventNames', () => {
+ it('should return an array of event names that have listeners', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test1', callback1);
+ emitter.on('test2', callback2);
+ expect(emitter.eventNames()).toEqual(['test1', 'test2']);
+ });
+ });
+
+ describe('removeAllListeners', () => {
+ it('should remove all listeners for all events', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test1', callback1);
+ emitter.on('test2', callback2);
+ emitter.removeAllListeners();
+ emitter.emit('test1', 'hello');
+ emitter.emit('test2', 'world');
+ expect(callback1).not.toHaveBeenCalled();
+ expect(callback2).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('setMaxListeners', () => {
+ it('should set the maximum number of listeners for an event', () => {
+ emitter.setMaxListeners(2);
+ expect(emitter.getMaxListeners()).toBe(2);
+ });
+ });
+});
From 607f4b25f6d946ea3f7ed5184a9961eeabb2dca6 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 4 Oct 2023 11:32:25 +0200
Subject: [PATCH 06/16] disable lint rule in a file and update yarn.lock
---
packages/web3-utils/src/event_emitter.ts | 3 ++-
.../web3-utils/test/unit/event_emitter.test.ts | 2 --
yarn.lock | 16 +++++++++++++++-
3 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts
index 5254c49e668..821acc68c20 100644
--- a/packages/web3-utils/src/event_emitter.ts
+++ b/packages/web3-utils/src/event_emitter.ts
@@ -14,6 +14,7 @@ GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
+/* eslint-disable max-classes-per-file */
import { EventEmitter as EventEmitterAtNode } from 'events';
@@ -31,7 +32,7 @@ const wrapFunction =
* This class copy the behavior of Node.js EventEmitter class.
* It is used to provide the same interface for the browser environment.
*/
-export class EventEmitterAtBrowser extends EventTarget {
+class EventEmitterAtBrowser extends EventTarget {
private _listeners: Record = {};
private maxListeners = Number.MAX_SAFE_INTEGER;
diff --git a/packages/web3-utils/test/unit/event_emitter.test.ts b/packages/web3-utils/test/unit/event_emitter.test.ts
index d3bdeb7a623..21a1aec7dbf 100644
--- a/packages/web3-utils/test/unit/event_emitter.test.ts
+++ b/packages/web3-utils/test/unit/event_emitter.test.ts
@@ -25,8 +25,6 @@ describe('EventEmitter', () => {
beforeEach(() => {
emitter = new EventEmitter();
-
- //emitter.removeAllListeners('test');
});
describe('on', () => {
diff --git a/yarn.lock b/yarn.lock
index f937f1f8418..e3012ba1959 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4021,13 +4021,20 @@ cross-fetch@^2.1.0:
node-fetch "^2.6.7"
whatwg-fetch "^2.0.4"
-cross-fetch@^3.0.4, cross-fetch@^3.1.5:
+cross-fetch@^3.0.4:
version "3.1.5"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
dependencies:
node-fetch "2.6.7"
+cross-fetch@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983"
+ integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==
+ dependencies:
+ node-fetch "^2.6.12"
+
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -8593,6 +8600,13 @@ node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7:
dependencies:
whatwg-url "^5.0.0"
+node-fetch@^2.6.12:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
+ integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
+ dependencies:
+ whatwg-url "^5.0.0"
+
node-gyp-build@4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4"
From 4c8bc1bfd157b016bb01748630c1fab576b08647 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 4 Oct 2023 14:24:07 +0200
Subject: [PATCH 07/16] apply fixes and add tests for EventEmitter
---
packages/web3-utils/src/event_emitter.ts | 10 +-
.../test/unit/event_emitter_dom.test.ts | 125 ++++++++++++++++++
...ter.test.ts => event_emitter_node.test.ts} | 4 +-
3 files changed, 136 insertions(+), 3 deletions(-)
create mode 100644 packages/web3-utils/test/unit/event_emitter_dom.test.ts
rename packages/web3-utils/test/unit/{event_emitter.test.ts => event_emitter_node.test.ts} (96%)
diff --git a/packages/web3-utils/src/event_emitter.ts b/packages/web3-utils/src/event_emitter.ts
index 821acc68c20..7d9c3ccdb2e 100644
--- a/packages/web3-utils/src/event_emitter.ts
+++ b/packages/web3-utils/src/event_emitter.ts
@@ -43,8 +43,8 @@ class EventEmitterAtBrowser extends EventTarget {
public once(eventName: string, fn: Callback) {
const onceCallback = async (params: Callback) => {
- await fn(params);
this.off(eventName, onceCallback);
+ await fn(params);
};
return this.on(eventName, onceCallback);
}
@@ -73,6 +73,14 @@ class EventEmitterAtBrowser extends EventTarget {
}
public removeAllListeners() {
+ Object.keys(this._listeners).forEach(event => {
+ this._listeners[event].forEach(
+ (listener: [key: Callback, value: EventTargetCallback]) => {
+ super.removeEventListener(event, listener[1] as EventListener);
+ },
+ );
+ });
+
this._listeners = {};
return this;
}
diff --git a/packages/web3-utils/test/unit/event_emitter_dom.test.ts b/packages/web3-utils/test/unit/event_emitter_dom.test.ts
new file mode 100644
index 00000000000..432bdcc54a8
--- /dev/null
+++ b/packages/web3-utils/test/unit/event_emitter_dom.test.ts
@@ -0,0 +1,125 @@
+/*
+This file is part of web3.js.
+
+web3.js is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+web3.js is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with web3.js. If not, see .
+*/
+
+// this file will contain the unit test for the event emitter in the DOM environment
+
+/**
+ * @jest-environment jsdom
+ */
+
+import { EventEmitter } from '../../src/event_emitter';
+
+describe('EventEmitter with DOM', () => {
+ let emitter: EventEmitter;
+
+ beforeEach(() => {
+ emitter = new EventEmitter();
+ });
+
+ describe('on', () => {
+ it('should add a listener for the specified event', () => {
+ const callback = jest.fn();
+ emitter.on('test', callback);
+ emitter.emit('test', 'hello');
+ expect(callback).toHaveBeenCalledWith('hello');
+ });
+ });
+
+ describe('once', () => {
+ it('should add a listener for the specified event that is only called once', () => {
+ const callback = jest.fn();
+ emitter.once('test', callback);
+ emitter.emit('test', 'hello');
+ emitter.emit('test', 'world');
+ expect(callback).toHaveBeenCalledTimes(1);
+ expect(callback).toHaveBeenCalledWith('hello');
+ });
+ });
+
+ describe('off', () => {
+ it('should remove a listener for the specified event', () => {
+ const callback = jest.fn();
+ emitter.on('test', callback);
+ emitter.off('test', callback);
+ emitter.emit('test', 'hello');
+ expect(callback).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('emit', () => {
+ it('should call all listeners for the specified event', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test', callback1);
+ emitter.on('test', callback2);
+ emitter.emit('test', 'hello');
+ expect(callback1).toHaveBeenCalledWith('hello');
+ expect(callback2).toHaveBeenCalledWith('hello');
+ });
+ });
+
+ describe('listenerCount', () => {
+ it('should return the number of listeners for the specified event', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test', callback1);
+ emitter.on('test', callback2);
+ expect(emitter.listenerCount('test')).toBe(2);
+ });
+ });
+
+ describe('listeners', () => {
+ it('should return an array of listeners for the specified event', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test', callback1);
+ emitter.on('test', callback2);
+ expect(emitter.listeners('test')).toEqual([callback1, callback2]);
+ });
+ });
+
+ describe('eventNames', () => {
+ it('should return an array of event names that have listeners', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test1', callback1);
+ emitter.on('test2', callback2);
+ expect(emitter.eventNames()).toEqual(['test1', 'test2']);
+ });
+ });
+
+ describe('removeAllListeners', () => {
+ it('should remove all listeners for all events', () => {
+ const callback1 = jest.fn();
+ const callback2 = jest.fn();
+ emitter.on('test1', callback1);
+ emitter.on('test2', callback2);
+ emitter.removeAllListeners();
+ emitter.emit('test1', 'hello');
+ emitter.emit('test2', 'world');
+ expect(callback1).not.toHaveBeenCalled();
+ expect(callback2).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('setMaxListeners', () => {
+ it('should set the maximum number of listeners for an event', () => {
+ emitter.setMaxListeners(2);
+ expect(emitter.getMaxListeners()).toBe(2);
+ });
+ });
+});
diff --git a/packages/web3-utils/test/unit/event_emitter.test.ts b/packages/web3-utils/test/unit/event_emitter_node.test.ts
similarity index 96%
rename from packages/web3-utils/test/unit/event_emitter.test.ts
rename to packages/web3-utils/test/unit/event_emitter_node.test.ts
index 21a1aec7dbf..a78fe8f63e1 100644
--- a/packages/web3-utils/test/unit/event_emitter.test.ts
+++ b/packages/web3-utils/test/unit/event_emitter_node.test.ts
@@ -15,11 +15,11 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-// this file will contain the unit test for the event emitter
+// this file will contain the unit test for the event emitter in the Node environment
import { EventEmitter } from '../../src/event_emitter';
-describe('EventEmitter', () => {
+describe('EventEmitter with Node', () => {
// let emitter = new EventEmitter();
let emitter: EventEmitter;
From e4d7317b21eafb4b3d4c77cc240adc7c793603fb Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 4 Oct 2023 15:33:16 +0200
Subject: [PATCH 08/16] configure `EventEmitter` test to run inside `jsdom`
---
packages/web3-utils/package.json | 1 +
.../test/unit/event_emitter_dom.test.ts | 13 +-
yarn.lock | 367 +++++++++++++++++-
3 files changed, 370 insertions(+), 11 deletions(-)
diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json
index 89728c246ac..3958ddabe1c 100644
--- a/packages/web3-utils/package.json
+++ b/packages/web3-utils/package.json
@@ -52,6 +52,7 @@
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"jest": "^28.1.3",
+ "jest-environment-jsdom": "^29.7.0",
"jest-extended": "^3.0.1",
"js-sha3": "^0.8.0",
"prettier": "^2.7.1",
diff --git a/packages/web3-utils/test/unit/event_emitter_dom.test.ts b/packages/web3-utils/test/unit/event_emitter_dom.test.ts
index 432bdcc54a8..b58ab6de1a8 100644
--- a/packages/web3-utils/test/unit/event_emitter_dom.test.ts
+++ b/packages/web3-utils/test/unit/event_emitter_dom.test.ts
@@ -1,3 +1,7 @@
+/**
+ * @jest-environment jsdom
+ */
+
/*
This file is part of web3.js.
@@ -15,12 +19,11 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-// this file will contain the unit test for the event emitter in the DOM environment
-
-/**
- * @jest-environment jsdom
- */
+// this file contains the unit test for the event emitter in the DOM environment
+// it is executed in the jsdom environment (see "@jest-environment jsdom" in the top comment of this file)
+// ignore the following rule to allow keeping `@jest-environment jsdom` on top:
+// eslint-disable-next-line header/header
import { EventEmitter } from '../../src/event_emitter';
describe('EventEmitter with DOM', () => {
diff --git a/yarn.lock b/yarn.lock
index e3012ba1959..bf95ec3254e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -712,6 +712,16 @@
"@types/node" "*"
jest-mock "^28.1.3"
+"@jest/environment@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7"
+ integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==
+ dependencies:
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+
"@jest/expect-utils@^28.1.3":
version "28.1.3"
resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.3.tgz#58561ce5db7cd253a7edddbc051fb39dda50f525"
@@ -739,6 +749,18 @@
jest-mock "^28.1.3"
jest-util "^28.1.3"
+"@jest/fake-timers@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565"
+ integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@sinonjs/fake-timers" "^10.0.2"
+ "@types/node" "*"
+ jest-message-util "^29.7.0"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
"@jest/globals@^28.1.3":
version "28.1.3"
resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.3.tgz#a601d78ddc5fdef542728309894895b4a42dc333"
@@ -793,6 +815,13 @@
dependencies:
"@sinclair/typebox" "^0.25.16"
+"@jest/schemas@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
+ integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
+ dependencies:
+ "@sinclair/typebox" "^0.27.8"
+
"@jest/source-map@^24.9.0":
version "24.9.0"
resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714"
@@ -882,6 +911,18 @@
"@types/yargs" "^17.0.8"
chalk "^4.0.0"
+"@jest/types@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
+ integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
"@jridgewell/gen-mapping@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
@@ -1823,6 +1864,11 @@
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718"
integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==
+"@sinclair/typebox@^0.27.8":
+ version "0.27.8"
+ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
+ integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
+
"@sinonjs/commons@^1.7.0":
version "1.8.3"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
@@ -1830,6 +1876,20 @@
dependencies:
type-detect "4.0.8"
+"@sinonjs/commons@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72"
+ integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^10.0.2":
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66"
+ integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==
+ dependencies:
+ "@sinonjs/commons" "^3.0.0"
+
"@sinonjs/fake-timers@^9.1.2":
version "9.1.2"
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c"
@@ -2079,6 +2139,15 @@
expect "^28.0.0"
pretty-format "^28.0.0"
+"@types/jsdom@^20.0.0":
+ version "20.0.1"
+ resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808"
+ integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==
+ dependencies:
+ "@types/node" "*"
+ "@types/tough-cookie" "*"
+ parse5 "^7.0.0"
+
"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
@@ -2188,6 +2257,11 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
+"@types/tough-cookie@*":
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.3.tgz#3d06b6769518450871fbc40770b7586334bdfd90"
+ integrity sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg==
+
"@types/webpack@^5.28.0":
version "5.28.0"
resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-5.28.0.tgz#78dde06212f038d77e54116cfe69e88ae9ed2c03"
@@ -2491,6 +2565,11 @@ JSONStream@^1.0.4:
jsonparse "^1.2.0"
through ">=2.2.7 <3"
+abab@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
+ integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
+
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -2560,6 +2639,14 @@ accepts@~1.3.8:
mime-types "~2.1.34"
negotiator "0.6.3"
+acorn-globals@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3"
+ integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==
+ dependencies:
+ acorn "^8.1.0"
+ acorn-walk "^8.0.2"
+
acorn-import-assertions@^1.7.6:
version "1.8.0"
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
@@ -2570,7 +2657,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-acorn-walk@^8.0.0, acorn-walk@^8.1.1:
+acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1:
version "8.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
@@ -2580,6 +2667,11 @@ acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
+acorn@^8.1.0, acorn@^8.8.1:
+ version "8.10.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
+ integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
+
add-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
@@ -4054,6 +4146,23 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+cssom@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36"
+ integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==
+
+cssom@~0.3.6:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+ integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
+ integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
+ dependencies:
+ cssom "~0.3.6"
+
cypress-jest-adapter@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/cypress-jest-adapter/-/cypress-jest-adapter-0.1.1.tgz#d1aa9d84393b6a5007022d1d33b3cdd3ce9672af"
@@ -4076,6 +4185,15 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
+data-urls@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143"
+ integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==
+ dependencies:
+ abab "^2.0.6"
+ whatwg-mimetype "^3.0.0"
+ whatwg-url "^11.0.0"
+
date-fns@^2.30.0:
version "2.30.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
@@ -4127,6 +4245,11 @@ decamelize@^4.0.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
+decimal.js@^10.4.2:
+ version "10.4.3"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
+ integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
+
declaration-bundler-webpack-plugin@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/declaration-bundler-webpack-plugin/-/declaration-bundler-webpack-plugin-1.0.3.tgz#9fb5ae393c63ed4175e7b6de4b58bafde34f097a"
@@ -4337,6 +4460,13 @@ dom-walk@^0.1.0:
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
+domexception@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673"
+ integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==
+ dependencies:
+ webidl-conversions "^7.0.0"
+
dot-prop@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
@@ -4471,6 +4601,11 @@ enquirer@^2.3.0, enquirer@~2.3.6:
dependencies:
ansi-colors "^4.1.1"
+entities@^4.4.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
+ integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
env-paths@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
@@ -4580,6 +4715,17 @@ escape-string-regexp@^2.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+escodegen@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17"
+ integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==
+ dependencies:
+ esprima "^4.0.1"
+ estraverse "^5.2.0"
+ esutils "^2.0.2"
+ optionalDependencies:
+ source-map "~0.6.1"
+
eslint-config-airbnb-base@^15.0.0:
version "15.0.0"
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236"
@@ -4776,7 +4922,7 @@ espree@^9.3.2, espree@^9.3.3:
acorn-jsx "^5.3.2"
eslint-visitor-keys "^3.3.0"
-esprima@^4.0.0:
+esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
@@ -6232,6 +6378,13 @@ hosted-git-info@^6.0.0, hosted-git-info@^6.1.1:
dependencies:
lru-cache "^7.5.1"
+html-encoding-sniffer@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9"
+ integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==
+ dependencies:
+ whatwg-encoding "^2.0.0"
+
html-escaper@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
@@ -6309,7 +6462,7 @@ https-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==
-https-proxy-agent@^5.0.0:
+https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
@@ -6346,7 +6499,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
-iconv-lite@^0.6.2:
+iconv-lite@0.6.3, iconv-lite@^0.6.2:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
@@ -6808,6 +6961,11 @@ is-plain-object@^5.0.0:
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
+is-potential-custom-element-name@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+ integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
+
is-regex@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
@@ -7121,6 +7279,20 @@ jest-each@^28.1.3:
jest-util "^28.1.3"
pretty-format "^28.1.3"
+jest-environment-jsdom@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f"
+ integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/jsdom" "^20.0.0"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+ jsdom "^20.0.0"
+
jest-environment-node@^28.1.3:
version "28.1.3"
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.3.tgz#7e74fe40eb645b9d56c0c4b70ca4357faa349be5"
@@ -7240,6 +7412,21 @@ jest-message-util@^28.1.3:
slash "^3.0.0"
stack-utils "^2.0.3"
+jest-message-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3"
+ integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^29.6.3"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
jest-mock@^28.1.3:
version "28.1.3"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.3.tgz#d4e9b1fc838bea595c77ab73672ebf513ab249da"
@@ -7248,6 +7435,15 @@ jest-mock@^28.1.3:
"@jest/types" "^28.1.3"
"@types/node" "*"
+jest-mock@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347"
+ integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-util "^29.7.0"
+
jest-pnp-resolver@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c"
@@ -7382,6 +7578,18 @@ jest-util@^28.0.0, jest-util@^28.1.3:
graceful-fs "^4.2.9"
picomatch "^2.2.3"
+jest-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
+ integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
jest-validate@^28.1.3:
version "28.1.3"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.3.tgz#e322267fd5e7c64cea4629612c357bbda96229df"
@@ -7481,6 +7689,38 @@ jsbn@~0.1.0:
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
+jsdom@^20.0.0:
+ version "20.0.3"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db"
+ integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==
+ dependencies:
+ abab "^2.0.6"
+ acorn "^8.8.1"
+ acorn-globals "^7.0.0"
+ cssom "^0.5.0"
+ cssstyle "^2.3.0"
+ data-urls "^3.0.2"
+ decimal.js "^10.4.2"
+ domexception "^4.0.0"
+ escodegen "^2.0.0"
+ form-data "^4.0.0"
+ html-encoding-sniffer "^3.0.0"
+ http-proxy-agent "^5.0.0"
+ https-proxy-agent "^5.0.1"
+ is-potential-custom-element-name "^1.0.1"
+ nwsapi "^2.2.2"
+ parse5 "^7.1.1"
+ saxes "^6.0.0"
+ symbol-tree "^3.2.4"
+ tough-cookie "^4.1.2"
+ w3c-xmlserializer "^4.0.0"
+ webidl-conversions "^7.0.0"
+ whatwg-encoding "^2.0.0"
+ whatwg-mimetype "^3.0.0"
+ whatwg-url "^11.0.0"
+ ws "^8.11.0"
+ xml-name-validator "^4.0.0"
+
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -8914,6 +9154,11 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
+nwsapi@^2.2.2:
+ version "2.2.7"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30"
+ integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==
+
nx@15.9.4, "nx@>=15.5.2 < 16":
version "15.9.4"
resolved "https://registry.yarnpkg.com/nx/-/nx-15.9.4.tgz#1075bc33fe8ee6c6546c21ec6ffcfd2e000946c6"
@@ -9358,6 +9603,13 @@ parse-url@^8.1.0:
dependencies:
parse-path "^7.0.0"
+parse5@^7.0.0, parse5@^7.1.1:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32"
+ integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==
+ dependencies:
+ entities "^4.4.0"
+
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -9567,6 +9819,15 @@ pretty-format@^28.0.0, pretty-format@^28.1.3:
ansi-styles "^5.0.0"
react-is "^18.0.0"
+pretty-format@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
+ integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
proc-log@^2.0.0, proc-log@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
@@ -9666,7 +9927,7 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
-psl@^1.1.28:
+psl@^1.1.28, psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
@@ -9700,6 +9961,11 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
+querystringify@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
+ integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
+
queue-microtask@^1.2.2, queue-microtask@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -10182,6 +10448,13 @@ safe-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+saxes@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5"
+ integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==
+ dependencies:
+ xmlchars "^2.2.0"
+
schema-utils@^3.1.0, schema-utils@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
@@ -10556,7 +10829,7 @@ source-map@^0.5.6:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
-source-map@^0.6.0, source-map@^0.6.1:
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -10868,6 +11141,11 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+symbol-tree@^3.2.4:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
synckit@^0.8.5:
version "0.8.5"
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3"
@@ -11064,6 +11342,16 @@ totalist@^1.0.0:
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
+tough-cookie@^4.1.2:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
+ integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
+ dependencies:
+ psl "^1.1.33"
+ punycode "^2.1.1"
+ universalify "^0.2.0"
+ url-parse "^1.5.3"
+
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -11072,6 +11360,13 @@ tough-cookie@~2.5.0:
psl "^1.1.28"
punycode "^2.1.1"
+tr46@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9"
+ integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==
+ dependencies:
+ punycode "^2.1.1"
+
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
@@ -11389,6 +11684,11 @@ universalify@^0.1.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+universalify@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
+ integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
+
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
@@ -11437,6 +11737,14 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==
+url-parse@^1.5.3:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
+ integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
+ dependencies:
+ querystringify "^2.1.1"
+ requires-port "^1.0.0"
+
use@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
@@ -11576,6 +11884,13 @@ vscode-textmate@5.2.0:
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e"
integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==
+w3c-xmlserializer@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073"
+ integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==
+ dependencies:
+ xml-name-validator "^4.0.0"
+
walk-up-path@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e"
@@ -11636,6 +11951,11 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+webidl-conversions@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
+ integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
+
webpack-bundle-analyzer@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66"
@@ -11712,11 +12032,31 @@ webpack@^5, webpack@^5.73.0:
watchpack "^2.4.0"
webpack-sources "^3.2.3"
+whatwg-encoding@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53"
+ integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==
+ dependencies:
+ iconv-lite "0.6.3"
+
whatwg-fetch@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==
+whatwg-mimetype@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7"
+ integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==
+
+whatwg-url@^11.0.0:
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018"
+ integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==
+ dependencies:
+ tr46 "^3.0.0"
+ webidl-conversions "^7.0.0"
+
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
@@ -11878,6 +12218,11 @@ ws@^7.3.1, ws@^7.4.6:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
+ws@^8.11.0:
+ version "8.14.2"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
+ integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==
+
ws@^8.8.1:
version "8.8.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0"
@@ -11893,6 +12238,16 @@ xhr@^2.2.0:
parse-headers "^2.0.0"
xtend "^4.0.0"
+xml-name-validator@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
+ integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
+
+xmlchars@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
+ integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
From 1eed66dc2ff4449c1a117e2d904ed9d2532064ed Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Fri, 6 Oct 2023 09:27:01 +0200
Subject: [PATCH 09/16] fix issue with detecting Uint8Array (fix: `value "..."
at "/0" must pass "bytes" validation`)
---
packages/web3-eth-accounts/src/account.ts | 5 ++++-
.../web3-eth-accounts/src/tx/transactionFactory.ts | 4 ++--
packages/web3-utils/src/converters.ts | 10 +++++++---
packages/web3-validator/src/validation/bytes.ts | 12 +++++++++---
4 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts
index 793f1f76bbc..d2a642cf9b5 100644
--- a/packages/web3-eth-accounts/src/account.ts
+++ b/packages/web3-eth-accounts/src/account.ts
@@ -82,7 +82,10 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean):
}
try {
- privateKeyUint8Array = data instanceof Uint8Array ? data : bytesToUint8Array(data);
+ privateKeyUint8Array =
+ data instanceof Uint8Array || data.constructor.name === 'Uint8Array'
+ ? (data as Uint8Array)
+ : bytesToUint8Array(data);
} catch {
throw new InvalidPrivateKeyError();
}
diff --git a/packages/web3-eth-accounts/src/tx/transactionFactory.ts b/packages/web3-eth-accounts/src/tx/transactionFactory.ts
index dd74bee4eee..a17cf567536 100644
--- a/packages/web3-eth-accounts/src/tx/transactionFactory.ts
+++ b/packages/web3-eth-accounts/src/tx/transactionFactory.ts
@@ -104,8 +104,8 @@ export class TransactionFactory {
* @param txOptions - The transaction options
*/
public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {}) {
- if (data instanceof Uint8Array) {
- return this.fromSerializedData(data, txOptions);
+ if (data instanceof Uint8Array || data.constructor.name === 'Uint8Array') {
+ return this.fromSerializedData(data as Uint8Array, txOptions);
}
if (Array.isArray(data)) {
// It is a legacy transaction
diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts
index eed4e5caa1a..d75c35b8a4c 100644
--- a/packages/web3-utils/src/converters.ts
+++ b/packages/web3-utils/src/converters.ts
@@ -88,8 +88,8 @@ export type EtherUnits = keyof typeof ethUnitMap;
export const bytesToUint8Array = (data: Bytes): Uint8Array | never => {
validator.validate(['bytes'], [data]);
- if (data instanceof Uint8Array) {
- return data;
+ if (data instanceof Uint8Array || data.constructor.name === 'Uint8Array') {
+ return data as Uint8Array;
}
if (Array.isArray(data)) {
@@ -585,7 +585,11 @@ export const toChecksumAddress = (address: Address): string => {
const lowerCaseAddress = address.toLowerCase().replace(/^0x/i, '');
- const hash = utils.uint8ArrayToHexString(keccak256(utf8ToBytes(lowerCaseAddress)));
+ // calling `Uint8Array.from` because `noble-hashes` checks with `instanceof Uint8Array` that fails in some edge cases:
+ // https://github.com/paulmillr/noble-hashes/issues/25#issuecomment-1750106284
+ const hash = utils.uint8ArrayToHexString(
+ keccak256(Uint8Array.from(utf8ToBytes(lowerCaseAddress))),
+ );
if (
isNullish(hash) ||
diff --git a/packages/web3-validator/src/validation/bytes.ts b/packages/web3-validator/src/validation/bytes.ts
index ef15fbc0120..7947be68cbd 100644
--- a/packages/web3-validator/src/validation/bytes.ts
+++ b/packages/web3-validator/src/validation/bytes.ts
@@ -22,7 +22,8 @@ import { isHexStrict } from './string.js';
/**
* checks input if typeof data is valid Uint8Array input
*/
-export const isUint8Array = (data: ValidInputTypes) => data instanceof Uint8Array;
+export const isUint8Array = (data: ValidInputTypes) =>
+ data instanceof Uint8Array || data.constructor.name === 'Uint8Array';
export const isBytes = (
value: ValidInputTypes | Uint8Array | number[],
@@ -30,7 +31,12 @@ export const isBytes = (
abiType: 'bytes',
},
) => {
- if (typeof value !== 'string' && !Array.isArray(value) && !(value instanceof Uint8Array)) {
+ if (
+ typeof value !== 'string' &&
+ !Array.isArray(value) &&
+ !(value instanceof Uint8Array) &&
+ value.constructor.name !== 'Uint8Array'
+ ) {
return false;
}
@@ -57,7 +63,7 @@ export const isBytes = (
}
valueToCheck = new Uint8Array(value);
} else {
- valueToCheck = value;
+ valueToCheck = value as Uint8Array;
}
if (options?.abiType) {
From 5f195bb01468c66c2ac7bad42dedd7e7afa64cd5 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Fri, 6 Oct 2023 10:41:43 +0200
Subject: [PATCH 10/16] prevent throwing if value is null when checking
value.constructor.name
---
packages/web3-eth-accounts/src/account.ts | 2 +-
packages/web3-eth-accounts/src/tx/transactionFactory.ts | 2 +-
packages/web3-utils/src/converters.ts | 2 +-
packages/web3-validator/src/validation/bytes.ts | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts
index d2a642cf9b5..dcdbe3fc4ed 100644
--- a/packages/web3-eth-accounts/src/account.ts
+++ b/packages/web3-eth-accounts/src/account.ts
@@ -83,7 +83,7 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean):
try {
privateKeyUint8Array =
- data instanceof Uint8Array || data.constructor.name === 'Uint8Array'
+ data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array'
? (data as Uint8Array)
: bytesToUint8Array(data);
} catch {
diff --git a/packages/web3-eth-accounts/src/tx/transactionFactory.ts b/packages/web3-eth-accounts/src/tx/transactionFactory.ts
index a17cf567536..605b32ca1aa 100644
--- a/packages/web3-eth-accounts/src/tx/transactionFactory.ts
+++ b/packages/web3-eth-accounts/src/tx/transactionFactory.ts
@@ -104,7 +104,7 @@ export class TransactionFactory {
* @param txOptions - The transaction options
*/
public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {}) {
- if (data instanceof Uint8Array || data.constructor.name === 'Uint8Array') {
+ if (data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array') {
return this.fromSerializedData(data as Uint8Array, txOptions);
}
if (Array.isArray(data)) {
diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts
index d75c35b8a4c..66e3047024d 100644
--- a/packages/web3-utils/src/converters.ts
+++ b/packages/web3-utils/src/converters.ts
@@ -88,7 +88,7 @@ export type EtherUnits = keyof typeof ethUnitMap;
export const bytesToUint8Array = (data: Bytes): Uint8Array | never => {
validator.validate(['bytes'], [data]);
- if (data instanceof Uint8Array || data.constructor.name === 'Uint8Array') {
+ if (data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array') {
return data as Uint8Array;
}
diff --git a/packages/web3-validator/src/validation/bytes.ts b/packages/web3-validator/src/validation/bytes.ts
index 7947be68cbd..5cc4bcf63d8 100644
--- a/packages/web3-validator/src/validation/bytes.ts
+++ b/packages/web3-validator/src/validation/bytes.ts
@@ -23,7 +23,7 @@ import { isHexStrict } from './string.js';
* checks input if typeof data is valid Uint8Array input
*/
export const isUint8Array = (data: ValidInputTypes) =>
- data instanceof Uint8Array || data.constructor.name === 'Uint8Array';
+ data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array';
export const isBytes = (
value: ValidInputTypes | Uint8Array | number[],
@@ -35,7 +35,7 @@ export const isBytes = (
typeof value !== 'string' &&
!Array.isArray(value) &&
!(value instanceof Uint8Array) &&
- value.constructor.name !== 'Uint8Array'
+ value?.constructor?.name !== 'Uint8Array'
) {
return false;
}
From 4b5d6cff211869015875ae04ba8d15ce5e0a1948 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Tue, 10 Oct 2023 00:46:50 +0200
Subject: [PATCH 11/16] improve type checking for Uint8Array
---
packages/web3-eth-abi/src/utils.ts | 4 ++--
packages/web3-eth-accounts/src/account.ts | 16 +++++++---------
packages/web3-eth-accounts/src/common/utils.ts | 8 ++++++--
.../src/tx/transactionFactory.ts | 5 +++--
packages/web3-utils/src/converters.ts | 7 ++++---
packages/web3-utils/src/formatter.ts | 4 ++--
packages/web3-utils/src/uint8array.ts | 17 +++++++++++++++++
.../web3-validator/src/validation/address.ts | 5 +++--
packages/web3-validator/src/validation/bytes.ts | 11 +++--------
9 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/packages/web3-eth-abi/src/utils.ts b/packages/web3-eth-abi/src/utils.ts
index e8212c28329..081e4e544ce 100644
--- a/packages/web3-eth-abi/src/utils.ts
+++ b/packages/web3-eth-abi/src/utils.ts
@@ -16,7 +16,7 @@ along with web3.js. If not, see .
*/
import { AbiError } from 'web3-errors';
-import { isNullish, leftPad, rightPad, toHex } from 'web3-utils';
+import { isNullish, isUint8Array, leftPad, rightPad, toHex } from 'web3-utils';
import {
AbiInput,
AbiCoderStruct,
@@ -189,7 +189,7 @@ export const formatParam = (type: string, _param: unknown): unknown => {
// Format correct length for bytes[0-9]+
match = paramTypeBytes.exec(type);
if (match) {
- const hexParam = param instanceof Uint8Array ? toHex(param) : param;
+ const hexParam = isUint8Array(param) ? toHex(param) : param;
// format to correct length
const size = parseInt(match[1], 10);
diff --git a/packages/web3-eth-accounts/src/account.ts b/packages/web3-eth-accounts/src/account.ts
index dcdbe3fc4ed..323162d1e14 100644
--- a/packages/web3-eth-accounts/src/account.ts
+++ b/packages/web3-eth-accounts/src/account.ts
@@ -49,6 +49,7 @@ import {
bytesToHex,
fromUtf8,
hexToBytes,
+ isUint8Array,
numberToHex,
randomBytes,
sha3Raw,
@@ -82,10 +83,7 @@ export const parseAndValidatePrivateKey = (data: Bytes, ignoreLength?: boolean):
}
try {
- privateKeyUint8Array =
- data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array'
- ? (data as Uint8Array)
- : bytesToUint8Array(data);
+ privateKeyUint8Array = isUint8Array(data) ? (data ) : bytesToUint8Array(data);
} catch {
throw new InvalidPrivateKeyError();
}
@@ -344,7 +342,7 @@ export const recover = (
const V_INDEX = 130; // r = first 32 bytes, s = second 32 bytes, v = last byte of signature
const hashedMessage = prefixedOrR ? data : hashMessage(data);
- let v = parseInt(signatureOrV.substring(V_INDEX),16); // 0x + r + s + v
+ let v = parseInt(signatureOrV.substring(V_INDEX), 16); // 0x + r + s + v
if (v > 26) {
v -= 27;
}
@@ -359,7 +357,7 @@ export const recover = (
const address = toChecksumAddress(`0x${publicHash.slice(-40)}`);
return address;
-};
+};;
/**
* Get the ethereum Address from a private key
@@ -393,7 +391,7 @@ export const privateKeyToAddress = (privateKey: Bytes): string => {
* Get the public key from a private key
*
* @param privateKey - String or Uint8Array of 32 bytes
- * @param isCompressed - if true, will generate a 33 byte compressed public key instead of a 65 byte public key
+ * @param isCompressed - if true, will generate a 33 byte compressed public key instead of a 65 byte public key
* @returns The public key
* @example
* ```ts
@@ -401,7 +399,7 @@ export const privateKeyToAddress = (privateKey: Bytes): string => {
* > "0x42beb65f179720abaa3ec9a70a539629cbbc5ec65bb57e7fc78977796837e537662dd17042e6449dc843c281067a4d6d8d1a1775a13c41901670d5de7ee6503a" // uncompressed public key
* ```
*/
- export const privateKeyToPublicKey = (privateKey: Bytes, isCompressed: boolean): string => {
+export const privateKeyToPublicKey = (privateKey: Bytes, isCompressed: boolean): string => {
const privateKeyUint8Array = parseAndValidatePrivateKey(privateKey);
// Get public key from private key in compressed format
@@ -495,7 +493,7 @@ export const encrypt = async (
salt = randomBytes(32);
}
- if (!(isString(password) || password instanceof Uint8Array)) {
+ if (!(isString(password) || isUint8Array(password))) {
throw new InvalidPasswordError();
}
diff --git a/packages/web3-eth-accounts/src/common/utils.ts b/packages/web3-eth-accounts/src/common/utils.ts
index f243ede269d..a1d46c36140 100644
--- a/packages/web3-eth-accounts/src/common/utils.ts
+++ b/packages/web3-eth-accounts/src/common/utils.ts
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
import { isHexPrefixed, isHexString } from 'web3-validator';
-import { bytesToHex, hexToBytes, numberToHex } from 'web3-utils';
+import { bytesToHex, hexToBytes, isUint8Array, numberToHex } from 'web3-utils';
import { secp256k1 } from '../tx/constants.js';
import { Hardfork } from './enums.js';
import { ToBytesInputTypes, TypeOutput, TypeOutputReturnType } from './types.js';
@@ -331,6 +331,10 @@ export const toUint8Array = function (v: ToBytesInputTypes): Uint8Array {
return v;
}
+ if (v?.constructor?.name === 'Uint8Array') {
+ return Uint8Array.from(v as unknown as Uint8Array);
+ }
+
if (Array.isArray(v)) {
return Uint8Array.from(v);
}
@@ -420,7 +424,7 @@ const setLength = function (msg: Uint8Array, length: number, right: boolean) {
* @param {Uint8Array} input value to check
*/
export function assertIsUint8Array(input: unknown): asserts input is Uint8Array {
- if (!(input instanceof Uint8Array)) {
+ if (!isUint8Array(input)) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
const msg = `This method only supports Uint8Array but input was: ${input}`;
throw new Error(msg);
diff --git a/packages/web3-eth-accounts/src/tx/transactionFactory.ts b/packages/web3-eth-accounts/src/tx/transactionFactory.ts
index 605b32ca1aa..16be0c7c9cd 100644
--- a/packages/web3-eth-accounts/src/tx/transactionFactory.ts
+++ b/packages/web3-eth-accounts/src/tx/transactionFactory.ts
@@ -14,6 +14,7 @@ GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
+import { isUint8Array } from 'web3-utils';
import { toUint8Array, uint8ArrayToBigInt } from '../common/utils.js';
import { FeeMarketEIP1559Transaction } from './eip1559Transaction.js';
import { AccessListEIP2930Transaction } from './eip2930Transaction.js';
@@ -104,8 +105,8 @@ export class TransactionFactory {
* @param txOptions - The transaction options
*/
public static fromBlockBodyData(data: Uint8Array | Uint8Array[], txOptions: TxOptions = {}) {
- if (data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array') {
- return this.fromSerializedData(data as Uint8Array, txOptions);
+ if (isUint8Array(data)) {
+ return this.fromSerializedData(data , txOptions);
}
if (Array.isArray(data)) {
// It is a legacy transaction
diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts
index 66e3047024d..649545df7dc 100644
--- a/packages/web3-utils/src/converters.ts
+++ b/packages/web3-utils/src/converters.ts
@@ -37,6 +37,7 @@ import {
InvalidNumberError,
InvalidUnitError,
} from 'web3-errors';
+import { ensureIfUint8Array, isUint8Array } from './uint8array.js';
const base = BigInt(10);
const expo10 = (expo: number) => base ** BigInt(expo);
@@ -88,8 +89,8 @@ export type EtherUnits = keyof typeof ethUnitMap;
export const bytesToUint8Array = (data: Bytes): Uint8Array | never => {
validator.validate(['bytes'], [data]);
- if (data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array') {
- return data as Uint8Array;
+ if (isUint8Array(data)) {
+ return data;
}
if (Array.isArray(data)) {
@@ -588,7 +589,7 @@ export const toChecksumAddress = (address: Address): string => {
// calling `Uint8Array.from` because `noble-hashes` checks with `instanceof Uint8Array` that fails in some edge cases:
// https://github.com/paulmillr/noble-hashes/issues/25#issuecomment-1750106284
const hash = utils.uint8ArrayToHexString(
- keccak256(Uint8Array.from(utf8ToBytes(lowerCaseAddress))),
+ keccak256(ensureIfUint8Array(utf8ToBytes(lowerCaseAddress))),
);
if (
diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts
index 0cfeb600b9a..1901e1fde21 100644
--- a/packages/web3-utils/src/formatter.ts
+++ b/packages/web3-utils/src/formatter.ts
@@ -20,7 +20,7 @@ import { isNullish, isObject, JsonSchema, utils, ValidationSchemaInput } from 'w
import { bytesToUint8Array, bytesToHex, numberToHex, toBigInt } from './converters.js';
import { mergeDeep } from './objects.js';
import { padLeft } from './string_manipulation.js';
-import { uint8ArrayConcat } from './uint8array.js';
+import { isUint8Array, uint8ArrayConcat } from './uint8array.js';
const { parseBaseType } = utils;
@@ -112,7 +112,7 @@ export const convertScalarValue = (value: unknown, ethType: string, format: Data
let paddedValue;
if (baseTypeSize) {
if (typeof value === 'string') paddedValue = padLeft(value, baseTypeSize * 2);
- else if (value instanceof Uint8Array) {
+ else if (isUint8Array(value)) {
paddedValue = uint8ArrayConcat(
new Uint8Array(baseTypeSize - value.length),
value,
diff --git a/packages/web3-utils/src/uint8array.ts b/packages/web3-utils/src/uint8array.ts
index 0f1173b04e7..772e648920c 100644
--- a/packages/web3-utils/src/uint8array.ts
+++ b/packages/web3-utils/src/uint8array.ts
@@ -14,6 +14,23 @@ GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
+
+export function isUint8Array(data: unknown | Uint8Array): data is Uint8Array {
+ return (
+ data instanceof Uint8Array ||
+ (data as { constructor: { name: string } })?.constructor?.name === 'Uint8Array'
+ );
+}
+export function ensureIfUint8Array(data: T) {
+ if (
+ !(data instanceof Uint8Array) &&
+ (data as { constructor: { name: string } })?.constructor?.name === 'Uint8Array'
+ ) {
+ return Uint8Array.from(data as unknown as Uint8Array);
+ }
+ return data;
+}
+
export function uint8ArrayConcat(...parts: Uint8Array[]): Uint8Array {
const length = parts.reduce((prev, part) => {
const agg = prev + part.length;
diff --git a/packages/web3-validator/src/validation/address.ts b/packages/web3-validator/src/validation/address.ts
index f1c5b820a35..2fb61c5b9a3 100644
--- a/packages/web3-validator/src/validation/address.ts
+++ b/packages/web3-validator/src/validation/address.ts
@@ -20,6 +20,7 @@ import { utf8ToBytes } from 'ethereum-cryptography/utils.js';
import { ValidInputTypes } from '../types.js';
import { uint8ArrayToHexString } from '../utils.js';
import { isHexStrict } from './string.js';
+import { isUint8Array } from './bytes.js';
/**
* Checks the checksum of a given address. Will also return false on non-checksum addresses.
@@ -47,13 +48,13 @@ export const checkAddressCheckSum = (data: string): boolean => {
* Checks if a given string is a valid Ethereum address. It will also check the checksum, if the address has upper and lowercase letters.
*/
export const isAddress = (value: ValidInputTypes, checkChecksum = true) => {
- if (typeof value !== 'string' && !(value instanceof Uint8Array)) {
+ if (typeof value !== 'string' && !isUint8Array(value)) {
return false;
}
let valueToCheck: string;
- if (value instanceof Uint8Array) {
+ if (isUint8Array(value)) {
valueToCheck = uint8ArrayToHexString(value);
} else if (typeof value === 'string' && !isHexStrict(value)) {
valueToCheck = value.toLowerCase().startsWith('0x') ? value : `0x${value}`;
diff --git a/packages/web3-validator/src/validation/bytes.ts b/packages/web3-validator/src/validation/bytes.ts
index 5cc4bcf63d8..ab6ab2fbdd0 100644
--- a/packages/web3-validator/src/validation/bytes.ts
+++ b/packages/web3-validator/src/validation/bytes.ts
@@ -22,7 +22,7 @@ import { isHexStrict } from './string.js';
/**
* checks input if typeof data is valid Uint8Array input
*/
-export const isUint8Array = (data: ValidInputTypes) =>
+export const isUint8Array = (data: ValidInputTypes): data is Uint8Array =>
data instanceof Uint8Array || data?.constructor?.name === 'Uint8Array';
export const isBytes = (
@@ -31,12 +31,7 @@ export const isBytes = (
abiType: 'bytes',
},
) => {
- if (
- typeof value !== 'string' &&
- !Array.isArray(value) &&
- !(value instanceof Uint8Array) &&
- value?.constructor?.name !== 'Uint8Array'
- ) {
+ if (typeof value !== 'string' && !Array.isArray(value) && !isUint8Array(value)) {
return false;
}
@@ -63,7 +58,7 @@ export const isBytes = (
}
valueToCheck = new Uint8Array(value);
} else {
- valueToCheck = value as Uint8Array;
+ valueToCheck = value ;
}
if (options?.abiType) {
From c5a71542c174e20bee9f19f1e50bdb9ea4a6ad43 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Tue, 10 Oct 2023 01:00:12 +0200
Subject: [PATCH 12/16] remove a white space
---
packages/web3-validator/src/validation/bytes.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/web3-validator/src/validation/bytes.ts b/packages/web3-validator/src/validation/bytes.ts
index ab6ab2fbdd0..68c431c50ee 100644
--- a/packages/web3-validator/src/validation/bytes.ts
+++ b/packages/web3-validator/src/validation/bytes.ts
@@ -58,7 +58,7 @@ export const isBytes = (
}
valueToCheck = new Uint8Array(value);
} else {
- valueToCheck = value ;
+ valueToCheck = value;
}
if (options?.abiType) {
From 992d5bf467525bdd1c69b6acf3bf76ccea303871 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 3 Jan 2024 13:46:42 +0100
Subject: [PATCH 13/16] remove a comment that was left be mistake
---
packages/web3-utils/test/integration/event_emitter.test.ts | 5 -----
1 file changed, 5 deletions(-)
diff --git a/packages/web3-utils/test/integration/event_emitter.test.ts b/packages/web3-utils/test/integration/event_emitter.test.ts
index 7bf018dd00c..68a35796887 100644
--- a/packages/web3-utils/test/integration/event_emitter.test.ts
+++ b/packages/web3-utils/test/integration/event_emitter.test.ts
@@ -15,11 +15,6 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
-// this file contains the unit test for the event emitter in the DOM environment
-// it is executed in the jsdom environment (see "@jest-environment jsdom" in the top comment of this file)
-
-// ignore the following rule to allow keeping `@jest-environment jsdom` on top:
-// eslint-disable-next-line header/header
import { EventEmitter } from '../../src/event_emitter';
describe('EventEmitter in the browser with Cypress', () => {
From 62c8c85cf6988f047005cce0e6dd447cf9e252fc Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 3 Jan 2024 15:34:43 +0100
Subject: [PATCH 14/16] add tests for Uint8Array in jsdom
---
.../test/unit/account_dom.test.ts | 248 ++++++++++
packages/web3-utils/src/uint8array.ts | 2 +
.../test/unit/converters_dom.test.ts | 439 ++++++++++++++++++
.../web3-utils/test/unit/hash_dom.test.ts | 166 +++++++
yarn.lock | 37 +-
5 files changed, 885 insertions(+), 7 deletions(-)
create mode 100644 packages/web3-eth-accounts/test/unit/account_dom.test.ts
create mode 100644 packages/web3-utils/test/unit/converters_dom.test.ts
create mode 100644 packages/web3-utils/test/unit/hash_dom.test.ts
diff --git a/packages/web3-eth-accounts/test/unit/account_dom.test.ts b/packages/web3-eth-accounts/test/unit/account_dom.test.ts
new file mode 100644
index 00000000000..587996a721c
--- /dev/null
+++ b/packages/web3-eth-accounts/test/unit/account_dom.test.ts
@@ -0,0 +1,248 @@
+/**
+ * @jest-environment jsdom
+ */
+
+/*
+This file is part of web3.js.
+
+web3.js is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+web3.js is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with web3.js. If not, see .
+*/
+
+// this file contains the unit test for the event emitter in the DOM environment
+// it is executed in the jsdom environment (see "@jest-environment jsdom" in the top comment of this file)
+
+// ignore the following rule to allow keeping `@jest-environment jsdom` on top:
+// eslint-disable-next-line header/header
+import { TextEncoder } from 'util';
+import crypto from 'crypto';
+// polyfill for jsdom
+global.TextEncoder = TextEncoder;
+// @ts-expect-error "Cannot assign to 'subtle' because it is a read-only property."
+global.crypto.subtle = crypto.webcrypto.subtle;
+
+/* eslint-disable import/first */
+import { Address } from 'web3-types';
+import { Web3ValidatorError, isHexStrict } from 'web3-validator';
+import {
+ create,
+ decrypt,
+ encrypt,
+ hashMessage,
+ privateKeyToAccount,
+ privateKeyToAddress,
+ recover,
+ recoverTransaction,
+ sign,
+ signTransaction,
+ privateKeyToPublicKey,
+} from '../../src/account';
+import {
+ invalidDecryptData,
+ invalidEncryptData,
+ invalidKeyStore,
+ invalidPrivateKeytoAccountData,
+ invalidPrivateKeyToAddressData,
+ signatureRecoverData,
+ transactionsTestData,
+ validDecryptData,
+ validEncryptData,
+ validHashMessageData,
+ validPrivateKeytoAccountData,
+ validPrivateKeyToAddressData,
+ validPrivateKeyToPublicKeyData,
+ validRecover,
+} from '../fixtures/account';
+import { TransactionFactory } from '../../src/tx/transactionFactory';
+import { TxData } from '../../src/tx/types';
+
+describe('accounts', () => {
+ describe('create', () => {
+ describe('valid cases', () => {
+ it('%s', () => {
+ const account = create();
+ expect(typeof account.privateKey).toBe('string');
+ expect(typeof account.address).toBe('string');
+ expect(isHexStrict(account.address)).toBe(true);
+ expect(typeof account.encrypt).toBe('function');
+ expect(typeof account.sign).toBe('function');
+ expect(typeof account.signTransaction).toBe('function');
+ });
+ });
+ });
+
+ describe('privateKeyToAddress', () => {
+ describe('valid cases', () => {
+ it.each(validPrivateKeyToAddressData)('%s', (input, output) => {
+ expect(privateKeyToAddress(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(invalidPrivateKeyToAddressData)('%s', (input, output) => {
+ expect(() => privateKeyToAddress(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('privateKeyToAccount', () => {
+ describe('valid cases', () => {
+ it.each(validPrivateKeytoAccountData)('%s', (input, output) => {
+ expect(JSON.stringify(privateKeyToAccount(input.address, input.ignoreLength))).toEqual(
+ JSON.stringify(output),
+ );
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(invalidPrivateKeytoAccountData)('%s', (input, output) => {
+ expect(() => privateKeyToAccount(input)).toThrow(output);
+ });
+ });
+ });
+ describe('privateKeyToPublicKey', () => {
+ describe('valid cases', () => {
+ it.each(validPrivateKeyToPublicKeyData)('%s', (privateKey, isCompressed, output) => {
+ expect(privateKeyToPublicKey(privateKey, isCompressed)).toEqual(output);
+ });
+ });
+ });
+
+ describe('Signing and Recovery of Transaction', () => {
+ it.each(transactionsTestData)('sign transaction', async txData => {
+ const account = create();
+
+ const signedResult = await signTransaction(
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ TransactionFactory.fromTxData(txData as unknown as TxData),
+ account.privateKey,
+ );
+ expect(signedResult).toBeDefined();
+ expect(signedResult.messageHash).toBeDefined();
+ expect(signedResult.rawTransaction).toBeDefined();
+ expect(signedResult.transactionHash).toBeDefined();
+ expect(signedResult.r).toMatch(/0[xX][0-9a-fA-F]{64}/);
+ expect(signedResult.s).toMatch(/0[xX][0-9a-fA-F]{64}/);
+ expect(signedResult.v).toMatch(/0[xX][0-9a-fA-F]+/);
+ });
+
+ it.each(transactionsTestData)('Recover transaction', async txData => {
+ const account = create();
+ const txObj = { ...txData, from: account.address };
+ const signedResult = await signTransaction(
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+ TransactionFactory.fromTxData(txObj),
+ account.privateKey,
+ );
+ expect(signedResult).toBeDefined();
+
+ const address: Address = recoverTransaction(signedResult.rawTransaction);
+ expect(address).toBeDefined();
+ expect(address).toEqual(account.address);
+ });
+ });
+
+ describe('Hash Message', () => {
+ it.each(validHashMessageData)('%s', (message, hash) => {
+ expect(hashMessage(message)).toEqual(hash);
+ });
+ });
+
+ describe('Sign Message', () => {
+ describe('sign', () => {
+ it.each(signatureRecoverData)('%s', (data, testObj) => {
+ const result = sign(data, testObj.privateKey);
+ expect(result.signature).toEqual(testObj.signature || testObj.signatureOrV); // makes sure we get signature and not V value
+ expect(result.r).toEqual(testObj.r);
+ expect(result.s).toEqual(testObj.s);
+ });
+ });
+
+ describe('recover', () => {
+ it.each(signatureRecoverData)('%s', (data, testObj) => {
+ const address = recover(data, testObj.signatureOrV, testObj.prefixedOrR, testObj.s);
+ expect(address).toEqual(testObj.address);
+ });
+ });
+ });
+
+ describe('encrypt', () => {
+ describe('valid cases', () => {
+ it.each(validEncryptData)('%s', async (input, output) => {
+ const result = await encrypt(input[0], input[1], input[2]).catch(err => {
+ throw err;
+ });
+ expect(result.version).toBe(output.version);
+ expect(result.address).toBe(output.address);
+ expect(result.crypto.ciphertext).toBe(output.crypto.ciphertext);
+ expect(result.crypto.cipherparams).toEqual(output.crypto.cipherparams);
+ expect(result.crypto.cipher).toEqual(output.crypto.cipher);
+ expect(result.crypto.kdf).toBe(output.crypto.kdf);
+ expect(result.crypto.kdfparams).toEqual(output.crypto.kdfparams);
+ expect(typeof result.version).toBe('number');
+ expect(typeof result.id).toBe('string');
+ expect(typeof result.crypto.mac).toBe('string');
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(invalidEncryptData)('%s', async (input, output) => {
+ const result = encrypt(input[0], input[1], input[2]);
+ await expect(result).rejects.toThrow(output);
+ });
+ });
+ });
+
+ describe('decrypt', () => {
+ describe('valid cases', () => {
+ it.each(validDecryptData)('%s', async input => {
+ const keystore = await encrypt(input[0], input[1], input[2]).catch(err => {
+ throw err;
+ });
+
+ // make sure decrypt does not throw invalid password error
+ const result = await decrypt(keystore, input[1]);
+
+ expect(JSON.stringify(result)).toEqual(JSON.stringify(privateKeyToAccount(input[3])));
+
+ const keystoreString = JSON.stringify(keystore);
+
+ const stringResult = await decrypt(keystoreString, input[1], true);
+
+ expect(JSON.stringify(stringResult)).toEqual(JSON.stringify(privateKeyToAccount(input[3])));
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(invalidDecryptData)('%s', async (input, output) => {
+ const result = decrypt(input[0], input[1]);
+
+ await expect(result).rejects.toThrow(output);
+ });
+ });
+
+ describe('invalid keystore, fails validation', () => {
+ it.each(invalidKeyStore)('%s', async input => {
+ const result = decrypt(input[0], input[1]);
+
+ await expect(result).rejects.toThrow(Web3ValidatorError);
+ });
+ });
+
+ describe('valid signatures for recover', () => {
+ it.each(validRecover)('&s', (data, signature) => {
+ recover(data, signature);
+ });
+ });
+ });
+});
diff --git a/packages/web3-utils/src/uint8array.ts b/packages/web3-utils/src/uint8array.ts
index 772e648920c..5fa8b952711 100644
--- a/packages/web3-utils/src/uint8array.ts
+++ b/packages/web3-utils/src/uint8array.ts
@@ -21,6 +21,8 @@ export function isUint8Array(data: unknown | Uint8Array): data is Uint8Array {
(data as { constructor: { name: string } })?.constructor?.name === 'Uint8Array'
);
}
+
+// @TODO: Remove this function and its usages once all sub dependencies uses version 1.3.3 or above of @noble/hashes
export function ensureIfUint8Array(data: T) {
if (
!(data instanceof Uint8Array) &&
diff --git a/packages/web3-utils/test/unit/converters_dom.test.ts b/packages/web3-utils/test/unit/converters_dom.test.ts
new file mode 100644
index 00000000000..e7ed91a9573
--- /dev/null
+++ b/packages/web3-utils/test/unit/converters_dom.test.ts
@@ -0,0 +1,439 @@
+/**
+ * @jest-environment jsdom
+ */
+
+/*
+This file is part of web3.js.
+
+web3.js is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+web3.js is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with web3.js. If not, see .
+*/
+
+// this file contains the unit test for the event emitter in the DOM environment
+// it is executed in the jsdom environment (see "@jest-environment jsdom" in the top comment of this file)
+
+// ignore the following rule to allow keeping `@jest-environment jsdom` on top:
+// eslint-disable-next-line header/header
+import { TextDecoder, TextEncoder } from 'util';
+// polyfill for jsdom
+// @ts-expect-error ignore the error 'Type 'typeof TextDecoder' is not assignable to type ...'
+global.TextDecoder = TextDecoder;
+global.TextEncoder = TextEncoder;
+
+/* eslint-disable import/first */
+import {
+ asciiToHex,
+ bytesToHex,
+ fromAscii,
+ fromDecimal,
+ fromUtf8,
+ fromWei,
+ hexToAscii,
+ hexToBytes,
+ hexToNumber,
+ hexToNumberString,
+ hexToString,
+ hexToUtf8,
+ numberToHex,
+ stringToHex,
+ toAscii,
+ toDecimal,
+ toHex,
+ toNumber,
+ toUtf8,
+ toWei,
+ utf8ToHex,
+ toChecksumAddress,
+ bytesToUint8Array,
+ toBigInt,
+ toBool,
+} from '../../src/converters';
+
+import {
+ asciiToHexValidData,
+ bytesToHexInvalidData,
+ bytesToHexValidData,
+ fromWeiInvalidData,
+ fromWeiValidData,
+ hexToAsciiValidData,
+ hexToBytesInvalidData,
+ hexToBytesValidData,
+ hexToNumberInvalidData,
+ hexToNumberValidData,
+ hexToUtf8InvalidData,
+ hexToUtf8ValidData,
+ toUtf8ValidData,
+ numberToHexInvalidData,
+ numberToHexValidData,
+ toHexValidData,
+ toHexInvalidData,
+ toWeiInvalidData,
+ toWeiValidData,
+ utf8ToHexInvalidData,
+ utf8ToHexValidData,
+ toCheckSumValidData,
+ bytesToUint8ArrayInvalidData,
+ bytesToUint8ArrayValidData,
+ toBigIntValidData,
+ toBigIntInvalidData,
+ toCheckSumInvalidData,
+ numberToHexstrictValidData,
+ toBoolValidData,
+ toBoolInvalidData,
+} from '../fixtures/converters';
+
+describe('converters', () => {
+ describe('bytesToHex', () => {
+ describe('valid cases', () => {
+ it.each(bytesToHexValidData)('%s', (input, output) => {
+ expect(bytesToHex(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(bytesToHexInvalidData)('%s', (input, output) => {
+ expect(() => bytesToHex(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('hexToBytes', () => {
+ describe('valid cases', () => {
+ it.each(hexToBytesValidData)('%s', (input, output) => {
+ expect(hexToBytes(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToBytesInvalidData)('%s', (input, output) => {
+ expect(() => hexToBytes(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('numberToHex', () => {
+ describe('valid cases', () => {
+ it.each(numberToHexValidData)('%s', (input, output) => {
+ expect(numberToHex(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(numberToHexInvalidData)('%s', (input, output) => {
+ expect(() => numberToHex(input)).toThrow(output);
+ });
+ });
+
+ describe('valid hexstrict cases', () => {
+ it.each(numberToHexstrictValidData)('%s', (input, output) => {
+ expect(numberToHex(input, true)).toEqual(output);
+ });
+ });
+ });
+
+ describe('fromDecimal', () => {
+ describe('valid cases', () => {
+ it.each(numberToHexValidData)('%s', (input, output) => {
+ expect(fromDecimal(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(numberToHexInvalidData)('%s', (input, output) => {
+ expect(() => fromDecimal(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('hexToNumber', () => {
+ describe('valid cases', () => {
+ it.each(hexToNumberValidData)('%s', (input, output) => {
+ expect(hexToNumber(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToNumberInvalidData)('%s', (input, output) => {
+ expect(() => hexToNumber(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('toDecimal', () => {
+ describe('valid cases', () => {
+ it.each(hexToNumberValidData)('%s', (input, output) => {
+ expect(toDecimal(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToNumberInvalidData)('%s', (input, output) => {
+ expect(() => toDecimal(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('hexToNumberString', () => {
+ it.each(hexToNumberValidData)('%s', (input, output) => {
+ expect(hexToNumberString(input)).toEqual(output.toString());
+ });
+ });
+
+ describe('utf8ToHex', () => {
+ describe('valid cases', () => {
+ it.each(utf8ToHexValidData)('%s', (input, output) => {
+ expect(utf8ToHex(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(utf8ToHexInvalidData)('%s', (input, output) => {
+ expect(() => utf8ToHex(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('fromUtf8', () => {
+ describe('valid cases', () => {
+ it.each(utf8ToHexValidData)('%s', (input, output) => {
+ expect(fromUtf8(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(utf8ToHexInvalidData)('%s', (input, output) => {
+ expect(() => fromUtf8(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('stringToHex', () => {
+ describe('valid cases', () => {
+ it.each(utf8ToHexValidData)('%s', (input, output) => {
+ expect(stringToHex(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(utf8ToHexInvalidData)('%s', (input, output) => {
+ expect(() => stringToHex(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('hexToUtf8', () => {
+ describe('valid cases', () => {
+ it.each(hexToUtf8ValidData)('%s', (input, output) => {
+ expect(hexToUtf8(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToUtf8InvalidData)('%s', (input, output) => {
+ expect(() => hexToUtf8(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('toUtf8', () => {
+ describe('valid cases', () => {
+ it.each(toUtf8ValidData)('%s', (input, output) => {
+ expect(toUtf8(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToUtf8InvalidData)('%s', (input, output) => {
+ expect(() => toUtf8(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('hexToString', () => {
+ describe('valid cases', () => {
+ it.each(hexToUtf8ValidData)('%s', (input, output) => {
+ expect(hexToString(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToUtf8InvalidData)('%s', (input, output) => {
+ expect(() => hexToString(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('asciiToHex', () => {
+ describe('valid cases', () => {
+ it.each(asciiToHexValidData)('%s', (input, output) => {
+ expect(asciiToHex(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(utf8ToHexInvalidData)('%s', (input, output) => {
+ expect(() => asciiToHex(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('fromAscii', () => {
+ describe('valid cases', () => {
+ it.each(asciiToHexValidData)('%s', (input, output) => {
+ expect(fromAscii(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(utf8ToHexInvalidData)('%s', (input, output) => {
+ expect(() => fromAscii(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('hexToAscii', () => {
+ describe('valid cases', () => {
+ it.each(hexToAsciiValidData)('%s', (input, output) => {
+ expect(hexToAscii(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToUtf8InvalidData)('%s', (input, output) => {
+ expect(() => hexToAscii(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('toAscii', () => {
+ describe('valid cases', () => {
+ it.each(hexToAsciiValidData)('%s', (input, output) => {
+ expect(toAscii(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(hexToUtf8InvalidData)('%s', (input, output) => {
+ expect(() => toAscii(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('toHex', () => {
+ describe('return value', () => {
+ it.each(toHexValidData)('%s', (input, output) => {
+ expect(toHex(input)).toEqual(output[0]);
+ });
+ });
+
+ describe('return type', () => {
+ it.each(toHexValidData)('%s', (input, output) => {
+ expect(toHex(input, true)).toEqual(output[1]);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(toHexInvalidData)('%s', (input, output) => {
+ expect(() => toHex(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('toNumber', () => {
+ it.each([...hexToNumberValidData, [123, 123], ['123', 123]])('%s', (input, output) => {
+ expect(toNumber(input)).toEqual(output);
+ });
+ });
+
+ describe('fromWei', () => {
+ describe('valid cases', () => {
+ it.each(fromWeiValidData)('%s', (input, output) => {
+ expect(fromWei(input[0], input[1])).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(fromWeiInvalidData)('%s', (input, output) => {
+ expect(() => fromWei(input[0], input[1])).toThrow(output);
+ });
+ });
+ });
+
+ describe('toWei', () => {
+ describe('valid cases', () => {
+ it.each(toWeiValidData)('%s', (input, output) => {
+ expect(toWei(output, input[1])).toEqual(input[0].toString());
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(toWeiInvalidData)('%s', (input, output) => {
+ expect(() => toWei(input[0], input[1])).toThrow(output);
+ });
+ });
+ });
+ describe('toChecksumAddress', () => {
+ describe('valid cases', () => {
+ it.each(toCheckSumValidData)('%s', (input, output) => {
+ expect(toChecksumAddress(input)).toEqual(output);
+ });
+ });
+ describe('invalid cases', () => {
+ it.each(toCheckSumInvalidData)('%s', (input, output) => {
+ expect(() => toChecksumAddress(input)).toThrow(output);
+ });
+ });
+ });
+ describe('bytesToUint8Array', () => {
+ describe('bytesToUint8Array', () => {
+ describe('valid cases', () => {
+ it.each(bytesToUint8ArrayValidData)('%s', (input, output) => {
+ expect(bytesToUint8Array(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(bytesToUint8ArrayInvalidData)('%s', (input, output) => {
+ expect(() => bytesToUint8Array(input)).toThrow(output);
+ });
+ });
+ });
+ });
+ describe('toBigInt', () => {
+ describe('valid cases', () => {
+ it.each(toBigIntValidData)('%s', (input, output) => {
+ expect(toBigInt(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(toBigIntInvalidData)('%s', (input, output) => {
+ expect(() => toBigInt(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('toBool', () => {
+ describe('valid cases', () => {
+ it.each(toBoolValidData)('%s', (input, output) => {
+ expect(toBool(input)).toEqual(output);
+ });
+ });
+
+ describe('invalid cases', () => {
+ it.each(toBoolInvalidData)('%s', (input, output) => {
+ expect(() => toBool(input)).toThrow(output);
+ });
+ });
+ });
+});
diff --git a/packages/web3-utils/test/unit/hash_dom.test.ts b/packages/web3-utils/test/unit/hash_dom.test.ts
new file mode 100644
index 00000000000..1e4dd67cf0c
--- /dev/null
+++ b/packages/web3-utils/test/unit/hash_dom.test.ts
@@ -0,0 +1,166 @@
+/**
+ * @jest-environment jsdom
+ */
+
+/*
+This file is part of web3.js.
+
+web3.js is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+web3.js is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with web3.js. If not, see .
+*/
+
+// this file contains the unit test for the event emitter in the DOM environment
+// it is executed in the jsdom environment (see "@jest-environment jsdom" in the top comment of this file)
+
+// ignore the following rule to allow keeping `@jest-environment jsdom` on top:
+// eslint-disable-next-line header/header
+import { TextEncoder } from 'util';
+// polyfill for jsdom
+global.TextEncoder = TextEncoder;
+
+/* eslint-disable import/first */
+import { keccak256 } from 'js-sha3';
+import {
+ sha3,
+ sha3Raw,
+ soliditySha3,
+ soliditySha3Raw,
+ encodePacked,
+ keccak256 as web3keccak256,
+} from '../../src/hash';
+import {
+ sha3Data,
+ sha3ValidData,
+ soliditySha3RawValidData,
+ sha3RawValidData,
+ soliditySha3ValidData,
+ soliditySha3InvalidData,
+ compareSha3JSValidData,
+ compareSha3JSRawValidData,
+ encodePackData,
+ encodePackedInvalidData,
+ keccak256ValidData,
+ soliditySha3BigIntValidData,
+} from '../fixtures/hash';
+
+describe('hash', () => {
+ describe('sha3', () => {
+ describe('valid cases', () => {
+ it.each(sha3ValidData)('%s', (input, output) => {
+ expect(sha3(input)).toEqual(output);
+ });
+ });
+
+ describe('compare with js-sha3 normal cases', () => {
+ it.each(sha3Data)('%s', input => {
+ expect(sha3(input)).toBe(`0x${keccak256(input)}`);
+ });
+ });
+
+ describe('compare with js-sha3 uint8array cases', () => {
+ it.each(compareSha3JSValidData)('%s', (input, output) => {
+ expect(sha3(input)).toBe(`0x${keccak256(output)}`);
+ });
+ });
+ });
+
+ describe('sha3Raw', () => {
+ describe('valid cases', () => {
+ it.each(sha3RawValidData)('%s', (input, output) => {
+ expect(sha3Raw(input)).toEqual(output);
+ });
+ });
+ describe('comparing with js-sha3 cases', () => {
+ it.each(compareSha3JSRawValidData)('%s', (input, output) => {
+ expect(sha3Raw(input)).toBe(`0x${keccak256(output)}`);
+ });
+ });
+ });
+
+ describe('soliditySha3', () => {
+ describe('valid cases', () => {
+ it.each(soliditySha3ValidData)('%s', (input, output) => {
+ expect(soliditySha3(...input)).toEqual(output);
+ });
+ });
+ describe('invalid cases', () => {
+ it.each(soliditySha3InvalidData)('%s', (input, output) => {
+ expect(() => soliditySha3(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('soliditySha3Raw', () => {
+ describe('valid cases', () => {
+ it.each(soliditySha3RawValidData)('%s', (input, output) => {
+ expect(soliditySha3Raw(...input)).toEqual(output);
+ });
+ });
+ describe('invalid cases', () => {
+ it.each(soliditySha3InvalidData)('%s', (input, output) => {
+ expect(() => soliditySha3Raw(input)).toThrow(output);
+ });
+ });
+ });
+
+ describe('encodePacked', () => {
+ describe('valid cases', () => {
+ it.each(encodePackData)('%s', (input, output) => {
+ expect(encodePacked(...input)).toEqual(output);
+ });
+ });
+ describe('invalid cases', () => {
+ it.each(encodePackedInvalidData)('%s', (input, output) => {
+ expect(() => encodePacked(input)).toThrow(output);
+ });
+ });
+ });
+ describe('keccak256', () => {
+ describe('valid cases', () => {
+ it.each(keccak256ValidData)('%s', (input, output) => {
+ expect(web3keccak256(input)).toEqual(output);
+ });
+ });
+ });
+
+ describe('extra types supporting', () => {
+ it('object', () => {
+ const res = soliditySha3({
+ historicBlock: {
+ hash: '0xcba0b90a5e65512202091c12a2e3b328f374715b9f1c8f32cb4600c726fe2aa6',
+ height: 1,
+ },
+ networkId: 5777,
+ });
+ expect(res).toBe('0x00203462b63e3a8ca15da715e490c676b0e370f47823e31383fe43c25da3b78d');
+ });
+ it('object in string', () => {
+ const res = soliditySha3(
+ '{"contents":"pragma solidity >=0.4.21 <0.6.0;\\n\\ncontract Migrations {\\n address public owner;\\n uint public last_completed_migration;\\n\\n constructor() public {\\n owner = msg.sender;\\n }\\n\\n modifier restricted() {\\n if (msg.sender == owner) _;\\n }\\n\\n function setCompleted(uint completed) public restricted {\\n last_completed_migration = completed;\\n }\\n\\n function upgrade(address new_address) public restricted {\\n Migrations upgraded = Migrations(new_address);\\n upgraded.setCompleted(last_completed_migration);\\n }\\n}\\n","sourcePath":"/Users/gnidan/src/work/reproduce/2019/01/21/artifacts/contracts/Migrations.sol"}',
+ );
+ expect(res).toBe('0xdb092e2751b8dcb7c8509baade3c0ac290414a71685823c3cbeb28667970b0bd');
+ });
+ it('another object in string', () => {
+ const res = soliditySha3(
+ '{"bytes":"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610314806100606000396000f3fe608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630900f01014610067578063445df0ac146100b85780638da5cb5b146100e3578063fdacd5761461013a575b600080fd5b34801561007357600080fd5b506100b66004803603602081101561008a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610175565b005b3480156100c457600080fd5b506100cd61025d565b6040518082815260200191505060405180910390f35b3480156100ef57600080fd5b506100f8610263565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561014657600080fd5b506101736004803603602081101561015d57600080fd5b8101908080359060200190929190505050610288565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561025a5760008190508073ffffffffffffffffffffffffffffffffffffffff1663fdacd5766001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561024057600080fd5b505af1158015610254573d6000803e3d6000fd5b50505050505b50565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102e557806001819055505b5056fea165627a7a7230582013359aba5684f88626fb6a58a003236e309ef1462172af4afb4afb9bd2532b510029","linkReferences":[]}',
+ );
+ expect(res).toBe('0x46e99868594ceb46b7cd37e4b33d635f12a7751671f8c51dd8218fa0dcf82901');
+ });
+
+ describe('BigInt soliditySha3', () => {
+ it.each(soliditySha3BigIntValidData)('%s', (input, output) => {
+ expect(soliditySha3(...input)).toEqual(output);
+ });
+ });
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 18cbb781cec..90bbf007848 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1386,12 +1386,12 @@
dependencies:
"@noble/hashes" "1.3.1"
-"@noble/hashes@1.1.2", "@noble/hashes@~1.1.1":
+"@noble/hashes@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183"
integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==
-"@noble/hashes@1.3.0", "@noble/hashes@~1.3.0":
+"@noble/hashes@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1"
integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==
@@ -1401,10 +1401,15 @@
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9"
integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==
-"@noble/hashes@~1.3.1":
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
- integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
+"@noble/hashes@~1.1.1":
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11"
+ integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==
+
+"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
+ integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
"@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0":
version "1.6.3"
@@ -2301,6 +2306,11 @@
dependencies:
"@babel/types" "^7.3.0"
+"@types/benchmark@^2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@types/benchmark/-/benchmark-2.1.5.tgz#940c1850c18fdfdaee3fd6ed29cd92ae0d445b45"
+ integrity sha512-cKio2eFB3v7qmKcvIHLUMw/dIx/8bhWPuzpzRT4unCPRTD8VdA9Zb0afxpcxOqR4PixRS7yT42FqGS8BYL8g1w==
+
"@types/bn.js@^4.11.3":
version "4.11.6"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
@@ -3505,6 +3515,14 @@ before-after-hook@^2.2.0:
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e"
integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==
+benchmark@^2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629"
+ integrity sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==
+ dependencies:
+ lodash "^4.17.4"
+ platform "^1.3.3"
+
big-integer@^1.6.44:
version "1.6.51"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
@@ -8913,7 +8931,7 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
-lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21:
+lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -10463,6 +10481,11 @@ pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
+platform@^1.3.3:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
+ integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
+
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
From f865290adb6325bcdaf6a56bf26aeb07895b295d Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 3 Jan 2024 18:29:00 +0100
Subject: [PATCH 15/16] update CHANGELOG.md files
---
CHANGELOG.md | 4 ++--
packages/web3-eth-abi/CHANGELOG.md | 4 ++++
packages/web3-eth-accounts/CHANGELOG.md | 1 +
packages/web3-utils/CHANGELOG.md | 6 +++++-
packages/web3-validator/CHANGELOG.md | 6 +++++-
5 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3455d22a904..1b059877dff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2287,7 +2287,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f
#### web3-utils
-- Fix unecessary array copy when pack encoding (#6553)
+- Fix unnecessary array copy when pack encoding (#6553)
## [Unreleased]
@@ -2322,4 +2322,4 @@ If there are any bugs, improvements, optimizations or any new feature proposal f
#### web3-utils
-- Fix unecessary array copy when pack encoding (#6553)
+- Fix unnecessary array copy when pack encoding (#6553)
diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md
index 2192a71e872..486ca6ab34b 100644
--- a/packages/web3-eth-abi/CHANGELOG.md
+++ b/packages/web3-eth-abi/CHANGELOG.md
@@ -159,3 +159,7 @@ Documentation:
### Changed
- Use `AbiError` instead of `Error` for errors at web3-eth-abi (#6641).
+
+### Fixed
+
+- Fixed an issue with detecting Uint8Array (#6486)
diff --git a/packages/web3-eth-accounts/CHANGELOG.md b/packages/web3-eth-accounts/CHANGELOG.md
index 337dd2292b0..11bddfffab1 100644
--- a/packages/web3-eth-accounts/CHANGELOG.md
+++ b/packages/web3-eth-accounts/CHANGELOG.md
@@ -154,3 +154,4 @@ Documentation:
### Fixed
- Send Transaction config used to be ignored if the passed `common` did not have a `copy()` and the `chainId` was not provided (#6663)
+- Fixed an issue with detecting Uint8Array (#6486)
diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md
index 953d1ff035a..30c854f6e09 100644
--- a/packages/web3-utils/CHANGELOG.md
+++ b/packages/web3-utils/CHANGELOG.md
@@ -179,6 +179,10 @@ Documentation:
### Fixed
-- Fix unecessary array copy when pack encoding (#6553)
+- Fix unnecessary array copy when pack encoding (#6553)
## [Unreleased]
+
+### Fixed
+
+- Fixed an issue with detecting Uint8Array (#6486)
diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md
index d36b2f7af2a..9d8ac2e190b 100644
--- a/packages/web3-validator/CHANGELOG.md
+++ b/packages/web3-validator/CHANGELOG.md
@@ -156,4 +156,8 @@ Documentation:
- Validator will now properly handle all valid numeric type sizes: intN / uintN where 8 < = N < = 256 and N % 8 == 0 (#6434)
- Will now throw SchemaFormatError when unsupported format is passed to `convertToZod` method (#6434)
-## [Unreleased]
\ No newline at end of file
+## [Unreleased]
+
+### Fixed
+
+- Fixed an issue with detecting Uint8Array (#6486)
From 557132b5e65f98a9651047779d5a670ff5af5257 Mon Sep 17 00:00:00 2001
From: Muhammad-Altabba <24407834+Muhammad-Altabba@users.noreply.github.com>
Date: Wed, 3 Jan 2024 23:55:26 +0100
Subject: [PATCH 16/16] move `ensureIfUint8Array` to `web3-validator`
---
packages/web3-utils/src/converters.ts | 4 ++--
packages/web3-utils/src/hash.ts | 7 +++----
packages/web3-utils/src/uint8array.ts | 11 -----------
packages/web3-validator/src/utils.ts | 11 +++++++++++
packages/web3-validator/src/validation/address.ts | 4 ++--
5 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts
index 52fb864e4fc..b84d5c28335 100644
--- a/packages/web3-utils/src/converters.ts
+++ b/packages/web3-utils/src/converters.ts
@@ -42,7 +42,7 @@ import {
InvalidNumberError,
InvalidUnitError,
} from 'web3-errors';
-import { ensureIfUint8Array, isUint8Array } from './uint8array.js';
+import { isUint8Array } from './uint8array.js';
// Ref: https://ethdocs.org/en/latest/ether.html
// Note: this could be simplified using ** operator, but babel does not handle it well (https://github.com/babel/babel/issues/13109)
@@ -596,7 +596,7 @@ export const toChecksumAddress = (address: Address): string => {
// calling `Uint8Array.from` because `noble-hashes` checks with `instanceof Uint8Array` that fails in some edge cases:
// https://github.com/paulmillr/noble-hashes/issues/25#issuecomment-1750106284
const hash = utils.uint8ArrayToHexString(
- keccak256(ensureIfUint8Array(utf8ToBytes(lowerCaseAddress))),
+ keccak256(validatorUtils.ensureIfUint8Array(utf8ToBytes(lowerCaseAddress))),
);
if (
diff --git a/packages/web3-utils/src/hash.ts b/packages/web3-utils/src/hash.ts
index bb4bbd44636..6e498138c29 100644
--- a/packages/web3-utils/src/hash.ts
+++ b/packages/web3-utils/src/hash.ts
@@ -59,7 +59,7 @@ import {
TypedObject,
TypedObjectAbbreviated,
} from 'web3-types';
-import { isAddress, isNullish, isHexStrict } from 'web3-validator';
+import { utils as validatorUtils, isAddress, isNullish, isHexStrict } from 'web3-validator';
import {
bytesToUint8Array,
bytesToHex,
@@ -71,7 +71,6 @@ import {
} from './converters.js';
import { leftPad, rightPad, toTwosComplement } from './string_manipulation.js';
-
const SHA3_EMPTY_BYTES = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470';
/**
@@ -100,7 +99,7 @@ export const sha3 = (data: Bytes): string | undefined => {
} else {
updatedData = data;
}
- const hash = bytesToHex(keccak256(updatedData));
+ const hash = bytesToHex(keccak256(validatorUtils.ensureIfUint8Array(updatedData)));
// EIP-1052 if hash is equal to c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, keccak was given empty data
return hash === SHA3_EMPTY_BYTES ? undefined : hash;
@@ -159,7 +158,7 @@ export const keccak256Wrapper = (
} else {
processedData = bytesToUint8Array(data as Bytes);
}
- return bytesToHex(keccak256(processedData));
+ return bytesToHex(keccak256(validatorUtils.ensureIfUint8Array(processedData)));
};
export { keccak256Wrapper as keccak256 };
diff --git a/packages/web3-utils/src/uint8array.ts b/packages/web3-utils/src/uint8array.ts
index 5fa8b952711..cf5d7ee7a45 100644
--- a/packages/web3-utils/src/uint8array.ts
+++ b/packages/web3-utils/src/uint8array.ts
@@ -22,17 +22,6 @@ export function isUint8Array(data: unknown | Uint8Array): data is Uint8Array {
);
}
-// @TODO: Remove this function and its usages once all sub dependencies uses version 1.3.3 or above of @noble/hashes
-export function ensureIfUint8Array(data: T) {
- if (
- !(data instanceof Uint8Array) &&
- (data as { constructor: { name: string } })?.constructor?.name === 'Uint8Array'
- ) {
- return Uint8Array.from(data as unknown as Uint8Array);
- }
- return data;
-}
-
export function uint8ArrayConcat(...parts: Uint8Array[]): Uint8Array {
const length = parts.reduce((prev, part) => {
const agg = prev + part.length;
diff --git a/packages/web3-validator/src/utils.ts b/packages/web3-validator/src/utils.ts
index 6be75256ce3..f7d632d1dc9 100644
--- a/packages/web3-validator/src/utils.ts
+++ b/packages/web3-validator/src/utils.ts
@@ -495,3 +495,14 @@ export function hexToUint8Array(hex: string): Uint8Array {
}
return bytes
}
+
+// @TODO: Remove this function and its usages once all sub dependencies uses version 1.3.3 or above of @noble/hashes
+export function ensureIfUint8Array(data: T) {
+ if (
+ !(data instanceof Uint8Array) &&
+ (data as { constructor: { name: string } })?.constructor?.name === 'Uint8Array'
+ ) {
+ return Uint8Array.from(data as unknown as Uint8Array);
+ }
+ return data;
+}
\ No newline at end of file
diff --git a/packages/web3-validator/src/validation/address.ts b/packages/web3-validator/src/validation/address.ts
index 2fb61c5b9a3..38ebebe65f6 100644
--- a/packages/web3-validator/src/validation/address.ts
+++ b/packages/web3-validator/src/validation/address.ts
@@ -18,7 +18,7 @@ along with web3.js. If not, see .
import { keccak256 } from 'ethereum-cryptography/keccak.js';
import { utf8ToBytes } from 'ethereum-cryptography/utils.js';
import { ValidInputTypes } from '../types.js';
-import { uint8ArrayToHexString } from '../utils.js';
+import { ensureIfUint8Array, uint8ArrayToHexString } from '../utils.js';
import { isHexStrict } from './string.js';
import { isUint8Array } from './bytes.js';
@@ -30,7 +30,7 @@ export const checkAddressCheckSum = (data: string): boolean => {
const address = data.slice(2);
const updatedData = utf8ToBytes(address.toLowerCase());
- const addressHash = uint8ArrayToHexString(keccak256(updatedData)).slice(2);
+ const addressHash = uint8ArrayToHexString(keccak256(ensureIfUint8Array(updatedData))).slice(2);
for (let i = 0; i < 40; i += 1) {
// the nth letter should be uppercase if the nth digit of casemap is 1