Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 3ab3b39

Browse files
create a new type Eip1193Compatible (#6407)
* add asEip1193Compatible to Web3BaseProvider * modify jest config at web3-types * update CHANGELOG.md at web3-types
1 parent dd4de22 commit 3ab3b39

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

packages/web3-types/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,7 @@ Documentation:
158158
- Dependencies updated
159159

160160
## [Unreleased]
161+
162+
### Added
163+
164+
- add `asEIP1193Provider` to `Web3BaseProvider` so every inherited class can have the returned value of `request` method, fully compatible with EIP-1193. (#6407)

packages/web3-types/src/web3_base_provider.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ export interface EIP1193Provider<API extends Web3APISpec> extends SimpleProvider
133133
removeListener(event: 'accountsChanged', listener: (accounts: ProviderAccounts) => void): void;
134134
}
135135

136+
export type Eip1193Compatible<API extends Web3APISpec = EthExecutionAPI> = Omit<
137+
// eslint-disable-next-line no-use-before-define
138+
Omit<Web3BaseProvider, 'request'>,
139+
'asEIP1193Provider'
140+
> & {
141+
request<
142+
Method extends Web3APIMethod<API>,
143+
ResultType = Web3APIReturnType<API, Method> | unknown,
144+
>(
145+
request: Web3APIPayload<API, Method>,
146+
): Promise<ResultType>;
147+
};
148+
136149
// Provider interface compatible with EIP-1193
137150
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md
138151
export abstract class Web3BaseProvider<API extends Web3APISpec = EthExecutionAPI>
@@ -189,6 +202,40 @@ export abstract class Web3BaseProvider<API extends Web3APISpec = EthExecutionAPI
189202
>;
190203
}
191204

205+
/**
206+
* Modify the return type of the request method to be fully compatible with EIP-1193
207+
*
208+
* [deprecated] In the future major releases (\>= v5) all providers are supposed to be fully compatible with EIP-1193.
209+
* So this method will not be needed and would not be available in the future.
210+
*
211+
* @returns A new instance of the provider with the request method fully compatible with EIP-1193
212+
*
213+
* @example
214+
* ```ts
215+
* const provider = new Web3HttpProvider('http://localhost:8545');
216+
* const fullyCompatibleProvider = provider.asEIP1193Provider();
217+
* const result = await fullyCompatibleProvider.request({ method: 'eth_getBalance' });
218+
* console.log(result); // '0x0234c8a3397aab58' or something like that
219+
* ```
220+
*/
221+
public asEIP1193Provider(): Eip1193Compatible<API> {
222+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
223+
const newObj = Object.create(this) as Eip1193Compatible<API>;
224+
// eslint-disable-next-line @typescript-eslint/unbound-method
225+
const originalRequest = newObj.request;
226+
newObj.request = async function request(
227+
args: Web3APIPayload<API, Web3APIMethod<API>>,
228+
): Promise<unknown> {
229+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
230+
const response = (await originalRequest(args)) as JsonRpcResponseWithResult<unknown>;
231+
return response.result;
232+
} as typeof newObj.request;
233+
// @ts-expect-error the property should not be available in the new object because of using Object.create(this).
234+
// But it is available if we do not delete it.
235+
newObj.asEIP1193Provider = undefined; // to prevent the user for calling this method again
236+
return newObj;
237+
}
238+
192239
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md#request
193240
public abstract request<
194241
Method extends Web3APIMethod<API>,

packages/web3-types/test/unit/jest.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ const base = require('../config/jest.config');
33
module.exports = {
44
...base,
55
testMatch: ['<rootDir>/test/unit/**/*.(spec|test).(js|ts)'],
6-
6+
moduleNameMapper: {
7+
'^(\\.{1,2}/.*)\\.js$': '$1',
8+
},
79
coverageDirectory: '.coverage/unit',
810
collectCoverageFrom: ['src/**'],
911
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
This file is part of web3.js.
3+
4+
web3.js is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
web3.js is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
import {
19+
EthExecutionAPI,
20+
JsonRpcResponseWithResult,
21+
Web3APIMethod,
22+
Web3APIPayload,
23+
Web3APIReturnType,
24+
Web3BaseProvider,
25+
} from '../../src/index.js';
26+
27+
// @ts-expect-error mock class for testing. The abstract methods are not implemented.
28+
class Web3ChildProvider extends Web3BaseProvider {
29+
// eslint-disable-next-line class-methods-use-this
30+
public async request<
31+
Method extends Web3APIMethod<EthExecutionAPI>,
32+
ResultType = Web3APIReturnType<EthExecutionAPI, Method> | unknown,
33+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
34+
>(_: Web3APIPayload<EthExecutionAPI, Method>): Promise<JsonRpcResponseWithResult<ResultType>> {
35+
return new Promise(resolve =>
36+
// eslint-disable-next-line no-promise-executor-return
37+
resolve({
38+
jsonrpc: '2.0',
39+
id: 1,
40+
result: 'result' as unknown as ResultType,
41+
}),
42+
);
43+
}
44+
}
45+
46+
describe('Web3BaseProvider', () => {
47+
it('asEIP1193Provider will fix the returned result of the request method', async () => {
48+
const childProvider = new Web3ChildProvider();
49+
const returnValue = await childProvider.request({ method: 'eth_getBalance' });
50+
expect(returnValue.result).toBe('result');
51+
52+
const eip1193CompatibleClass = childProvider.asEIP1193Provider();
53+
const returnValue2 = await eip1193CompatibleClass.request({
54+
method: 'eth_getBalance',
55+
});
56+
expect(returnValue2).toBe('result');
57+
});
58+
59+
it('asEIP1193Provider would not be available inside the newly generated class', () => {
60+
const childProvider = new Web3ChildProvider();
61+
62+
const eip1193CompatibleClass = childProvider.asEIP1193Provider();
63+
expect((eip1193CompatibleClass as any).asEIP1193Provider).toBeUndefined();
64+
});
65+
});

0 commit comments

Comments
 (0)