Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependency to 5.0.1, and add ERC4906 support #60

Merged
merged 15 commits into from
Mar 7, 2024
186 changes: 97 additions & 89 deletions src/datasources/erc721.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from '@graphprotocol/graph-ts'

import {
ERC721Contract,
ERC721Transfer,
} from '../../generated/schema'

Expand Down Expand Up @@ -40,34 +41,39 @@ import {

export function handleTransfer(event: TransferEvent): void {
let contract = fetchERC721(event.address)
if (contract != null) {
let token = fetchERC721Token(contract, event.params.tokenId)
let from = fetchAccount(event.params.from)
let to = fetchAccount(event.params.to)

token.owner = to.id
token.approval = fetchAccount(Address.zero()).id // implicit approval reset on transfer
token.save()

let ev = new ERC721Transfer(events.id(event))
ev.emitter = contract.id
ev.transaction = transactions.log(event).id
ev.timestamp = event.block.timestamp
ev.contract = contract.id
ev.token = token.id
ev.from = from.id
ev.to = to.id
ev.save()
}
if (contract == null) return

let token = fetchERC721Token(contract, event.params.tokenId)
let from = fetchAccount(event.params.from)
let to = fetchAccount(event.params.to)

token.owner = to.id
token.approval = fetchAccount(Address.zero()).id // implicit approval reset on transfer
token.save()

let ev = new ERC721Transfer(events.id(event))
ev.emitter = contract.id
ev.transaction = transactions.log(event).id
ev.timestamp = event.block.timestamp
ev.contract = contract.id
ev.token = token.id
ev.from = from.id
ev.to = to.id
ev.save()
}

export function handleConsecutiveTransfer(event: ConsecutiveTransfer): void {
let contract = fetchERC721(event.address)
if (contract != null) {
let from = fetchAccount(event.params.fromAddress)
let to = fetchAccount(event.params.toAddress)
if (contract == null) return

let from = fetchAccount(event.params.fromAddress)
let to = fetchAccount(event.params.toAddress)
let fromTokenId = event.params.fromTokenId.toU64()
let toTokenId = event.params.toTokenId.toU64()
ernestognw marked this conversation as resolved.
Show resolved Hide resolved

for (let tokenId = event.params.fromTokenId.toU64(); tokenId <= event.params.toTokenId.toU64(); ++tokenId) {
// Updates of blocks larger than 5000 tokens may DoS the subgraph, we skip them
if (toTokenId - fromTokenId <= 5000) {
for (let tokenId = fromTokenId; tokenId <= toTokenId; ++tokenId) {
let token = fetchERC721Token(contract, BigInt.fromU64(tokenId))
token.owner = to.id
token.approval = fetchAccount(Address.zero()).id // implicit approval reset on transfer
Expand All @@ -88,87 +94,89 @@ export function handleConsecutiveTransfer(event: ConsecutiveTransfer): void {

export function handleApproval(event: ApprovalEvent): void {
let contract = fetchERC721(event.address)
if (contract != null) {
let token = fetchERC721Token(contract, event.params.tokenId)
let owner = fetchAccount(event.params.owner)
let approved = fetchAccount(event.params.approved)

token.owner = owner.id // this should not be necessary, owner changed is signaled by a transfer event
token.approval = approved.id

token.save()
owner.save()
approved.save()

// let ev = new Approval(events.id(event))
// ev.emitter = contract.id
// ev.transaction = transactions.log(event).id
// ev.timestamp = event.block.timestamp
// ev.token = token.id
// ev.owner = owner.id
// ev.approved = approved.id
// ev.save()
}
if (contract == null) return

let token = fetchERC721Token(contract, event.params.tokenId)
let owner = fetchAccount(event.params.owner)
let approved = fetchAccount(event.params.approved)

token.owner = owner.id // this should not be necessary, owner changed is signaled by a transfer event
token.approval = approved.id

token.save()
owner.save()
approved.save()

// let ev = new Approval(events.id(event))
// ev.emitter = contract.id
// ev.transaction = transactions.log(event).id
// ev.timestamp = event.block.timestamp
// ev.token = token.id
// ev.owner = owner.id
// ev.approved = approved.id
// ev.save()
}

export function handleApprovalForAll(event: ApprovalForAllEvent): void {
let contract = fetchERC721(event.address)
if (contract != null) {
let owner = fetchAccount(event.params.owner)
let operator = fetchAccount(event.params.operator)
let delegation = fetchERC721Operator(contract, owner, operator)

delegation.approved = event.params.approved

delegation.save()

// let ev = new ApprovalForAll(events.id(event))
// ev.emitter = contract.id
// ev.transaction = transactions.log(event).id
// ev.timestamp = event.block.timestamp
// ev.delegation = delegation.id
// ev.owner = owner.id
// ev.operator = operator.id
// ev.approved = event.params.approved
// ev.save()
}
if (contract == null) return

let owner = fetchAccount(event.params.owner)
let operator = fetchAccount(event.params.operator)
let delegation = fetchERC721Operator(contract, owner, operator)

delegation.approved = event.params.approved

delegation.save()

// let ev = new ApprovalForAll(events.id(event))
// ev.emitter = contract.id
// ev.transaction = transactions.log(event).id
// ev.timestamp = event.block.timestamp
// ev.delegation = delegation.id
// ev.owner = owner.id
// ev.operator = operator.id
// ev.approved = event.params.approved
// ev.save()
}

export function handleMetadataUpdate(event: MetadataUpdateEvent) : void {
let erc721 = IERC721.bind(event.address)
let contract = fetchERC721(event.address)
if (contract == null) return

if (contract != null) {
if (contract.supportsMetadata) {
let token = fetchERC721Token(contract, event.params._tokenId)
let try_tokenURI = erc721.try_tokenURI(event.params._tokenId)
token.uri = try_tokenURI.reverted ? '' : try_tokenURI.value
token.save()
} else {
// add a warning ?
}
if (contract.supportsMetadata) {
_updateURI(contract, event.params._tokenId)
} else {
// add a warning ?
ernestognw marked this conversation as resolved.
Show resolved Hide resolved
}
}

export function handleBatchMetadataUpdate(event: BatchMetadataUpdateEvent) : void {
let erc721 = IERC721.bind(event.address)
let contract = fetchERC721(event.address)

if (contract != null) {
if (contract.supportsMetadata) {
const from = event.params._fromTokenId.toU64();
const to = event.params._toTokenId.toU64();
// Updates of blocks larger than 5000 tokens may DoS the subgraph, we skip them
if (to - from <= 5000) {
for (let tokenId =from; tokenId <= to; ++tokenId) {
let token = fetchERC721Token(contract, BigInt.fromU64(tokenId))
let try_tokenURI = erc721.try_tokenURI(BigInt.fromU64(tokenId))
token.uri = try_tokenURI.reverted ? '' : try_tokenURI.value
token.save()
}
if (contract == null) return

if (contract.supportsMetadata) {
let fromTokenId = event.params._fromTokenId.toU64()
let toTokenId = event.params._toTokenId.toU64()
// Updates of blocks larger than 5000 tokens may DoS the subgraph, we skip them
ernestognw marked this conversation as resolved.
Show resolved Hide resolved
if (toTokenId - fromTokenId <= 5000) {
for (let tokenId = fromTokenId; tokenId <= toTokenId; ++tokenId) {
_updateURI(contract, BigInt.fromU64(tokenId))
}
} else {
// add a warning ?
}
} else {
// add a warning ?
}
}

function _updateURI(contract: ERC721Contract, tokenId: BigInt) : void {
let erc721 = IERC721.bind(Address.fromBytes(contract.id))
let token = fetchERC721Token(contract, tokenId)
let try_tokenURI = erc721.try_tokenURI(tokenId)
token.uri = try_tokenURI.reverted ? '' : try_tokenURI.value
// If token was never minted (transfered) then the owner was set to 0 by default in `fetchERC721Token`
// In that case we don't want to save to token to the database.
if (token.owner != Address.zero()) {
token.save()
}
}
6 changes: 3 additions & 3 deletions src/fetch/erc721.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ export function fetchERC721Token(contract: ERC721Contract, identifier: BigInt):
let token = ERC721Token.load(id)

if (token == null) {
const AddressZero = fetchAccount(Address.zero())
fetchAccount(Address.zero())
token = new ERC721Token(id)
token.contract = contract.id
token.identifier = identifier
token.owner = AddressZero.id
token.approval = AddressZero.id
token.owner = Address.zero()
token.approval = Address.zero()

if (contract.supportsMetadata) {
let erc721 = IERC721.bind(Address.fromBytes(contract.id))
Expand Down