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

feat: add mph subgraph #1283

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion blockscout-ens/bens-server/config/prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@
"story"
]
},
"2818": {
"blockscout": {
"url": "https://explorer.morphl2.io/"
},
"use_protocols": [
"morph"
]
},
"10200": {
"blockscout": {
"url": "https://gnosis-chiado.blockscout.com"
Expand Down Expand Up @@ -535,7 +543,25 @@
"icon_url": "https://i.imgur.com/yYc2C6V.png",
"docs_url": "https://docs.space.id/"
}
},
"morph": {
"tld_list": ["mph"],
"network_id": 2818,
"subgraph_name": "morph-subgraph",
"address_resolve_technique": "reverse_registry",
"specific": {
"type": "ens_like",
"native_token_contract": "0x0000000000000000000000000000000000000000",
"empty_label_hash": "0x5566ea1c3e332b5d4a102ad9932ee7aa8564019f518499556bc2fd1baecb044d"
},
"meta": {
"short_name": "SPACE ID",
"title": "SPACE ID",
"description": "SPACE ID is a universal domain name and identity platform",
"icon_url": "https://i.imgur.com/yYc2C6V.png",
"docs_url": "https://docs.space.id/"
}
}
}
}
}
}
5 changes: 5 additions & 0 deletions blockscout-ens/graph-node/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,8 @@ provider = [
]
shard = "primary"

[chains.morph-mainnet]
provider = [
{ label = "morph-mainnet", url = "https://rpc.morphl2.io", features = [] }
]
shard = "primary"
5 changes: 5 additions & 0 deletions blockscout-ens/graph-node/deployer/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
"subgraph_path": "../subgraphs/story-subgraph",
"subgraph_name": "story-subgraph",
"network": "story-mainnet"
},
"morph": {
"subgraph_path": "../subgraphs/morph-subgraph",
"subgraph_name": "morph-subgraph",
"network": "morph-mainnet"
}
}
}
Expand Down
39 changes: 39 additions & 0 deletions blockscout-ens/graph-node/subgraph-writer/protocols/morph.yaml

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions blockscout-ens/graph-node/subgraphs/morph-subgraph/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Graph cli generated
.docker
generated
build/
.DS_STORE
data
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Built output
dist

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
jspm_packages/
dist/


# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

# intellij
.idea

/tests/.bin

*.xlsx
*.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Morph Name Service Subgraph
15 changes: 15 additions & 0 deletions blockscout-ens/graph-node/subgraphs/morph-subgraph/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
graph_node_url := "http://127.0.0.1:8020"
ipfs_url := "http://127.0.0.1:5001"
network := "morph-mainnet"
name := "morph-name-service-subgraph"

create:
yarn graph create --node {{graph_node_url}} {{name}}

deploy VERSION:
yarn graph deploy --node {{graph_node_url}} --ipfs {{ipfs_url}} {{name}} --network {{network}} --version-label {{VERSION}}

deploy-remote VERSION:
just graph_node_url={{graph_node_url}} ipfs_url=http://ipfs.node.blockscout.com network={{network}} name={{name}} \
deploy {{VERSION}}

