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

Commit 80b07dd

Browse files
authored
✨ Make the web3 constructor parameters optional (#5139)
* 🎨 Update the code for small fixes * ✅ Update failing tests * ✅ Fix failing tests * 🎨 Add version attribute to 'Web3' class * 🚚 Rename the misused promievent names * ✏️ Fix the typos in tests * ✏️ Fix some typo in tests files * 🎨 Improve the code as per feedback * 🎨 Improve code with feedback * 🎨 Fix some typo in refactoring * 🏗️ Update the default return format to bigint * 🧪 Fix few eth tests * ✅ Fix all tests for web3-eth * 🎨 Add more test cases for the validator * ✅ Fix tests for eth-personal * ✅ Fix contracts tests * ✨ Add optional provider support to web3 * ✨ Add optional provider support to web3 * 🎨 Fix some merge issues * ✅ Update unit tests for web3-core * 🎨 Add more integration tests for web3 * ⚰️ Fix dead code caused by merge * 🐛 Update a provider init logic * 🎨 Update test snapshots * 🎨 Update the eth constructor logic to inject subscriptions * ✅ Add more tests for web3 instance
1 parent 0beb794 commit 80b07dd

File tree

12 files changed

+181
-64
lines changed

12 files changed

+181
-64
lines changed

packages/web3-core/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const isLegacySendAsyncProvider = <API extends Web3APISpec>(
4141

4242
export const isSupportedProvider = <API extends Web3APISpec>(
4343
provider: SupportedProviders<API>,
44-
): boolean =>
44+
): provider is SupportedProviders<API> =>
4545
Web3BaseProvider.isWeb3Provider(provider) ||
4646
isLegacyRequestProvider(provider) ||
4747
isLegacySendAsyncProvider(provider) ||

packages/web3-core/src/web3_context.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
Web3BaseWalletAccount,
2222
Web3AccountProvider,
2323
} from 'web3-common';
24-
import { HexString } from 'web3-utils';
24+
import { HexString, isNullish } from 'web3-utils';
2525
import { SupportedProviders } from './types';
2626
import { isSupportedProvider } from './utils';
2727
// eslint-disable-next-line import/no-cycle
@@ -41,7 +41,7 @@ export type Web3ContextObject<
4141
} = any,
4242
> = {
4343
config: Web3ConfigOptions;
44-
provider: SupportedProviders<API>;
44+
provider?: SupportedProviders<API> | string;
4545
requestManager: Web3RequestManager<API>;
4646
subscriptionManager?: Web3SubscriptionManager<API, RegisteredSubs> | undefined;
4747
registeredSubscriptions?: RegisteredSubs;
@@ -59,7 +59,7 @@ export type Web3ContextInitOptions<
5959
} = any,
6060
> = {
6161
config?: Partial<Web3ConfigOptions>;
62-
provider: SupportedProviders<API> | string;
62+
provider?: SupportedProviders<API> | string;
6363
requestManager?: Web3RequestManager<API>;
6464
subscriptionManager?: Web3SubscriptionManager<API, RegisteredSubs> | undefined;
6565
registeredSubscriptions?: RegisteredSubs;
@@ -99,17 +99,24 @@ export class Web3Context<
9999

100100
public constructor(
101101
providerOrContext?:
102+
| string
102103
| SupportedProviders<API>
103-
| Web3ContextInitOptions<API, RegisteredSubs>
104-
| string,
104+
| Web3ContextInitOptions<API, RegisteredSubs>,
105105
) {
106106
super();
107+
108+
// If "providerOrContext" is provided as "string" or an objects matching "SupportedProviders" interface
107109
if (
108-
typeof providerOrContext === 'string' ||
110+
isNullish(providerOrContext) ||
111+
(typeof providerOrContext === 'string' && providerOrContext.trim() !== '') ||
109112
isSupportedProvider(providerOrContext as SupportedProviders<API>)
110113
) {
111114
this._requestManager = new Web3RequestManager<API>(
112-
providerOrContext as SupportedProviders<API>,
115+
providerOrContext as undefined | string | SupportedProviders<API>,
116+
);
117+
this._subscriptionManager = new Web3SubscriptionManager(
118+
this._requestManager,
119+
{} as RegisteredSubs,
113120
);
114121

115122
return;
@@ -123,7 +130,7 @@ export class Web3Context<
123130
registeredSubscriptions,
124131
accountProvider,
125132
wallet,
126-
} = providerOrContext as Partial<Web3ContextObject<API, RegisteredSubs>>;
133+
} = providerOrContext as Web3ContextInitOptions<API, RegisteredSubs>;
127134

128135
this.setConfig(config ?? {});
129136

@@ -229,19 +236,19 @@ export class Web3Context<
229236
});
230237
}
231238

