Skip to content

Latest commit

 

History

History
161 lines (128 loc) · 4.67 KB

README.md

File metadata and controls

161 lines (128 loc) · 4.67 KB

NFT Subgraph Workshop

Slides

Top Slide

Cheatsheet

Cheatsheet

Good subgraphs:

Info

Prerequisites

  • Install graph-cli: yarn global add @graphprotocol/graph-cli

First Steps

graph init \
    --studio \
    --protocol ethereum \
    --from-contract 0xc2c747e0f7004f9e8817db2ca4997657a7746928 \
    --index-events \
    --contract-name Hashmasks \
    --network mainnet \
    hashmasks hashmasks-subgraph
  • Inspect the source
  • Change startblock:
source:
    address: "0xc2c747e0f7004f9e8817db2ca4997657a7746928"
    abi: Hashmasks
    startBlock: 11743743

– Create new subgraph on Subgraph Studio named "Hashmasks"

  • graph auth --studio ...
  • yarn deploy

Remove unused Entities and Events

# schema.graphql
type Transfer @entity {
  id: ID!
  from: Bytes! # address
  to: Bytes! # address
  tokenId: BigInt! # uint256
}

Extend events

Make them immutable for performance improvements

type Transfer @entity(immutable: true) {
  id: ID!
  from: Bytes! # address
  to: Bytes! # address
  tokenId: BigInt! # uint256
  timestamp: BigInt!
  blockNumber: BigInt!
}

Use event.transaction.hash.toHex() + "-" + event.logIndex.toString() as the id for events

export function handleTransfer(event: TransferEvent): void {
  let entity = new Transfer(
    event.transaction.hash.toHex() + "-" + event.logIndex.toString()
  );
  entity.blockNumber = event.block.number;
  entity.timestamp = event.block.timestamp;
  entity.from = event.params.from;
  entity.to = event.params.to;
  entity.tokenId = event.params.tokenId;
  entity.save();
}

Store logical entities

  • Identify the important entities: Token, Owner, Contract
  • Link them
type Transfer @entity(immutable: true) {
  id: ID!
  from: Owner!
  to: Owner!
  token: Token!
  timestamp: BigInt!
  blockNumber: BigInt!
}

type Token @entity {
  id: ID!
  owner: Owner
  uri: String
  transfers: [Transfer!]! @derivedFrom(field: "token")
  contract: Contract
}

type Owner @entity {
  id: Bytes! # Use bytes as ID
  ownedTokens: [Token!]! @derivedFrom(field: "owner")
  balance: BigInt
}

type Contract @entity {
  id: ID!
  name: String
  symbol: String
  totalSupply: BigInt
  mintedTokens: [Token!]! @derivedFrom(field: "contract")
}

Other resources