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

Commit 75f4b3e

Browse files
spacesailor24avkosmpetrunicMuhammad-Altabbajdevcs
authored
Release/4.0.1 alpha.2 merge conflicts (#5692)
* Update CHANGELOG version headers * Contract call with tuple is missing param names (#5613) * call special output type * fix * fix: enable outputs to have param names (#5624) * hot fix * add type if only one param * overloaded inputs types * fix resolver tests * add type tests * simplify types * revert registry unit test * test firefox * revert firefox test * update changelogs Co-authored-by: Marin Petrunić <[email protected]> * Fix `isHex` and `isHexStrict` for some edge cases and enrich their tests (#5655) * Change `isHex` to return true for negative numbers (for example `-123`) * Change both `isHex` and `isHexStrict` to return `false` for `-0x` * Change `isHex` to return `false` for empty strings ''. * Remove erroneous set provider code for Contract constructor (#5669) * Remove erroneous set provider code for Contract constructor. Add Contract constructor provider set test * Update CHANGELOGs * Debugging failing integration tests * Apply suggestions from code review * Use getSystemTestProvider instead of hardcoded string * Refactor ternaries in Contract constructor to if statements * Correct CHANGELOG entries * Remove unneeded checks in if statements * Test with injected external providers (#5652) * fix: sending tx with injected provider (#5651) Co-authored-by: Marin Petrunic <[email protected]> * adding a test for using `ganache` provider * enable the jsonrpc `id` to optionally be incremented starting from a number (Inspired by: #5373 (comment) and needed as a work around for blockchainsllc/in3#46) * test with `in3` as a provider & skip `in3` test if it takes too long * increase integration test timeout at web3 package * add a test for using `hardhat` provider * improve how legacy providers, such as hardhat, is used * implement `isPromise` that works in the browsers * refactor external providers tests * update CHANGELOG.md * Use Error ABI to parse errors when sending a transaction (#5662) * use Error ABI when sending a transaction * update CHANGELOG.md for #5587 * Remove merge conflict marker Co-authored-by: Oleksii Kosynskyi <[email protected]> Co-authored-by: Marin Petrunić <[email protected]> Co-authored-by: Muhammad Altabba <[email protected]> Co-authored-by: jdevcs <[email protected]>
1 parent 09da7b4 commit 75f4b3e

File tree

36 files changed

+1749
-198
lines changed

36 files changed

+1749
-198
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ tsconfig.tsbuildinfo
3636
package-lock.json
3737

3838
tmp/
39+
40+
# Incubed (in3) nodelist
41+
packages/web3/.in3/

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,20 +895,32 @@ should use 4.0.1-alpha.0 for testing.
895895

896896
### Added
897897

898+
#### web3-eth-contract
899+
900+
- Decoding error data, using Error ABI if available, if error was returned from a smart contract function call (#5662).
901+
898902
#### web3-types
899903

900904
- These types were moved from `web3-eth-accounts` to `web3-types` package: Cipher, CipherOptions, ScryptParams, PBKDF2SHA256Params, KeyStore (#5581 )
901905

902906
#### web3-utils
903907

904908
- Export a new function `uuidV4` that generates a random v4 Uuid (#5373).
909+
- Enable passing a starting number, to increment based on it, for the Json Rpc Request `id` (#5652).
910+
- Export a new function `isPromise` that checks if an object is a promise (#5652).
911+
912+
#### web3-eth-contract
913+
914+
- `SpecialOutput` type was added as a generic type into the call function to support reassigning output types (#5631)
915+
- Overloaded functions types (`ContractOverloadedMethodInputs`, `ContractOverloadedMethodOutputs`) was added (#5631)
905916

906917
### Fixed
907918

908919
#### web3-eth-contract
909920

910921
- Emit past contract events based on `fromBlock` when passed to `contract.events.someEventName` (#5201)
911922
- Use different types for `ContractOptions` -> `jsonInterface` setter and getter (#5474)
923+
- An issue within the `Contract` constructor where `provider` wasn't being set when provided within the `optionsOrContextOrReturnFormat` argument (#5669)
912924

913925
#### web3-types
914926

@@ -918,6 +930,14 @@ should use 4.0.1-alpha.0 for testing.
918930

919931
- Use Uuid for the response id, to fix the issue "Responses get mixed up due to conflicting payload IDs" (#5373).
920932

933+
#### web3-validator
934+
935+
- Fix `isHex`returning `false` for `-123`, fix `isHexStrict` returning `true` for `-0x`, and fix `isHex` returning `true` for empty strings `` (#5373).
936+
937+
#### web3-eth-abi
938+
939+
- Fix ContractMethodOutputParameters type to support output object types by index and string key. Also, it returns void if ABI doesn't have outputs and returns exactly one type if the output array has only one element. (#5631)
940+
921941
### Removed
922942

923943
#### web3-eth-accounts

docs/docs/guides/web3_migration_guide/web3_utils_migration_guide.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,37 @@ web3.utils.toWei('0.1');
2828
// 4.x
2929
web3.utils.toWei('0.1', 'ether');
3030
```
31+
32+
## Validation functions
33+
34+
Validation functions has been moved to the new package `web3-validator`. Actually, you can still import them from `web3-util`. But they are marked as "deprecated" and you are encouraged to import them from `web3-validator`.
35+
36+
However, there are changes for the following:
37+
38+
### `isHex` and `isHexStrict` validation functions
39+
40+
There is a fix, and some edge-cases-changes for those 2 functions but the overall functionality stayed the same. And here is exactly whet changed:
41+
42+
#### `isHex` now returns `true` for all negative numbers
43+
44+
```ts
45+
isHex('-123'); // in 1.x used to return `false`. But changed in 4.x to return `true`
46+
// `true`
47+
```
48+
49+
#### `isHex` now returns `false` for an empty string
50+
51+
```ts
52+
isHex(''); // in 1.x used to return `true`. But changed in 4.x to return `false`
53+
// `false`
54+
```
55+
56+
#### `isHex` and `isHexStrict` now returns `false` for `'-0x'`
57+
58+
```ts
59+
isHex('-0x'); // in 1.x used to return `true`. But changed in 4.x to return `false`
60+
// `false`
61+
62+
isHexStrict('-0x'); // in 1.x used to return `true`. But changed in 4.x to return `false`
63+
// `false`
64+
```

packages/web3-core/src/utils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ export const isEIP1193Provider = <API extends Web3APISpec>(
4141
): provider is EIP1193Provider<API> =>
4242
typeof provider !== 'string' &&
4343
'request' in provider &&
44-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
45-
(provider.request as any)[Symbol.toStringTag] === 'AsyncFunction';
44+
provider.request.constructor.name === 'AsyncFunction';
4645

4746
export const isLegacySendProvider = <API extends Web3APISpec>(
4847
provider: SupportedProviders<API>,

packages/web3-core/src/web3_request_manager.ts

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717

1818
import { Socket } from 'net';
19+
1920
import {
2021
ContractExecutionError,
2122
InvalidResponseError,
@@ -42,7 +43,7 @@ import {
4243
Web3BaseProvider,
4344
Web3BaseProviderConstructor,
4445
} from 'web3-types';
45-
import { isNullish, jsonRpc } from 'web3-utils';
46+
import { isNullish, isPromise, jsonRpc } from 'web3-utils';
4647
import {
4748
isEIP1193Provider,
4849
isLegacyRequestProvider,
@@ -200,34 +201,55 @@ export class Web3RequestManager<
200201
);
201202
}
202203

203-
// TODO: This should be deprecated and removed.
204+
// TODO: This could be deprecated and removed.
204205
if (isLegacyRequestProvider(provider)) {
205-
return new Promise<JsonRpcResponse<ResponseType>>((resolve, reject): void => {
206-
provider.request<ResponseType>(payload, (err, response) => {
207-
if (err) {
208-
return reject(
209-
this._processJsonRpcResponse(
210-
payload,
211-
err as unknown as JsonRpcResponse<ResponseType>,
212-
{
213-
legacy: true,
214-
error: true,
215-
},
216-
),
217-
);
218-
}
219-
220-
return resolve(
206+
return new Promise<JsonRpcResponse<ResponseType>>((resolve, reject) => {
207+
const rejectWithError = (err: unknown) =>
208+
reject(
209+
this._processJsonRpcResponse(
210+
payload,
211+
err as JsonRpcResponse<ResponseType>,
212+
{
213+
legacy: true,
214+
error: true,
215+
},
216+
),
217+
);
218+
const resolveWithResponse = (response: JsonRpcResponse<ResponseType>) =>
219+
resolve(
221220
this._processJsonRpcResponse(payload, response, {
222221
legacy: true,
223222
error: false,
224223
}),
225224
);
226-
});
225+
const result = provider.request<ResponseType>(
226+
payload,
227+
// a callback that is expected to be called after getting the response:
228+
(err, response) => {
229+
if (err) {
230+
return rejectWithError(err);
231+
}
232+
233+
return resolveWithResponse(response);
234+
},
235+
);
236+
// Some providers, that follow a previous drafted version of EIP1193, has a `request` function
237+
// that is not defined as `async`, but it returns a promise.
238+
// Such providers would not be picked with if(isEIP1193Provider(provider)) above
239+
// because the `request` function was not defined with `async` and so the function definition is not `AsyncFunction`.
240+
// Like this provider: https://github.dev/NomicFoundation/hardhat/blob/62bea2600785595ba36f2105564076cf5cdf0fd8/packages/hardhat-core/src/internal/core/providers/backwards-compatibility.ts#L19
241+
// So check if the returned result is a Promise, and resolve with it accordingly.
242+
// Note: in this case we expect the callback provided above to never be called.
243+
if (isPromise(result)) {
244+
const responsePromise = result as unknown as Promise<
245+
JsonRpcResponse<ResponseType>
246+
>;
247+
responsePromise.then(resolveWithResponse).catch(rejectWithError);
248+
}
227249
});
228250
}
229251

230-
// TODO: This should be deprecated and removed.
252+
// TODO: This could be deprecated and removed.
231253
if (isLegacySendProvider(provider)) {
232254
return new Promise<JsonRpcResponse<ResponseType>>((resolve, reject): void => {
233255
provider.send<ResponseType>(payload, (err, response) => {
@@ -261,7 +283,7 @@ export class Web3RequestManager<
261283
});
262284
}
263285

264-
// TODO: This should be deprecated and removed.
286+
// TODO: This could be deprecated and removed.
265287
if (isLegacySendAsyncProvider(provider)) {
266288
return provider
267289
.sendAsync<ResponseType>(payload)

packages/web3-eth-abi/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5353
- Updated Web3.js dependencies (#5664)
5454

5555
## [Unreleased]
56+
57+
### Fixed
58+
59+
- Fix ContractMethodOutputParameters type to support output object types by index and string key. Also, it returns void if ABI doesn't have outputs and returns exactly one type if the output array has only one element. (5631)

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

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ export type PrimitiveTupleType<
173173
: never
174174
: never;
175175

176+
type ObjectToArray<T extends unknown[]> = T extends [...infer R, infer A]
177+
? Record<R['length'], A> & ObjectToArray<R>
178+
: T;
179+
type ArrToObjectWithFunctions<T extends unknown[]> = Array<unknown> & ObjectToArray<T>;
180+
176181
export type MatchPrimitiveType<
177182
Type extends string,
178183
Components extends ReadonlyArray<AbiParameter> | undefined,
@@ -185,18 +190,52 @@ export type MatchPrimitiveType<
185190
| PrimitiveTupleType<Type, Components>
186191
| never;
187192

188-
export type ContractMethodOutputParameters<Params extends ReadonlyArray<unknown> | undefined> =
193+
type ContractMethodOutputParametersRecursiveArray<
194+
Params extends ReadonlyArray<unknown> | undefined,
195+
> =
196+
// check if params are empty array
189197
Params extends readonly []
190198
? []
191-
: Params extends readonly [infer H, ...infer R]
199+
: Params extends readonly [infer H, ...infer R] // check if Params is an array
192200
? H extends AbiParameter
193-
? // TODO: Find a way to set name for tuple item
194-
[MatchPrimitiveType<H['type'], H['components']>, ...ContractMethodOutputParameters<R>]
195-
: ContractMethodOutputParameters<R>
196-
: Params extends undefined | unknown
201+
? [
202+
MatchPrimitiveType<H['type'], H['components']>,
203+
...ContractMethodOutputParametersRecursiveArray<R>,
204+
]
205+
: []
206+
: [];
207+
208+
type ContractMethodOutputParametersRecursiveRecord<
209+
Params extends ReadonlyArray<unknown> | undefined,
210+
> =
211+
// check if params are empty array
212+
Params extends readonly []
213+
? []
214+
: Params extends readonly [infer H, ...infer R] // check if Params is an array
215+
? H extends AbiParameter
216+
? H['name'] extends '' // check if output param name is empty string
217+
? ContractMethodOutputParametersRecursiveRecord<R>
218+
: Record<H['name'], MatchPrimitiveType<H['type'], H['components']>> & // sets key-value pair of output param name and type
219+
ContractMethodOutputParametersRecursiveRecord<R>
220+
: ContractMethodOutputParametersRecursiveRecord<R>
221+
: Params extends undefined | unknown // param is not array, check if undefined
197222
? []
198223
: Params;
199224

225+
export type ContractMethodOutputParameters<Params extends ReadonlyArray<unknown> | undefined> =
226+
// check if params are empty array
227+
Params extends readonly []
228+
? void
229+
: Params extends readonly [infer H, ...infer R] // check if Params is an array
230+
? R extends readonly [] // if only one output in array
231+
? H extends AbiParameter
232+
? MatchPrimitiveType<H['type'], H['components']>
233+
: []
234+
: // if more than one output
235+
ArrToObjectWithFunctions<[...ContractMethodOutputParametersRecursiveArray<Params>]> &
236+
ContractMethodOutputParametersRecursiveRecord<Params>
237+
: [];
238+
200239
export type ContractMethodInputParameters<Params extends ReadonlyArray<unknown> | undefined> =
201240
Params extends readonly []
202241
? []

packages/web3-eth-abi/test/unit/types.test.ts

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
1717

1818
import { Address, Bytes, Numbers } from 'web3-types';
1919
import { expectTypeOf, typecheck } from '@humeris/espresso-shot';
20-
import { MatchPrimitiveType } from '../../src/types';
20+
import { ContractMethodOutputParameters, MatchPrimitiveType } from '../../src';
2121

2222
describe('types', () => {
2323
describe('primitive types', () => {
@@ -157,4 +157,101 @@ describe('types', () => {
157157
);
158158
});
159159
});
160+
161+
describe('contract', () => {
162+
describe('outputs', () => {
163+
typecheck('empty outputs should result in []', () =>
164+
expectTypeOf<ContractMethodOutputParameters<[]>>().toExtend<void>(),
165+
);
166+
167+
typecheck('single outputs should result in that type', () => {
168+
const abi = [
169+
{
170+
name: '',
171+
type: 'string',
172+
},
173+
] as const;
174+
return expectTypeOf<
175+
ContractMethodOutputParameters<typeof abi>
176+
>().toExtend<string>();
177+
});
178+
179+
typecheck('multiple outputs should result in object indexed by numbers', () => {
180+
const abi = [
181+
{
182+
name: '',
183+
type: 'string',
184+
},
185+
{
186+
name: '',
187+
type: 'int',
188+
},
189+
] as const;
190+
191+
return expectTypeOf<
192+
ContractMethodOutputParameters<typeof abi>[0]
193+
>().toExtend<string>();
194+
});
195+
196+
typecheck('multiple outputs should result in object indexed by numbers', () => {
197+
const abi = [
198+
{
199+
name: '',
200+
type: 'string',
201+
},
202+
{
203+
name: '',
204+
type: 'int',
205+
},
206+
] as const;
207+
return expectTypeOf<
208+
ContractMethodOutputParameters<typeof abi>[1]
209+
>().toExtend<Numbers>();
210+
});
211+
212+
typecheck('multiple outputs should result in object indexed by name', () => {
213+
const abi = [
214+
{
215+
name: 'first',
216+
type: 'string',
217+
},
218+
{
219+
name: 'second',
220+
type: 'int',
221+
},
222+
] as const;
223+
return expectTypeOf<
224+
ContractMethodOutputParameters<typeof abi>['first']
225+
>().toExtend<string>();
226+
});
227+
228+
typecheck('multiple outputs should result in object indexed by name', () => {
229+
const abi = [
230+
{
231+
name: 'first',
232+
type: 'string',
233+
},
234+
{
235+
name: 'second',
236+
type: 'int',
237+
},
238+
] as const;
239+
return expectTypeOf<
240+
ContractMethodOutputParameters<typeof abi>['second']
241+
>().toExtend<Numbers>();
242+
});
243+
244+
typecheck('single output should result as in exactly one type', () => {
245+
const abi = [
246+
{
247+
name: 'first',
248+
type: 'string',
249+
},
250+
] as const;
251+
return expectTypeOf<
252+
ContractMethodOutputParameters<typeof abi>
253+
>().toExtend<string>();
254+
});
255+
});
256+
});
160257
});

0 commit comments

Comments
 (0)