Skip to main content

Event Tracking

Event Tracking is a universal solution for tracking progress for web3 games. It provides infrastructure for handling on-chain & off-chain game events.

Main advantages:

  • Push-based architecture

  • Granular configuration

  • Scalable

  • Supports several data sources

Actions

Mental Model

Event Tracking introduces separation of activities & actions concepts.

Activity is a game-specific domain logic that has nothing in common with gg.xyz. Players play games and all their in-game interactions lead to some game-specific activities. For example player is playing some slasher. Player kills zombie and this is an in-game “zombie killed“ activity. Player kills skeleton -> “skeleton killed” activity. This may have been used for quests like “Kill 10 zombies” or “Kill 15 skeletons”. Problems come when we have quests like “Kill 25 monsters”. System should somehow understand that “zombie killed” activity should be handled for both “Kill 10 zombies” and “Kill 25 monsters” quests. To overcome this issue actions are introduced.

Action is an atomic part of each activity. Activities could consist from one or several actions. Event Tracking tracks only actions not activities. By doing so Event Tracking could effectively track progress in several quests for a single game-specific activity. In the above example “zombie killed” activity could consist of 2 different actions:

  • kill zombie

  • kill monster

Amount of actions associated with some activity is limited by each game needs. action schema

Action Anatomy

Action is a keccak256 hash of any human-readable string. All actions are unique within single game. Game Developers should predefine actions before creating quests. Actions could be created with POST /api/v2/actions endpoint (see Swagger). For example “Kill Zombie“ action will be represented as 0xbfd74c70c46a298db3c6c7a0e70fbb2755351afa6bf0946b98e677159235ed2d hash. API provide a CRUD for actions (see Swagger).

Data Sources

Event Tracking could be used with different data sources. This allows to be as flexible as possible and cover all major use cases.

On-chain Action Dispatcher

This approach utilizes smart contracts for dispatching events. This could be used ONLY with new or upgradable game smart contracts. It uses singleton ActionDispatcher smart contract to dispatch on-chain actions.

interface IActionDispatcher {
event ActionDispatched(uint256 indexed _gameId, address indexed _player, bytes32[] _actions, bytes _data);
function dispatch(uint256 _gameId, address _player, bytes32[] calldata _actions) external;
function dispatch(uint256 _gameId, address _player, string[] calldata _actions) external;
}

See interface and implementation source code for more details.

Flow:

  1. Game contract calls ActionDispatcher contract

  2. ActionDispatcher contract emits event

  3. gg.xyz backend listens for events and puts them in queue

  4. gg.xyz backend processes all actions from queue

On-chain Data Indexing

This approach utilizes third-party indexing solutions like The Graph or Ponder. This could be used for existing smart contracts that can not be upgraded or do not use ActionDispatcher for any other reason. Game-specific smart contract events should be adopted to GraphQL Action type.

Flow:

  1. Game makes HTTP request to gg.xyz public API

  2. gg.xyz backend processes requests and put actions in queue

  3. gg.xyz backend processes all actions from queue

Game Contract Whitelist

TBD

Quest Limitations

Quest Limitations are a set of options that could be used to configure a quest. Using Quest Limitations allows to build highly customizable quest systems in different games.

Overview

TBD

shema

Validation Rules

TBD

alt text

Sub-quests

Sub-quest is a core mechanism to associate specific actions with quests. Sub-quest should be considered as steps to complete the quest. Each sub-quest has only one associated action with it. Each quest must have at least one sub-quest.

class SubquestDto {
actionId: string;
title: string;
description: string | null;
target: number;
priority: number | null;
}
  • actionId is used to associate sub-quest with specific action. Associating sub-quest with action means that system will track quest progress with this sub-quest

  • title is used to display some sub-quest name

  • description could be used to provide some additional info about sub-quest. Could be used if sub-quest is not trivial and using only title is insufficient

  • target indicates how many times some action should be dispatched to finish sub-quest. Quest is finished automatically one all quest's sub-quests are finished

  • priority is used to provide a strict order in which sub-quests should be finished. This field must be used only with dedicated limitation

Database

TBD

Implementation

TBD

Integration

TBD