38 changes: 38 additions & 0 deletions blockscout-ens/graph-node/subgraphs/morph-subgraph/networks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"morph-mainnet": {
"Registry": {
"address": "0x5dc881dda4e4a8d312be3544ad13118d1a04cb17",
"startBlock": 1147851
},
"Resolver": {
"startBlock": 1147851
},
"RegistrarController": {
"address": "0xd7b837a0e388b4c25200983bdaa3ef3a83ca86b7",
"startBlock": 1147851
},
"Base": {
"address": "0xe3b46508112af26f72b0d2d5f62d811ba20bcab0",
"startBlock": 1147851
},
"": ""
},
"morph-faucet": {
"Registry": {
"address": "",
"startBlock": 0
},
"Resolver": {
"startBlock": 0
},
"RegistrarController": {
"address": "",
"startBlock": 0
},
"Base": {
"address": "",
"startBlock": 0
},
"": ""
}
}
21 changes: 21 additions & 0 deletions blockscout-ens/graph-node/subgraphs/morph-subgraph/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "morph-name-service-subgraph",
"license": "UNLICENSED",
"scripts": {
"codegen": "graph codegen",
"build": "graph build",
"deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ morph-name-service-subgraph",
"create-local": "graph create --node http://localhost:8020/ morph-name-service-subgraph",
"remove-local": "graph remove --node http://localhost:8020/ morph-name-service-subgraph",
"deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 morph-name-service-subgraph",
"test": "graph test"
},
"devDependencies": {
"@ensdomains/content-hash": "^2.5.3",
"@graphprotocol/graph-cli": "^0.67.2",
"@graphprotocol/graph-ts": "^0.31.0",
"assemblyscript": "^0.19.0",
"matchstick-as": "^0.6.0",
"typescript": "^4.9.4"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ type Domain @entity {

"The events associated with the domain"
events: [DomainEvent!]! @derivedFrom(field: "domain")

"Is domain stored offchain"
storedOffchain: Boolean!
"Is domain resolved with wildcard"
resolvedWithWildcard: Boolean!
}

interface DomainEvent {
Expand Down
111 changes: 111 additions & 0 deletions blockscout-ens/graph-node/subgraphs/morph-subgraph/src/Base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Import types and APIs from graph-ts
import { BigInt, ByteArray, crypto, ens } from "@graphprotocol/graph-ts";

import {
byteArrayFromHex,
checkValidLabel,
concat,
createEventID,
BASE_NODE,
uint256ToByteArray,
BASE_NODE_HASH,
} from "./utils";

// Import event types from the registry contract ABI
import {
NameRegistered as NameRegisteredEvent,
NameRenewed as NameRenewedEvent,
Transfer as TransferEvent,
} from "../generated/Base/Base";

// Import entity types generated from the GraphQL schema
import {
Account,
Domain,
NameRegistered,
NameRenewed,
NameTransferred,
Registration,
} from "../generated/schema";

const GRACE_PERIOD_SECONDS = BigInt.fromI32(7776000); // 90 days

var rootNode: ByteArray = byteArrayFromHex(BASE_NODE_HASH);

export function handleNameRegistered(event: NameRegisteredEvent): void {
let account = new Account(event.params.owner.toHex());
account.save();

let label = uint256ToByteArray(event.params.id);
let registration = new Registration(label.toHex());
let domain = Domain.load(crypto.keccak256(concat(rootNode, label)).toHex())!;

registration.domain = domain.id;
registration.registrationDate = event.block.timestamp;
registration.expiryDate = event.params.expires;
registration.registrant = account.id;

domain.registrant = account.id;
domain.expiryDate = event.params.expires.plus(GRACE_PERIOD_SECONDS);

let labelName = ens.nameByHash(label.toHexString());
if (labelName != null) {
domain.labelName = labelName;
domain.name = labelName! + BASE_NODE;
registration.labelName = labelName;
}
domain.save();
registration.save();

let registrationEvent = new NameRegistered(createEventID(event));
registrationEvent.registration = registration.id;
registrationEvent.blockNumber = event.block.number.toI32();
registrationEvent.transactionID = event.transaction.hash;
registrationEvent.registrant = account.id;
registrationEvent.expiryDate = event.params.expires;
registrationEvent.save();
}


export function handleNameRenewed(event: NameRenewedEvent): void {
let label = uint256ToByteArray(event.params.id);
let registration = Registration.load(label.toHex())!;
let domain = Domain.load(crypto.keccak256(concat(rootNode, label)).toHex())!;

registration.expiryDate = event.params.expires;
domain.expiryDate = event.params.expires.plus(GRACE_PERIOD_SECONDS);

registration.save();
domain.save();

let registrationEvent = new NameRenewed(createEventID(event));
registrationEvent.registration = registration.id;
registrationEvent.blockNumber = event.block.number.toI32();
registrationEvent.transactionID = event.transaction.hash;
registrationEvent.expiryDate = event.params.expires;
registrationEvent.save();
}

export function handleNameTransferred(event: TransferEvent): void {
let account = new Account(event.params.to.toHex());
account.save();

let label = uint256ToByteArray(event.params.tokenId);
let registration = Registration.load(label.toHex());
if (registration == null) return;

let domain = Domain.load(crypto.keccak256(concat(rootNode, label)).toHex())!;

registration.registrant = account.id;
domain.registrant = account.id;

domain.save();
registration.save();

let transferEvent = new NameTransferred(createEventID(event));
transferEvent.registration = label.toHex();
transferEvent.blockNumber = event.block.number.toI32();
transferEvent.transactionID = event.transaction.hash;
transferEvent.newOwner = account.id;
transferEvent.save();
}
Loading