Skip to content

Commit

Permalink
feat: sdk reusable query hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
MartianGreed committed Feb 26, 2025
1 parent 0f71833 commit 2f78852
Show file tree
Hide file tree
Showing 20 changed files with 1,209 additions and 264 deletions.
16 changes: 16 additions & 0 deletions .changeset/good-eagles-speak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@dojoengine/sdk": minor
"template-vite-ts": minor
"@dojoengine/core": minor
"@dojoengine/create-burner": minor
"@dojoengine/create-dojo": minor
"@dojoengine/predeployed-connector": minor
"@dojoengine/react": minor
"@dojoengine/state": minor
"@dojoengine/torii-client": minor
"@dojoengine/torii-wasm": minor
"@dojoengine/utils": minor
"@dojoengine/utils-wasm": minor
---

feat: add reusable sdk react hooks
3 changes: 1 addition & 2 deletions examples/example-nodejs-bot/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"outDir": "dist",
"types": ["bun-types"]
"outDir": "dist"
},
"include": [
"./src/**/*",
Expand Down
2 changes: 1 addition & 1 deletion examples/example-vite-react-sdk/dojoConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createDojoConfig } from "@dojoengine/core";

import manifest from "../../worlds/dojo-starter/manifest_dev.json";
import manifest from "../../../dojo-starter/manifest_dev.json";

