> For the complete documentation index, see [llms.txt](https://calnix.gitbook.io/eth-dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calnix.gitbook.io/eth-dev/compendium/solidity-basics/reference-types/struct.md).

# struct

#### Picking up from the mapping example:

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.1;

contract MappingStructExmaple {

    struct Payment {
            uint amount;
            uint timestamp;
    }
    struct Balance {
        uint totalBalance;
        uint numPayments;
        mapping (uint => Payment) payments; //map numPayments to struct Payment - called payments
    }
    mapping(address => Balance) public balanceReceived;

    function getBalance() public view returns(uint){
        return address(this).balance;
    }

    function sendMoney() public payable {
        balanceReceived[msg.sender].totalBalance += msg.value;   // balance init @0. incremented from there.

        Payment memory payment = Payment(msg.value, block.timestamp);        //payment = Payment(amt, time)
        
        balanceReceived[msg.sender].payments[balanceReceived[msg.sender].numPayments] = payment;
        balanceReceived[msg.sender].numPayments++;
    }

    function partialWithdraw(uint _withdraw_amt, address payable _to) public {
        require(_withdraw_amt <= balanceReceived[msg.sender].totalBalance, "Balance exceeded");  //do you hav enuff to withdraw
            balanceReceived[msg.sender].totalBalance -= _withdraw_amt;       //update balances
            _to.transfer(_withdraw_amt);                                    // whr u want to send to?
    }

    function withdrawAllMoney(address payable _to) public {   //i can withdraw to addr of choice
        uint user_balance = balanceReceived[msg.sender].totalBalance;
        balanceReceived[msg.sender].totalBalance = 0;
        // checks-effect interaction pattern 
        _to.transfer(user_balance);
    }
}
```

### Create object:  **`Payment,`**

* Payment.amount&#x20;
* Payment.time

to reflect the value and datetime per transaction.&#x20;

### Create object: **`Balance`**,&#x20;

* Balance.totalBalance
* numPayments          *(initialized @ 0)*
* mapping(uint => Payment) payments

### Create : `mapping(address => Balance) public balanceReceived;`

Because mappings have no length, we can't do something like `balanceReceived.length` or `payments.length`. It's technically not possible. In order to store the length of the payments mapping, we have an additional helper variable `numPayments`.

So, if you want to the first payment for address 0x123... you could address it like this: `balanceReceived[0x123...].payments[0].amount = ...`. But that would mean we have static keys for the payments mapping inside the Balance struct. We actually store the keys in `numPayments`, that would mean, the current payment is in `balanceReceived[0x123...].numPayments`. If we put this together, we can do `balanceReceived[0x123...].payments[balanceReceived[0x123...].numPayments].amount = ...`.

{% hint style="warning" %}
numPayments **is not** number of payments made.&#x20;

no. of payments made = numPayments -1 (since we start frm 0) &#x20;

numPayments serves as an incrementing counter, to load the next "index" into the mapping to create a sequence starting with 0.&#x20;
{% endhint %}

#### balanceReceived

```solidity
    //mapping(address => uint) public balanceReceived;
    mapping(address => Balance) public balanceReceived;
```

In this new mapping, `balanceReceived[addr]` returns a struct:&#x20;

* `balanceReceived[addr].totalbalance`&#x20;
* `balanceReceived[addr].numPayments`

### sendmoney()

#### Updating total balance&#x20;

`balanceReceived[msg.sender].totalBalance += msg.value;`

`Balance.totalBalance += msg.value`

The first simplifies to the second line, where the Balance object is respective to the address fed in the first.

#### Updating individual payments as per ledger

Balance object, contains a mapping as a member, mapping (uint => Payment) payments; it maps an integer ("index") to an object Payment.

First we will create the individual transaction.

```solidity
// create the payment: insit + assign
// payment = Payment(amt, time)
Payment memory payment = Payment(msg.value, now);      //memory cos ref. type
```

Now we need to book the transaction into our "ledger", which is the mapping **`payments`**

```solidity
// booking .numPayment
// x= 0, on init
	balanceReceived[msg.sender].payments[x] = payment  //(Payment(msg.value, now))

the key x is:
	balanceReceived[msg.sender].numPayments (= 0, on init.)
	
nesting it:
	balanceReceived[msg.sender].payments[balanceReceived[msg.sender].numPayments] = payments
```

Loading the transaction is easy enough, from the first line. But how to create a running sequence?

We would need an index/counter -> `numPayments` -> key value of mapping **`payments`**.

* `uint numPayments` init as 0, so our counter starts at 0 for the first payment.

After booking a transaction, increment `numPayments` in preparation for the next transaction

* `balanceReceived[msg.sender].numPayments++;`

{% hint style="info" %}
Might wonder, why not use array? Gas costs; we rarely touch arrays.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnix.gitbook.io/eth-dev/compendium/solidity-basics/reference-types/struct.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
