Skip to content

Commit

Permalink
Update web3-eth-contract to use web3-eth methods (#4806)
Browse files Browse the repository at this point in the history
* Add @ethereumjs/tx dependency

* Update Web3BaseProvider to SupportedProviders for Web3Eth constructor

* WIP eth-tx

* Add support for undefined values for convertToValidType

* Remove unused Web3BaseProvider

* WIP eth-tx utils

* Export privateKeyToAddress

* Add web3-eth-accounts dependency

* WIP web3-eth-tx util methods

* Replace inline errors with error constructors

* Change types for transaction r and s properties. Correct hardforks in detectTransactionType

* Init formatTransaction tests and fixture

* Init detectTransactionType and fixture

* Add more descriptive error messages

* Logic fixes for validateTransactionForSigning

* Init validateTransactionForSigning tests and fixtures

* Add esModuleInterop: true to tsconfig

* Small bug fixes and added TODOs

* Add parent describe to detect_transaction_type test

* Add parent describe to format_transaction test

* Add web3-providers-http as dev dependency for tests

* Init populate_transaction tests

* Move types from eth_tx.ts to types.ts

* Remove TODOs

* Add missing ,

* Remove TODO

* Remove TODO

* Fix transaction type import issues

* Update convertToValidType test data for undefined

* Update override method tests

* Update packages/web3-eth/src/eth_tx.ts

Co-authored-by: jdevcs <86780488+jdevcs@users.noreply.github.com>

* Move getBlock to after type check for populateTransaction

* Replace N/A with name of error for error.msg

* Assign formattedTransaction type Transaction<ReturnType>

* convertToValidType now throws error for value === undefined

* NumberType extends Numbers

* Transaction type related changes

* Refactor DesiredType logic

* Convert to deep copy for formatTransaction method

* skip override method test - needs to be refactored. General formatting

* Skip override method test - needs to be refactored. Set input.type > 0x7f

* Refactor formatTransaction

* Add error codes to web3-eth errors

* Refactor validateGate if statements into readable consts

* Update comment

* Add link to error message from 1.x

* Fix bug with is gas consts in validateGas

* Init InvalidConvertibleValueError

* Replace error with InvalidConvertibleValueError

* Update tests for formatting undefined

* Update expected errors for validateGas tests

* No longer default tx.type if undefined

* Refactor detectTransactionType

* Fix type error for return in detectTransactionType

* Init rpc_method_wrappers.ts

* Remove Web3Eth import

* Refactor use of web3Context.defaults

* Restore Formatted transaction types

* Init web3_rpc_method_wrappers tests

* Refactor web3_eth_methods_with_parameters test

* Replace if X === undefined checks with ?

* Un-export consts that aren't used

* Add defaultTransactionType and defaultMaxPriorityFeePerGas

* Update defaults for chain and hardfork to mainnet and london

* Update to use web3Context.default chain and hardfork. Init tests for defaults

* Update test to account for added defaults

* Refactor validateGas to use helper methods

* remove TODO

* Init error TransactionGasMismatchError

* Fix tests and refactor transaction validator helper methods

* Move validation methods to validation.ts

* Add input to Transaction type

* Add @ethereumjs/common dependency

* yarn format

* Remove null for defaultTransactionType

* Add default for defaultTransactionType

* Update default for defaultTransactionType

* Bug fixes, refactors, and init prepareTransactionForSigning and tests

* Remove unused test code

* revert transaction data and value to default to 0x

* Fix failing populate_transaction tests

* Add defaultNetworkId to web3_config

* Add TODO for failing prepare_transaction_for_signing test

* Remove TODO

* Init TransactionDataAndInputError

* Add else if to populateTransaction - data

* Refactor populateTransaction - chainId

* Comment out unused ifs

* Remove populateTransaction - gas

* Remove populateTransaction - hexTxType

* Replace use of ValidReturnTypes[ValidTypes.HexString] with HexString

* Remove toHex import

* Remove | null for Web3ConfigOptions defaultChain and defaultHardfork

* Refactor getEthereumjsTransactionOptions

* Remove no longer needed populateTransaction - gas test

* Update packages/web3-eth/src/validation.ts

* Remove unnecessary rpc method wrappers

* Web3Eth now extends Web3Context instead of instantiating it

* Init getPendingTransactions

* Init requestAccounts

* Add EIP-1102 as a comment for requestAccounts

* Init getChainId

* Init getProof

* Init Web3EthExecutionAPI

* Fix imports for AccountObject in fixtures

* Add formatting to getPendingTransactions. Move formatTransaction to seperate file

* Add TODO to investigate transaction.data

* Add formatting to getChainId response

* Init getNodeInfo

* Revert esModuleInterop change

* Combine networkId and chainId if statements

* yarn format

* Add Partial to type of transaction for eth_sendTransaction

* Init transactionReceiptPollingInterval and transactionConfirmationPollingInterval

* Add TODO and Partial to transaction type for sendTransaction

* WIP sendTransaction and PromiEvent integration

* Add eslint-disable-next-line

* Add eslint-disable-next-line

* Move TransactionEvents

* eslint fixes

* Update sendSignedTransaction to use PromiEvent

* Init signTransaction

* Refactor TransactionCall

* Comment out validation for call

* Init TransactionCall type for web3-eth types

* Remove as BaseTransaction from isTransactionCall

* Implement call for rpc_method_wrappers

* Uncomment sendTransaction, signTransaction, and call

* ✨ Update estimate gas method to use web3-eth

* 🎨 Update contract mehtod send to use web3-eth utility functions

* 🎨 Update contract method call to use web3-eth utilities

* 🎨 Fix code introduced in merge conflicts

Co-authored-by: Wyatt Barnes <me@wyatt.email>
Co-authored-by: jdevcs <86780488+jdevcs@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 4, 2022
1 parent 39f8fd5 commit 568b4b2
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 193 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ Released with 1.0.0-beta.37 code base.
4. `recover` function's last param is boolean `hashed`, it is used to indicate if data provided is already hashed or not. By default this function will assume data is not hashed.
5. The `Wallet` no more supports address/number indexing. Have to use `wallet.get` instead.
6. `Wallet.create` function doesn't accepts `entropy` param
7. `contract.method.send()` will resolve to transaction receipt instead of `transactionHash`. User can use `receipt.transactionHash` instead.

#### web3-net

Expand All @@ -368,3 +369,4 @@ Released with 1.0.0-beta.37 code base.
2. `setContent` is not supported in web3-eth-ens 4.x as its deprecated in ENS public resolver (https://github.com/ensdomains/resolvers/blob/master/contracts/PublicResolver.sol)
3. `getContent` is not supported in web3-eth-ens 4.x as its deprecated in ENS public resolver.
4. `getMultihash` is not supported in web3-eth-ens 4.x as its deprecated in ENS public resolver.

12 changes: 12 additions & 0 deletions packages/web3-common/src/web3_event_emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,16 @@ export class Web3EventEmitter<T extends Web3EventMap> implements Web3Emitter<T>
public emit<K extends Web3EventKey<T>>(eventName: K, params: T[K]) {
this._emitter.emit(eventName, params);
}

public listenerCount<K extends Web3EventKey<T>>(eventName: K) {
return this._emitter.listenerCount(eventName);
}

public listeners<K extends Web3EventKey<T>>(eventName: K) {
return this._emitter.listeners(eventName);
}

public eventNames() {
return this._emitter.eventNames();
}
}
3 changes: 2 additions & 1 deletion packages/web3-eth-contract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"web3-core": "4.0.0-alpha.0",
"web3-eth-abi": "4.0.0-alpha.0",
"web3-utils": "4.0.0-alpha.1",
"web3-validator": "0.1.0-alpha.0"
"web3-validator": "0.1.0-alpha.0",
"web3-eth": "4.0.0-alpha.1"
},
"devDependencies": {
"@humeris/espresso-shot": "^4.0.0",
Expand Down
151 changes: 67 additions & 84 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import {
isAbiFunctionFragment,
jsonInterfaceMethodToString,
} from 'web3-eth-abi';
import { estimateGas, sendTransaction, call } from 'web3-eth/src/rpc_method_wrappers';
import {
Address,
BlockNumberOrTag,
BlockTags,
hexToNumber,
toChecksumAddress,
HexString,
toChecksumAddress,
ValidTypes,
} from 'web3-utils';
import { validator } from 'web3-validator';
import { decodeMethodReturn, encodeEventABI, encodeMethodABI } from './encoding';
Expand Down Expand Up @@ -164,47 +165,38 @@ export class Contract<Abi extends ContractAbi>

return {
arguments: args,
// TODO: Use `web3-eth-tx` package to return `PromiEvent` instead.
send: async (options?: PayableCallOptions) => {
const modifiedOptions = { ...options };
delete modifiedOptions.to;

const txHash = await this._contractMethodSend(
const promiEvent = this._contractMethodSend(
abi as AbiFunctionFragment,
args,
modifiedOptions,
contractOptions,
);

return txHash;

// TODO: Use eth-tx functions to
//
// 1. Get the transaction receipt from the above txHash
// 2. Extract the contract address from the receipt
// 3. Get the code from eth_getCode for the contract address
// 4. Return the contract instance with the new address and the code
//
// return new Contract<Abi>(this._jsonInterface, contractAddress as HexString, {
// gas: this.options.gas,
// gasPrice: this.options.gasPrice,
// gasLimit: this.options.gasLimit,
// from: this.options.from,
// data: this.options.data,
// provider: this.currentProvider,
// });
// eslint-disable-next-line no-void
void promiEvent.then(res => {
this._address = res.contractAddress;
});

return promiEvent;
},
estimateGas: async (options?: PayableCallOptions, block?: BlockNumberOrTag) => {
estimateGas: async <ReturnType extends ValidTypes = ValidTypes.HexString>(
options?: PayableCallOptions,
returnType?: ReturnType,
) => {
const modifiedOptions = { ...options };
delete modifiedOptions.to;

return this._contractMethodEstimateGas(
abi as AbiFunctionFragment,
args,
modifiedOptions,
block,
return this._contractMethodEstimateGas({
abi: abi as AbiFunctionFragment,
params: args,
returnType,
options: modifiedOptions,
contractOptions,
);
});
},
encodeABI: () => encodeMethodABI(abi as AbiFunctionFragment, args, data),
};
Expand Down Expand Up @@ -296,11 +288,12 @@ export class Contract<Abi extends ContractAbi>
arguments: params,
call: async (options?: PayableCallOptions, block?: BlockNumberOrTag) =>
this._contractMethodCall(abi, params, options, block),
// TODO: Use `web3-eth-tx` package to return `PromiEvent` instead.
send: async (options?: PayableCallOptions) =>
send: (options?: PayableCallOptions) =>
this._contractMethodSend(abi, params, options),
estimateGas: async (options?: PayableCallOptions, block?: BlockNumberOrTag) =>
this._contractMethodEstimateGas(abi, params, options, block),
estimateGas: async <ReturnType extends ValidTypes = ValidTypes.HexString>(
options?: PayableCallOptions,
returnType?: ReturnType,
) => this._contractMethodEstimateGas({ abi, params, returnType, options }),
encodeABI: () => encodeMethodABI(abi, params),
} as unknown as PayableMethodObject<
ContractMethod<T>['Inputs'],
Expand All @@ -312,10 +305,12 @@ export class Contract<Abi extends ContractAbi>
arguments: params,
call: async (options?: NonPayableCallOptions, block?: BlockNumberOrTag) =>
this._contractMethodCall(abi, params, options, block),
send: async (options?: NonPayableCallOptions) =>
send: (options?: NonPayableCallOptions) =>
this._contractMethodSend(abi, params, options),
estimateGas: async (options?: NonPayableCallOptions, block?: BlockNumberOrTag) =>
this._contractMethodEstimateGas(abi, params, options, block),
estimateGas: async <ReturnType extends ValidTypes = ValidTypes.HexString>(
options?: NonPayableCallOptions,
returnType?: ReturnType,
) => this._contractMethodEstimateGas({ abi, params, returnType, options }),
encodeABI: () => encodeMethodABI(abi, params),
} as unknown as NonPayableMethodObject<
ContractMethod<T>['Inputs'],
Expand All @@ -330,68 +325,56 @@ export class Contract<Abi extends ContractAbi>
options?: Options,
block?: BlockNumberOrTag,
) {
return decodeMethodReturn(
const tx = getEthTxCallParams({
abi,
await this.requestManager.send({
method: 'eth_call',
params: [
getEthTxCallParams({
abi,
params,
options,
contractOptions: this.options,
}),
block ?? BlockTags.LATEST,
],
}),
);
params,
options,
contractOptions: this.options,
});

return decodeMethodReturn(abi, await call(this, tx, block));
}