export const dojoConfig = createDojoConfig({
manifest,
Expand Down
4 changes: 2 additions & 2 deletions examples/example-vite-react-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"@starknet-react/core": "catalog:",
"@types/uuid": "^10.0.0",
"immer": "^10.1.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "catalog:",
"react-dom": "catalog:",
"starknet": "catalog:",
"uuid": "^10.0.0",
"vite-plugin-top-level-await": "^1.5.0",
Expand Down
96 changes: 24 additions & 72 deletions examples/example-vite-react-sdk/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { useEffect, useMemo } from "react";
import { KeysClause, ToriiQueryBuilder } from "@dojoengine/sdk";
import { getEntityIdFromKeys } from "@dojoengine/utils";
import { AccountInterface, addAddressPadding, CairoCustomEnum } from "starknet";

import { ModelsMapping } from "./typescript/models.gen.ts";
import { useSystemCalls } from "./useSystemCalls.ts";
import { useAccount } from "@starknet-react/core";
import { WalletAccount } from "./wallet-account.tsx";
import { HistoricalEvents } from "./historical-events.tsx";
import { useDojoSDK, useModel } from "@dojoengine/sdk/react";
import {
useDojoSDK,
useEntityId,
useEntityQuery,
useModel,
} from "@dojoengine/sdk/react";
import { addAddressPadding, CairoCustomEnum } from "starknet";
import { Events } from "./events.tsx";

/**
* Main application component that provides game functionality and UI.
Expand All @@ -17,79 +21,26 @@ import { useDojoSDK, useModel } from "@dojoengine/sdk/react";
* @param props.sdk - The Dojo SDK instance configured with the game schema
*/
function App() {
const { useDojoStore, client, sdk } = useDojoSDK();
const { useDojoStore, client } = useDojoSDK();
const { account } = useAccount();
const state = useDojoStore((state) => state);
const entities = useDojoStore((state) => state.entities);

const { spawn } = useSystemCalls();

const entityId = useMemo(() => {
if (account) {
return getEntityIdFromKeys([BigInt(account.address)]);
}
return BigInt(0);
}, [account]);

// This is experimental feature.
// Use those queries if you want to be closer to how you should query your ecs system with torii
// useEffect(() => {
// async function fetchToriiClause() {
// const res = await sdk.client.getEntities(
// new ToriiQueryBuilder()
// .withClause(
// new ClauseBuilder()
// .keys([], [undefined], "VariableLen")
// .build()
// )
// .withLimit(2)
// .addOrderBy(ModelsMapping.Moves, "remaining", "Desc")
// .build()
// );
// return res;
// }
// fetchToriiClause().then(console.log);
// });

useEffect(() => {
let unsubscribe: (() => void) | undefined;

const subscribe = async (account: AccountInterface) => {
const [initialData, subscription] = await sdk.subscribeEntityQuery({
query: new ToriiQueryBuilder()
.withClause(
// Querying Moves and Position models that has at least [account.address] as key
KeysClause(
[ModelsMapping.Moves, ModelsMapping.Position],
[addAddressPadding(account.address)],
"VariableLen"
).build()
)
.includeHashedKeys(),
callback: ({ error, data }) => {
if (error) {
console.error("Error setting up entity sync:", error);
} else if (data && data[0].entityId !== "0x0") {
state.updateEntity(data[0]);
}
},
});

state.setEntities(initialData);

unsubscribe = () => subscription.cancel();
};

if (account) {
subscribe(account);
}

return () => {
if (unsubscribe) {
unsubscribe();
}
};
}, [sdk, account, state]);
const entityId = useEntityId(account?.address ?? "0");

useEntityQuery(
new ToriiQueryBuilder()
.withClause(
// Querying Moves and Position models that has at least [account.address] as key
KeysClause(
[ModelsMapping.Moves, ModelsMapping.Position],
[addAddressPadding(account?.address ?? "0")],
"FixedLen"
).build()
)
.includeHashedKeys()
);

const moves = useModel(entityId as string, ModelsMapping.Moves);
const position = useModel(entityId as string, ModelsMapping.Position);
Expand Down Expand Up @@ -253,6 +204,7 @@ function App() {
</table>
</div>

<Events />
{/* // Here sdk is passed as props but this can be done via contexts */}
<HistoricalEvents />
</div>
Expand Down
40 changes: 40 additions & 0 deletions examples/example-vite-react-sdk/src/events.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { KeysClause, ToriiQueryBuilder } from "@dojoengine/sdk";
import { useEntityId, useEventQuery, useModel } from "@dojoengine/sdk/react";
import { useAccount } from "@starknet-react/core";
import { addAddressPadding } from "starknet";
import { ModelsMapping } from "./typescript/models.gen";

export function Events() {
const { account } = useAccount();
const entityId = useEntityId(account?.address ?? "0");
useEventQuery(
new ToriiQueryBuilder()
.withClause(
KeysClause(
[],
[addAddressPadding(account?.address ?? "0")],
"VariableLen"
).build()
)
.includeHashedKeys()
);
const moved = useModel(entityId, ModelsMapping.Moved);
if (!account) {
return (
<div className="mt-6">
<h2 className="text-white">Please connect your wallet</h2>
</div>
);
}
return (
<div className="mt-6">
<h2 className="text-white">
Player Last Movement : {moved && moved.direction}{" "}
</h2>

{/* {events.map((e: ParsedEntity<SchemaType>, key) => {
return <Event event={e} key={key} />;
})} */}
</div>
);
}
57 changes: 12 additions & 45 deletions examples/example-vite-react-sdk/src/historical-events.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,20 @@
import { KeysClause, ParsedEntity, ToriiQueryBuilder } from "@dojoengine/sdk";
import { useAccount } from "@starknet-react/core";
import { SchemaType } from "./typescript/models.gen";
import { AccountInterface, addAddressPadding } from "starknet";
import { useEffect, useState } from "react";
import { Subscription } from "@dojoengine/torii-client";
import { useDojoSDK } from "@dojoengine/sdk/react";
import { addAddressPadding } from "starknet";
import { useHistoricalEventsQuery } from "@dojoengine/sdk/react";

export function HistoricalEvents() {
const { account } = useAccount();
const { sdk } = useDojoSDK();
const [events, setEvents] = useState<ParsedEntity<SchemaType>[]>([]);
const [subscription, setSubscription] = useState<Subscription | null>(null);

useEffect(() => {
async function subscribeHistoricalEvent(account: AccountInterface) {
try {
const [e, s] = await sdk.subscribeEventQuery({
query: new ToriiQueryBuilder().withClause(
KeysClause(
[],
[addAddressPadding(account.address)],
"VariableLen"
).build()
),
callback: ({ data, error }) => {
if (data && data.length > 0) {
console.log(data);
}
if (error) {
console.error(error);
}
},
historical: true,
});
setEvents(e as unknown as ParsedEntity<SchemaType>[]);
setSubscription(s);
} catch (error) {
setEvents([]);
if (subscription) {
subscription.free();
}
console.error(error);
}
}

if (account) {
subscribeHistoricalEvent(account);
}
}, [account, setEvents, sdk]);

const events = useHistoricalEventsQuery(
new ToriiQueryBuilder().withClause(
KeysClause(
[],
[addAddressPadding(account?.address ?? "0")],
"VariableLen"
).build()
)
);
if (!account) {
return (
<div className="mt-6">
Expand All @@ -59,6 +25,7 @@ export function HistoricalEvents() {
return (
<div className="mt-6">
<h2 className="text-white">Player Events :</h2>
{/* @ts-ignore */}
{events.map((e: ParsedEntity<SchemaType>, key) => {
return <Event event={e} key={key} />;
})}
Expand Down
1 change: 1 addition & 0 deletions examples/example-vite-react-sdk/src/starknet-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function StarknetProvider({ children }: PropsWithChildren) {
explorer={voyager}
autoConnect
>
{/* @ts-ignore react version mismatch */}
{children}
</StarknetConfig>
);
Expand Down
2 changes: 1 addition & 1 deletion examples/example-vite-react-sdk/tsconfig.app.tsbuildinfo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"root":["./src/app.tsx","./src/historical-events.tsx","./src/main.tsx","./src/starknet-provider.tsx","./src/usesystemcalls.ts","./src/vite-env.d.ts","./src/wallet-account.tsx","./src/typescript/contracts.gen.ts","./src/typescript/models.gen.ts"],"version":"5.7.3"}
{"root":["./src/app.tsx","./src/events.tsx","./src/historical-events.tsx","./src/main.tsx","./src/starknet-provider.tsx","./src/usesystemcalls.ts","./src/vite-env.d.ts","./src/wallet-account.tsx","./src/typescript/contracts.gen.ts","./src/typescript/models.gen.ts"],"version":"5.7.3"}
72 changes: 15 additions & 57 deletions examples/example-vite-react-sql/src/hooks/usePlayerActions.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,20 @@
import { useEffect, useMemo } from "react";

import { KeysClause, ParsedEntity, ToriiQueryBuilder } from "@dojoengine/sdk";
import { useDojoSDK } from "@dojoengine/sdk/react";
import { getEntityIdFromKeys } from "@dojoengine/utils";
import { ModelsMapping, SchemaType } from "@/typescript/models.gen";
import { KeysClause, ToriiQueryBuilder } from "@dojoengine/sdk";
import { useEntityId, useEntityQuery } from "@dojoengine/sdk/react";
import { ModelsMapping, type SchemaType } from "@/typescript/models.gen";
import { addAddressPadding } from "starknet";

export function usePlayerActions(address: string | undefined) {
const { sdk, useDojoStore } = useDojoSDK();
const state = useDojoStore((state) => state);

const entityId = useMemo(() => {
if (address) {
return getEntityIdFromKeys([BigInt(address)]);
}
return BigInt(0);
}, [address]);

useEffect(() => {
let unsubscribe: (() => void) | undefined;

const subscribe = async (address: string) => {
const [entities, subscription] = await sdk.subscribeEntityQuery({
query: new ToriiQueryBuilder()
.withClause(
KeysClause(
[ModelsMapping.Moves, ModelsMapping.Position],
[addAddressPadding(address)],
"VariableLen"
).build()
)
.includeHashedKeys(),
callback: ({ error, data }) => {
if (error) {
console.error("Error setting up entity sync:", error);
} else if (
data &&
(data[0] as ParsedEntity<SchemaType>).entityId !== "0x0"
) {
state.updateEntity(data[0] as ParsedEntity<SchemaType>);
}
},
});
state.setEntities(entities);

unsubscribe = () => subscription.cancel();
};

if (address) {
subscribe(address);
}

return () => {
if (unsubscribe) {
unsubscribe();
}
};
}, [sdk, address]);

const entityId = useEntityId(address ?? "0");
useEntityQuery<SchemaType>(
new ToriiQueryBuilder()
.withClause(
KeysClause(
[ModelsMapping.Moves, ModelsMapping.Position],
[addAddressPadding(address ?? "0")],
"VariableLen"
).build()
)
.includeHashedKeys()
);
return entityId;
}
1 change: 1 addition & 0 deletions examples/example-vite-react-sql/src/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function RootComponent() {
<div className="min-h-screen bg-background">
<Header />
<main className="container py-6 mx-auto my-0">
{/* @ts-ignore */}
<Outlet />
</main>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export const Player = (props: any) => {

return (
<>
{/* @ts-ignore */}
<Cone
castShadow
key="player"
Expand Down
Loading

0 comments on commit 2f78852

Please sign in to comment.