Skip to content

Commit

Permalink
transaction integration tests (#6071)
Browse files Browse the repository at this point in the history
* transactions test data

* transactions integration test

* bug fix 6063

* changelog update

* fillGasPrice option param and test fixes

* tx tests fix

* fixed acct tests

* fixed gas estimation error before signing in tests

* updated test for type

* updated tx type in tests

* additional test with flag

* updated prepareTransactionForSigning , defaultTransactionBuilder and tests

* changelog update

* update change log
  • Loading branch information
jdevcs committed May 25, 2023
1 parent fe959a1 commit 210455a
Show file tree
Hide file tree
Showing 10 changed files with 5,486 additions and 30 deletions.
1 change: 1 addition & 0 deletions packages/web3-core/src/web3_context.ts
Expand Up @@ -374,6 +374,7 @@ export type TransactionBuilder<API extends Web3APISpec = unknown> = <
transaction: Transaction;
web3Context: Web3Context<API>;
privateKey?: HexString | Uint8Array;
fillGasPrice?: boolean;
}) => Promise<ReturnType>;

/**
Expand Down
5 changes: 5 additions & 0 deletions packages/web3-eth/CHANGELOG.md
Expand Up @@ -126,9 +126,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- Fixed `ignoreGasPricing` bug with wallet in context (#6071)

### Changed

- `formatTransaction` no longer throws a `TransactionDataAndInputError` if it's passed a transaction object with both `data` and `input` properties set (as long as they are the same value) (#6064)
- Refactored documentation for `rpc_method_wrappers` to point to the previously duplicated documentation found under the `Web3Eth` class documentation (#6054)
- Replaced Buffer for Uint8Array (#6004)
- Refactored `defaultTransactionTypeParser` to return correct EIP-2718 types, prior implementation was prioritizing `transaction.hardfork` and ignoring the use of `transaction.gasLimit`. `defaultTransactionTypeParser` will now throw `InvalidPropertiesForTransactionTypeError`s for properties are used that are incompatible with `transaction.type` (#6102)
- `prepareTransactionForSigning` and `defaultTransactionBuilder` now accepts optional `fillGasPrice` flag and by default will not fill gas(#6071)
Expand Up @@ -124,11 +124,13 @@ export const prepareTransactionForSigning = async (
transaction: Transaction,
web3Context: Web3Context<EthExecutionAPI>,
privateKey?: HexString | Uint8Array,
fillGasPrice = false,
) => {
const populatedTransaction = (await transactionBuilder({
transaction,
web3Context,
privateKey,
fillGasPrice,
})) as unknown as PopulatedUnsignedTransaction;

const formattedTransaction = formatTransaction(
Expand Down
35 changes: 20 additions & 15 deletions packages/web3-eth/src/utils/transaction_builder.ts
Expand Up @@ -49,10 +49,10 @@ import { NUMBER_DATA_FORMAT } from '../constants';
// eslint-disable-next-line import/no-cycle
import { getChainId, getTransactionCount } from '../rpc_method_wrappers';
import { detectTransactionType } from './detect_transaction_type';
// eslint-disable-next-line import/no-cycle
import { getTransactionGasPricing } from './get_transaction_gas_pricing';
import { transactionSchema } from '../schemas';
import { InternalTransaction } from '../types';
// eslint-disable-next-line import/no-cycle
import { getTransactionGasPricing } from './get_transaction_gas_pricing';

export const getTransactionFromOrToAttr = (
attr: 'from' | 'to',
Expand Down Expand Up @@ -128,6 +128,7 @@ export async function defaultTransactionBuilder<ReturnType = Transaction>(option
transaction: Transaction;
web3Context: Web3Context<EthExecutionAPI & Web3NetAPI>;
privateKey?: HexString | Uint8Array;
fillGasPrice?: boolean;
}): Promise<ReturnType> {
// let populatedTransaction = { ...options.transaction } as unknown as InternalTransaction;
let populatedTransaction = format(
Expand Down Expand Up @@ -228,24 +229,28 @@ export async function defaultTransactionBuilder<ReturnType = Transaction>(option
populatedTransaction.accessList = [];
}

populatedTransaction = {
...populatedTransaction,
...(await getTransactionGasPricing(
populatedTransaction,
options.web3Context,
ETH_DATA_FORMAT,
)),
};
if (options.fillGasPrice)
populatedTransaction = {
...populatedTransaction,
...(await getTransactionGasPricing(
populatedTransaction,
options.web3Context,
ETH_DATA_FORMAT,
)),
};

return populatedTransaction as ReturnType;
}

export const transactionBuilder = async <ReturnType = Transaction>(options: {
transaction: Transaction;
web3Context: Web3Context<EthExecutionAPI>;
privateKey?: HexString | Uint8Array;
export const transactionBuilder = async <ReturnType = Transaction>(
options: {
transaction: Transaction;
web3Context: Web3Context<EthExecutionAPI>;
privateKey?: HexString | Uint8Array;
fillGasPrice?: boolean;
},
// eslint-disable-next-line @typescript-eslint/require-await
}) =>
) =>
(options.web3Context.transactionBuilder ?? defaultTransactionBuilder)({
...options,
transaction: options.transaction,
Expand Down
57 changes: 53 additions & 4 deletions packages/web3-eth/test/unit/default_transaction_builder.test.ts
Expand Up @@ -134,6 +134,7 @@ describe('defaultTransactionBuilder', () => {
// VALID_ETH_BASE_TYPES.HexString,
// '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709',
// overrideFunction,
fillGasPrice: true,
});
expect(overrideFunction).toHaveBeenCalledWith(input);
});
Expand All @@ -149,6 +150,7 @@ describe('defaultTransactionBuilder', () => {
transaction: input,
web3Context,
privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709',
fillGasPrice: true,
});
expect(result.from).toBe(expectedFrom);
});
Expand All @@ -169,6 +171,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.from).toBe(expectedFrom);
});
Expand All @@ -183,7 +186,7 @@ describe('defaultTransactionBuilder', () => {
delete input.maxFeePerGas;

await expect(
defaultTransactionBuilder({ transaction: input, web3Context }),
defaultTransactionBuilder({ transaction: input, web3Context, fillGasPrice: true }),
).rejects.toThrow(new UnableToPopulateNonceError());
});

Expand All @@ -196,6 +199,26 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.nonce).toBe(expectedNonce);
expect(getTransactionCountSpy).toHaveBeenCalledWith(
web3Context.requestManager,
expectedFrom,
web3Context.defaultBlock,
);
});

it('should use web3Eth.getTransactionCount to populate nonce without gas fill', async () => {
const input = { ...transaction };
delete input.nonce;
delete input.maxPriorityFeePerGas;
delete input.maxFeePerGas;

const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: false,
});
expect(result.nonce).toBe(expectedNonce);
expect(getTransactionCountSpy).toHaveBeenCalledWith(
Expand All @@ -216,6 +239,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.value).toBe('0x');
});
Expand All @@ -232,6 +256,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.input).toBe('0x');
expect(result.data).toBe('0x');
Expand All @@ -247,6 +272,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.input).toBe('0x123');
expect(result.data).toBe('0x123');
Expand Down Expand Up @@ -277,6 +303,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.chain).toBe('mainnet');
});
Expand All @@ -293,6 +320,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.chain).toBe(web3Context.defaultChain);
});
Expand All @@ -309,6 +337,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.hardfork).toBe('london');
});
Expand All @@ -325,6 +354,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.hardfork).toBe(web3Context.defaultHardfork);
});
Expand Down Expand Up @@ -357,6 +387,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.common).toStrictEqual(customCommon);
});
Expand All @@ -373,6 +404,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.chainId).toBe(expectedChainId);
});
Expand All @@ -388,6 +420,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.networkId).toBe(expectedNetworkId);
});
Expand All @@ -403,6 +436,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.gasLimit).toBe(expectedGasLimit);
});
Expand All @@ -414,7 +448,7 @@ describe('defaultTransactionBuilder', () => {
input.type = '0x8'; // // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2718.md#transactions

await expect(
defaultTransactionBuilder({ transaction: input, web3Context }),
defaultTransactionBuilder({ transaction: input, web3Context, fillGasPrice: true }),
).rejects.toThrow(new UnsupportedTransactionTypeError(input.type));
});

Expand All @@ -441,6 +475,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.type).toBe(web3Context.defaultTransactionType);
});
Expand All @@ -454,7 +489,11 @@ describe('defaultTransactionBuilder', () => {
delete input.maxPriorityFeePerGas;
input.type = '0x0';

const result = await defaultTransactionBuilder({ transaction: input, web3Context });
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.gasPrice).toBe(expectedGasPrice);
});

Expand All @@ -468,6 +507,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.gasPrice).toBe(expectedGasPrice);
});
Expand All @@ -484,6 +524,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip2930Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.accessList).toStrictEqual([]);
});
Expand All @@ -497,6 +538,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.accessList).toStrictEqual([]);
});
Expand All @@ -516,7 +558,7 @@ describe('defaultTransactionBuilder', () => {
input.type = '0x2';

await expect(
defaultTransactionBuilder({ transaction: input, web3Context }),
defaultTransactionBuilder({ transaction: input, web3Context, fillGasPrice: true }),
).rejects.toThrow(new Eip1559NotSupportedError());
});

Expand All @@ -530,6 +572,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});

expect(result.maxPriorityFeePerGas).toBeDefined();
Expand All @@ -546,6 +589,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.maxPriorityFeePerGas).toBe(expectedMaxPriorityFeePerGas); // 2.5 Gwei, hardcoded in defaultTransactionBuilder;
expect(result.maxFeePerGas).toBe(expectedMaxFeePerGas);
Expand All @@ -560,6 +604,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.maxPriorityFeePerGas).toBe(expectedMaxPriorityFeePerGas); // 2.5 Gwei, hardcoded in defaultTransactionBuilder;
expect(result.maxFeePerGas).toBe(expectedMaxFeePerGas);
Expand All @@ -574,6 +619,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.maxPriorityFeePerGas).toBe(expectedMaxPriorityFeePerGas); // 2.5 Gwei, hardcoded in defaultTransactionBuilder;
expect(result.maxFeePerGas).toBe(expectedMaxFeePerGas);
Expand All @@ -596,6 +642,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.maxPriorityFeePerGas).toBe(web3Context.defaultMaxPriorityFeePerGas); // 2.5 Gwei, hardcoded in defaultTransactionBuilder;
expect(result.maxFeePerGas).toBe(expectedMaxFeePerGas);
Expand All @@ -617,6 +664,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.maxPriorityFeePerGas).toBe(web3Context.defaultMaxPriorityFeePerGas); // 2.5 Gwei, hardcoded in defaultTransactionBuilder;
expect(result.maxFeePerGas).toBe(expectedMaxFeePerGas);
Expand All @@ -638,6 +686,7 @@ describe('defaultTransactionBuilder', () => {
const result = await defaultTransactionBuilder<PopulatedUnsignedEip1559Transaction>({
transaction: input,
web3Context,
fillGasPrice: true,
});
expect(result.maxPriorityFeePerGas).toBe(web3Context.defaultMaxPriorityFeePerGas); // 2.5 Gwei, hardcoded in defaultTransactionBuilder;
expect(result.maxFeePerGas).toBe(expectedMaxFeePerGas);
Expand Down
Expand Up @@ -59,6 +59,7 @@ describe('prepareTransactionForSigning', () => {
expectedTransaction,
web3Context,
expectedPrivateKey,
true,
);

// should produce an web3-utils/tx instance
Expand Down

0 comments on commit 210455a

Please sign in to comment.