Web3 module to interact with Ethereum smart contracts with TypeScript type safety
—
Low-level encoding, decoding, and utility functions for contract interaction, address generation, and transaction parameter management.
Functions for encoding method calls and decoding return values.
/**
* Encode method ABI with parameters for contract calls
* @param abi - The function or constructor fragment from contract ABI
* @param args - Arguments to encode
* @param deployData - Optional deployment bytecode for constructor calls
* @returns Encoded method call data as hex string
*/
function encodeMethodABI(
abi: AbiFunctionFragment | AbiConstructorFragment,
args: unknown[],
deployData?: HexString
): string;
/**
* Decode method parameters from transaction input data
* Alias for decodeFunctionCall from web3-eth-abi
* @param abi - The function fragment from contract ABI
* @param data - Encoded transaction input data
* @returns Decoded parameters object
*/
function decodeMethodParams(
abi: AbiFunctionFragment,
data: HexString
): DecodedParams & { __method__: string; __length__: number };
/**
* Decode method return values from transaction result
* Alias for decodeFunctionReturn from web3-eth-abi
* @param abi - The function fragment from contract ABI
* @param returnValues - Encoded return data
* @returns Decoded return values
*/
function decodeMethodReturn(
abi: AbiFunctionFragment,
returnValues: HexString
): unknown;Functions for encoding event filters and decoding event logs.
/**
* Encode event ABI for log filtering
* @param abi - The event fragment from contract ABI
* @param options - Event filtering options
* @returns Encoded filter with topics and block range
*/
function encodeEventABI(
abi: AbiEventFragment,
options?: ContractEventOptions
): {
topics: Topic[];
fromBlock?: BlockNumberOrTag;
};
/**
* Decode event from log data (re-exported from web3-eth)
* @param abi - The event fragment or full ABI
* @param data - Log data to decode
* @param topics - Log topics array
* @param nonIndexedData - Non-indexed event data
* @returns Decoded event data
*/
function decodeEventABI(
abi: AbiEventFragment | ContractAbi,
data: LogsInput,
topics: string[],
nonIndexedData?: string
): EventLog;Utilities for generating contract addresses for deployment.
/**
* Generate contract address using CREATE opcode (deterministic from deployer and nonce)
* @param from - Deployer address
* @param nonce - Transaction nonce
* @returns Computed contract address
*/
function createContractAddress(from: Address, nonce: Numbers): Address;
/**
* Generate contract address using CREATE2 opcode (deterministic from salt and init code)
* @param from - Deployer address
* @param salt - Salt value for CREATE2
* @param initCode - Contract initialization code
* @returns Computed CREATE2 contract address
*/
function create2ContractAddress(
from: Address,
salt: Bytes,
initCode: Bytes
): Address;Internal utilities for preparing transaction parameters (exported for advanced usage).
/**
* Get parameters for sending transactions
* @param options - Contract transaction options
* @param contractOptions - Contract default options
* @returns Formatted transaction parameters
*/
function getSendTxParams(options: {
options?: PayableCallOptions | NonPayableCallOptions;
contractOptions?: ContractOptions;
}): TransactionCall;
/**
* Get parameters for eth_call operations
* @param options - Contract call options
* @param contractOptions - Contract default options
* @returns Formatted call parameters
*/
function getEthTxCallParams(options: {
options?: PayableCallOptions | NonPayableCallOptions;
contractOptions?: ContractOptions;
}): TransactionCall;
/**
* Get parameters for gas estimation
* @param options - Contract gas estimation options
* @param contractOptions - Contract default options
* @returns Formatted gas estimation parameters
*/
function getEstimateGasParams(options: {
options?: PayableCallOptions | NonPayableCallOptions;
contractOptions?: ContractOptions;
}): TransactionCall;
/**
* Get parameters for access list creation
* @param options - Contract access list options
* @param contractOptions - Contract default options
* @returns Formatted access list parameters
*/
function getCreateAccessListParams(options: {
options?: PayableCallOptions | NonPayableCallOptions;
contractOptions?: ContractOptions;
}): TransactionForAccessList;Utility for validating Web3 contract context objects.
/**
* Type guard to check if an object is a Web3ContractContext
* @param options - Object to check
* @returns True if object is Web3ContractContext
*/
function isWeb3ContractContext(options: unknown): options is Web3ContractContext;import { encodeMethodABI, decodeMethodParams, decodeMethodReturn } from "web3-eth-contract";
// Encode method call
const abi = {
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" }
],
name: "transfer",
outputs: [{ name: "", type: "bool" }],
stateMutability: "nonpayable",
type: "function"
} as const;
const encodedData = encodeMethodABI(
abi,
["0x1234567890123456789012345678901234567890", "1000000000000000000"]
);
console.log("Encoded method call:", encodedData);
// Output: 0xa9059cbb000000000000000000000000123456789012345678901234567890123456789000000000000000000000000000000000000000000000000000de0b6b3a7640000
// Decode method parameters from transaction input
const decodedParams = decodeMethodParams(abi, encodedData);
console.log("Decoded parameters:", {
to: decodedParams.to,
amount: decodedParams.amount,
method: decodedParams.__method__, // "transfer(address,uint256)"
length: decodedParams.__length__ // 2
});
// Decode method return values
const returnData = "0x0000000000000000000000000000000000000000000000000000000000000001";
const decodedReturn = decodeMethodReturn(abi, returnData);
console.log("Method returned:", decodedReturn); // trueimport { encodeEventABI, decodeEventABI } from "web3-eth-contract";
// Encode event filter
const eventAbi = {
anonymous: false,
inputs: [
{ indexed: true, name: "from", type: "address" },
{ indexed: true, name: "to", type: "address" },
{ indexed: false, name: "value", type: "uint256" }
],
name: "Transfer",
type: "event"
} as const;
const encodedFilter = encodeEventABI(eventAbi, {
filter: {
from: "0x1234567890123456789012345678901234567890",
to: ["0xabcd...", "0xefgh..."] // Multiple values
},
fromBlock: 1000000
});
console.log("Encoded filter:", {
topics: encodedFilter.topics,
fromBlock: encodedFilter.fromBlock
});
// Decode event from logs
const logData = {
address: "0x...",
topics: [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", // Transfer signature
"0x000000000000000000000000abcdefabcdefabcdefabcdefabcdefabcdefabcdef", // from
"0x000000000000000000000000123456789012345678901234567890123456789" // to
],
data: "0x00000000000000000000000000000000000000000000000000de0b6b3a7640000", // value
blockNumber: 1000001
};
const decodedEvent = decodeEventABI(eventAbi, logData, logData.topics);
console.log("Decoded event:", {
event: decodedEvent.event, // "Transfer"
from: decodedEvent.returnValues.from,
to: decodedEvent.returnValues.to,
value: decodedEvent.returnValues.value
});import { createContractAddress, create2ContractAddress } from "web3-eth-contract";
// Generate address for CREATE deployment
const deployerAddress = "0x1234567890123456789012345678901234567890";
const nonce = 42;
const contractAddress = createContractAddress(deployerAddress, nonce);
console.log("CREATE contract address:", contractAddress);
// Generate address for CREATE2 deployment
const salt = "0x0000000000000000000000000000000000000000000000000000000000000001";
const initCode = "0x608060405234801561001057600080fd5b50..."; // Contract bytecode + constructor args
const create2Address = create2ContractAddress(deployerAddress, salt, initCode);
console.log("CREATE2 contract address:", create2Address);
// Pre-compute address before deployment
console.log("Contract will be deployed at:", create2Address);
// Deploy and verify
const deployedContract = await contract.deploy({
data: initCode
}).send({ from: deployerAddress });
console.log("Actual deployed address:", deployedContract.options.address);
// Should match create2Addressimport {
getSendTxParams,
getEstimateGasParams,
getCreateAccessListParams
} from "web3-eth-contract";
const contractOptions = {
from: "0x1234567890123456789012345678901234567890",
gas: 100000,
gasPrice: "20000000000"
};
const callOptions = {
from: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef",
gas: 150000,
value: "1000000000000000000" // 1 ETH
};
// Get parameters for sending transaction
const sendParams = getSendTxParams({
options: callOptions,
contractOptions
});
console.log("Send transaction params:", sendParams);
// Merged options with callOptions taking precedence
// Get parameters for gas estimation
const gasParams = getEstimateGasParams({
options: callOptions,
contractOptions
});
console.log("Gas estimation params:", gasParams);
// Get parameters for access list creation
const accessListParams = getCreateAccessListParams({
options: callOptions,
contractOptions
});
console.log("Access list params:", accessListParams);import { isWeb3ContractContext } from "web3-eth-contract";
function handleContractInput(input: unknown) {
if (isWeb3ContractContext(input)) {
// TypeScript now knows input is Web3ContractContext
console.log("Provider:", input.provider);
console.log("Request manager:", input.requestManager);
console.log("Config:", input.config);
} else {
console.log("Not a valid Web3ContractContext");
}
}
// Test with various inputs
handleContractInput({
provider: web3Provider,
config: web3Config
}); // Valid context
handleContractInput({
from: "0x123...",
gas: 100000
}); // Not a contextimport {
encodeMethodABI,
createContractAddress,
getSendTxParams
} from "web3-eth-contract";
import { sendTransaction } from "web3-eth";
// Manual contract interaction without Contract class
async function manualContractCall() {
const methodAbi = {
inputs: [{ name: "value", type: "uint256" }],
name: "setValue",
outputs: [],
stateMutability: "nonpayable",
type: "function"
} as const;
// Encode method call
const encodedData = encodeMethodABI(methodAbi, [42]);
// Prepare transaction parameters
const txParams = getSendTxParams({
options: {
from: "0x1234567890123456789012345678901234567890",
to: "0xcontractaddress...",
data: encodedData,
gas: 100000
},
contractOptions: {}
});
// Send transaction using web3-eth directly
const receipt = await sendTransaction(web3, txParams);
console.log("Transaction sent:", receipt.transactionHash);
}import { createContractAddress, create2ContractAddress } from "web3-eth-contract";
class DeploymentPlanner {
private deployerAddress: string;
private currentNonce: number;
constructor(deployerAddress: string, currentNonce: number) {
this.deployerAddress = deployerAddress;
this.currentNonce = currentNonce;
}
predictNextContractAddress(): string {
return createContractAddress(this.deployerAddress, this.currentNonce);
}
predictContractAddressAtNonce(nonce: number): string {
return createContractAddress(this.deployerAddress, nonce);
}
predictCreate2Address(salt: string, initCode: string): string {
return create2ContractAddress(this.deployerAddress, salt, initCode);
}
planDeployments(contracts: Array<{ name: string; bytecode: string; salt?: string }>) {
const plan = contracts.map((contract, index) => {
const address = contract.salt
? this.predictCreate2Address(contract.salt, contract.bytecode)
: this.predictContractAddressAtNonce(this.currentNonce + index);
return {
name: contract.name,
predictedAddress: address,
deploymentMethod: contract.salt ? 'CREATE2' : 'CREATE'
};
});
console.log("Deployment plan:", plan);
return plan;
}
}
// Usage
const planner = new DeploymentPlanner(
"0x1234567890123456789012345678901234567890",
await web3.eth.getTransactionCount("0x1234567890123456789012345678901234567890")
);
const deploymentPlan = planner.planDeployments([
{ name: "Token", bytecode: tokenBytecode },
{ name: "Exchange", bytecode: exchangeBytecode, salt: "0x01" }
]);Install with Tessl CLI
npx tessl i tessl/npm-web3-eth-contract