Advanced features
Methods in events
For some use cases it could be helpful to be able to call a method when a certain event occurs.
One use case is recording all erc20 Transfer
events, and wanting to parse the value using the decimals.
We don't know the decimals in advance, so we can call decimals()
at the time the event occurs. This is the syntax:
query eth_transfers {
chain = "ethereum"
event Transfer {
abi = "erc20.abi.json"
outputs = ["from", "to", "value"]
// Will automatically know to call the method on the
// event address
method decimals {
outputs = ["decimals"]
}
transform {
value = parse_decimals(value, decimals)
}
}
save {
...
}
note
Since decimals
stay the same per token, the result is cached per token, resulting in a lot less calls
for schema's like this.
Loops
Sometimes, you will want to execute a query for a lot of different addresses or chains. One example
could be to listen for Transfer
events on a couple stablecoins, like USDT, USDC and DAI. Another example could
be cross-chain queries, where you want to run the same query on a different chain with a different smart contract address.
For this, apollo
has loops. The loop
block is a top-level element, and always requires an items
property.
This property will contain the elements you want to loop over. Finally you define your query, with access
to each item
element. Let's look at an example.
Imagine you want to see the mid prices of both the Sushiswap USDC-ETH pool on Arbitrum, and the Uniswap
USDC-ETH pool on Ethereum. The variables are thus the chain
and the address
, which we can store
in the loop items
. We can then define our query, and the loop elements will be found in item
.
Make sure to save item.chain
, otherwise you won't be able to differentiate the output.
loop {
items = [
{chain = "arbitrum", address = "0x905dfCD5649217c42684f23958568e533C711Aa3"},
{chain = "ethereum", address = "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"},
]
query usdc_eth_reserves {
// Get the element chain
chain = item.chain
contract {
// Get the element address
address = item.address
abi = "unipair.abi.json"
// Call getReserves
method getReserves {
outputs = ["_reserve0", "_reserve1"]
}
transform {
eth_reserve = parse_decimals(_reserve0, 18)
usdc_reserve = parse_decimals(_reserve1, 6)
}
}
save {
block = blocknumber
timestamp = timestamp
// Save chain to differentiate outputs
chain = item.chain
usdc_reserve = usdc_reserve
eth_reserve = eth_reserve
// Calculate mid price
mid_price = usdc_reserve / eth_reserve
}
}
}
Custom Helper Functions
For some very common operations, apollo
has helper functions. For now, these are
limited to balance
, for getting native balances, and token_balance
, for getting
ERC20 token balances. See some examples here