Skip to content

Commit

Permalink
✨ Add game management in sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
bal7hazar committed Jan 9, 2025
1 parent f37445f commit 1bbf036
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 20 deletions.
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bal7hazar/arcade-sdk",
"version": "0.0.13",
"version": "0.0.14",
"description": "Cartridge Arcade SDK",
"license": "MIT",
"repository": {
Expand Down
182 changes: 182 additions & 0 deletions packages/sdk/src/modules/registry/game.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import * as torii from "@dojoengine/torii-client";
import { NAMESPACE } from "../../constants";
import { shortString } from "starknet";

const MODEL_NAME = `${NAMESPACE}-Game`;
const DEFAULT_KEYS_CLAUSES: torii.EntityKeysClause[] = [
{ Keys: { keys: [undefined, undefined], pattern_matching: "FixedLen", models: [MODEL_NAME] } },
];
const DEFAULT_CLAUSE: torii.Clause = {
Keys: { keys: [undefined, undefined], pattern_matching: "FixedLen", models: [MODEL_NAME] },
};

export class GameModel {
constructor(
public worldAddress: string,
public namespace: string,
public project: string,
public active: boolean,
public published: boolean,
public whitelisted: boolean,
public priority: number,
public karma: number,
public metadata: Metadata,
public socials: Socials,
public owner: string,
) {
this.worldAddress = worldAddress;
this.namespace = namespace;
this.project = project;
this.active = active;
this.published = published;
this.whitelisted = whitelisted;
this.priority = priority;
this.karma = karma;
this.metadata = metadata;
this.socials = socials;
this.owner = owner;
}

static from(model: torii.Model) {
const worldAddress = String(model.world_address.value);
const namespace = shortString.decodeShortString(String(model.namespace.value));
const project = shortString.decodeShortString(String(model.project.value));
const active = !!model.active.value;
const published = !!model.published.value;
const whitelisted = !!model.whitelisted.value;
const priority = Number(model.priority.value);
const karma = Number(model.karma.value);
const metadata = Metadata.from(String(model.metadata.value));
const socials = Socials.from(String(model.socials.value));
const owner = BigInt(String(model.owner.value)).toString(16);
return new GameModel(
worldAddress,
namespace,
project,
active,
published,
whitelisted,
priority,
karma,
metadata,
socials,
owner,
);
}
}

export class Metadata {
constructor(
public color: string,
public name: string,
public description: string,
public image: string,
public banner: string,
) {
this.color = color;
this.name = name;
this.description = description;
this.image = image;
this.banner = banner;
}

static from(value: string) {
const json = JSON.parse(value);
return new Metadata(json.color, json.name, json.description, json.image, json.banner);
}
}

export class Socials {
constructor(
public discord: string,
public telegram: string,
public twitter: string,
public youtube: string,
public website: string,
) {
this.discord = discord;
this.telegram = telegram;
this.twitter = twitter;
this.youtube = youtube;
this.website = website;
}

static from(value: string) {
const json = JSON.parse(value);
return new Socials(json.discord, json.telegram, json.twitter, json.youtube, json.website);
}
}

export const Game = {
client: undefined as torii.ToriiClient | undefined,
unsubscribe: undefined as torii.Subscription | undefined,

init: (toriiClient: torii.ToriiClient) => {
Game.client = toriiClient;
},

fetch: async (
callback: (models: GameModel[]) => void,
clause: torii.Clause = DEFAULT_CLAUSE,
limit: number = 1000,
offset: number = 0,
order_by: torii.OrderBy[] = [],
entity_models: string[] = [],
dont_include_hashed_keys: boolean = false,
entity_updated_after: number = 0,
historical: boolean = false,
) => {
if (!Game.client) return;
const models: GameModel[] = [];
while (true) {
const entities: torii.Entities = await Game.client.getEventMessages(
{
limit,
offset,
clause,
order_by,
entity_models,
dont_include_hashed_keys,
entity_updated_after,
},
historical,
);
Object.values(entities).forEach((event: torii.Entity) => {
if (!event[MODEL_NAME]) return;
const model = event[MODEL_NAME];
const gameModel = GameModel.from(model);
models.push(gameModel);
});
if (models.length < limit) break;
offset += limit;
}
callback(models);
},

sub: async (
callback: (event: GameModel) => void,
clauses: torii.EntityKeysClause[] = DEFAULT_KEYS_CLAUSES,
historical: boolean = false,
) => {
if (!Game.client) return;
const wrappedCallback = (_fetchedEntities: any, event: any) => {
if (!event[MODEL_NAME]) return;
const model = event[MODEL_NAME];
const gameModel = GameModel.from(model);
callback(gameModel);
};
const subscription = async () => {
if (!Game.client) return;
return Game.client.onEventMessageUpdated(clauses, historical, wrappedCallback);
};
subscription()
.then((sync) => (Game.unsubscribe = sync))
.catch((error) => console.error("Error setting up entity sync:", error));
},

unsub: () => {
if (!Game.unsubscribe) return;
Game.unsubscribe.cancel();
Game.unsubscribe = undefined;
},
};
5 changes: 4 additions & 1 deletion packages/sdk/src/modules/registry/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as torii from "@dojoengine/torii-client";
import { Pinning, PinningEvent } from "./pinning";
export type { PinningEvent };
import { Game, GameModel, Metadata, Socials } from "./game";
export type { PinningEvent, GameModel, Metadata, Socials };

export const Registry = {
Pinning: Pinning,
Game: Game,

init: (toriiClient: torii.ToriiClient) => {
Pinning.init(toriiClient);
Game.init(toriiClient);
},
};
41 changes: 23 additions & 18 deletions packages/sdk/src/modules/registry/pinning.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import * as torii from "@dojoengine/torii-client";
import { NAMESPACE } from "../../constants";

const MODEL_NAME = "ARCADE-TrophyPinning";
const MODEL_NAME = `${NAMESPACE}-TrophyPinning`;
const DEFAULT_KEYS_CLAUSES: torii.EntityKeysClause[] = [
{ Keys: { keys: [undefined, undefined], pattern_matching: "FixedLen", models: [MODEL_NAME] } },
];
const DEFAULT_CLAUSE: torii.Clause = {
Keys: { keys: [undefined, undefined], pattern_matching: "FixedLen", models: [MODEL_NAME] },
};

export type PinningEvent = {
playerId: string;
achievementId: string;
time: number;
};
export class PinningEvent {
constructor(
public playerId: string,
public achievementId: string,
public time: number,
) {
this.playerId = playerId;
this.achievementId = achievementId;
this.time = time;
}

static from(model: torii.Model) {
const playerId = BigInt(String(model.player_id.value)).toString(16);
const achievementId = BigInt(String(model.achievement_id.value)).toString(16);
const time = Number(model.time.value);
return new PinningEvent(playerId, achievementId, time);
}
}

export const Pinning = {
client: undefined as torii.ToriiClient | undefined,
Expand Down Expand Up @@ -51,14 +65,8 @@ export const Pinning = {
Object.values(entities).forEach((event: torii.Entity) => {
if (!event[MODEL_NAME]) return;
const model = event[MODEL_NAME];
const playerId = BigInt(String(model.player_id.value)).toString(16);
const achievementId = BigInt(String(model.achievement_id.value)).toString(16);
const time = Number(model.time.value);
events.push({
playerId,
achievementId,
time,
});
const pinningEvent = PinningEvent.from(model);
events.push(pinningEvent);
});
if (events.length < limit) break;
offset += limit;
Expand All @@ -75,10 +83,7 @@ export const Pinning = {
const wrappedCallback = (_fetchedEntities: any, event: any) => {
if (!event[MODEL_NAME]) return;
const model = event[MODEL_NAME];
const playerId = BigInt(String(model.player_id.value)).toString(16);
const achievementId = BigInt(String(model.achievement_id.value)).toString(16);
const time = Number(model.time.value);
const pinningEvent: PinningEvent = { playerId, achievementId, time };
const pinningEvent = PinningEvent.from(model);
callback(pinningEvent);
};
const subscription = async () => {
Expand Down

0 comments on commit 1bbf036

Please sign in to comment.