Question: How does one parse the contents of a custom struct emitted as an indexed parameter with a contract event? Or, is it even possible to emit and then parse a custom struct from the event args?
I'm working on a generational NFT minting solidity contract which tracks each generation via a counter and a mapping of an internally defined struct GenInfo
:
// Generation Counter
uint256 private s_generationCounter;
// Generation Struct
struct GenInfo {
uint256 mintPrice;
uint256 mintCap;
uint256 supplyCap;
uint256 startTime;
string metadataCID;
}
// Mapping of generation number to GenInfo
mapping(uint256 => GenInfo) s_generationInfo;
An event is emitted with 2 indexed parameters when a new generation is created:
event NewGenerationCreated(
uint256 indexed generation,
GenInfo indexed genInfo
);
I am using ethers.js to submit the transaction and fetch the transaction receipt and would like to be able to decode the values within the indexed GenInfo
struct emitted with the NewGenerationCreated
event into a readable JavaScript object:
// createGenerationTxReceipt.events[0].args
[
BigNumber { _hex: '0x01', _isBigNumber: true },
{
_isIndexed: true,
hash: '0xc7ca7439fa64d98b58ae965bc052bcf154fcb3f7deec49e026bc7091c4fb4d72',
constructor: [Function: Indexed] { isIndexed: [Function (anonymous)] }
}
]
I can reconstruct the first param (uint256 generation
) with
const newGeneration = creatGenerationTxReceipt.events[0].args[0].toNumber()
// newGeneration = 1
However, I'm having difficulty figuring out how to parse or decode the data format of the second parameter, my custom GenInfo
struct, into a JavaScript object.
const genInfo = creatGenerationTxReceipt.events[0].args[1]
// genInfo - how to parse this into a JavaScript object?
{
_isIndexed: true,
hash: '0xc7ca7439fa64d98b58ae965bc052bcf154fcb3f7deec49e026bc7091c4fb4d72',
constructor: [Function: Indexed] { isIndexed: [Function (anonymous)] }
}
I have tried using the interface associated with the contract to parse the logs but still just receive the same opaque object:
const data = creatGenerationTxReceipt.events[0].data
const topics = creatGenerationTxReceipt.events[0].topics
const logDescription = generationalNftContract.interface.parseLog({ data, topics })
// logDescripton.args
[
BigNumber { _hex: '0x01', _isBigNumber: true },
{
_isIndexed: true,
hash: '0x88f9f72724878230f7fe58eaf66cb38f2b5c3ba477c38faf1be850482903ec51',
constructor: [Function]
}
]
In the ABI of the contract, I can see that the NewGenerationCreated event has an input that matches the internalType of the struct:
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "generation",
"type": "uint256"
},
{
"components": [
{
"internalType": "uint256",
"name": "mintPrice",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "mintCap",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "supplyCap",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "startTime",
"type": "uint256"
},
{
"internalType": "string",
"name": "metadataCID",
"type": "string"
}
],
"indexed": true,
"internalType": "struct GenerationalNftContract.GenInfo",
"name": "genInfo",
"type": "tuple"
}
],
"name": "NewGenerationCreated",
"type": "event"
}
This gives me the impression that there is a way to decode the output of the event args to reconstruct this input data from the struct GenerationalNftContract.GenInfo
internalType to an object comprised of the struct's key/values by their internalType. However, in all my googling and reading through the ethers.js and solidity docs I'm unable to find a suitable method to parse this data.
Any help on this would be much appreciated!