-
Notifications
You must be signed in to change notification settings - Fork 3
Common Patterns
A list of common patterns for writing mappings, schemas, subgraph manifests, dealing with smart contracts patterns, and using AssemblyScript.
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!
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.
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
.
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!
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.
We have added a file with a few helper functions, that add functionality to the AssemblyScript Library. See them here