How to store data on the blockchain and query it?

Hi everyone,

I am sketching an application on Algorand and I need to store some actions that the users will make.
A sort of a bidding app, where each user will submit an offer related to a specific asset.

My questions is what would be the best way to store this on chain and also how would I then query it to get the best offer?

I was following this tutorial Example Digital Exchange Smart Contract Application | Algorand Developer Portal but the way it stores information on the user local storage and queries it trough the indexer does not seem efficient at all.

This sounds like a problem that can be solved via a stateful smart contract. If you only want to track the highest bid, you could simply keep track of the highest bidder’s address and the corresponding bid in 2 global states.

If there are multiple assets, then you will need more global states. Per the docs here, you can store a maximum of 64 key/value pairs in the global state of an app.

This is large enough storage to keep track of the top 5 bids so long as you have 6 or fewer assets to track (6 * 5 * 2 = 60 < 64).

To query the best offer, you would just need to read the global states.


Thank you so much for your answer.

So let me make this even harder.

Imagine I have this specific asset, and I get 20.000 bids, I want to not only show them on a gui, but also in the smart contract select the bigger one.

What you are telling me, is that I would always keep the best bid on the contract global state right?

But how would I query the full 20.000 bids?

Yes! global state seems the best way to track the highest bid.

That is a bit trickier! 20.000 bids would rule out the use of global state to track everything, so I think you would have to use the indexer with one of 2 approaches:

  1. Store the information in user local storage and query it through the indexer, as you mention above

  2. Iterate through the actual transactions sent to the contract with the indexer, looking for new bids

The difference in runtime will come from: reading from user local state (1) as opposed to parsing transactions of a certain address (2). If I had to guess, I would expect the second approach to be faster! But, you should always test!

If you’re willing to do a bit of cryptography, you can have the smart contract store a cryptographic hash (e.g., SHA256) of the list of bids. This way you can have the indexer gets all the bids (as @danger_dave explained) only once, and store all the bids inside any storage (e.g., AWS S3).
Then anyone can download the bids from the storage and check whether it matches the hash.
The person uploading the bids to the S3 bucket does not need to be trusted: if they cheat, the hash will be invalid.
(And if they cheat, you can always revert down to querying the indexer.)

To hash a list of bids, you can use the following process:

hash = SHA256(bid42 || SHA256(bid41 || SHA256(... || SHA256(bid1 || 0)))

Performance-wise, a usual computer can do at least 1M SHA256 hash of 64-byte values/s, so verification should take much less than one second.

Note: Maybe this solution is overkill and directly querying the indexer each time is good enough.