Skip to content

Commit

Permalink
Merge pull request #299 from gnosisguild/subgraph-last-updated
Browse files Browse the repository at this point in the history
subgraph: add `lastUpdated` field for role
  • Loading branch information
jfschwarz authored Nov 11, 2024
2 parents 01761e5 + e2f08db commit 23c148c
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 38 deletions.
4 changes: 2 additions & 2 deletions packages/deployments/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zodiac-roles-deployments",
"version": "2.2.6",
"version": "2.2.7",
"license": "LGPL-3.0+",
"main": "build/cjs/index.js",
"module": "build/esm/index.js",
Expand Down Expand Up @@ -28,4 +28,4 @@
"installConfig": {
"hoistingLimits": "workspaces"
}
}
}
18 changes: 9 additions & 9 deletions packages/deployments/src/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,54 @@ export const chains = {
name: "mainnet",
prefix: "eth",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-mainnet/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-mainnet/v2.3.0",
},
[10]: {
name: "optimism",
prefix: "oeth",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-optimism/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-optimism/v2.3.0",
},
[100]: {
name: "gnosis",
prefix: "gno",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-gnosis/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-gnosis/v2.3.0",
},
[137]: {
name: "polygon",
prefix: "matic",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-polygon/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-polygon/v2.3.0",
},
[1101]: {
name: "zkevm",
prefix: "zkevm",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-zkevm/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-zkevm/v2.3.0",
},
[42161]: {
name: "arbitrumOne",
prefix: "arb1",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-arbitrum-one/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-arbitrum-one/v2.3.0",
},
[43114]: {
name: "avalanche",
prefix: "avax",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-avalanche/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-avalanche/v2.3.0",
},
[8453]: {
name: "base",
prefix: "base",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-base/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-base/v2.3.0",
},
[11155111]: {
name: "sepolia",
prefix: "sep",
subgraph:
"https://api.studio.thegraph.com/query/23167/zodiac-roles-sepolia/v2.2.3",
"https://api.studio.thegraph.com/query/93263/zodiac-roles-sepolia/v2.3.0",
},
} as const
22 changes: 17 additions & 5 deletions packages/deployments/src/fetchRole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ import {
Target,
} from "./types"

interface Props {
type Props = {
address: `0x${string}`
roleKey: `0x${string}`
chainId: ChainId
}
} & (
| {
/** pass a chainId to use query against a dev subgraph */
chainId: ChainId
}
| {
/** pass your own subgraph endpoint for production use */
subgraph: string
}
)

const QUERY = `
query Role($id: String) {
Expand Down Expand Up @@ -41,6 +49,7 @@ query Role($id: String) {
uri
schema
}
lastUpdate
}
}
`.trim()
Expand All @@ -51,10 +60,13 @@ const getRoleId = (address: `0x${string}`, roleKey: `0x${string}`) =>
type FetchOptions = Omit<RequestInit, "method" | "body">

