Skip to content

Commit

Permalink
ON-553: Refactor handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Lima committed Dec 12, 2023
1 parent 9fca751 commit 785fe0b
Show file tree
Hide file tree
Showing 43 changed files with 1,633 additions and 363 deletions.
586 changes: 586 additions & 0 deletions abis/SftRolesRegistry.json

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ enum NftType {
}

type Nft @entity {
id: ID! # tokenId + tokenAddress
id: ID! # tokenAddress + tokenId
tokenAddress: String!
tokenId: BigInt!
owner: Account!
Expand All @@ -22,7 +22,7 @@ type Account @entity {
}

type RoleAssignment @entity {
id: ID! # rolesRegistryAddress + grantorAddress + tokenId + tokenAddress + granteeAddress + roleHash
id: ID! # rolesRegistryAddress + grantorAddress + tokenAddress + tokenId + granteeAddress + roleHash
role: Role!
nft: Nft!
grantor: Account!
Expand All @@ -35,10 +35,11 @@ type RoleAssignment @entity {
}

type Role @entity {
id: ID! # rolesRegistryAddress + tokenId + tokenAddress + roleHash
id: ID! # rolesRegistryAddress + tokenAddress + tokenId + roleHash
rolesRegistry: RolesRegistry!
roleHash: Bytes!
nft: Nft!
lastNonRevocableExpirationDate: BigInt!
roleAssignments: [RoleAssignment!] @derivedFrom(field: "role")
}

Expand All @@ -48,10 +49,20 @@ type RoleApproval @entity {
grantor: Account!
operator: Account!
tokenAddress: String!
isApproved: Boolean!
}

type RolesRegistry @entity {
id: ID! # contractAddress
roles: [Role!] @derivedFrom(field: "rolesRegistry")
roleApprovals: [RoleApproval!] @derivedFrom(field: "rolesRegistry")
}

# Helper Entities

type HelperNftOwnership @entity {
id: ID! # tokenAddress + tokenId + owner
nft: Nft!
originalOwner: Account!
isSameOwner: Boolean!
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function handleTransferBatch(event: TransferBatch): void {
const amounts = event.params.values

if (tokenIds.length != amounts.length) {
log.error('[erc1155][handleTransferBatch] tokenIds length {} does not match amounts length {}, tx {}', [
log.error('[erc-1155][handleTransferBatch] tokenIds length {} does not match amounts length {}, tx {}', [
tokenIds.length.toString(),
amounts.length.toString(),
event.transaction.hash.toHex(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function handleTransferSingle(event: TransferSingle): void {

const nft = upsertERC1155Nft(tokenAddress, tokenId, amount, fromAddress, toAddress)

log.warning('[erc1155][handleTransferSingle] NFT {} amount {} transferred from {} to {} tx {}', [
log.warning('[erc-1155][handleTransferSingle] NFT {} amount {} transferred from {} to {} tx {}', [
nft.id,
amount.toString(),
fromAddress,
Expand Down
1 change: 1 addition & 0 deletions src/erc-721/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { handleTransfer } from './transfer-handler'
28 changes: 28 additions & 0 deletions src/erc-721/transfer-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Transfer } from '../../generated/ERC721/ERC721'
import { upsertERC721Nft, upsertHelperNftOwnership } from '../../utils'
import { log } from '@graphprotocol/graph-ts'

/**
@dev This handler is called when a token is transferred.
@param event Transfer The event emitted by the contract.
Example:
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
*/
export function handleTransfer(event: Transfer): void {
const tokenAddress = event.address.toHex()
const tokenId = event.params.tokenId
const from = event.params.from.toHex()
const to = event.params.to.toHex()

const nft = upsertERC721Nft(tokenAddress, tokenId, to)
upsertHelperNftOwnership(nft, from)
upsertHelperNftOwnership(nft, to)

log.warning('[erc-721][handleTransfer] NFT {} transferred from {} to {} tx {}', [
tokenId.toString(),
from,
to,
event.transaction.hash.toHex(),
])
}
3 changes: 3 additions & 0 deletions src/erc-7432/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { handleRoleGranted } from './role-granted-handler'
export { handleRoleRevoked } from './role-revoked-handler'
export { handleRoleApprovalForAll } from './role-approval-for-all-handler'
30 changes: 30 additions & 0 deletions src/erc-7432/role-approval-for-all-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { RoleApprovalForAll } from '../../generated/ERC7432/ERC7432'
import { findOrCreateRoleApproval, findOrCreateAccount, findOrCreateRolesRegistry } from '../../utils'
import { log } from '@graphprotocol/graph-ts'

/**
@dev This handler is called when a role approval for all is set.
@param event RoleApprovalForAll The event emitted by the contract.
Example:
event RoleApprovalForAll(address indexed _tokenAddress, address indexed _operator, bool _isApproved);
*/
export function handleRoleApprovalForAll(event: RoleApprovalForAll): void {
const rolesRegistryAddress = event.address.toHex()
const grantorAddress = event.transaction.from.toHex()
const operatorAddress = event.params._operator.toHex()
const tokenAddress = event.params._tokenAddress.toHex()
const isApproved = event.params._isApproved

const grantor = findOrCreateAccount(grantorAddress)
const operator = findOrCreateAccount(operatorAddress)
const rolesRegistry = findOrCreateRolesRegistry(rolesRegistryAddress)
const roleApproval = findOrCreateRoleApproval(rolesRegistry, grantor, operator, tokenAddress)
roleApproval.isApproved = isApproved
roleApproval.save()

log.warning('[erc-7432][handleRoleApprovalForAll] Updated RoleAssignment Approval: {} Tx: {}', [
roleApproval.id,
event.transaction.hash.toHex(),
])
}
61 changes: 61 additions & 0 deletions src/erc-7432/role-granted-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { log } from '@graphprotocol/graph-ts'
import { RoleGranted } from '../../generated/ERC7432/ERC7432'
import { Account, Nft } from '../../generated/schema'
import { generateERC721NftId, findOrCreateAccount, upsertRoleAssignment } from '../../utils'

/**
@dev This handler is called when a role is granted.
@param event RoleGranted The event emitted by the contract.
Example:
event RoleGranted(
bytes32 indexed _role,
address indexed _tokenAddress,
uint256 indexed _tokenId,
address _grantor,
address _grantee,
uint64 _expirationDate,
bool _revocable,
bytes _data
);
*/
export function handleRoleGranted(event: RoleGranted): void {
const tokenId = event.params._tokenId
const tokenAddress = event.params._tokenAddress.toHex()

const nftId = generateERC721NftId(tokenAddress, tokenId)
const nft = Nft.load(nftId)
if (!nft) {
log.error('[erc-7432][handleRoleGranted] NFT {} does not exist, tx {} skipping...', [
nftId,
event.transaction.hash.toHex(),
])
return
}

const grantorAddress = event.params._grantor.toHex()
const grantorAccount = Account.load(grantorAddress)
if (!grantorAccount) {
log.error('[erc-7432][handleRoleGranted] grantor {} does not exist, tx {} skipping...', [
grantorAddress,
event.transaction.hash.toHex(),
])
return
}
if (grantorAccount.id != nft.owner) {
log.error('[erc-7432][handleRoleGranted] NFT {} is not owned by {}, tx {} skipping...', [
nftId,
grantorAccount.id,
event.transaction.hash.toHex(),
])
return
}

const granteeAccount = findOrCreateAccount(event.params._grantee.toHex())
const roleAssignment = upsertRoleAssignment(event, grantorAccount, granteeAccount, nft)
log.warning('[erc-7432][handleRoleGranted] roleAssignment: {} NFT: {} Tx: {}', [
roleAssignment.id,
nftId,
event.transaction.hash.toHex(),
])
}
87 changes: 87 additions & 0 deletions src/erc-7432/role-revoked-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { BigInt, log } from '@graphprotocol/graph-ts'
import { RoleRevoked } from '../../generated/ERC7432/ERC7432'
import { Account, Nft, RoleAssignment } from '../../generated/schema'
import { findOrCreateRole, findOrCreateRolesRegistry, generateERC721NftId, generateRoleAssignmentId } from '../../utils'

/**
@dev This handler is called when a role is revoked.
@param event RoleRevoked The event emitted by the contract.
Example:
event RoleRevoked(
bytes32 indexed _role,
address indexed _tokenAddress,
uint256 indexed _tokenId,
address _revoker,
address _grantee
);
*/
export function handleRoleRevoked(event: RoleRevoked): void {
const tokenId = event.params._tokenId
const tokenAddress = event.params._tokenAddress.toHexString()

const nftId = generateERC721NftId(tokenAddress, tokenId)
const nft = Nft.load(nftId)
if (!nft) {
log.error('[erc-7432][handleRoleRevoked] NFT {} does not exist, tx {} skipping...', [
nftId,
event.transaction.hash.toHex(),
])
return
}

const revokerAddress = event.params._revoker.toHex()
const revoker = Account.load(revokerAddress)
if (!revoker) {
log.error('[erc-7432][handleRoleGranted] revoker {} does not exist, tx {} skipping...', [
revokerAddress,
event.transaction.hash.toHex(),
])
return
}

const granteeAddress = event.params._grantee.toHex()
const grantee = Account.load(granteeAddress)
if (!grantee) {
log.error('[erc-7432][handleRoleGranted] grantee {} does not exist, tx {} skipping...', [
granteeAddress,
event.transaction.hash.toHex(),
])
return
}

const rolesRegistry = findOrCreateRolesRegistry(event.address.toHex())
const roleAssignmentId = generateRoleAssignmentId(rolesRegistry, revoker, grantee, nft, event.params._role)
const roleAssignment = RoleAssignment.load(roleAssignmentId)
if (!roleAssignment) {
log.error('[erc-7432][handleRoleRevoked] RoleAssignment {} does not exist, tx {} skipping...', [
roleAssignmentId,
event.transaction.hash.toHex(),
])
return
}
if (event.block.timestamp > roleAssignment.expirationDate) {
log.error('[erc-7432][handleRoleRevoked] RoleAssignment {} already expired, tx {} skipping...', [
roleAssignmentId,
event.transaction.hash.toHex(),
])
return
}

roleAssignment.expirationDate = event.block.timestamp
roleAssignment.save()

if (!roleAssignment.revocable) {
// smart contract validate that if a role is not revocable, it can only be revoked by the grantee
// in that case, we can set the lastNonRevocableExpirationDate to zero, assuming that the grantee is revoking its own role
const role = findOrCreateRole(rolesRegistry, nft, event.params._role)
role.lastNonRevocableExpirationDate = BigInt.zero()
role.save()
}

log.warning('[[erc-7432]handleRoleRevoked] Revoked RoleAssignment: {} NFT: {} tx: {}', [
roleAssignmentId,
nftId,
event.transaction.hash.toHex(),
])
}
18 changes: 0 additions & 18 deletions src/erc721/index.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/erc7432/index.ts

This file was deleted.

35 changes: 0 additions & 35 deletions src/erc7432/role/role-approval-handler.ts

This file was deleted.

3 changes: 3 additions & 0 deletions src/sftRolesRegistry/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { handleRoleGranted } from './role-granted-handler'
export { handleRoleRevoked } from './role-revoked-handler'
export { handleRoleApprovalForAll } from './role-approval-for-all-handler'
30 changes: 30 additions & 0 deletions src/sftRolesRegistry/role-approval-for-all-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { RoleApprovalForAll } from '../../generated/SftRolesRegistry/SftRolesRegistry'
import { findOrCreateRoleApproval, findOrCreateAccount, findOrCreateRolesRegistry } from '../../utils'
import { log } from '@graphprotocol/graph-ts'

/**
@dev This handler is called when a role approval for all is set.
@param event RoleApprovalForAll The event emitted by the contract.
Example:
event RoleApprovalForAll(address indexed _tokenAddress, address indexed _operator, bool _isApproved);
*/
export function handleRoleApprovalForAll(event: RoleApprovalForAll): void {
const rolesRegistryAddress = event.address.toHex()
const grantorAddress = event.transaction.from.toHex()
const operatorAddress = event.params._operator.toHex()
const tokenAddress = event.params._tokenAddress.toHex()
const isApproved = event.params._isApproved

const grantor = findOrCreateAccount(grantorAddress)
const operator = findOrCreateAccount(operatorAddress)
const rolesRegistry = findOrCreateRolesRegistry(rolesRegistryAddress)
const roleApproval = findOrCreateRoleApproval(rolesRegistry, grantor, operator, tokenAddress)
roleApproval.isApproved = isApproved
roleApproval.save()

log.warning('[sftRolesRegistry][handleRoleApprovalForAll] Updated RoleAssignment Approval: {} Tx: {}', [
roleApproval.id,
event.transaction.hash.toHex(),
])
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { log } from '@graphprotocol/graph-ts'
import { RoleGranted } from '../../../generated/ERC7432/ERC7432'
import { Account, Nft } from '../../../generated/schema'
import { generateERC721NftId, findOrCreateAccount, findOrCreateRoleAssignment } from '../../../utils'
import { RoleGranted } from '../../generated/SftRolesRegistry/SftRolesRegistry'
import { Account, Nft } from '../../generated/schema'
import { generateERC721NftId, findOrCreateAccount, findOrCreateRoleAssignment } from '../../utils'

export function handleRoleGranted(event: RoleGranted): void {
const tokenId = event.params._tokenId
Expand Down
Loading

0 comments on commit 785fe0b

Please sign in to comment.