This package contains the source code for Unlock Protocol subgraph, that indexes and allows easier querying from the EVM blockchains using The Graph.
# create correct ABIs and config files
yarn prepare
# generate graph code from source
yarn codegen
# build Web Assemly binaries
yarn build <network-name>There is subgraph deployed for each network where Unlock Protocol is deployed. While code is similar for all, the addresses where the contracts are deployed vary, requiring a specifying config per network stored in networks.json.
The networks.json file is generated from our @unlock-protocol/networks package.
# build the `subgraph.yaml` with the correct contract address per network
yarn prepare:networksAre Unlock's contracts are upgradable, we parse the multiple ABIs that are required from our @unlock-protocol/contracts package.
# parse and build the require ABIs
yarn prepare:abisDeploy the latest subgraph code to the graph node.
export SUBGRAPH_DEPLOY_KEY=<api-key>
# build
yarn run build <network-name>
# deploy a single network
yarn run deploy <network-name>
# deploy all networks
yarn run deploy-all(preferred way) Run the tests using Docker
yarn test -d
Run coverage
yarn test -d -c
Show all events from different contract versions.
yarn show-eventsTo add a particular property to the subgraph you need to
- add to schema
- edit the mappings
- test it
- republish the new subgraph
@@ -7,6 +7,7 @@ type Lock @entity {
version: BigInt!
+ maxNumberOfKeys: BigInt
keys: [Key!] @derivedFrom(field: "lock")
}Rebuild the code
yarn codegen
in src/unlock.ts, to store data into the graph
export function handleNewLock(event: NewLock): void {
...
+ // make sure we check for revert to previous various versions from breaking
+ let maxNumberOfKeys = lockContract.try_maxNumberOfKeys()
+ if (!publicLockVersion.reverted) {
+ lock.maxNumberOfKeys = maxNumberOfKeys.value
+ }
+The unit tests are used to make sure we properly handle the data from a specific event. We test event handlers with known data. For instance, the event NewLock(address,address) has a handler called handleNewLock that stores the data in the graph.
We create a "fake" event with intended parameters to pass the handler function from our library. We use a createNewLockEvent in tests/lock-utils.ts that creates an event, then test it as follow:
import { handleNewLock } from '../src/unlock'
import { maxNumberOfKeys } from './constants'
describe('Describe Lock creation', () => {
beforeAll(() => {
const newLockEvent = createNewLockEvent(
Address.fromString(lockOwner),
Address.fromString(lockAddress)
)
handleNewLock(newLockEvent)
})
afterAll(() => {
clearStore()
})
test('Lock created and stored', () => {
assert.entityCount('Lock', 1)
...
assert.fieldEquals('Lock', lockAddress, 'maxNumberOfKeys', maxNumberOfKeys)
...
})If the handler does any calls to a contract, this will have to be mocked. All mocks are stored in tests/mocks.
import { maxNumberOfKeys } from './constants'
createMockedFunction(
Address.fromString(lockAddress),
'maxNumberOfKeys',
'maxNumberOfKeys():(uint256)'
)
.withArgs([])
.returns([ethereum.Value.fromUnsignedBigInt(BigInt.fromU32(maxNumberOfKeys))])To retrieve the error message for failed subgraphs - on the hosted service
- Find your Deployment ID ("Qm....")
- Go to https://graphiql-online.com/
- Enter API https://api.thegraph.com/index-node/graphql
- Run Query:
{
indexingStatuses(subgraphs: ["Qm..."]) {
subgraph
synced
health
entityCount
fatalError {
handler
message
deterministic
block {
hash
number
}
}
chains {
chainHeadBlock {
number
}
earliestBlock {
number
}
latestBlock {
number
}
}
}
}