232-
public get provider(): SupportedProviders<API> {
239+
public get provider(): SupportedProviders<API> | string | undefined {
233240
return this.requestManager.provider;
234241
}
235242

236-
public set provider(provider: SupportedProviders<API> | string) {
243+
public set provider(provider: SupportedProviders<API> | string | undefined) {
237244
this.requestManager.setProvider(provider);
238245
}
239246

240-
public get currentProvider(): SupportedProviders<API> {
247+
public get currentProvider(): SupportedProviders<API> | string | undefined {
241248
return this.requestManager.provider;
242249
}
243250

244-
public set currentProvider(provider: SupportedProviders<API> | string) {
251+
public set currentProvider(provider: SupportedProviders<API> | string | undefined) {
245252
this.requestManager.setProvider(provider);
246253
}
247254

@@ -250,7 +257,7 @@ export class Web3Context<
250257
return Web3Context.givenProvider;
251258
}
252259

253-
public setProvider(provider: SupportedProviders<API>) {
260+
public setProvider(provider?: SupportedProviders<API> | string) {
254261
this.provider = provider;
255262
}
256263

packages/web3-core/src/web3_request_manager.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
Web3APIRequest,
3232
Web3APIReturnType,
3333
Web3APISpec,
34-
Web3BaseProvider,
3534
Web3EventEmitter,
3635
} from 'web3-common';
3736
import HttpProvider from 'web3-providers-http';
@@ -60,14 +59,14 @@ const availableProviders = {
6059
export class Web3RequestManager<
6160
API extends Web3APISpec = EthExecutionAPI,
6261
> extends Web3EventEmitter<{
63-
[key in Web3RequestManagerEvent]: SupportedProviders<API>;
62+
[key in Web3RequestManagerEvent]: SupportedProviders<API> | undefined;
6463
}> {
65-
private _provider!: SupportedProviders<API>;
64+
private _provider?: SupportedProviders<API>;
6665

6766
public constructor(provider?: SupportedProviders<API> | string, net?: Socket) {
6867
super();
6968

70-
if (provider) {
69+
if (!isNullish(provider)) {
7170
this.setProvider(provider, net);
7271
}
7372
}
@@ -77,10 +76,6 @@ export class Web3RequestManager<
7776
}
7877

7978
public get provider() {
80-
if (!this._provider) {
81-
throw new ProviderError('Provider not available');
82-
}
83-
8479
return this._provider;
8580
}
8681

@@ -89,8 +84,8 @@ export class Web3RequestManager<
8984
return availableProviders;
9085
}
9186

92-
public setProvider(provider: SupportedProviders<API> | string, net?: Socket) {
93-
let newProvider!: Web3BaseProvider<API>;
87+
public setProvider(provider?: SupportedProviders<API> | string, net?: Socket) {
88+
let newProvider: SupportedProviders<API> | undefined;
9489

9590
// autodetect provider
9691
if (provider && typeof provider === 'string' && this.providers) {
@@ -106,12 +101,17 @@ export class Web3RequestManager<
106101
} else if (typeof net === 'object' && typeof net.connect === 'function') {
107102
newProvider = new this.providers.IpcProvider<API>(provider, net);
108103
} else {
109-
throw new ProviderError(`Can't autodetect provider for "${provider}'"`);
104+
throw new ProviderError(`Can't autodetect provider for "${provider}"`);
110105
}
106+
} else if (isNullish(provider)) {
107+
// In case want to unset the provider
108+
newProvider = undefined;
109+
} else {
110+
newProvider = provider as SupportedProviders<API>;
111111
}
112112

113113
this.emit(Web3RequestManagerEvent.BEFORE_PROVIDER_CHANGE, this._provider);
114-
this._provider = newProvider ?? provider;
114+
this._provider = newProvider;
115115
this.emit(Web3RequestManagerEvent.PROVIDER_CHANGED, this._provider);
116116
}
117117

@@ -142,6 +142,12 @@ export class Web3RequestManager<
142142
): Promise<JsonRpcResponse<ResponseType>> {
143143
const { provider } = this;
144144

145+
if (isNullish(provider)) {
146+
throw new ProviderError(
147+
'Provider not available. Use `.setProvider` or `.provider=` to initialize the provider.',
148+
);
149+
}
150+
145151
const payload = jsonRpc.isBatchRequest(request)
146152
? jsonRpc.toBatchPayload(request)
147153
: jsonRpc.toPayload(request);

packages/web3-core/src/web3_subscription_manager.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ export class Web3SubscriptionManager<
126126
}
127127

128128
public supportsSubscriptions(): boolean {
129-
return isSupportSubscriptions(this.requestManager.provider);
129+
return isNullish(this.requestManager.provider)
130+
? false
131+
: isSupportSubscriptions(this.requestManager.provider);
130132
}
131133
}

packages/web3-core/test/unit/__snapshots__/web3_context.test.ts.snap

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ Object {
3333
"IpcProvider": [Function],
3434
"WebsocketProvider": [Function],
3535
},
36-
"registeredSubscriptions": undefined,
36+
"registeredSubscriptions": Object {},
3737
"requestManager": Web3RequestManager {
3838
"_emitter": EventEmitter {
39-
"_events": Object {},
40-
"_eventsCount": 0,
39+
"_events": Object {
40+
"BEFORE_PROVIDER_CHANGE": [Function],
41+
"PROVIDER_CHANGED": [Function],
42+
},
43+
"_eventsCount": 2,
4144
"_maxListeners": undefined,
4245
Symbol(kCapture): false,
4346
},
@@ -46,7 +49,25 @@ Object {
4649
"httpProviderOptions": undefined,
4750
},
4851
},
49-
"subscriptionManager": undefined,
52+
"subscriptionManager": Web3SubscriptionManager {
53+
"_subscriptions": Map {},
54+
"registeredSubscriptions": Object {},
55+
"requestManager": Web3RequestManager {
56+
"_emitter": EventEmitter {
57+
"_events": Object {
58+
"BEFORE_PROVIDER_CHANGE": [Function],
59+
"PROVIDER_CHANGED": [Function],
60+
},
61+
"_eventsCount": 2,
62+
"_maxListeners": undefined,
63+
Symbol(kCapture): false,
64+
},
65+
"_provider": HttpProvider {
66+
"clientUrl": "http://test/abc",
67+
"httpProviderOptions": undefined,
68+
},
69+
},
70+
},
5071
"wallet": undefined,
5172
}
5273
`;

packages/web3-core/test/unit/web3_request_manager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ describe('Web3RequestManager', () => {
233233
const manager = new Web3RequestManager();
234234

235235
expect(() => manager.setProvider(providerString)).toThrow(
236-
`Can't autodetect provider for "pc://mydomain.com'"`,
236+
`Can't autodetect provider for "pc://mydomain.com"`,
237237
);
238238
});
239239
});