export const fetchRole = async (
{ address, roleKey, chainId }: Props,
{ address, roleKey, ...rest }: Props,
options?: FetchOptions
): Promise<Role | null> => {
const res = await fetch(chains[chainId].subgraph, {
const endpoint =
"subgraph" in rest ? rest.subgraph : chains[rest.chainId].subgraph

const res = await fetch(endpoint, {
...options,
method: "POST",
headers: {
Expand Down
22 changes: 17 additions & 5 deletions packages/deployments/src/fetchRolesMod.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { chains } from "./chains"
import { ChainId, Clearance, ExecutionOptions, Function } from "./types"

interface Props {
type Props = {
address: `0x${string}`
chainId: ChainId
}
} & (
| {
/** pass a chainId to use query against a dev subgraph */
chainId: ChainId
}
| {
/** pass your own subgraph endpoint for production use */
subgraph: string
}
)

const QUERY = `
query RolesMod($id: String) {
Expand Down Expand Up @@ -34,17 +42,21 @@ const QUERY = `
unwrapAdapters(where: {selector: "0x8d80ff0a", adapterAddress: "0x93b7fcbc63ed8a3a24b59e1c3e6649d50b7427c0"}) {
targetAddress
}
lastUpdate
}
}
`

type FetchOptions = Omit<RequestInit, "method" | "body">

export const fetchRolesMod = async (
{ address, chainId }: Props,
{ address, ...rest }: Props,
options?: FetchOptions
): Promise<RolesModifier | null> => {
const res = await fetch(chains[chainId].subgraph, {
const endpoint =
"subgraph" in rest ? rest.subgraph : chains[rest.chainId].subgraph

const res = await fetch(endpoint, {
...options,
method: "POST",
headers: {
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zodiac-roles-sdk",
"version": "2.14.5",
"version": "2.15.0",
"license": "LGPL-3.0+",
"main": "build/cjs/sdk/src/index.js",
"module": "build/esm/sdk/src/index.js",
Expand Down
1 change: 0 additions & 1 deletion packages/subgraph/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ SUBGRAPH_GNOSIS=zodiac-roles-gnosis
SUBGRAPH_ARBITRUM_ONE=zodiac-roles-arbitrum-one
SUBGRAPH_SEPOLIA=zodiac-roles-sepolia
SUBGRAPH_AVALANCHE=zodiac-roles-avalanche
SUBGRAPH_BSC=zodiac-roles-bsc
SUBGRAPH_OPTIMISM=zodiac-roles-optimism
SUBGRAPH_POLYGON=zodiac-roles-polygon
SUBGRAPH_ZKEVM=zodiac-roles-zkevm
Expand Down
4 changes: 0 additions & 4 deletions packages/subgraph/networks/bsc.json

This file was deleted.

4 changes: 1 addition & 3 deletions packages/subgraph/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"deploy:gnosis": "yarn prepare:gnosis && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_GNOSIS'",
"deploy:arbitrum-one": "yarn prepare:arbitrum-one && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_ARBITRUM_ONE'",
"deploy:avalanche": "yarn prepare:avalanche && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_AVALANCHE'",
"deploy:bsc": "yarn prepare:bsc && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_BSC'",
"deploy:optimism": "yarn prepare:optimism && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_OPTIMISM'",
"deploy:base": "yarn prepare:base && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_BASE'",
"deploy:polygon": "yarn prepare:polygon && bash -c 'source .env || true && graph deploy --studio $SUBGRAPH_POLYGON'",
Expand All @@ -23,7 +22,6 @@
"prepare:gnosis": "mustache networks/gnosis.json subgraph.template.yaml > subgraph.yaml",
"prepare:arbitrum-one": "mustache networks/arbitrum-one.json subgraph.template.yaml > subgraph.yaml",
"prepare:avalanche": "mustache networks/avalanche.json subgraph.template.yaml > subgraph.yaml",
"prepare:bsc": "mustache networks/bsc.json subgraph.template.yaml > subgraph.yaml",
"prepare:optimism": "mustache networks/optimism.json subgraph.template.yaml > subgraph.yaml",
"prepare:base": "mustache networks/base.json subgraph.template.yaml > subgraph.yaml",
"prepare:polygon": "mustache networks/polygon.json subgraph.template.yaml > subgraph.yaml",
Expand All @@ -41,4 +39,4 @@
"installConfig": {
"hoistingLimits": "workspaces"
}
}
}
1 change: 1 addition & 0 deletions packages/subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ type Role @entity {
targets: [Target!]! @derivedFrom(field: "role")
members: [RoleAssignment!]! @derivedFrom(field: "role")
annotations: [Annotation!]! @derivedFrom(field: "role")
lastUpdate: BigInt! # block number of the last update
}

type Target @entity {
Expand Down
7 changes: 5 additions & 2 deletions packages/subgraph/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
Role,
RolesModifier,
Target,
Condition,
Member,
Allowance,
UnwrapAdapter,
Expand All @@ -25,19 +24,23 @@ export const getUnwrapAdapterId = (targetAddress: Address, selector: Bytes, role
rolesModifierId + "-ADAPTER-" + targetAddress.toHex() + "." + selector.toHex()
export const getAnnotationId = (uri: string, rolesModifierId: string): string => rolesModifierId + "-ANNOTATION-" + uri

export const getOrCreateRole = (roleId: string, rolesModifierId: string, key: Bytes): Role => {
export const getOrCreateRole = (roleId: string, rolesModifierId: string, key: Bytes, blockNumber: BigInt): Role => {
let role = Role.load(roleId)

// save role if this is the first time we encounter it
if (!role) {
role = new Role(roleId)
role.key = key
role.rolesModifier = rolesModifierId
role.lastUpdate = blockNumber
role.save()
log.info("Created new role #{}", [roleId])
} else {
log.debug("Loaded existing role #{}", [roleId])
// already now set the last update block number, so we don't have to remember to do it before saving
role.lastUpdate = blockNumber
}

return role
}

Expand Down
20 changes: 16 additions & 4 deletions packages/subgraph/src/permissions.mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function handleAllowTarget(event: AllowTarget): void {

// Make sure the role exists
const roleId = getRoleId(rolesModifierId, event.params.roleKey)
getOrCreateRole(roleId, rolesModifierId, event.params.roleKey)
const role = getOrCreateRole(roleId, rolesModifierId, event.params.roleKey, event.block.number)

const targetAddress = event.params.targetAddress
const targetId = getTargetId(roleId, targetAddress)
Expand All @@ -42,6 +42,9 @@ export function handleAllowTarget(event: AllowTarget): void {
target.clearance = ClearanceKeys[Clearance.Target]
target.save()

// update role lastUpdate field
role.save()

log.info("Permission has been granted to call any function of target {}", [targetId])
}

Expand All @@ -56,7 +59,7 @@ export function handleScopeTarget(event: ScopeTarget): void {

// Make sure the role exists
const roleId = getRoleId(rolesModifierId, event.params.roleKey)
getOrCreateRole(roleId, rolesModifierId, event.params.roleKey)
const role = getOrCreateRole(roleId, rolesModifierId, event.params.roleKey, event.block.number)

const targetAddress = event.params.targetAddress
const targetId = getTargetId(roleId, targetAddress)
Expand All @@ -65,6 +68,9 @@ export function handleScopeTarget(event: ScopeTarget): void {
target.clearance = ClearanceKeys[Clearance.Function]
target.save()

// update role lastUpdate field
role.save()

log.info("Target {} has been set to scoped", [targetId])
}

Expand Down Expand Up @@ -97,7 +103,7 @@ export function handleAllowFunction(event: AllowFunction): void {

// Make sure the role exists
const roleId = getRoleId(rolesModifierId, event.params.roleKey)
getOrCreateRole(roleId, rolesModifierId, event.params.roleKey)
const role = getOrCreateRole(roleId, rolesModifierId, event.params.roleKey, event.block.number)

// Make sure the target exists
const targetAddress = event.params.targetAddress
Expand All @@ -111,6 +117,9 @@ export function handleAllowFunction(event: AllowFunction): void {
func.condition = null
func.save()

// update role lastUpdate field
role.save()

log.info("Wildcard permission to call {} has been granted", [functionId])
}

Expand All @@ -123,7 +132,7 @@ export function handleScopeFunction(event: ScopeFunction): void {

// Make sure the role exists
const roleId = getRoleId(rolesModifierId, event.params.roleKey)
getOrCreateRole(roleId, rolesModifierId, event.params.roleKey)
const role = getOrCreateRole(roleId, rolesModifierId, event.params.roleKey, event.block.number)

// Make sure the target exists
const targetAddress = event.params.targetAddress
Expand All @@ -148,6 +157,9 @@ export function handleScopeFunction(event: ScopeFunction): void {

func.save()

// update role lastUpdate field
role.save()

log.info("Function {} has been scoped with condition {} and exec options {}", [
functionId,
rootCondition.id,
Expand Down
11 changes: 9 additions & 2 deletions packages/subgraph/src/roles.mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function handleAssignRoles(event: AssignRoles): void {

for (let i = 0; i < roleKeys.length; i++) {
const roleId = getRoleId(rolesModifierId, roleKeys[i])
const role = getOrCreateRole(roleId, rolesModifierId, roleKeys[i])
const role = getOrCreateRole(roleId, rolesModifierId, roleKeys[i], event.block.number)
const assignmentId = getAssignmentId(memberId, roleId)
let assignment = RoleAssignment.load(assignmentId)
if (!assignment) {
Expand All @@ -48,6 +48,9 @@ export function handleAssignRoles(event: AssignRoles): void {
assignment.member = memberId
assignment.role = roleId
assignment.save()

// update role lastUpdate field
role.save()
} else {
// nothing to do the member - role relationship does not exist
log.warning("Trying to remove member {} from role #{}, but it's not a member", [memberId, roleId])
Expand All @@ -59,6 +62,9 @@ export function handleAssignRoles(event: AssignRoles): void {
} else {
// removing a member-role relationship
store.remove("RoleAssignment", assignmentId)

// update role lastUpdate field
role.save()
}
}
}
Expand Down Expand Up @@ -126,8 +132,9 @@ export function handleSetDefaultRole(event: SetDefaultRole): void {

const roleKey = event.params.defaultRoleKey
const roleId = getRoleId(rolesModifierId, roleKey)

// create role if it does not exist yet
getOrCreateRole(roleId, rolesModifierId, roleKey)
getOrCreateRole(roleId, rolesModifierId, roleKey, event.block.number)

member.defaultRole = roleId
member.save()
Expand Down

0 comments on commit 23c148c

Please sign in to comment.