I'm prototyping a simple smart contract for donations. My intention is to have a mapping for balances and another mapping for structs. The issue is that I get the following error:
TypeError: Member "push" not found or not visible after argument-dependent lookup in struct donMapping.Donation storage ref. --> sc.sol:79:9: | 79 | donations[_recipient].push(Donation(id++,amount,_donor,_msg,block.timestamp)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^
I'm guessing that donations[_recipient] is not recognized as a struct, so push can't be used there (similar syntax as I use for pushing into a regular struct i.e. donation.push(Donation(...))).
What is the proper way to push a struct into a mapping of structs? I tried searching through existing questions in stackexchange with this error, but none seemed to apply to this case. Here's the full prototype code:
contract donMapping{
struct Donation {
uint id;
uint amount;
string donor;
string msg;
uint timestamp; //seconds since unix start
}
uint amount = 0;
uint id = 0;
mapping(address => uint) public balances;
mapping(address => Donation) public donations;
Donation[] public donation;
function donate(address _recipient, string calldata _donor, string calldata _msg) public payable {
require(msg.value > 0, "The donation needs to be >0 in order for it to go through");
amount = msg.value;
balances[_recipient] += amount;
donations[_recipient].push(Donation(id++,amount,_donor,_msg,block.timestamp));
}
}
Thanks!
Edit: Thanks to bguiz's answer I realized what I wanted to do was have a mapping of struct arrays (so the only thing missing was the [] on the second mapping definition). Here's the working solution I came up with:
contract mappingOfArrayOfStructs{
struct Donation {
uint id;
uint amount;
string donor;
string msg;
uint timestamp; //seconds since unix start
}
uint amount = 0;
uint id = 0;
mapping(address => uint) public balances;
mapping(address => Donation[]) public donationsMap;
function donate(address _recipient, string calldata _donor, string calldata _msg) public payable {
require(msg.value > 0, "The donation needs to be >0 in order for it to go through");
amount = msg.value;
balances[_recipient] += amount;
donationsMap[_recipient].push(Donation(id++,amount,_donor,_msg,block.timestamp));
}
function donations_getter(address _recipient, uint _id) public view returns (Donation[] memory){
return donationsMap[_recipient];//shows up as a tuple
}
}
.push
method. Unlike arrays, mappings already have all the keys possible already declared and mapped to 0 values. So you don't actually push a new element to the mapping, you just re-declare the key to be equal to the new value like in @bguiz's answer.