When it comes to indexing your tables, you have to be mindful of which data you'll need to access quickly/frequently within your contract. Less frequently accessed data can be handed using an off-chain indexer, or even a simple API call if you aren't storing tons of rows in your tables.
There are several options here, I'll outline the most common approaches below.
available_primary_key
This is the most straightforward of all. This method will just use the next available key, based on the highest value currently stored in your table. For example...
Let's say you have a table, and you are 100% certain that each user in the table will only need 1 row. You can handle this simply by using the user.value
struct[[eosio::table, eosio::contract(CONTRACT_NAME)]]balances { eosio::name wallet; eosio::asset balance;uint64_tprimary_key() const { returnwallet.value; }};usingbalances_table= eosio::multi_index< "balances"_n,balances >;ACTIONsomeaction( constname& user ){require_auth( user ); balances_table bal_t=balances_table( _self,_self.value );auto itr =bal_t.require_find( user.value,"you do not have a balance" );}
By uint128_t Of 2 Values
Let's say for example, you have an NFT market contract. All of the drop purchases are stored in a single table, under the same scope. Each drop can contain multiple orders, and each user can have orders for multiple drops. Using the drop ID, or the user's wallet as a primary index will not work in this case. You can solve this using the following method.
#definemix64to128(a, b) (uint128_t(a) <<64|uint128_t(b))struct[[eosio::table, eosio::contract(CONTRACT_NAME)]]orders {uint64_t order_id; eosio::name wallet;uint64_t drop_id; uint64_tprimary_key() const { return order_id; }uint128_tsecondary_key() const { returnmix64to128( wallet.value, drop_id ); }};usingorders_table= eosio::multi_index<"orders"_n, orders,eosio::indexed_by<"userdropmix"_n, eosio::const_mem_fun<orders,uint128_t,&orders::secondary_key>>>;ACTIONfindorder( constname& wallet,constuint64_t& drop_id ){ orders_table orders_t=orders_table( _self,_self.value );auto orders_secondary =orders_t.get_index<"userdropmix"_n>();uint128_t user_drop_key =mix64to128( wallet.value, drop_id );auto itr =orders_secondary.require_find( user_drop_key,"no match found for this user + drop" );}
By checksum256
Sometimes 128 bits is not enough to meet the needs for an index. For example, you may have a contract where you need to index by a combination of user, token and contract and be able to easily find that key. You can accomplish this by using a checksum256 hash, as demonstrated below.