Skip to content

Common Patterns

David Kajpust edited this page Feb 14, 2019 · 4 revisions

Common Patterns

A list of common patterns for writing mappings, schemas, subgraph manifests, dealing with smart contracts patterns, and using AssemblyScript.

Mappings

Updating entities in the store efficiently

The most efficient way to update an existing entity in the store is to create a new entity, rather than loading it from the store with load(). The new entity will only overwrite the fields that it has changed from what exists in the store. The fields that are not updated at all , stay the same. The reason this is more efficient, is you get to avoid a whole load() operation from the store. You should only use load() when you need a value that exists in the store within your mapping. See an example below from the decentraland subgraph:

export function handleOrderSuccessful(event: OrderSuccessful): void {
  let orderID = event.params.id.toHex()
  let parcelId = event.params.assetId.toHex()
  // Mark the order as sold
  let order = new Order(orderID)
  order.type = 'parcel'
  order.status = 'sold'
  order.buyer = event.params.buyer
  order.price = event.params.totalPrice
  order.blockTimeCreatedAt = event.block.timestamp
  order.nftAddress = event.params.nftAddress
  order.save()
}

This entity already exists in the store, but we are just updating the entities fields to reflect that the order has been successful. There is no need to load!

Creating IDs for the entities

ID's must be unique in the store. If the event doesn't emit a unique ID already, you can sometimes use event.transaction.hash. It is also common that a uniqueID gets concatenated with a counter, as seen below:

0-0x0000000000000000000000000000000000000001
1-0x0000000000000000000000000000000000000001
2-0x0000000000000000000000000000000000000001

As long as you can come up with unique IDS for each entity in a pattern that makes sense, you should be good to go.

Subgraph Manifest

Switching Between Testnet and Mainnet

For quick testing, it is helpful to have the testnet address commented out right beside the mainnet address in the subgraph manifest. Then just point the graph nodes ethereum node connection to a testnet (i.e. rinkeby.infura.io) and you should be able to switch between testnet and mainnet easily. It is also useful to keep seperate postgres databases for each network. You could do createdb graph-node-mainnet and createdb graph-node-testnet.

Contracts

Dealing with Proxy Contracts

The Decentraland Subgraph is a great example of a subgraph that sources events from proxy contracts. Proxy contracts actually make it simple to track events, because all the events usually get emitted from one address, while the logic contracts can keep changing, and you don't have to worry about it. However, you do need to make sure you get the abi from each logic contract, and use that abi for the proxy contract. Which brings us to our next pattern!

Dealing with Upgradeable Contracts

One of the advantages of proxy contracts are that they allow you to upgrade the logic of your contracts. To be certain your subgraph is getting every piece of data correctly, you should investigate the abi and the events emitted by every single version of a contract that has been deployed to mainnet. This means you might have a few different abis, or events with different named fields in the future. This can get really tedious in subgraph production, but putting in the time up front is worth it. Decentraland is also a great example to follow for this.

AssemblyScript

Helper Functions

We have added a file with a few helper functions, that add functionality to the AssemblyScript Library. See them here