Using JavaScript to access secondary indexes on tables in a smart contract in WAX

Posted on

The tables in which we will store the information of our smart contracts in an EOSio type string, such as WAX Blockchain, can have up to a total of 20 indexes to facilitate access to the data. Some previous issues need to be taken into account:

  • The most important thing to keep in mind is that each index must refer to an integer numeric content. (The value of a name field can be considered numeric by serializing account names)
  • The primary index must be unique; all other indexes don't have to be unique.

To illustrate this explanation I will use one of the tables contained in my smart contract for the auction house WAX Arena, on WAX Blockchain.

This table saves the information for the active auctions and, as assumed, will be the most queried table in all possible ways. I have tried to anticipate the needs of consultation by creating 8 indexes:

  • primary_key: Primary and single key index (no repetitions). Accesses the table by auction ID.
  • getasset: Allows you to access the table through the IDs of the assets.
  • getowner: Allows access to the table through the names of the owners (who created the auction)
  • getbidder: Access the table through the names of the current bidder (maximum bidder and token winner candidate).
  • getdate: Access to the table is done by the auction creation date (UNIX format).
  • getfinish: Uses the duration of auctions as a search and access field.
  • getbids: Through this index we can check the number of bids for each active auction.
  • getvalue: Allows you to access the table by the value that the next bid will have. The intention is to allow you to sort the listing taking into account its price, but if an auction does not have bids that price is 0, so I have decided to take as a reference the value of the next bid to be made.

Reading the active auctions

To access the tables we will use the library for JavaScript eosjs (https://github.com/EOSIO/eosjs)

When running this code we will access the 'activebids' table of the smart contract 'waxarena3dk1' through the primary index, since we have not indicated any indexes. The list will show up to the first 100 records in the table sorted by the record ID.

Accessing through the secondary indexes of the table

Let's say we want to access the table taking into account the value of the auctioned assets. To do this we have defined the index "getvalue" which, if you look at the code of the smart contract, is at position 8.

In the JSON of the get_table_rows we need to add the necessary information regarding the index that we are going to use:

  • index_postion: Position that occupies the index in the smart contract. In this example, position 8
  • key_type: The data type of the index. In this case it is a 64-bit integer, which is represented as "i64"

I have added the "reverse" parameter to reverse the search order (from highest to lowest). I've also limited the search to the first 5 records.

If we wanted to get a list sorted by the most active auctions we would have to resort to the index "getbids" (7) and also specify reverse: true;

Squeezing the search through conditions

Let's create more specific searches. We've already seen how to get a list sorted by the most active auctions, but now we're going to filter that result by auctions that have more than 4 bids.

Now a new parameter comes into play: lower_bound.

lower_bound will search for records whose requested indexing key is greater than or equal to the specified value.

This would be like filtering with a conditional:

if bid_count > 4 -> valid data.

If we want to filter by asking for key values greater than the indicated key we can use upper_bound. So, if we change in the code:

lower_bound: 4

By

upper_bound: 4

we'll get auctions with 5 or more bids.

If bid_count > 4 -> valid data

We can also combine the two parameters into one reading. In this case the filter will behave in a special way; you will begin to qualify for records that pass the lower_bound but not records that meet upper_bound. Let's look at an example:

With this configuration we will be able to access all auctions whose number of bids is between 2 and 4, both included.

This setting is also useful for searching for records of a particular value, such as a seller's name:

With this code, we are filtering the results for those user-created auctions "radaquesttcg" thanks to the "getowner" filter, which occupies position 3.

I hope that with these examples the use of secondary indexes will be much easier from now on.