mirror of
https://github.com/cerc-io/watcher-ts
synced 2026-09-08 08:54:05 +00:00
Handle subgraph schema field with derivedFrom directive (#60)
* Handle subgraph schema field with derivedFrom directive * Handle derivedFrom directive in eden-watcher * Fix 1 to N relation error by removing limit from query * Order by id for derivedFrom relations to match graph-node * Refactor example subgraph schema entities * Fix watcher queries to return correct relation field values * Fix hierarchical query for getting two entities at same block
This commit is contained in:
@@ -12,30 +12,33 @@ import {
|
||||
BigDecimal
|
||||
} from "@graphprotocol/graph-ts";
|
||||
|
||||
export class RelatedEntity extends Entity {
|
||||
export class Blog extends Entity {
|
||||
constructor(id: string) {
|
||||
super();
|
||||
this.set("id", Value.fromString(id));
|
||||
|
||||
this.set("paramBigInt", Value.fromBigInt(BigInt.zero()));
|
||||
this.set("bigIntArray", Value.fromBigIntArray(new Array(0)));
|
||||
this.set("kind", Value.fromString(""));
|
||||
this.set("isActive", Value.fromBoolean(false));
|
||||
this.set("reviews", Value.fromBigIntArray(new Array(0)));
|
||||
this.set("author", Value.fromString(""));
|
||||
this.set("categories", Value.fromStringArray(new Array(0)));
|
||||
}
|
||||
|
||||
save(): void {
|
||||
let id = this.get("id");
|
||||
assert(id != null, "Cannot save RelatedEntity entity without an ID");
|
||||
assert(id != null, "Cannot save Blog entity without an ID");
|
||||
if (id) {
|
||||
assert(
|
||||
id.kind == ValueKind.STRING,
|
||||
"Cannot save RelatedEntity entity with non-string ID. " +
|
||||
"Cannot save Blog entity with non-string ID. " +
|
||||
'Considering using .toHex() to convert the "id" to a string.'
|
||||
);
|
||||
store.set("RelatedEntity", id.toString(), this);
|
||||
store.set("Blog", id.toString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
static load(id: string): RelatedEntity | null {
|
||||
return changetype<RelatedEntity | null>(store.get("RelatedEntity", id));
|
||||
static load(id: string): Blog | null {
|
||||
return changetype<Blog | null>(store.get("Blog", id));
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
@@ -47,56 +50,79 @@ export class RelatedEntity extends Entity {
|
||||
this.set("id", Value.fromString(value));
|
||||
}
|
||||
|
||||
get paramBigInt(): BigInt {
|
||||
let value = this.get("paramBigInt");
|
||||
return value!.toBigInt();
|
||||
get kind(): string {
|
||||
let value = this.get("kind");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set paramBigInt(value: BigInt) {
|
||||
this.set("paramBigInt", Value.fromBigInt(value));
|
||||
set kind(value: string) {
|
||||
this.set("kind", Value.fromString(value));
|
||||
}
|
||||
|
||||
get bigIntArray(): Array<BigInt> {
|
||||
let value = this.get("bigIntArray");
|
||||
get isActive(): boolean {
|
||||
let value = this.get("isActive");
|
||||
return value!.toBoolean();
|
||||
}
|
||||
|
||||
set isActive(value: boolean) {
|
||||
this.set("isActive", Value.fromBoolean(value));
|
||||
}
|
||||
|
||||
get reviews(): Array<BigInt> {
|
||||
let value = this.get("reviews");
|
||||
return value!.toBigIntArray();
|
||||
}
|
||||
|
||||
set bigIntArray(value: Array<BigInt>) {
|
||||
this.set("bigIntArray", Value.fromBigIntArray(value));
|
||||
set reviews(value: Array<BigInt>) {
|
||||
this.set("reviews", Value.fromBigIntArray(value));
|
||||
}
|
||||
|
||||
get author(): string {
|
||||
let value = this.get("author");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set author(value: string) {
|
||||
this.set("author", Value.fromString(value));
|
||||
}
|
||||
|
||||
get categories(): Array<string> {
|
||||
let value = this.get("categories");
|
||||
return value!.toStringArray();
|
||||
}
|
||||
|
||||
set categories(value: Array<string>) {
|
||||
this.set("categories", Value.fromStringArray(value));
|
||||
}
|
||||
}
|
||||
|
||||
export class ExampleEntity extends Entity {
|
||||
export class Author extends Entity {
|
||||
constructor(id: string) {
|
||||
super();
|
||||
this.set("id", Value.fromString(id));
|
||||
|
||||
this.set("count", Value.fromBigInt(BigInt.zero()));
|
||||
this.set("paramString", Value.fromString(""));
|
||||
this.set("blogCount", Value.fromBigInt(BigInt.zero()));
|
||||
this.set("name", Value.fromString(""));
|
||||
this.set("rating", Value.fromBigDecimal(BigDecimal.zero()));
|
||||
this.set("paramInt", Value.fromI32(0));
|
||||
this.set("paramBoolean", Value.fromBoolean(false));
|
||||
this.set("paramBytes", Value.fromBytes(Bytes.empty()));
|
||||
this.set("paramEnum", Value.fromString(""));
|
||||
this.set("paramBigDecimal", Value.fromBigDecimal(BigDecimal.zero()));
|
||||
this.set("related", Value.fromString(""));
|
||||
this.set("manyRelated", Value.fromStringArray(new Array(0)));
|
||||
}
|
||||
|
||||
save(): void {
|
||||
let id = this.get("id");
|
||||
assert(id != null, "Cannot save ExampleEntity entity without an ID");
|
||||
assert(id != null, "Cannot save Author entity without an ID");
|
||||
if (id) {
|
||||
assert(
|
||||
id.kind == ValueKind.STRING,
|
||||
"Cannot save ExampleEntity entity with non-string ID. " +
|
||||
"Cannot save Author entity with non-string ID. " +
|
||||
'Considering using .toHex() to convert the "id" to a string.'
|
||||
);
|
||||
store.set("ExampleEntity", id.toString(), this);
|
||||
store.set("Author", id.toString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
static load(id: string): ExampleEntity | null {
|
||||
return changetype<ExampleEntity | null>(store.get("ExampleEntity", id));
|
||||
static load(id: string): Author | null {
|
||||
return changetype<Author | null>(store.get("Author", id));
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
@@ -108,22 +134,31 @@ export class ExampleEntity extends Entity {
|
||||
this.set("id", Value.fromString(value));
|
||||
}
|
||||
|
||||
get count(): BigInt {
|
||||
let value = this.get("count");
|
||||
get blogCount(): BigInt {
|
||||
let value = this.get("blogCount");
|
||||
return value!.toBigInt();
|
||||
}
|
||||
|
||||
set count(value: BigInt) {
|
||||
this.set("count", Value.fromBigInt(value));
|
||||
set blogCount(value: BigInt) {
|
||||
this.set("blogCount", Value.fromBigInt(value));
|
||||
}
|
||||
|
||||
get paramString(): string {
|
||||
let value = this.get("paramString");
|
||||
get name(): string {
|
||||
let value = this.get("name");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set paramString(value: string) {
|
||||
this.set("paramString", Value.fromString(value));
|
||||
set name(value: string) {
|
||||
this.set("name", Value.fromString(value));
|
||||
}
|
||||
|
||||
get rating(): BigDecimal {
|
||||
let value = this.get("rating");
|
||||
return value!.toBigDecimal();
|
||||
}
|
||||
|
||||
set rating(value: BigDecimal) {
|
||||
this.set("rating", Value.fromBigDecimal(value));
|
||||
}
|
||||
|
||||
get paramInt(): i32 {
|
||||
@@ -135,15 +170,6 @@ export class ExampleEntity extends Entity {
|
||||
this.set("paramInt", Value.fromI32(value));
|
||||
}
|
||||
|
||||
get paramBoolean(): boolean {
|
||||
let value = this.get("paramBoolean");
|
||||
return value!.toBoolean();
|
||||
}
|
||||
|
||||
set paramBoolean(value: boolean) {
|
||||
this.set("paramBoolean", Value.fromBoolean(value));
|
||||
}
|
||||
|
||||
get paramBytes(): Bytes {
|
||||
let value = this.get("paramBytes");
|
||||
return value!.toBytes();
|
||||
@@ -153,68 +179,40 @@ export class ExampleEntity extends Entity {
|
||||
this.set("paramBytes", Value.fromBytes(value));
|
||||
}
|
||||
|
||||
get paramEnum(): string {
|
||||
let value = this.get("paramEnum");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set paramEnum(value: string) {
|
||||
this.set("paramEnum", Value.fromString(value));
|
||||
}
|
||||
|
||||
get paramBigDecimal(): BigDecimal {
|
||||
let value = this.get("paramBigDecimal");
|
||||
return value!.toBigDecimal();
|
||||
}
|
||||
|
||||
set paramBigDecimal(value: BigDecimal) {
|
||||
this.set("paramBigDecimal", Value.fromBigDecimal(value));
|
||||
}
|
||||
|
||||
get related(): string {
|
||||
let value = this.get("related");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set related(value: string) {
|
||||
this.set("related", Value.fromString(value));
|
||||
}
|
||||
|
||||
get manyRelated(): Array<string> {
|
||||
let value = this.get("manyRelated");
|
||||
get blogs(): Array<string> {
|
||||
let value = this.get("blogs");
|
||||
return value!.toStringArray();
|
||||
}
|
||||
|
||||
set manyRelated(value: Array<string>) {
|
||||
this.set("manyRelated", Value.fromStringArray(value));
|
||||
set blogs(value: Array<string>) {
|
||||
this.set("blogs", Value.fromStringArray(value));
|
||||
}
|
||||
}
|
||||
|
||||
export class ManyRelatedEntity extends Entity {
|
||||
export class Category extends Entity {
|
||||
constructor(id: string) {
|
||||
super();
|
||||
this.set("id", Value.fromString(id));
|
||||
|
||||
this.set("name", Value.fromString(""));
|
||||
this.set("count", Value.fromBigInt(BigInt.zero()));
|
||||
}
|
||||
|
||||
save(): void {
|
||||
let id = this.get("id");
|
||||
assert(id != null, "Cannot save ManyRelatedEntity entity without an ID");
|
||||
assert(id != null, "Cannot save Category entity without an ID");
|
||||
if (id) {
|
||||
assert(
|
||||
id.kind == ValueKind.STRING,
|
||||
"Cannot save ManyRelatedEntity entity with non-string ID. " +
|
||||
"Cannot save Category entity with non-string ID. " +
|
||||
'Considering using .toHex() to convert the "id" to a string.'
|
||||
);
|
||||
store.set("ManyRelatedEntity", id.toString(), this);
|
||||
store.set("Category", id.toString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
static load(id: string): ManyRelatedEntity | null {
|
||||
return changetype<ManyRelatedEntity | null>(
|
||||
store.get("ManyRelatedEntity", id)
|
||||
);
|
||||
static load(id: string): Category | null {
|
||||
return changetype<Category | null>(store.get("Category", id));
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
@@ -226,6 +224,15 @@ export class ManyRelatedEntity extends Entity {
|
||||
this.set("id", Value.fromString(value));
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
let value = this.get("name");
|
||||
return value!.toString();
|
||||
}
|
||||
|
||||
set name(value: string) {
|
||||
this.set("name", Value.fromString(value));
|
||||
}
|
||||
|
||||
get count(): BigInt {
|
||||
let value = this.get("count");
|
||||
return value!.toBigInt();
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
enum EnumType {
|
||||
choice1
|
||||
choice2
|
||||
enum BlogKind {
|
||||
short
|
||||
long
|
||||
}
|
||||
|
||||
type RelatedEntity @entity {
|
||||
type Blog @entity {
|
||||
id: ID!
|
||||
paramBigInt: BigInt!
|
||||
bigIntArray: [BigInt!]!
|
||||
kind: BlogKind!
|
||||
isActive: Boolean!
|
||||
reviews: [BigInt!]!
|
||||
author: Author!
|
||||
categories: [Category!]!
|
||||
}
|
||||
|
||||
type ExampleEntity @entity {
|
||||
type Author @entity {
|
||||
id: ID!
|
||||
count: BigInt!
|
||||
paramString: String! # string
|
||||
blogCount: BigInt!
|
||||
name: String! # string
|
||||
rating: BigDecimal!
|
||||
paramInt: Int! # uint8
|
||||
paramBoolean: Boolean!
|
||||
paramBytes: Bytes!
|
||||
paramEnum: EnumType!
|
||||
paramBigDecimal: BigDecimal!
|
||||
related: RelatedEntity!
|
||||
manyRelated: [ManyRelatedEntity!]!
|
||||
blogs: [Blog!]! @derivedFrom(field: "author")
|
||||
}
|
||||
|
||||
type ManyRelatedEntity @entity {
|
||||
type Category @entity {
|
||||
id: ID!
|
||||
name: String!
|
||||
count: BigInt!
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
Example1,
|
||||
Test
|
||||
} from '../generated/Example1/Example1';
|
||||
import { ExampleEntity, ManyRelatedEntity, RelatedEntity } from '../generated/schema';
|
||||
import { Author, Blog, Category } from '../generated/schema';
|
||||
|
||||
export function handleTest (event: Test): void {
|
||||
log.debug('event.address: {}', [event.address.toHexString()]);
|
||||
@@ -15,52 +15,54 @@ export function handleTest (event: Test): void {
|
||||
|
||||
// Entities can be loaded from the store using a string ID; this ID
|
||||
// needs to be unique across all entities of the same type
|
||||
let entity = ExampleEntity.load(event.transaction.from.toHex());
|
||||
let author = Author.load(event.transaction.from.toHex());
|
||||
|
||||
// Entities only exist after they have been saved to the store;
|
||||
// `null` checks allow to create entities on demand
|
||||
if (!entity) {
|
||||
entity = new ExampleEntity(event.transaction.from.toHex());
|
||||
if (!author) {
|
||||
author = new Author(event.transaction.from.toHex());
|
||||
|
||||
// Entity fields can be set using simple assignments
|
||||
entity.count = BigInt.fromString('0');
|
||||
author.blogCount = BigInt.fromString('0');
|
||||
}
|
||||
|
||||
// BigInt and BigDecimal math are supported
|
||||
entity.count = entity.count + BigInt.fromString('1');
|
||||
author.blogCount = author.blogCount + BigInt.fromString('1');
|
||||
|
||||
// Entity fields can be set based on event parameters
|
||||
entity.paramString = event.params.param1;
|
||||
entity.paramInt = event.params.param2;
|
||||
entity.paramBoolean = true;
|
||||
entity.paramBytes = event.address;
|
||||
entity.paramEnum = 'choice1';
|
||||
entity.paramBigDecimal = BigDecimal.fromString('123');
|
||||
|
||||
let relatedEntity = RelatedEntity.load(event.params.param1);
|
||||
|
||||
if (!relatedEntity) {
|
||||
relatedEntity = new RelatedEntity(event.params.param1);
|
||||
relatedEntity.paramBigInt = BigInt.fromString('123');
|
||||
}
|
||||
|
||||
const bigIntArray = relatedEntity.bigIntArray;
|
||||
bigIntArray.push(entity.count);
|
||||
relatedEntity.bigIntArray = bigIntArray;
|
||||
|
||||
relatedEntity.save();
|
||||
entity.related = relatedEntity.id;
|
||||
|
||||
const manyRelatedEntity = new ManyRelatedEntity(event.transaction.hash.toHexString());
|
||||
manyRelatedEntity.count = entity.count;
|
||||
manyRelatedEntity.save();
|
||||
|
||||
const manyRelated = entity.manyRelated;
|
||||
manyRelated.push(manyRelatedEntity.id);
|
||||
entity.manyRelated = manyRelated;
|
||||
author.name = event.params.param1;
|
||||
author.paramInt = event.params.param2;
|
||||
author.paramBytes = event.address;
|
||||
author.rating = BigDecimal.fromString('4');
|
||||
|
||||
// Entities can be written to the store with `.save()`
|
||||
entity.save();
|
||||
author.save();
|
||||
|
||||
let category = Category.load(author.blogCount.toString());
|
||||
|
||||
if (!category) {
|
||||
category = new Category(author.blogCount.toString());
|
||||
category.name = event.params.param1;
|
||||
}
|
||||
|
||||
category.count = category.count + BigInt.fromString('1');
|
||||
category.save();
|
||||
|
||||
const blog = new Blog(event.transaction.hash.toHexString());
|
||||
blog.kind = 'long';
|
||||
blog.isActive = true;
|
||||
|
||||
const blogReviews = blog.reviews;
|
||||
blogReviews.push(BigInt.fromString('4'));
|
||||
blog.reviews = blogReviews;
|
||||
|
||||
blog.author = author.id;
|
||||
|
||||
const categories = blog.categories;
|
||||
categories.push(category.id);
|
||||
blog.categories = categories;
|
||||
|
||||
blog.save();
|
||||
|
||||
const contractAddress = dataSource.address();
|
||||
const contract = Example1.bind(contractAddress);
|
||||
|
||||
Reference in New Issue
Block a user