/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see .
*/
import { Web3ContractError } from 'web3-errors';
import {
TransactionForAccessList,
AbiFunctionFragment,
TransactionWithSenderAPI,
TransactionCall,
HexString,
Address,
NonPayableCallOptions,
PayableCallOptions,
ContractOptions,
} from 'web3-types';
import { isNullish, mergeDeep, isContractInitOptions } from 'web3-utils';
import { encodeMethodABI } from './encoding.js';
import { Web3ContractContext } from './types.js';
const dataInputEncodeMethodHelper = (
txParams: TransactionCall | TransactionForAccessList,
abi: AbiFunctionFragment,
params: unknown[],
dataInputFill?: 'data' | 'input' | 'both',
): { data?: HexString; input?: HexString } => {
const tx: { data?: HexString; input?: HexString } = {};
if (!isNullish(txParams.data) || dataInputFill === 'both') {
tx.data = encodeMethodABI(abi, params, (txParams.data ?? txParams.input) as HexString);
}
if (!isNullish(txParams.input) || dataInputFill === 'both') {
tx.input = encodeMethodABI(abi, params, (txParams.input ?? txParams.data) as HexString);
}
// if input and data is empty, use web3config default
if (isNullish(tx.input) && isNullish(tx.data)) {
tx[dataInputFill as 'data' | 'input'] = encodeMethodABI(abi, params);
}
return { data: tx.data as HexString, input: tx.input as HexString };
};
export const getSendTxParams = ({
abi,
params,
options,
contractOptions,
}: {
abi: AbiFunctionFragment;
params: unknown[];
options?: (PayableCallOptions | NonPayableCallOptions) & {
input?: HexString;
data?: HexString;
to?: Address;
dataInputFill?: 'input' | 'data' | 'both';
};
contractOptions: ContractOptions;
}): TransactionCall => {
const deploymentCall =
options?.input ?? options?.data ?? contractOptions.input ?? contractOptions.data;
if (!deploymentCall && !options?.to && !contractOptions.address) {
throw new Web3ContractError('Contract address not specified');
}
if (!options?.from && !contractOptions.from) {
throw new Web3ContractError('Contract "from" address not specified');
}
let txParams = mergeDeep(
{
to: contractOptions.address,
gas: contractOptions.gas,
gasPrice: contractOptions.gasPrice,
from: contractOptions.from,
input: contractOptions.input,
maxPriorityFeePerGas: contractOptions.maxPriorityFeePerGas,
maxFeePerGas: contractOptions.maxFeePerGas,
data: contractOptions.data,
},
options as unknown as Record,
) as unknown as TransactionCall;
const dataInput = dataInputEncodeMethodHelper(txParams, abi, params, options?.dataInputFill);
txParams = { ...txParams, data: dataInput.data, input: dataInput.input };
return txParams;
};
export const getEthTxCallParams = ({
abi,
params,
options,
contractOptions,
}: {
abi: AbiFunctionFragment;
params: unknown[];
options?: (PayableCallOptions | NonPayableCallOptions) & {
to?: Address;
dataInputFill?: 'input' | 'data' | 'both';
};
contractOptions: ContractOptions;
}): TransactionCall => {
if (!options?.to && !contractOptions.address) {
throw new Web3ContractError('Contract address not specified');
}
let txParams = mergeDeep(
{
to: contractOptions.address,
gas: contractOptions.gas,
gasPrice: contractOptions.gasPrice,
from: contractOptions.from,
input: contractOptions.input,
maxPriorityFeePerGas: contractOptions.maxPriorityFeePerGas,
maxFeePerGas: contractOptions.maxFeePerGas,
data: contractOptions.data,
},
options as unknown as Record,
) as unknown as TransactionCall;
const dataInput = dataInputEncodeMethodHelper(txParams, abi, params, options?.dataInputFill);
txParams = { ...txParams, data: dataInput.data, input: dataInput.input };
return txParams;
};
export const getEstimateGasParams = ({
abi,
params,
options,
contractOptions,
}: {
abi: AbiFunctionFragment;
params: unknown[];
options?: (PayableCallOptions | NonPayableCallOptions) & {
dataInputFill?: 'input' | 'data' | 'both';
};
contractOptions: ContractOptions;
}): Partial => {
let txParams = mergeDeep(
{
to: contractOptions.address,
gas: contractOptions.gas,
gasPrice: contractOptions.gasPrice,
from: contractOptions.from,
input: contractOptions.input,
data: contractOptions.data,
},
options as unknown as Record,
) as unknown as TransactionCall;
const dataInput = dataInputEncodeMethodHelper(txParams, abi, params, options?.dataInputFill);
txParams = { ...txParams, data: dataInput.data, input: dataInput.input };
return txParams as TransactionWithSenderAPI;
};
export const isWeb3ContractContext = (options: unknown): options is Web3ContractContext =>
typeof options === 'object' &&
!isNullish(options) &&
Object.keys(options).length !== 0 &&
!isContractInitOptions(options);
export const getCreateAccessListParams = ({
abi,
params,
options,
contractOptions,
}: {
abi: AbiFunctionFragment;
params: unknown[];
options?: (PayableCallOptions | NonPayableCallOptions) & {
to?: Address;
dataInputFill?: 'input' | 'data' | 'both';
};
contractOptions: ContractOptions;
}): TransactionForAccessList => {
if (!options?.to && !contractOptions.address) {
throw new Web3ContractError('Contract address not specified');
}
if (!options?.from && !contractOptions.from) {
throw new Web3ContractError('Contract "from" address not specified');
}
let txParams = mergeDeep(
{
to: contractOptions.address,
gas: contractOptions.gas,
gasPrice: contractOptions.gasPrice,
from: contractOptions.from,
input: contractOptions.input,
maxPriorityFeePerGas: contractOptions.maxPriorityFeePerGas,
maxFeePerGas: contractOptions.maxFeePerGas,
data: contractOptions.data,
},
options as unknown as Record,
) as unknown as TransactionForAccessList;
const dataInput = dataInputEncodeMethodHelper(txParams, abi, params, options?.dataInputFill);
txParams = { ...txParams, data: dataInput.data, input: dataInput.input };
return txParams;
};