Skip to content

Commit

Permalink
Release/4.0.1 alpha.2 merge conflicts (#5692)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
5 people authored Dec 8, 2022
1 parent 09da7b4 commit 75f4b3e
Show file tree
Hide file tree
Showing 36 changed files with 1,749 additions and 198 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ tsconfig.tsbuildinfo
package-lock.json

tmp/

# Incubed (in3) nodelist
packages/web3/.in3/
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -895,20 +895,32 @@ should use 4.0.1-alpha.0 for testing.

### Added

#### web3-eth-contract

- Decoding error data, using Error ABI if available, if error was returned from a smart contract function call (#5662).

#### web3-types

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

#### web3-utils

- Export a new function `uuidV4` that generates a random v4 Uuid (#5373).
- Enable passing a starting number, to increment based on it, for the Json Rpc Request `id` (#5652).
- Export a new function `isPromise` that checks if an object is a promise (#5652).

#### web3-eth-contract

- `SpecialOutput` type was added as a generic type into the call function to support reassigning output types (#5631)
- Overloaded functions types (`ContractOverloadedMethodInputs`, `ContractOverloadedMethodOutputs`) was added (#5631)

### Fixed

#### web3-eth-contract

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

#### web3-types

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

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

#### web3-validator

- Fix `isHex`returning `false` for `-123`, fix `isHexStrict` returning `true` for `-0x`, and fix `isHex` returning `true` for empty strings `` (#5373).

#### web3-eth-abi

- 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)

### Removed

#### web3-eth-accounts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,37 @@ web3.utils.toWei('0.1');
// 4.x
web3.utils.toWei('0.1', 'ether');
```

## Validation functions

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`.

However, there are changes for the following:

### `isHex` and `isHexStrict` validation functions

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:

#### `isHex` now returns `true` for all negative numbers

```ts
isHex('-123'); // in 1.x used to return `false`. But changed in 4.x to return `true`
// `true`
```

#### `isHex` now returns `false` for an empty string

```ts
isHex(''); // in 1.x used to return `true`. But changed in 4.x to return `false`
// `false`
```

#### `isHex` and `isHexStrict` now returns `false` for `'-0x'`

```ts
isHex('-0x'); // in 1.x used to return `true`. But changed in 4.x to return `false`
// `false`

isHexStrict('-0x'); // in 1.x used to return `true`. But changed in 4.x to return `false`
// `false`
```
3 changes: 1 addition & 2 deletions packages/web3-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ export const isEIP1193Provider = <API extends Web3APISpec>(
): provider is EIP1193Provider<API> =>
typeof provider !== 'string' &&
'request' in provider &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(provider.request as any)[Symbol.toStringTag] === 'AsyncFunction';
provider.request.constructor.name === 'AsyncFunction';

export const isLegacySendProvider = <API extends Web3APISpec>(
provider: SupportedProviders<API>,
Expand Down
64 changes: 43 additions & 21 deletions packages/web3-core/src/web3_request_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

import { Socket } from 'net';

import {
ContractExecutionError,
InvalidResponseError,
Expand All @@ -42,7 +43,7 @@ import {
Web3BaseProvider,
Web3BaseProviderConstructor,
} from 'web3-types';
import { isNullish, jsonRpc } from 'web3-utils';
import { isNullish, isPromise, jsonRpc } from 'web3-utils';
import {
isEIP1193Provider,
isLegacyRequestProvider,
Expand Down Expand Up @@ -200,34 +201,55 @@ export class Web3RequestManager<
);
}

// TODO: This should be deprecated and removed.
// TODO: This could be deprecated and removed.
if (isLegacyRequestProvider(provider)) {
return new Promise<JsonRpcResponse<ResponseType>>((resolve, reject): void => {
provider.request<ResponseType>(payload, (err, response) => {
if (err) {
return reject(
this._processJsonRpcResponse(
payload,
err as unknown as JsonRpcResponse<ResponseType>,
{
legacy: true,
error: true,
},
),
);
}

return resolve(
return new Promise<JsonRpcResponse<ResponseType>>((resolve, reject) => {
const rejectWithError = (err: unknown) =>
reject(
this._processJsonRpcResponse(
payload,
err as JsonRpcResponse<ResponseType>,
{
legacy: true,
error: true,
},
),
);
const resolveWithResponse = (response: JsonRpcResponse<ResponseType>) =>
resolve(
this._processJsonRpcResponse(payload, response, {
legacy: true,
error: false,
}),
);
});
const result = provider.request<ResponseType>(
payload,
// a callback that is expected to be called after getting the response:
(err, response) => {
if (err) {
return rejectWithError(err);
}

return resolveWithResponse(response);
},
);
// Some providers, that follow a previous drafted version of EIP1193, has a `request` function
// that is not defined as `async`, but it returns a promise.
// Such providers would not be picked with if(isEIP1193Provider(provider)) above
// because the `request` function was not defined with `async` and so the function definition is not `AsyncFunction`.
// Like this provider: https://github.dev/NomicFoundation/hardhat/blob/62bea2600785595ba36f2105564076cf5cdf0fd8/packages/hardhat-core/src/internal/core/providers/backwards-compatibility.ts#L19
// So check if the returned result is a Promise, and resolve with it accordingly.
// Note: in this case we expect the callback provided above to never be called.
if (isPromise(result)) {
const responsePromise = result as unknown as Promise<
JsonRpcResponse<ResponseType>
>;
responsePromise.then(resolveWithResponse).catch(rejectWithError);
}
});
}

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

// TODO: This should be deprecated and removed.
// TODO: This could be deprecated and removed.
if (isLegacySendAsyncProvider(provider)) {
return provider
.sendAsync<ResponseType>(payload)
Expand Down
4 changes: 4 additions & 0 deletions packages/web3-eth-abi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated Web3.js dependencies (#5664)

## [Unreleased]

### Fixed

- 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)
51 changes: 45 additions & 6 deletions packages/web3-eth-abi/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ export type PrimitiveTupleType<
: never
: never;

type ObjectToArray<T extends unknown[]> = T extends [...infer R, infer A]
? Record<R['length'], A> & ObjectToArray<R>
: T;
type ArrToObjectWithFunctions<T extends unknown[]> = Array<unknown> & ObjectToArray<T>;

export type MatchPrimitiveType<
Type extends string,
Components extends ReadonlyArray<AbiParameter> | undefined,
Expand All @@ -185,18 +190,52 @@ export type MatchPrimitiveType<
| PrimitiveTupleType<Type, Components>
| never;

export type ContractMethodOutputParameters<Params extends ReadonlyArray<unknown> | undefined> =
type ContractMethodOutputParametersRecursiveArray<
Params extends ReadonlyArray<unknown> | undefined,
> =
// check if params are empty array
Params extends readonly []
? []
: Params extends readonly [infer H, ...infer R]
: Params extends readonly [infer H, ...infer R] // check if Params is an array
? H extends AbiParameter
? // TODO: Find a way to set name for tuple item
[MatchPrimitiveType<H['type'], H['components']>, ...ContractMethodOutputParameters<R>]
: ContractMethodOutputParameters<R>
: Params extends undefined | unknown
? [
MatchPrimitiveType<H['type'], H['components']>,
...ContractMethodOutputParametersRecursiveArray<R>,
]
: []
: [];

type ContractMethodOutputParametersRecursiveRecord<
Params extends ReadonlyArray<unknown> | undefined,
> =
// check if params are empty array
Params extends readonly []
? []
: Params extends readonly [infer H, ...infer R] // check if Params is an array
? H extends AbiParameter
? H['name'] extends '' // check if output param name is empty string
? ContractMethodOutputParametersRecursiveRecord<R>
: Record<H['name'], MatchPrimitiveType<H['type'], H['components']>> & // sets key-value pair of output param name and type
ContractMethodOutputParametersRecursiveRecord<R>
: ContractMethodOutputParametersRecursiveRecord<R>
: Params extends undefined | unknown // param is not array, check if undefined
? []
: Params;

export type ContractMethodOutputParameters<Params extends ReadonlyArray<unknown> | undefined> =
// check if params are empty array
Params extends readonly []
? void
: Params extends readonly [infer H, ...infer R] // check if Params is an array
? R extends readonly [] // if only one output in array
? H extends AbiParameter
? MatchPrimitiveType<H['type'], H['components']>
: []
: // if more than one output
ArrToObjectWithFunctions<[...ContractMethodOutputParametersRecursiveArray<Params>]> &
ContractMethodOutputParametersRecursiveRecord<Params>
: [];

export type ContractMethodInputParameters<Params extends ReadonlyArray<unknown> | undefined> =
Params extends readonly []
? []
Expand Down
99 changes: 98 additions & 1 deletion packages/web3-eth-abi/test/unit/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.

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

describe('types', () => {
describe('primitive types', () => {
Expand Down Expand Up @@ -157,4 +157,101 @@ describe('types', () => {
);
});
});

describe('contract', () => {
describe('outputs', () => {
typecheck('empty outputs should result in []', () =>
expectTypeOf<ContractMethodOutputParameters<[]>>().toExtend<void>(),
);

typecheck('single outputs should result in that type', () => {
const abi = [
{
name: '',
type: 'string',
},
] as const;
return expectTypeOf<
ContractMethodOutputParameters<typeof abi>
>().toExtend<string>();
});

typecheck('multiple outputs should result in object indexed by numbers', () => {
const abi = [
{
name: '',
type: 'string',
},
{
name: '',
type: 'int',
},
] as const;

return expectTypeOf<
ContractMethodOutputParameters<typeof abi>[0]
>().toExtend<string>();
});

typecheck('multiple outputs should result in object indexed by numbers', () => {
const abi = [
{
name: '',
type: 'string',
},
{
name: '',
type: 'int',
},
] as const;
return expectTypeOf<
ContractMethodOutputParameters<typeof abi>[1]
>().toExtend<Numbers>();
});

typecheck('multiple outputs should result in object indexed by name', () => {
const abi = [
{
name: 'first',
type: 'string',
},
{
name: 'second',
type: 'int',
},
] as const;
return expectTypeOf<
ContractMethodOutputParameters<typeof abi>['first']
>().toExtend<string>();
});

typecheck('multiple outputs should result in object indexed by name', () => {
const abi = [
{
name: 'first',
type: 'string',
},
{
name: 'second',
type: 'int',
},
] as const;
return expectTypeOf<
ContractMethodOutputParameters<typeof abi>['second']
>().toExtend<Numbers>();
});

typecheck('single output should result as in exactly one type', () => {
const abi = [
{
name: 'first',
type: 'string',
},
] as const;
return expectTypeOf<
ContractMethodOutputParameters<typeof abi>
>().toExtend<string>();
});
});
});
});
Loading

0 comments on commit 75f4b3e

Please sign in to comment.