Setting up Database Schema

The studio.schema.ts file is a TypeScript file responsible for defining the data model or schema of your subgraph. It specifies the entities and their relationships within the indexed blockchain data.

Every project has single studio.schema.ts file where all schemas are defined.

import { String, Number } from "@blockflow-labs/utils";

export interface Transfer {
  id: String;
  from_address: string;
  to_address: string;
  amount: Number;
}

No comments are allowed in this file.

Once all schemas are defined use blockflow typegen command. It will create schema.ts file at src/types.


schema.ts

This is an autogenerated file containing class and interface of the schema we created.

// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.

import { Document } from "@blockflow-labs/utils";

export class Transfer {
  static entity = "Transfer";
  static schema = {
    id: { type: "String", index: true },
    from_address: "string",
    to_address: "string",
    amount: "Number",
    entityId: { type: "String", index: true },
    blocknumber: { type: "Number", index: true },
    chainId: { type: "String", index: true },
    instanceId: { type: "String", index: true },
  };
}

import { String, Number } from "@blockflow-labs/utils";

export interface ITransfer extends Document {
  id: String;
  from_address: string;
  to_address: string;
  amount: Number;
  blocknumber: String;
  entityId: String;
  instanceId: String;
  chainId: String;
}

As you can see there are four field injected to your schema. These are indexed by default making data querying faster.

To know more about instance follow these docs.


Supported Types

When defining the schema in the studio.schema.ts file, you can use a variety of data types to represent the fields and properties of your entities. The following types are supported:

const SUPPORTED = [
  "String",
  "string",
  "Boolean",
  "Number",
  "number",
  "[String]",
  "[string]",
  "[number]",
  "[Number]",
  "[Boolean]",
];


Using Object Type

In addition to the supported primitive types, you can also define and use object types in your schema. This allows you to represent complex data structures and relationships within your entities.

To use an object type, you first need to define it as a TypeScript type or interface. Here's an example:

// Define the object type
type BlockDetails = {
  block_timestamp: string;
  blocknumber: number;
};

Once you've defined the object type, you can use it as a field type in your schema interface:

import { String, Number } from "@blockflow-labs/utils";

export interface Transfer {
  id: String;
  from_address: string;
  to_address: string;
  amount: Number;
  updated_on: BlockDetails; // Using the object type as a field type
}

Remember object type can't contain nested objects or other defined types as well.

type DEF = {name: string, version: {name: string }} //wrong method

type GHI = {name: string, version: ABC} //correct method


Creating Indexed Fields

In addition to defining the data types for your schema fields, you can also specify whether a field should be indexed or not. Indexing a field can significantly improve query performance, especially for fields that are frequently used in filtering or sorting operations.

To create an indexed field, you can define an object with two properties: type and index. The type property specifies the data type of the field, while the index property is set to true to indicate that the field should be indexed.

type StringIndex = { type: "string", index: true };

export interface Transfer {
  id: String;
  from_address: StringIndex;
  to_address: StringIndex;
  amount: Number;
}


Defining Custom Classes and Schemas

While the studio.schema.ts file serves as the primary location for defining the schema and entities for your subgraph project, you also have the flexibility to define custom classes and schemas directly within your code files.

For example, you can define a custom class like this:

export class burnTransactionsTable {
  static entity = "transferTable";
  static schema = {
    id: { type: "String", index: true },
    transactionHash: "string",
    amount: "number",
    timeStamp: "string",
    entityId: { type: "String", index: true },
    blocknumber: { type: "Number", index: true },
    chainId: { type: "String", index: true },
    instanceId: { type: "String", index: true },
  };
}

Note that when defining custom classes and schemas, it is crucial to include the following four fields in the schema:

  • entityId: { type: "String", index: true }

  • blocknumber: { type: "Number", index: true }

  • chainId: { type: "String", index: true }

  • instanceId: { type: "String", index: true }

These fields are required for efficient indexing and querying of the data within the Blockflow system.

While defining custom classes and schemas directly in code files is possible, it is generally not recommended as it can lead to inconsistencies, maintainability issues, and potential deployment problems. Only the schemas defined in the studio.schema.ts file will be deployed to the Blockflow system. Custom classes and schemas defined elsewhere may not be recognised or indexed correctly.


Databases and Instances

  • Databases are compute specific and chain specific, if you have two instances running and both of them are using Transfer database, both have a different copy of transfer database.