web3-eth-contract
Advanced tools
Comparing version 4.3.1-dev.5341c3a.0 to 4.3.1-dev.578ebb6.0
import { Web3Context, Web3EventEmitter, Web3PromiEvent } from 'web3-core'; | ||
import { NewHeadsSubscription, SendTransactionEvents } from 'web3-eth'; | ||
import { AbiFunctionFragment, ContractAbi, ContractConstructorArgs, ContractEvent, ContractEvents, ContractMethod, ContractMethodInputParameters, ContractMethodOutputParameters, Address, EthExecutionAPI, Filter, FilterAbis, HexString, ContractInitOptions, PayableCallOptions, DataFormat, DEFAULT_RETURN_FORMAT, EventLog, ContractOptions, TransactionReceipt, FormatType } from 'web3-types'; | ||
import { AbiFunctionFragment, ContractAbi, ContractConstructorArgs, ContractEvent, ContractEvents, ContractMethod, ContractMethodInputParameters, ContractMethodOutputParameters, Address, EthExecutionAPI, Filter, FilterAbis, HexString, ContractInitOptions, PayableCallOptions, DataFormat, DEFAULT_RETURN_FORMAT, EventLog, ContractOptions, TransactionReceipt, FormatType, DecodedParams } from 'web3-types'; | ||
import { LogsSubscription } from './log_subscription.js'; | ||
@@ -163,2 +163,63 @@ import { ContractEventOptions, NonPayableMethodObject, PayableMethodObject, PayableTxOptions, Web3ContractContext } from './types.js'; | ||
* | ||
* ### decodeMethodData | ||
* Decodes the given ABI-encoded data, revealing both the method name and the parameters used in the smart contract call. | ||
* This function reverses the encoding process happens at the method `encodeABI`. | ||
* It's particularly useful for debugging and understanding the interactions with and between smart contracts. | ||
* | ||
* #### Parameters | ||
* | ||
* - `data` **HexString**: The string of ABI-encoded data that needs to be decoded. This should include the method signature and the encoded parameters. | ||
* | ||
* #### Returns | ||
* | ||
* - **Object**: This object combines both the decoded parameters and the method name in a readable format. Specifically, the returned object contains: | ||
* - `__method__` **String**: The name of the contract method, reconstructed from the ABI. | ||
* - `__length__` **Number**: The number of parameters decoded. | ||
* - Additional properties representing each parameter by name, as well as their position and values. | ||
* | ||
* #### Example | ||
* | ||
* Given an ABI-encoded string from a transaction, you can decode this data to identify the method called and the parameters passed. | ||
* Here's a simplified example: | ||
* | ||
* | ||
* ```typescript | ||
* const GreeterAbi = [ | ||
* { | ||
* inputs: [ | ||
* { | ||
* internalType: 'string', | ||
* name: '_greeting', | ||
* type: 'string', | ||
* }, | ||
* ], | ||
* name: 'setGreeting', | ||
* outputs: [], | ||
* type: 'function', | ||
* }, | ||
* ]; | ||
* const contract = new Contract(GreeterAbi); // Initialize with your contract's ABI | ||
* | ||
* // The ABI-encoded data string for "setGreeting('Hello World')" | ||
* const encodedData = | ||
* '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'; | ||
* | ||
* try { | ||
* const decoded = contract.decodeMethodData(encodedData); | ||
* console.log(decoded.__method__); // Outputs: "setGreeting(string)" | ||
* console.log(decoded); // Outputs the detailed parameter data | ||
* // This tells that the method called was `setGreeting` with a single string parameter "Hello World": | ||
* // { | ||
* // __method__: 'setGreeting(string)', | ||
* // __length__: 1, | ||
* // '0': 'Hello World', | ||
* // _greeting: 'Hello World' | ||
* // } | ||
* } catch (error) { | ||
* console.error(error); | ||
* } | ||
* ``` | ||
* | ||
* ### createAccessList | ||
@@ -371,2 +432,18 @@ * This will create an access list a method execution will access when executed in the EVM. | ||
* | ||
* // decoding | ||
* myContract.deploy({ | ||
* input: '0x12345...', | ||
* // arguments: [123, 'My Greeting'] if you just need to decode the data, you can skip the arguments | ||
* }) | ||
* .decodeData('0x12345...0000012345678765432'); | ||
* > { | ||
* __method__: 'constructor', | ||
* __length__: 2, | ||
* '0': '123', | ||
* _id: '123', | ||
* '1': 'My Greeting', | ||
* _greeting: 'My Greeting', | ||
* } | ||
* | ||
* | ||
* // Gas estimation | ||
@@ -402,2 +479,6 @@ * myContract.deploy({ | ||
encodeABI: () => string; | ||
decodeData: (data: HexString) => { | ||
__method__: string; | ||
__length__: number; | ||
}; | ||
}; | ||
@@ -447,2 +528,5 @@ /** | ||
private _parseAndSetAddress; | ||
decodeMethodData(data: HexString): DecodedParams & { | ||
__method__: string; | ||
}; | ||
private _parseAndSetJsonInterface; | ||
@@ -449,0 +533,0 @@ private _getAbiParams; |
@@ -160,2 +160,63 @@ "use strict"; | ||
* | ||
* ### decodeMethodData | ||
* Decodes the given ABI-encoded data, revealing both the method name and the parameters used in the smart contract call. | ||
* This function reverses the encoding process happens at the method `encodeABI`. | ||
* It's particularly useful for debugging and understanding the interactions with and between smart contracts. | ||
* | ||
* #### Parameters | ||
* | ||
* - `data` **HexString**: The string of ABI-encoded data that needs to be decoded. This should include the method signature and the encoded parameters. | ||
* | ||
* #### Returns | ||
* | ||
* - **Object**: This object combines both the decoded parameters and the method name in a readable format. Specifically, the returned object contains: | ||
* - `__method__` **String**: The name of the contract method, reconstructed from the ABI. | ||
* - `__length__` **Number**: The number of parameters decoded. | ||
* - Additional properties representing each parameter by name, as well as their position and values. | ||
* | ||
* #### Example | ||
* | ||
* Given an ABI-encoded string from a transaction, you can decode this data to identify the method called and the parameters passed. | ||
* Here's a simplified example: | ||
* | ||
* | ||
* ```typescript | ||
* const GreeterAbi = [ | ||
* { | ||
* inputs: [ | ||
* { | ||
* internalType: 'string', | ||
* name: '_greeting', | ||
* type: 'string', | ||
* }, | ||
* ], | ||
* name: 'setGreeting', | ||
* outputs: [], | ||
* type: 'function', | ||
* }, | ||
* ]; | ||
* const contract = new Contract(GreeterAbi); // Initialize with your contract's ABI | ||
* | ||
* // The ABI-encoded data string for "setGreeting('Hello World')" | ||
* const encodedData = | ||
* '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'; | ||
* | ||
* try { | ||
* const decoded = contract.decodeMethodData(encodedData); | ||
* console.log(decoded.__method__); // Outputs: "setGreeting(string)" | ||
* console.log(decoded); // Outputs the detailed parameter data | ||
* // This tells that the method called was `setGreeting` with a single string parameter "Hello World": | ||
* // { | ||
* // __method__: 'setGreeting(string)', | ||
* // __length__: 1, | ||
* // '0': 'Hello World', | ||
* // _greeting: 'Hello World' | ||
* // } | ||
* } catch (error) { | ||
* console.error(error); | ||
* } | ||
* ``` | ||
* | ||
* ### createAccessList | ||
@@ -200,4 +261,3 @@ * This will create an access list a method execution will access when executed in the EVM. | ||
let provider; | ||
if (typeof addressOrOptionsOrContext === 'object' && | ||
'provider' in addressOrOptionsOrContext) { | ||
if (typeof addressOrOptionsOrContext === 'object' && 'provider' in addressOrOptionsOrContext) { | ||
provider = addressOrOptionsOrContext.provider; | ||
@@ -209,4 +269,3 @@ } | ||
} | ||
else if (typeof contextOrReturnFormat === 'object' && | ||
'provider' in contextOrReturnFormat) { | ||
else if (typeof contextOrReturnFormat === 'object' && 'provider' in contextOrReturnFormat) { | ||
provider = contextOrReturnFormat.provider; | ||
@@ -433,2 +492,18 @@ } | ||
* | ||
* // decoding | ||
* myContract.deploy({ | ||
* input: '0x12345...', | ||
* // arguments: [123, 'My Greeting'] if you just need to decode the data, you can skip the arguments | ||
* }) | ||
* .decodeData('0x12345...0000012345678765432'); | ||
* > { | ||
* __method__: 'constructor', | ||
* __length__: 2, | ||
* '0': '123', | ||
* _id: '123', | ||
* '1': 'My Greeting', | ||
* _greeting: 'My Greeting', | ||
* } | ||
* | ||
* | ||
* // Gas estimation | ||
@@ -481,2 +556,3 @@ * myContract.deploy({ | ||
encodeABI: () => (0, encoding_js_1.encodeMethodABI)(abi, args, (0, web3_utils_1.format)({ format: 'bytes' }, deployData, web3_types_1.DEFAULT_RETURN_FORMAT)), | ||
decodeData: (data) => (Object.assign(Object.assign({}, (0, encoding_js_1.decodeMethodParams)(abi, data.replace(deployData, ''), false)), { __method__: abi.type })), | ||
}; | ||
@@ -531,4 +607,3 @@ } | ||
} | ||
return (String(log.returnValues[key]).toUpperCase() === | ||
String(filter[key]).toUpperCase()); | ||
return String(log.returnValues[key]).toUpperCase() === String(filter[key]).toUpperCase(); | ||
}); | ||
@@ -545,2 +620,11 @@ }); | ||
} | ||
decodeMethodData(data) { | ||
const methodSignature = data.slice(0, 10); | ||
const functionsAbis = this._jsonInterface.filter(j => j.type !== 'error'); | ||
const abi = functionsAbis.find(a => methodSignature === (0, web3_eth_abi_1.encodeFunctionSignature)((0, web3_eth_abi_1.jsonInterfaceMethodToString)(a))); | ||
if (!abi) { | ||
throw new web3_errors_1.Web3ContractError(`The ABI for the provided method signature ${methodSignature} was not found.`); | ||
} | ||
return Object.assign(Object.assign({}, (0, encoding_js_1.decodeMethodParams)(abi, data)), { __method__: (0, web3_eth_abi_1.jsonInterfaceMethodToString)(abi) }); | ||
} | ||
_parseAndSetJsonInterface(abis, returnFormat = web3_types_1.DEFAULT_RETURN_FORMAT) { | ||
@@ -574,6 +658,6 @@ var _a, _b, _c, _d, _e; | ||
signature: methodSignature, | ||
method: contractMethod, | ||
method: exactContractMethod, | ||
}; | ||
// We don't know a particular type of the Abi method so can't type check | ||
this._methods[abi.name] = this._functions[methodName].method; | ||
this._methods[abi.name] = contractMethod; | ||
// We don't know a particular type of the Abi method so can't type check | ||
@@ -664,5 +748,3 @@ this._methods[methodName] = | ||
arguments: abiParams, | ||
call: (options, block) => __awaiter(this, void 0, void 0, function* () { | ||
return this._contractMethodCall(methodAbi, abiParams, internalErrorsAbis, options, block); | ||
}), | ||
call: (options, block) => __awaiter(this, void 0, void 0, function* () { return this._contractMethodCall(methodAbi, abiParams, internalErrorsAbis, options, block); }), | ||
send: (options) => this._contractMethodSend(methodAbi, abiParams, internalErrorsAbis, options), | ||
@@ -678,2 +760,3 @@ estimateGas: (options, returnFormat = web3_types_1.DEFAULT_RETURN_FORMAT) => __awaiter(this, void 0, void 0, function* () { | ||
encodeABI: () => (0, encoding_js_1.encodeMethodABI)(methodAbi, abiParams), | ||
decodeData: (data) => (0, encoding_js_1.decodeMethodParams)(methodAbi, data), | ||
createAccessList: (options, block) => __awaiter(this, void 0, void 0, function* () { | ||
@@ -680,0 +763,0 @@ return this._contractMethodCreateAccessList(methodAbi, abiParams, internalErrorsAbis, options, block); |
@@ -10,2 +10,6 @@ import { AbiConstructorFragment, AbiEventFragment, AbiFunctionFragment, Filter, HexString, ContractOptions } from 'web3-types'; | ||
export declare const encodeMethodABI: (abi: AbiFunctionFragment | AbiConstructorFragment, args: unknown[], deployData?: HexString) => string; | ||
export declare const decodeMethodParams: (abi: AbiFunctionFragment | AbiConstructorFragment, data: HexString, methodSignatureProvided?: boolean) => { | ||
[key: string]: unknown; | ||
__length__: number; | ||
}; | ||
export declare const decodeMethodReturn: (abi: AbiFunctionFragment, returnValues?: HexString) => unknown; |
@@ -19,3 +19,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.decodeMethodReturn = exports.encodeMethodABI = exports.encodeEventABI = exports.decodeEventABI = void 0; | ||
exports.decodeMethodReturn = exports.decodeMethodParams = exports.encodeMethodABI = exports.encodeEventABI = exports.decodeEventABI = void 0; | ||
const web3_utils_1 = require("web3-utils"); | ||
@@ -111,2 +111,13 @@ const web3_types_1 = require("web3-types"); | ||
exports.encodeMethodABI = encodeMethodABI; | ||
const decodeMethodParams = (abi, data, methodSignatureProvided = true) => { | ||
const value = methodSignatureProvided && data && data.length >= 10 && data.startsWith('0x') | ||
? data.slice(10) | ||
: data; | ||
if (!abi.inputs) { | ||
throw new web3_errors_1.Web3ContractError('No inputs found in the ABI'); | ||
} | ||
const result = (0, web3_eth_abi_1.decodeParameters)([...abi.inputs], value); | ||
return result; | ||
}; | ||
exports.decodeMethodParams = decodeMethodParams; | ||
const decodeMethodReturn = (abi, returnValues) => { | ||
@@ -113,0 +124,0 @@ // If it was constructor then we need to return contract address |
@@ -167,2 +167,9 @@ import { Web3ContextInitOptions, Web3PromiEvent } from 'web3-core'; | ||
/** | ||
* Decode raw result of method call into readable value(s). | ||
* | ||
* @param data - The data to decode. | ||
* @returns - The decoded data. | ||
*/ | ||
decodeData<SpecialInputs = Inputs>(data: HexString): SpecialInputs; | ||
/** | ||
* This method generates an access list for a transaction. You must specify a `from` address and `gas` if it’s not specified in options. | ||
@@ -338,2 +345,9 @@ * | ||
/** | ||
* Decode raw result of method call into readable value(s). | ||
* | ||
* @param data - The data to decode. | ||
* @returns - The decoded data. | ||
*/ | ||
decodeData<SpecialInputs = Inputs>(data: HexString): SpecialInputs; | ||
/** | ||
* This method generates an access list for a transaction. You must specify a `from` address and `gas` if it’s not specified in options. | ||
@@ -340,0 +354,0 @@ * |
@@ -33,3 +33,3 @@ /* | ||
import { isNullish, validator, utils as validatorUtils, Web3ValidatorError, } from 'web3-validator'; | ||
import { decodeMethodReturn, encodeEventABI, encodeMethodABI } from './encoding.js'; | ||
import { decodeMethodReturn, decodeMethodParams, encodeEventABI, encodeMethodABI, } from './encoding.js'; | ||
import { LogsSubscription } from './log_subscription.js'; | ||
@@ -158,2 +158,63 @@ import { getCreateAccessListParams, getEstimateGasParams, getEthTxCallParams, getSendTxParams, isWeb3ContractContext, } from './utils.js'; | ||
* | ||
* ### decodeMethodData | ||
* Decodes the given ABI-encoded data, revealing both the method name and the parameters used in the smart contract call. | ||
* This function reverses the encoding process happens at the method `encodeABI`. | ||
* It's particularly useful for debugging and understanding the interactions with and between smart contracts. | ||
* | ||
* #### Parameters | ||
* | ||
* - `data` **HexString**: The string of ABI-encoded data that needs to be decoded. This should include the method signature and the encoded parameters. | ||
* | ||
* #### Returns | ||
* | ||
* - **Object**: This object combines both the decoded parameters and the method name in a readable format. Specifically, the returned object contains: | ||
* - `__method__` **String**: The name of the contract method, reconstructed from the ABI. | ||
* - `__length__` **Number**: The number of parameters decoded. | ||
* - Additional properties representing each parameter by name, as well as their position and values. | ||
* | ||
* #### Example | ||
* | ||
* Given an ABI-encoded string from a transaction, you can decode this data to identify the method called and the parameters passed. | ||
* Here's a simplified example: | ||
* | ||
* | ||
* ```typescript | ||
* const GreeterAbi = [ | ||
* { | ||
* inputs: [ | ||
* { | ||
* internalType: 'string', | ||
* name: '_greeting', | ||
* type: 'string', | ||
* }, | ||
* ], | ||
* name: 'setGreeting', | ||
* outputs: [], | ||
* type: 'function', | ||
* }, | ||
* ]; | ||
* const contract = new Contract(GreeterAbi); // Initialize with your contract's ABI | ||
* | ||
* // The ABI-encoded data string for "setGreeting('Hello World')" | ||
* const encodedData = | ||
* '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'; | ||
* | ||
* try { | ||
* const decoded = contract.decodeMethodData(encodedData); | ||
* console.log(decoded.__method__); // Outputs: "setGreeting(string)" | ||
* console.log(decoded); // Outputs the detailed parameter data | ||
* // This tells that the method called was `setGreeting` with a single string parameter "Hello World": | ||
* // { | ||
* // __method__: 'setGreeting(string)', | ||
* // __length__: 1, | ||
* // '0': 'Hello World', | ||
* // _greeting: 'Hello World' | ||
* // } | ||
* } catch (error) { | ||
* console.error(error); | ||
* } | ||
* ``` | ||
* | ||
* ### createAccessList | ||
@@ -198,4 +259,3 @@ * This will create an access list a method execution will access when executed in the EVM. | ||
let provider; | ||
if (typeof addressOrOptionsOrContext === 'object' && | ||
'provider' in addressOrOptionsOrContext) { | ||
if (typeof addressOrOptionsOrContext === 'object' && 'provider' in addressOrOptionsOrContext) { | ||
provider = addressOrOptionsOrContext.provider; | ||
@@ -207,4 +267,3 @@ } | ||
} | ||
else if (typeof contextOrReturnFormat === 'object' && | ||
'provider' in contextOrReturnFormat) { | ||
else if (typeof contextOrReturnFormat === 'object' && 'provider' in contextOrReturnFormat) { | ||
provider = contextOrReturnFormat.provider; | ||
@@ -431,2 +490,18 @@ } | ||
* | ||
* // decoding | ||
* myContract.deploy({ | ||
* input: '0x12345...', | ||
* // arguments: [123, 'My Greeting'] if you just need to decode the data, you can skip the arguments | ||
* }) | ||
* .decodeData('0x12345...0000012345678765432'); | ||
* > { | ||
* __method__: 'constructor', | ||
* __length__: 2, | ||
* '0': '123', | ||
* _id: '123', | ||
* '1': 'My Greeting', | ||
* _greeting: 'My Greeting', | ||
* } | ||
* | ||
* | ||
* // Gas estimation | ||
@@ -479,2 +554,3 @@ * myContract.deploy({ | ||
encodeABI: () => encodeMethodABI(abi, args, format({ format: 'bytes' }, deployData, DEFAULT_RETURN_FORMAT)), | ||
decodeData: (data) => (Object.assign(Object.assign({}, decodeMethodParams(abi, data.replace(deployData, ''), false)), { __method__: abi.type })), | ||
}; | ||
@@ -529,4 +605,3 @@ } | ||
} | ||
return (String(log.returnValues[key]).toUpperCase() === | ||
String(filter[key]).toUpperCase()); | ||
return String(log.returnValues[key]).toUpperCase() === String(filter[key]).toUpperCase(); | ||
}); | ||
@@ -543,2 +618,11 @@ }); | ||
} | ||
decodeMethodData(data) { | ||
const methodSignature = data.slice(0, 10); | ||
const functionsAbis = this._jsonInterface.filter(j => j.type !== 'error'); | ||
const abi = functionsAbis.find(a => methodSignature === encodeFunctionSignature(jsonInterfaceMethodToString(a))); | ||
if (!abi) { | ||
throw new Web3ContractError(`The ABI for the provided method signature ${methodSignature} was not found.`); | ||
} | ||
return Object.assign(Object.assign({}, decodeMethodParams(abi, data)), { __method__: jsonInterfaceMethodToString(abi) }); | ||
} | ||
_parseAndSetJsonInterface(abis, returnFormat = DEFAULT_RETURN_FORMAT) { | ||
@@ -572,6 +656,6 @@ var _a, _b, _c, _d, _e; | ||
signature: methodSignature, | ||
method: contractMethod, | ||
method: exactContractMethod, | ||
}; | ||
// We don't know a particular type of the Abi method so can't type check | ||
this._methods[abi.name] = this._functions[methodName].method; | ||
this._methods[abi.name] = contractMethod; | ||
// We don't know a particular type of the Abi method so can't type check | ||
@@ -662,5 +746,3 @@ this._methods[methodName] = | ||
arguments: abiParams, | ||
call: (options, block) => __awaiter(this, void 0, void 0, function* () { | ||
return this._contractMethodCall(methodAbi, abiParams, internalErrorsAbis, options, block); | ||
}), | ||
call: (options, block) => __awaiter(this, void 0, void 0, function* () { return this._contractMethodCall(methodAbi, abiParams, internalErrorsAbis, options, block); }), | ||
send: (options) => this._contractMethodSend(methodAbi, abiParams, internalErrorsAbis, options), | ||
@@ -676,2 +758,3 @@ estimateGas: (options, returnFormat = DEFAULT_RETURN_FORMAT) => __awaiter(this, void 0, void 0, function* () { | ||
encodeABI: () => encodeMethodABI(methodAbi, abiParams), | ||
decodeData: (data) => decodeMethodParams(methodAbi, data), | ||
createAccessList: (options, block) => __awaiter(this, void 0, void 0, function* () { | ||
@@ -678,0 +761,0 @@ return this._contractMethodCreateAccessList(methodAbi, abiParams, internalErrorsAbis, options, block); |
@@ -104,2 +104,12 @@ /* | ||
}; | ||
export const decodeMethodParams = (abi, data, methodSignatureProvided = true) => { | ||
const value = methodSignatureProvided && data && data.length >= 10 && data.startsWith('0x') | ||
? data.slice(10) | ||
: data; | ||
if (!abi.inputs) { | ||
throw new Web3ContractError('No inputs found in the ABI'); | ||
} | ||
const result = decodeParameters([...abi.inputs], value); | ||
return result; | ||
}; | ||
export const decodeMethodReturn = (abi, returnValues) => { | ||
@@ -106,0 +116,0 @@ // If it was constructor then we need to return contract address |
import { Web3Context, Web3EventEmitter, Web3PromiEvent } from 'web3-core'; | ||
import { NewHeadsSubscription, SendTransactionEvents } from 'web3-eth'; | ||
import { AbiFunctionFragment, ContractAbi, ContractConstructorArgs, ContractEvent, ContractEvents, ContractMethod, ContractMethodInputParameters, ContractMethodOutputParameters, Address, EthExecutionAPI, Filter, FilterAbis, HexString, ContractInitOptions, PayableCallOptions, DataFormat, DEFAULT_RETURN_FORMAT, EventLog, ContractOptions, TransactionReceipt, FormatType } from 'web3-types'; | ||
import { AbiFunctionFragment, ContractAbi, ContractConstructorArgs, ContractEvent, ContractEvents, ContractMethod, ContractMethodInputParameters, ContractMethodOutputParameters, Address, EthExecutionAPI, Filter, FilterAbis, HexString, ContractInitOptions, PayableCallOptions, DataFormat, DEFAULT_RETURN_FORMAT, EventLog, ContractOptions, TransactionReceipt, FormatType, DecodedParams } from 'web3-types'; | ||
import { LogsSubscription } from './log_subscription.js'; | ||
@@ -163,2 +163,63 @@ import { ContractEventOptions, NonPayableMethodObject, PayableMethodObject, PayableTxOptions, Web3ContractContext } from './types.js'; | ||
* | ||
* ### decodeMethodData | ||
* Decodes the given ABI-encoded data, revealing both the method name and the parameters used in the smart contract call. | ||
* This function reverses the encoding process happens at the method `encodeABI`. | ||
* It's particularly useful for debugging and understanding the interactions with and between smart contracts. | ||
* | ||
* #### Parameters | ||
* | ||
* - `data` **HexString**: The string of ABI-encoded data that needs to be decoded. This should include the method signature and the encoded parameters. | ||
* | ||
* #### Returns | ||
* | ||
* - **Object**: This object combines both the decoded parameters and the method name in a readable format. Specifically, the returned object contains: | ||
* - `__method__` **String**: The name of the contract method, reconstructed from the ABI. | ||
* - `__length__` **Number**: The number of parameters decoded. | ||
* - Additional properties representing each parameter by name, as well as their position and values. | ||
* | ||
* #### Example | ||
* | ||
* Given an ABI-encoded string from a transaction, you can decode this data to identify the method called and the parameters passed. | ||
* Here's a simplified example: | ||
* | ||
* | ||
* ```typescript | ||
* const GreeterAbi = [ | ||
* { | ||
* inputs: [ | ||
* { | ||
* internalType: 'string', | ||
* name: '_greeting', | ||
* type: 'string', | ||
* }, | ||
* ], | ||
* name: 'setGreeting', | ||
* outputs: [], | ||
* type: 'function', | ||
* }, | ||
* ]; | ||
* const contract = new Contract(GreeterAbi); // Initialize with your contract's ABI | ||
* | ||
* // The ABI-encoded data string for "setGreeting('Hello World')" | ||
* const encodedData = | ||
* '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'; | ||
* | ||
* try { | ||
* const decoded = contract.decodeMethodData(encodedData); | ||
* console.log(decoded.__method__); // Outputs: "setGreeting(string)" | ||
* console.log(decoded); // Outputs the detailed parameter data | ||
* // This tells that the method called was `setGreeting` with a single string parameter "Hello World": | ||
* // { | ||
* // __method__: 'setGreeting(string)', | ||
* // __length__: 1, | ||
* // '0': 'Hello World', | ||
* // _greeting: 'Hello World' | ||
* // } | ||
* } catch (error) { | ||
* console.error(error); | ||
* } | ||
* ``` | ||
* | ||
* ### createAccessList | ||
@@ -371,2 +432,18 @@ * This will create an access list a method execution will access when executed in the EVM. | ||
* | ||
* // decoding | ||
* myContract.deploy({ | ||
* input: '0x12345...', | ||
* // arguments: [123, 'My Greeting'] if you just need to decode the data, you can skip the arguments | ||
* }) | ||
* .decodeData('0x12345...0000012345678765432'); | ||
* > { | ||
* __method__: 'constructor', | ||
* __length__: 2, | ||
* '0': '123', | ||
* _id: '123', | ||
* '1': 'My Greeting', | ||
* _greeting: 'My Greeting', | ||
* } | ||
* | ||
* | ||
* // Gas estimation | ||
@@ -402,2 +479,6 @@ * myContract.deploy({ | ||
encodeABI: () => string; | ||
decodeData: (data: HexString) => { | ||
__method__: string; | ||
__length__: number; | ||
}; | ||
}; | ||
@@ -447,2 +528,5 @@ /** | ||
private _parseAndSetAddress; | ||
decodeMethodData(data: HexString): DecodedParams & { | ||
__method__: string; | ||
}; | ||
private _parseAndSetJsonInterface; | ||
@@ -449,0 +533,0 @@ private _getAbiParams; |
@@ -10,3 +10,7 @@ import { AbiConstructorFragment, AbiEventFragment, AbiFunctionFragment, Filter, HexString, ContractOptions } from 'web3-types'; | ||
export declare const encodeMethodABI: (abi: AbiFunctionFragment | AbiConstructorFragment, args: unknown[], deployData?: HexString) => string; | ||
export declare const decodeMethodParams: (abi: AbiFunctionFragment | AbiConstructorFragment, data: HexString, methodSignatureProvided?: boolean) => { | ||
[key: string]: unknown; | ||
__length__: number; | ||
}; | ||
export declare const decodeMethodReturn: (abi: AbiFunctionFragment, returnValues?: HexString) => unknown; | ||
//# sourceMappingURL=encoding.d.ts.map |
@@ -167,2 +167,9 @@ import { Web3ContextInitOptions, Web3PromiEvent } from 'web3-core'; | ||
/** | ||
* Decode raw result of method call into readable value(s). | ||
* | ||
* @param data - The data to decode. | ||
* @returns - The decoded data. | ||
*/ | ||
decodeData<SpecialInputs = Inputs>(data: HexString): SpecialInputs; | ||
/** | ||
* This method generates an access list for a transaction. You must specify a `from` address and `gas` if it’s not specified in options. | ||
@@ -338,2 +345,9 @@ * | ||
/** | ||
* Decode raw result of method call into readable value(s). | ||
* | ||
* @param data - The data to decode. | ||
* @returns - The decoded data. | ||
*/ | ||
decodeData<SpecialInputs = Inputs>(data: HexString): SpecialInputs; | ||
/** | ||
* This method generates an access list for a transaction. You must specify a `from` address and `gas` if it’s not specified in options. | ||
@@ -340,0 +354,0 @@ * |
{ | ||
"name": "web3-eth-contract", | ||
"version": "4.3.1-dev.5341c3a.0+5341c3a", | ||
"version": "4.3.1-dev.578ebb6.0+578ebb6", | ||
"description": "Web3 module to interact with Ethereum smart contracts.", | ||
@@ -48,9 +48,9 @@ "main": "./lib/commonjs/index.js", | ||
"dependencies": { | ||
"web3-core": "4.3.3-dev.5341c3a.0+5341c3a", | ||
"web3-errors": "1.1.5-dev.5341c3a.0+5341c3a", | ||
"web3-eth": "4.5.1-dev.5341c3a.0+5341c3a", | ||
"web3-eth-abi": "4.2.1-dev.5341c3a.0+5341c3a", | ||
"web3-types": "1.5.1-dev.5341c3a.0+5341c3a", | ||
"web3-utils": "4.2.3-dev.5341c3a.0+5341c3a", | ||
"web3-validator": "2.0.6-dev.5341c3a.0+5341c3a" | ||
"web3-core": "4.3.3-dev.578ebb6.0+578ebb6", | ||
"web3-errors": "1.1.5-dev.578ebb6.0+578ebb6", | ||
"web3-eth": "4.5.1-dev.578ebb6.0+578ebb6", | ||
"web3-eth-abi": "4.2.1-dev.578ebb6.0+578ebb6", | ||
"web3-types": "1.5.1-dev.578ebb6.0+578ebb6", | ||
"web3-utils": "4.2.3-dev.578ebb6.0+578ebb6", | ||
"web3-validator": "2.0.6-dev.578ebb6.0+578ebb6" | ||
}, | ||
@@ -72,6 +72,6 @@ "devDependencies": { | ||
"typescript": "^4.7.4", | ||
"web3-eth-accounts": "4.1.2-dev.5341c3a.0+5341c3a", | ||
"web3-providers-ws": "4.0.8-dev.5341c3a.0+5341c3a" | ||
"web3-eth-accounts": "4.1.2-dev.578ebb6.0+578ebb6", | ||
"web3-providers-ws": "4.0.8-dev.578ebb6.0+578ebb6" | ||
}, | ||
"gitHead": "5341c3ab30aee24f678fc155d3e41483e3f5e68f" | ||
"gitHead": "578ebb69f0c16a5fc742c214d11b79e3d777ea04" | ||
} |
@@ -87,2 +87,3 @@ /* | ||
FormatType, | ||
DecodedParams, | ||
} from 'web3-types'; | ||
@@ -103,3 +104,8 @@ import { | ||
} from 'web3-validator'; | ||
import { decodeMethodReturn, encodeEventABI, encodeMethodABI } from './encoding.js'; | ||
import { | ||
decodeMethodReturn, | ||
decodeMethodParams, | ||
encodeEventABI, | ||
encodeMethodABI, | ||
} from './encoding.js'; | ||
import { LogsSubscription } from './log_subscription.js'; | ||
@@ -328,2 +334,63 @@ import { | ||
* | ||
* ### decodeMethodData | ||
* Decodes the given ABI-encoded data, revealing both the method name and the parameters used in the smart contract call. | ||
* This function reverses the encoding process happens at the method `encodeABI`. | ||
* It's particularly useful for debugging and understanding the interactions with and between smart contracts. | ||
* | ||
* #### Parameters | ||
* | ||
* - `data` **HexString**: The string of ABI-encoded data that needs to be decoded. This should include the method signature and the encoded parameters. | ||
* | ||
* #### Returns | ||
* | ||
* - **Object**: This object combines both the decoded parameters and the method name in a readable format. Specifically, the returned object contains: | ||
* - `__method__` **String**: The name of the contract method, reconstructed from the ABI. | ||
* - `__length__` **Number**: The number of parameters decoded. | ||
* - Additional properties representing each parameter by name, as well as their position and values. | ||
* | ||
* #### Example | ||
* | ||
* Given an ABI-encoded string from a transaction, you can decode this data to identify the method called and the parameters passed. | ||
* Here's a simplified example: | ||
* | ||
* | ||
* ```typescript | ||
* const GreeterAbi = [ | ||
* { | ||
* inputs: [ | ||
* { | ||
* internalType: 'string', | ||
* name: '_greeting', | ||
* type: 'string', | ||
* }, | ||
* ], | ||
* name: 'setGreeting', | ||
* outputs: [], | ||
* type: 'function', | ||
* }, | ||
* ]; | ||
* const contract = new Contract(GreeterAbi); // Initialize with your contract's ABI | ||
* | ||
* // The ABI-encoded data string for "setGreeting('Hello World')" | ||
* const encodedData = | ||
* '0xa41368620000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000'; | ||
* | ||
* try { | ||
* const decoded = contract.decodeMethodData(encodedData); | ||
* console.log(decoded.__method__); // Outputs: "setGreeting(string)" | ||
* console.log(decoded); // Outputs the detailed parameter data | ||
* // This tells that the method called was `setGreeting` with a single string parameter "Hello World": | ||
* // { | ||
* // __method__: 'setGreeting(string)', | ||
* // __length__: 1, | ||
* // '0': 'Hello World', | ||
* // _greeting: 'Hello World' | ||
* // } | ||
* } catch (error) { | ||
* console.error(error); | ||
* } | ||
* ``` | ||
* | ||
* ### createAccessList | ||
@@ -452,7 +519,3 @@ * This will create an access list a method execution will access when executed in the EVM. | ||
jsonInterface: Abi, | ||
addressOrOptionsOrContext?: | ||
| Address | ||
| ContractInitOptions | ||
| Web3ContractContext | ||
| Web3Context, | ||
addressOrOptionsOrContext?: Address | ContractInitOptions | Web3ContractContext | Web3Context, | ||
optionsOrContextOrReturnFormat?: | ||
@@ -483,6 +546,3 @@ | ContractInitOptions | ||
let provider; | ||
if ( | ||
typeof addressOrOptionsOrContext === 'object' && | ||
'provider' in addressOrOptionsOrContext | ||
) { | ||
if (typeof addressOrOptionsOrContext === 'object' && 'provider' in addressOrOptionsOrContext) { | ||
provider = addressOrOptionsOrContext.provider; | ||
@@ -494,6 +554,3 @@ } else if ( | ||
provider = optionsOrContextOrReturnFormat.provider; | ||
} else if ( | ||
typeof contextOrReturnFormat === 'object' && | ||
'provider' in contextOrReturnFormat | ||
) { | ||
} else if (typeof contextOrReturnFormat === 'object' && 'provider' in contextOrReturnFormat) { | ||
provider = contextOrReturnFormat.provider; | ||
@@ -742,2 +799,18 @@ } else { | ||
* | ||
* // decoding | ||
* myContract.deploy({ | ||
* input: '0x12345...', | ||
* // arguments: [123, 'My Greeting'] if you just need to decode the data, you can skip the arguments | ||
* }) | ||
* .decodeData('0x12345...0000012345678765432'); | ||
* > { | ||
* __method__: 'constructor', | ||
* __length__: 2, | ||
* '0': '123', | ||
* _id: '123', | ||
* '1': 'My Greeting', | ||
* _greeting: 'My Greeting', | ||
* } | ||
* | ||
* | ||
* // Gas estimation | ||
@@ -826,2 +899,10 @@ * myContract.deploy({ | ||
), | ||
decodeData: (data: HexString) => ({ | ||
...decodeMethodParams( | ||
abi as AbiFunctionFragment, | ||
data.replace(deployData as string, ''), | ||
false, | ||
), | ||
__method__: abi.type, // abi.type is constructor | ||
}), | ||
}; | ||
@@ -958,6 +1039,3 @@ } | ||
return ( | ||
String(log.returnValues[key]).toUpperCase() === | ||
String(filter[key]).toUpperCase() | ||
); | ||
return String(log.returnValues[key]).toUpperCase() === String(filter[key]).toUpperCase(); | ||
}); | ||
@@ -976,2 +1054,17 @@ }); | ||
public decodeMethodData(data: HexString): DecodedParams & { __method__: string } { | ||
const methodSignature = data.slice(0, 10); | ||
const functionsAbis = this._jsonInterface.filter(j => j.type !== 'error'); | ||
const abi = functionsAbis.find( | ||
a => methodSignature === encodeFunctionSignature(jsonInterfaceMethodToString(a)), | ||
); | ||
if (!abi) { | ||
throw new Web3ContractError( | ||
`The ABI for the provided method signature ${methodSignature} was not found.`, | ||
); | ||
} | ||
return { ...decodeMethodParams(abi, data), __method__: jsonInterfaceMethodToString(abi) }; | ||
} | ||
private _parseAndSetJsonInterface( | ||
@@ -988,5 +1081,3 @@ abis: ContractAbi, | ||
const functionsAbi = abis.filter(abi => abi.type !== 'error'); | ||
const errorsAbi = abis.filter(abi => | ||
isAbiErrorFragment(abi), | ||
) as unknown as AbiErrorFragment[]; | ||
const errorsAbi = abis.filter(abi => isAbiErrorFragment(abi)) as unknown as AbiErrorFragment[]; | ||
@@ -1007,5 +1098,3 @@ for (const a of functionsAbi) { | ||
abi.constant = | ||
abi.stateMutability === 'view' ?? | ||
abi.stateMutability === 'pure' ?? | ||
abi.constant; | ||
abi.stateMutability === 'view' ?? abi.stateMutability === 'pure' ?? abi.constant; | ||
@@ -1030,9 +1119,7 @@ abi.payable = abi.stateMutability === 'payable' ?? abi.payable; | ||
signature: methodSignature, | ||
method: contractMethod, | ||
method: exactContractMethod, | ||
}; | ||
// We don't know a particular type of the Abi method so can't type check | ||
this._methods[abi.name as keyof ContractMethodsInterface<Abi>] = this._functions[ | ||
methodName | ||
].method as never; | ||
this._methods[abi.name as keyof ContractMethodsInterface<Abi>] = contractMethod as never; | ||
@@ -1153,10 +1240,3 @@ // We don't know a particular type of the Abi method so can't type check | ||
block?: BlockNumberOrTag, | ||
) => | ||
this._contractMethodCall( | ||
methodAbi, | ||
abiParams, | ||
internalErrorsAbis, | ||
options, | ||
block, | ||
), | ||
) => this._contractMethodCall(methodAbi, abiParams, internalErrorsAbis, options, block), | ||
@@ -1178,2 +1258,3 @@ send: (options?: PayableTxOptions | NonPayableTxOptions): ContractMethodSend => | ||
encodeABI: () => encodeMethodABI(methodAbi, abiParams), | ||
decodeData: (data: HexString) => decodeMethodParams(methodAbi, data), | ||
@@ -1369,7 +1450,3 @@ createAccessList: async ( | ||
return (...params: unknown[]) => { | ||
const { topics, fromBlock } = encodeEventABI( | ||
this.options, | ||
abi, | ||
params[0] as EventParameters, | ||
); | ||
const { topics, fromBlock } = encodeEventABI(this.options, abi, params[0] as EventParameters); | ||
const sub = new LogsSubscription( | ||
@@ -1384,6 +1461,3 @@ { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
subscriptionManager: this.subscriptionManager as Web3SubscriptionManager< | ||
unknown, | ||
any | ||
>, | ||
subscriptionManager: this.subscriptionManager as Web3SubscriptionManager<unknown, any>, | ||
returnFormat, | ||
@@ -1401,6 +1475,3 @@ }, | ||
.catch((error: Error) => { | ||
sub.emit( | ||
'error', | ||
new SubscriptionError('Failed to get past events.', error), | ||
); | ||
sub.emit('error', new SubscriptionError('Failed to get past events.', error)); | ||
}); | ||
@@ -1407,0 +1478,0 @@ } |
@@ -157,2 +157,18 @@ /* | ||
export const decodeMethodParams = ( | ||
abi: AbiFunctionFragment | AbiConstructorFragment, | ||
data: HexString, | ||
methodSignatureProvided = true, | ||
) => { | ||
const value = | ||
methodSignatureProvided && data && data.length >= 10 && data.startsWith('0x') | ||
? data.slice(10) | ||
: data; | ||
if (!abi.inputs) { | ||
throw new Web3ContractError('No inputs found in the ABI'); | ||
} | ||
const result = decodeParameters([...abi.inputs], value); | ||
return result; | ||
}; | ||
export const decodeMethodReturn = (abi: AbiFunctionFragment, returnValues?: HexString) => { | ||
@@ -159,0 +175,0 @@ // If it was constructor then we need to return contract address |
@@ -215,2 +215,10 @@ /* | ||
/** | ||
* Decode raw result of method call into readable value(s). | ||
* | ||
* @param data - The data to decode. | ||
* @returns - The decoded data. | ||
*/ | ||
decodeData<SpecialInputs = Inputs>(data: HexString): SpecialInputs; | ||
/** | ||
* This method generates an access list for a transaction. You must specify a `from` address and `gas` if it’s not specified in options. | ||
@@ -405,2 +413,10 @@ * | ||
/** | ||
* Decode raw result of method call into readable value(s). | ||
* | ||
* @param data - The data to decode. | ||
* @returns - The decoded data. | ||
*/ | ||
decodeData<SpecialInputs = Inputs>(data: HexString): SpecialInputs; | ||
/** | ||
* This method generates an access list for a transaction. You must specify a `from` address and `gas` if it’s not specified in options. | ||
@@ -407,0 +423,0 @@ * |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
397762
7288