private async _contractMethodSend<Options extends PayableCallOptions | NonPayableCallOptions>(
private _contractMethodSend<Options extends PayableCallOptions | NonPayableCallOptions>(
abi: AbiFunctionFragment,
params: unknown[],
options?: Options,
contractOptions?: ContractOptions,
) {
return decodeMethodReturn(
const tx = getSendTxParams({
abi,
await this.requestManager.send({
method: 'eth_sendTransaction',
params: [
getSendTxParams({
abi,
params,
options,
contractOptions: contractOptions ?? this.options,
}),
],
}),
);
params,
options,
contractOptions: contractOptions ?? this.options,
});

return sendTransaction(this, tx);
}

private async _contractMethodEstimateGas<
Options extends PayableCallOptions | NonPayableCallOptions,
>(
abi: AbiFunctionFragment,
params: unknown[],
options?: Options,
block?: BlockNumberOrTag,
contractOptions?: ContractOptions,
) {
return hexToNumber(
await this.requestManager.send({
method: 'eth_estimateGas',
params: [
getEstimateGasParams({
abi,
params,
options,
contractOptions: contractOptions ?? this.options,
}),
block ?? BlockTags.LATEST,
],
}),
);
ReturnType extends ValidTypes = ValidTypes.HexString,
>({
abi,
params,
returnType,
options,
contractOptions,
}: {
abi: AbiFunctionFragment;
params: unknown[];
returnType?: ReturnType;
options?: Options;
contractOptions?: ContractOptions;
}) {
const tx = getEstimateGasParams({
abi,
params,
options,
contractOptions: contractOptions ?? this.options,
});

return estimateGas(this, tx, BlockTags.LATEST, returnType);
}

// eslint-disable-next-line class-methods-use-this
Expand Down
55 changes: 17 additions & 38 deletions packages/web3-eth-contract/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { EthExecutionAPI, PromiEvent, ReceiptInfo } from 'web3-common';
import { EthExecutionAPI, ReceiptInfo } from 'web3-common';
import { SupportedProviders } from 'web3-core';
import { ContractAbi } from 'web3-eth-abi';
import { Address, BlockNumberOrTag, Bytes, Filter, HexString, Numbers, Uint } from 'web3-utils';
import { sendTransaction } from 'web3-eth/src/rpc_method_wrappers';
import { Address, BlockNumberOrTag, Bytes, Filter, HexString, Uint, ValidTypes } from 'web3-utils';

export interface EventLog {
event: string;
Expand Down Expand Up @@ -43,14 +44,14 @@ export interface ContractInitOptions {
export type TransactionReceipt = ReceiptInfo;

export interface NonPayableCallOptions {
nonce?: Numbers;
chainId?: Numbers;
nonce?: HexString;
chainId?: HexString;
from?: Address;
to?: Address;
data?: HexString;
gas?: string;
maxPriorityFeePerGas?: Numbers;
maxFeePerGas?: Numbers;
maxPriorityFeePerGas?: HexString;
maxFeePerGas?: HexString;
gasPrice?: string;
}

Expand All @@ -61,43 +62,21 @@ export interface PayableCallOptions extends NonPayableCallOptions {
export interface NonPayableMethodObject<Inputs = unknown[], Outputs = unknown[]> {
arguments: Inputs;
call(tx?: NonPayableCallOptions, block?: BlockNumberOrTag): Promise<Outputs>;
send(tx?: NonPayableCallOptions): PromiEvent<
TransactionReceipt,
{
sending: object;
sent: object;
transactionHash: string;
receipt: TransactionReceipt;
confirmation: {
confirmations: number;
receipt: TransactionReceipt;
latestBlockHash: HexString;
};
error: Error;
}
>;
estimateGas(tx?: NonPayableCallOptions): Promise<number>;
send(tx?: NonPayableCallOptions): ReturnType<typeof sendTransaction>;
estimateGas<ReturnType extends ValidTypes = ValidTypes.HexString>(
options?: NonPayableCallOptions,
returnType?: ReturnType,
): Promise<ReturnType>;
encodeABI(): string;
}

export interface PayableMethodObject<Inputs = unknown[], Outputs = unknown[]> {
arguments: Inputs;
call(tx?: PayableCallOptions, block?: BlockNumberOrTag): Promise<Outputs>;
send(tx?: PayableCallOptions): PromiEvent<
TransactionReceipt,
{
sending: object;
sent: object;
transactionHash: string;
receipt: TransactionReceipt;
confirmation: {
confirmations: number;
receipt: TransactionReceipt;
latestBlockHash: HexString;
};
error: Error;
}
>;
estimateGas(tx?: PayableCallOptions): Promise<number>;
send(tx?: PayableCallOptions): ReturnType<typeof sendTransaction>;
estimateGas<ReturnType extends ValidTypes = ValidTypes.HexString>(
options?: PayableCallOptions,
returnType?: ReturnType,
): Promise<ReturnType>;
encodeABI(): HexString;
}
9 changes: 5 additions & 4 deletions packages/web3-eth-contract/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TransactionCall, TransactionWithSender } from 'web3-common';
import { TransactionWithSender } from 'web3-common';
import { AbiFunctionFragment } from 'web3-eth-abi';
import { mergeDeep } from 'web3-utils';
import { TransactionCall } from 'web3-eth/src/types';
import { encodeMethodABI } from './encoding';
import { Web3ContractError } from './errors';
import { NonPayableCallOptions, PayableCallOptions, ContractOptions } from './types';
Expand All @@ -15,7 +16,7 @@ export const getSendTxParams = ({
params: unknown[];
options?: PayableCallOptions | NonPayableCallOptions;
contractOptions: ContractOptions;
}): TransactionWithSender & { data: string } => {
}): TransactionCall => {
if (!options?.to && !contractOptions.address) {
throw new Web3ContractError('Contract address not specified');
}
Expand All @@ -33,7 +34,7 @@ export const getSendTxParams = ({
data: contractOptions.data,
},
options as unknown as Record<string, unknown>,
) as unknown as TransactionWithSender & { data: string };
) as unknown as TransactionCall;

if (!txParams.data) {
txParams = {
Expand Down Expand Up @@ -114,5 +115,5 @@ export const getEstimateGasParams = ({
};
}

return txParams;
return txParams as TransactionWithSender;
};
Loading

0 comments on commit 568b4b2

Please sign in to comment.