packages/web3-eth-contract/src/contract.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export class Contract<Abi extends ContractAbi>
175175
super({
176176
...context,
177177
// Pass an empty string to avoid type issue. Error will be thrown from underlying validation
178-
provider: options?.provider ?? context?.provider ?? Contract.givenProvider ?? '',
178+
provider: options?.provider ?? context?.provider ?? Contract.givenProvider,
179179
registeredSubscriptions: {
180180
logs: LogsSubscription,
181181
newHeads: NewHeadsSubscription,

packages/web3-eth-contract/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export interface ContractInitOptions {
6161
readonly from?: Address;
6262
readonly data?: Bytes;
6363
readonly gasLimit?: Uint;
64-
readonly provider: SupportedProviders<EthExecutionAPI> | string;
64+
readonly provider?: SupportedProviders<EthExecutionAPI> | string;
6565
}
6666

6767
export type TransactionReceipt = ReceiptInfo;

packages/web3-eth/src/web3_eth.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
1818
// Disabling because returnTypes must be last param to match 1.x params
1919
/* eslint-disable default-param-last */
2020
import { DataFormat, DEFAULT_RETURN_FORMAT } from 'web3-common';
21-
import { SupportedProviders, Web3Context, Web3ContextInitOptions } from 'web3-core';
21+
import {
22+
isSupportedProvider,
23+
SupportedProviders,
24+
Web3Context,
25+
Web3ContextInitOptions,
26+
} from 'web3-core';
2227
import {
2328
Address,
2429
Bytes,
@@ -53,28 +58,40 @@ type RegisteredSubscription = {
5358
syncing: typeof SyncingSubscription;
5459
};
5560

61+
const registeredSubscriptions = {
62+
logs: LogsSubscription,
63+
newPendingTransactions: NewPendingTransactionsSubscription,
64+
newHeads: NewHeadsSubscription,
65+
syncing: SyncingSubscription,
66+
pendingTransactions: NewPendingTransactionsSubscription, // the same as newPendingTransactions. just for support API like in version 1.x
67+
newBlockHeaders: NewHeadsSubscription, // the same as newHeads. just for support API like in version 1.x
68+
};
69+
5670
export class Web3Eth extends Web3Context<Web3EthExecutionAPI, RegisteredSubscription> {
5771
public constructor(
58-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
59-
providerOrContext: SupportedProviders<any> | Web3ContextInitOptions | string,
72+
providerOrContext?: SupportedProviders<any> | Web3ContextInitOptions | string,
6073
) {
61-
super(
62-
typeof providerOrContext === 'object' &&
63-
(providerOrContext as Web3ContextInitOptions).provider
64-
? providerOrContext
65-
: {
66-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
67-
provider: providerOrContext as SupportedProviders<any>,
68-
registeredSubscriptions: {
69-
logs: LogsSubscription,
70-
newPendingTransactions: NewPendingTransactionsSubscription,
71-
newHeads: NewHeadsSubscription,
72-
syncing: SyncingSubscription,
73-
pendingTransactions: NewPendingTransactionsSubscription, // the same as newPendingTransactions. just for support API like in version 1.x
74-
newBlockHeaders: NewHeadsSubscription, // the same as newHeads. just for support API like in version 1.x
75-
},
76-
},
77-
);
74+
if (
75+
typeof providerOrContext === 'string' ||
76+
isSupportedProvider(providerOrContext as SupportedProviders<any>)
77+
) {
78+
super({
79+
provider: providerOrContext as SupportedProviders<any>,
80+
registeredSubscriptions,
81+
});
82+
83+
return;
84+
}
85+
86+
if ((providerOrContext as Web3ContextInitOptions).registeredSubscriptions) {
87+
super(providerOrContext as Web3ContextInitOptions);
88+
return;
89+
}
90+
91+
super({
92+
...(providerOrContext as Web3ContextInitOptions),
93+
registeredSubscriptions,
94+
});
7895
}
7996
public async getProtocolVersion() {
8097
return rpcMethods.getProtocolVersion(this.requestManager);

packages/web3-validator/src/validation/numbers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const isUInt = (
3838
) {
3939
return false;
4040
}
41+
4142
let size!: number;
4243

4344
if (options?.abiType) {

packages/web3/src/web3.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,11 @@ export class Web3 extends Web3Context<EthExecutionAPI> {
6161
Personal,
6262
};
6363

64+
public utils: typeof utils;
65+
6466
public eth: Web3Eth & {
6567
Iban: typeof Iban;
6668
ens: ENS;
67-
utils: typeof utils;
6869
net: Net;
6970
personal: Personal;
7071
Contract: typeof Contract & {
@@ -93,7 +94,7 @@ export class Web3 extends Web3Context<EthExecutionAPI> {
9394
};
9495
};
9596

96-
public constructor(provider: SupportedProviders<EthExecutionAPI> | string) {
97+
public constructor(provider?: SupportedProviders<EthExecutionAPI> | string) {
9798
const accountProvider = {
9899
create,
99100
privateKeyToAccount,
@@ -108,6 +109,8 @@ export class Web3 extends Web3Context<EthExecutionAPI> {
108109

109110
super({ provider, wallet, accountProvider });
110111

112+
this.utils = utils;
113+
111114
// Have to use local alias to initiate contract context
112115
// eslint-disable-next-line @typescript-eslint/no-this-alias
113116
const self = this;
@@ -146,8 +149,6 @@ export class Web3 extends Web3Context<EthExecutionAPI> {
146149
net: self.use(Net),
147150
personal: self.use(Personal),
148151

149-
utils,
150-
151152
// Contract helper and module
152153
Contract: ContractBuilder,
153154

0 commit comments

Comments
 (0)