Cover photo

Testing for Auction Subgraphs

Hey everyone!

In this article, we will be breaking down testing an event handler and its associated test cases in the wild world of subgraphs on The Graph Network. Subgraphs are amazing tools that allow you to index blockchain data more efficiently, but it's crucial to ensure that they're working as intended. So let’s dive into the intricacies of writing test cases for an AssemblyScript event handler using the matchstick-as library. 😎

Installation and Setup

Before diving into writing test cases for subgraphs, it is essential to have the required tools and libraries installed and set up on your local machine. The Graph documentation, is available at the following link.

https://thegraph.com/docs/en/developing/unit-testing-framework/#getting-started

The doc provides an excellent guide on how to install and configure your development environment for The Graph Network.

Code

The test cases can be found inside the test folder in the Github repo below.

https://github.com/Gnosis-Auction/auction-graph/tree/main/tests

In this article, we will be testing a function handler used to handle the NewAuction event emitted by the EasyAuction smart contract.

  • handleNewAuction: NewAuction event handler

https://gist.github.com/Asper9/99a1e15f4893a2815b42c086ab2075c3

  • Test case for handleNewAuction

https://gist.github.com/Asper9/ae1797634ad23c4fd49f9c8ed9058db4

Let’s break down the mapping handler and the corresponding test case further.

Code breakdown

handleNewAuction

  • First, we extract information from the event parameter. To find all the values accessible, you can hover over event.params in your IDE or check what values are emitted by the event.

let eventTimeStamp = event.block.timestamp;
let sellAmount = event.params._auctionedSellAmount;
let buyAmount = event.params._minBuyAmount;
// ...and so on
  • Then, we try to load a user with the given userId. If the user doesn't exist, the function simply returns.

let user = User.load(userId.toString());
if (!user) {
    return;
}
  • Next, we fetch the auction and token contract details.

let biddingERC20Contract = ERC20Contract.bind(addressBiddingToken);
let auctioningERC20Contract = ERC20Contract.bind(addressAuctioningToken);
let auctionContract = EasyAuction.bind(event.address);
// ...fetch contract details

Note: You can check the AssemblyScript API documentation to check out all the available apis

https://thegraph.com/docs/en/developing/assemblyscript-api/

  • We create a new order entity and populate its fields.

let order = new Order(entityId);
order.auctionId = auctionId;
order.buyAmount = buyAmount;
// ...order.save
  • Finally, we create a new auction detail entity and populate its fields.

let auctionDetails = new AuctionDetail(auctionId.toString());
auctionDetails.auctionId = auctionId;
auctionDetails.exactOrder = order.id;
// ...auctionDetails.save

Test Case

The purpose of this test case is to make sure that our handleNewAuction function can handle a custom NewAuction event. It checks whether a new AuctionDetail entity was added in store with the relevant details.

  • We start by adding a user to the store

// Add a user to the store
let user = new User("1");
// import { Bytes } from "@graphprotocol/graph-ts"; 
user.address = Bytes.fromHexString(addresses.get("userAddress1"));
user.auctions = new Array();
user.save();
  • Create a new AuctionEvent

// Create a new auction event
let newAuctionEvent = createNewAuctionEvent(
    0x1, // auctionId
    addresses.get("auctioningTokenAddress"),
    addresses.get("biddingTokenAddress"),
    dates.get("orderCancellationEndDate1"),
    dates.get("auctionEndDate1"),
    0x1, // userId
    TOKENS.get("1000"), // auctionedSellAmount
    TOKENS.get("2000"), // minBuyAmount
    TOKENS.get("1"), // minimumBiddingAmount
    TOKENS.get("100"), // minimumFundingThreshold
    addresses.get("zeroAddress"), // allowListContract
    "0x" // allowListData
);
  • Mock the function calls the handler will make to the smart contract

// Mock function calls which the handleAuction handler will make to the auction/token contracts
mockAuctionDataFunctionCall(
    BigInt.fromString("1"), // auctionId
    addresses.get("auctioningTokenAddress"),
    addresses.get("biddingTokenAddress"),
    dates.get("orderCancellationEndDate1"),
    dates.get("auctionEndDate1"),
    encodedOrders.get("initialAuctionOrder1"),
    TOKENS.get("1"), // minimumBiddingAmountPerOrder
    0, // interimSumBidAmount
    encodedOrders.get("startingOrder"), // interimOrder
    encodedOrders.get("zeroOrder"), // clearingPriceOrder
    0, // volumeClearingPriceOrder
    false, // minFundingThresholdNotReached
    false, // isAtomicClosureAllowed
    0, // feeNumerator
    TOKENS.get("100") // minFundingThresold
);

mockTokenSymbol(auctioningTokenContractAddress, "AUT");
mockTokenDecimals(auctioningTokenContractAddress, 18);

mockTokenSymbol(biddingTokenContractAddress, "BDT");
mockTokenDecimals(biddingTokenContractAddress, 18);
  • Pass the NewAuction event to the handleNewAuction event handler

// Add the auction to the entity store by passing it to the handleNewAuction handler
handleNewAuction(newAuctionEvent);
  • Finally make assertions to check whether the NewAuction event was handled properly

// Assertions
assert.entityCount(entityTypes.get("AuctionDetail"), 1);
log.success("Assert AuctionDetail entity count is 1", []);

assert.fieldEquals(
    entityTypes.get("AuctionDetail"),
    "1",
    "exactOrder",
    "1-1000000000000000000000-2000000000000000000000-1"
);

log.success("handleNewAuction adds a New Auction Detail entry to the store",	[]);

Conclusion

In this article, we explored the process of testing an event handler and its associated test case in the context of subgraphs on The Graph Network. By breaking down the handleNewAuction function and its corresponding test case, we demonstrated how to ensure that the event handler is working correctly and efficiently.

The use of the matchstick-as library simplifies the testing process for AssemblyScript event handlers, making it easier to develop robust and reliable subgraphs. Proper testing is crucial to the success of any subgraph project, as it guarantees that the indexed data is accurate and relevant.

Now that you have a solid understanding of how to write test cases for event handlers, you can confidently build and deploy your subgraphs on The Graph Network, ensuring that your blockchain data is indexed efficiently and accurately. Keep on testing and happy coding!

Links

  • The Graph Docs

https://thegraph.com/docs/en/

  • Auction FrontEnd Github repository

https://thegraph.com/docs/en/

  • Auction Contracts Github repository

https://github.com/Gnosis-Auction/auction-contracts

  • Auction Subgraph Github repository

https://github.com/Gnosis-Auction/auction-graph