joystream-query-node.md 4.3 KB

Joystream Query Node

Joystream query node can be generated by using substrate-query-node/cli.

Getting Started

Cli create a folder named generated and put everthing inside it.

$ cli codegen

Start graphql server:

$ cd generated/graphql-server
$ yarn start:dev

Start block indexer:

$ cd generated/indexer
$ yarn start

Add a new mapping for Joystream MemberRegistered event

  1. Every mapping function get a parameter of DB type

    import { DB } from '../generated/indexer';
    
  2. db object is for database operations save/get/remove and access to event itself

  3. Define the event handler function with the following signature and import the entity class

    import { MemberRegistereds } from '../generated/indexer/entities/MemberRegistereds';
    export async function handleMemberRegistered(db: DB) {}
    
  4. Inside the handler function create a new instance of the entity and fill properties with event data.

    // Get event data
    const { AccountId, MemberId } = db.event.event_params;
    const member = new MemberRegistereds({ accountId: AccountId.toString(), memberId: +MemberId });
    
  5. Call db.save() method to save data on database

    // Save to database.
    db.save<MemberRegistereds>(member);
    
  6. Query database

    // Query from database
    const findOptions = { where: { memberId: 123 } }; // match the record
    const m = await db.get(MemberRegistereds, findOptions);
    

Below you can find the complete code

Complete code

import { MemberRegistereds } from "../generated/indexer/entities/MemberRegistereds";
import { DB } from "../generated/indexer";

export async function handleMemberRegistered(db: DB) {
  // Get event data
  const { AccountId, MemberId } = db.event.event_params;

  const member = new MemberRegistereds({ accountId: AccountId.toString(), memberId: +MemberId };

  // Save to database.
  db.save<MemberRegistereds>(member);

  // Query from database
  const m = await db.get(MemberRegistereds, { where: { memberId: 123 } });
}

Query Node Constructs Explained

  1. schema.graphql is where you define types for graphql server. Graphql server use these types to generate db models, db tables, graphql resolvers.

Below you can find a type defination example:

type Membership {
  # Member's root account id
  accountId: String!

  # Member's id
  memberId: Int!

  # The unique handle chosen by member
  handle: String

  # A Url to member's Avatar image
  avatarUri: String

  # Short text chosen by member to share information about themselves
  about: String
}

Important Relationship between types not supported yet!

  1. Block indexer is block consumer and every block can have events that we want to store their data. So indexing data from events we need to send the event to a function or a class that can handle the event and stores the event data on the database. mappings are the functions that we use to update our database with events data. Functions that we define in our mappings will be called only when the event name match our function name (function name pattern is 'handle' + eventName). We call mapping functions as event handlers. Each event handler have only one parameter which is the db: DB. Every database operation is made with db object and the event can be accessed with db object. Below you can find an example for the event a handler:

    // mappings/index.ts
    
    import { DB } from '../generated/indexer';
    
    export function handleMemberRegistered(db: DB) {
    console.log(`Event parameters: ${db.event.event_params}`);
    }
    
  2. Block indexer connects to a blockchain node via WebSocket so we need to tell block indexer where to find the address of the node. Also, on the initialization of the indexer, we must pass the type register function as a parameter. So we put these variables inside the .env file that indexer can find and use them. For Joystream we will be running a local development node and add the name of the function, the package for the type registration:

    WS_PROVIDER_ENDPOINT_URI=ws://localhost:9944
    TYPE_REGISTER_PACKAGE_NAME=@joystream/types
    TYPE_REGISTER_FUNCTION=registerJoystreamTypes
    
  3. Database connections options are defined in .env:

    DB_NAME=test
    DB_USER=postgres
    DB_PASS=postgres
    DB_HOST=localhost
    DB_PORT=5432
    GRAPHQL_SERVER_PORT=4000