DubheSuiSchemasSchemas Config

Schemas Config & schemagen Tool

The schemagen CLI tool generates libraries for Schemas. It makes it much less error-prone than using the Schemas low-level API, and comes with typed Move APIs when setting and retrieving records.

Using schemagen with the Dubhe framework

If you are using the Dubhe framework and have a dubhe.config.ts file in your project, you can edit your Schemas config directly in this file!

A Schemas config should be named dubhe.config.ts, and placed at the root of your project.

This is the minimal config:

import { defineConfig } from '@0xobelisk/sui-common';
 
export const dubheConfig = defineConfig({
  name: 'example',
  description: 'example',
  enums: {},
  components: {},
  resources: {},
  errors: {}
});

Generating the schemas

To generate the schemas, run pnpm dubhe schemagen in the same folder as the config file.

If you are developing a game contract, we recommend using the ECS architecture, which can be easily implemented with components and resources. You can use components to define components for any entity. Regardless of what data the component is, an address entity key type will be generated by default in the contract. For example:

import { defineConfig } from '@0xobelisk/sui-common';
export const dubheConfig = defineConfig({
  name: 'example',
  description: 'example',
  enums: {},
  components: {
    player: {},
    level: 'u32',
    monster: {
      fields: {
        attack: 'u32',
        hp: 'u32'
      }
    }
  },
  resources: {}
});

The player component will generate a global array, where you can add any entity key to determine if this entity can move. The level component will generate a global key-value data type, allowing you to insert level data for each entity. The monster component will generate a key-multiple-value data type, allowing you to insert multiple data for an entity, such as the monster’s attack and health.

palyer::set(dapp_hub, entity_key1);
palyer::set(dapp_hub, entity_key2);

level::set(dapp_hub, entity_key1, 100);
level::set(dapp_hub, entity_key2, 101);

monster::set(dapp_hub, entity_key1, 100, 10000);
monster::set(dapp_hub, entity_key2, 200, 10000);

Combined with the Dubhe client SDK, you can easily query the corresponding data, such as querying all component data for entity_key1, or specific component data for entity_key1.

In addition to component data types, you may also use resources for global data that is not related to a single entity. You can use this to store data such as map data and leaderboard data.

import { defineConfig } from '@0xobelisk/sui-common';
export const dubheConfig = defineConfig({
  name: 'example',
  description: 'example',
  enums: {},
  components: {
    player: {},
    level: "u32",
    monster: {
      fields: {
        attack: 'u32',
        hp: 'u32'
      }
    },
  },
  resources: {
     switch: 'bool'
     maps: {
      fields: {
        map_id: 'u32',
        data: 'vector<u8>',
        height: 'u32',
        width: 'u32'
      },
      key: ['map_id']
    },
  }
})
switch::set(true);
maps::set(dapp_hub, map_id, data, height, width);

If you don’t want to store data but just want to implement notifications for game process results, you can use the offchain field. This makes it easy to implement something similar to events in native contracts.

import { defineConfig } from '@0xobelisk/sui-common';
export const dubheConfig = defineConfig({
  name: 'example',
  description: 'example',
  enums: {},
  components: {
    player: {},
    level: "u32",
    monster: {
      fields: {
        attack: 'u32',
        hp: 'u32'
      }
    },
  },
  resources: {
     switch: 'bool'
     maps: {
      fields: {
        map_id: 'u32',
        data: 'vector<u8>',
        height: 'u32',
        width: 'u32'
      },
      key: ['map_id']
    },
    capture_results: {
      fields: {
        monster: 'address',
        result: 'bool'
      },
      offchain: true
    }
  }
})
capture_results::set(dapp_hub, monster, result)

You can also customize errors. Just make sure the condition is true to pass, otherwise an error will be thrown.

import { defineConfig } from '@0xobelisk/sui-common';
export const dubheConfig = defineConfig({
  name: 'example',
  description: 'example',
  errors: {
    monster_not_found: 'Monster not found',
    game_not_start: "The game hasn't started yet"
  }
});
monster_not_found_error(condition);
game_not_start_error(condition);