Skip to content

Commit 0530d74

Browse files
Merge pull request #280 from dojoengine/feat/sdk-state
feat: draft zustand state management system
2 parents 69662d1 + cad1567 commit 0530d74

File tree

12 files changed

+1012
-118
lines changed

12 files changed

+1012
-118
lines changed

.github/workflows/npx-test.yaml

-26
This file was deleted.

examples/example-vite-react-sdk/package.json

+9-3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13-
"@dojoengine/core": "1.0.0-alpha.12",
13+
"@dojoengine/core": "workspace:*",
14+
"@dojoengine/create-burner": "workspace:*",
1415
"@dojoengine/sdk": "workspace:*",
15-
"@dojoengine/torii-wasm": "1.0.0-alpha.12",
16+
"@dojoengine/torii-wasm": "workspace:*",
17+
"@types/uuid": "^10.0.0",
18+
"immer": "^10.1.1",
1619
"react": "^18.3.1",
1720
"react-dom": "^18.3.1",
21+
"starknet": "6.11.0",
22+
"uuid": "^10.0.0",
1823
"vite-plugin-top-level-await": "^1.4.4",
19-
"vite-plugin-wasm": "^3.3.0"
24+
"vite-plugin-wasm": "^3.3.0",
25+
"zustand": "^4.5.5"
2026
},
2127
"devDependencies": {
2228
"@eslint/js": "^9.11.1",

examples/example-vite-react-sdk/src/App.tsx

+50-36
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect } from "react";
22
import "./App.css";
3-
import { ParsedEntity, SDK } from "@dojoengine/sdk";
3+
import { SDK, createDojoStore } from "@dojoengine/sdk";
44
import { Schema } from "./bindings.ts";
55

6+
import { v4 as uuidv4 } from "uuid";
7+
8+
export const useDojoStore = createDojoStore<Schema>();
9+
610
function App({ db }: { db: SDK<Schema> }) {
7-
const [entities, setEntities] = useState<ParsedEntity<Schema>[]>([]);
11+
const state = useDojoStore((state) => state);
12+
const entities = useDojoStore((state) => state.entities);
813

914
useEffect(() => {
1015
let unsubscribe: (() => void) | undefined;
@@ -28,15 +33,7 @@ function App({ db }: { db: SDK<Schema> }) {
2833
response.data &&
2934
response.data[0].entityId !== "0x0"
3035
) {
31-
console.log(response.data);
32-
setEntities((prevEntities) => {
33-
return prevEntities.map((entity) => {
34-
const newEntity = response.data?.find(
35-
(e) => e.entityId === entity.entityId
36-
);
37-
return newEntity ? newEntity : entity;
38-
});
39-
});
36+
state.setEntities(response.data);
4037
}
4138
},
4239
{ logging: true }
@@ -54,8 +51,6 @@ function App({ db }: { db: SDK<Schema> }) {
5451
};
5552
}, [db]);
5653

57-
console.log("entities:");
58-
5954
useEffect(() => {
6055
const fetchEntities = async () => {
6156
try {
@@ -76,23 +71,7 @@ function App({ db }: { db: SDK<Schema> }) {
7671
return;
7772
}
7873
if (resp.data) {
79-
console.log(resp.data);
80-
setEntities((prevEntities) => {
81-
const updatedEntities = [...prevEntities];
82-
resp.data?.forEach((newEntity) => {
83-
const index = updatedEntities.findIndex(
84-
(entity) =>
85-
entity.entityId ===
86-
newEntity.entityId
87-
);
88-
if (index !== -1) {
89-
updatedEntities[index] = newEntity;
90-
} else {
91-
updatedEntities.push(newEntity);
92-
}
93-
});
94-
return updatedEntities;
95-
});
74+
state.setEntities(resp.data);
9675
}
9776
}
9877
);
@@ -104,20 +83,55 @@ function App({ db }: { db: SDK<Schema> }) {
10483
fetchEntities();
10584
}, [db]);
10685

86+
const optimisticUpdate = async () => {
87+
const entityId =
88+
"0x571368d35c8fe136adf81eecf96a72859c43de7efd8fdd3d6f0d17e308df984";
89+
90+
const transactionId = uuidv4();
91+
92+
state.applyOptimisticUpdate(transactionId, (draft) => {
93+
draft.entities[entityId].models.dojo_starter.Moves!.remaining = 10;
94+
});
95+
96+
try {
97+
// Wait for the entity to be updated before full resolving the transaction. Reverts if the condition is not met.
98+
const updatedEntity = await state.waitForEntityChange(
99+
entityId,
100+
(entity) => {
101+
// Define your specific condition here
102+
return entity?.models.dojo_starter.Moves?.can_move === true;
103+
}
104+
);
105+
106+
console.log("Entity has been updated to active:", updatedEntity);
107+
108+
console.log("Updating entities...");
109+
} catch (error) {
110+
console.error("Error updating entities:", error);
111+
state.revertOptimisticUpdate(transactionId);
112+
} finally {
113+
console.log("Updating entities...");
114+
state.confirmTransaction(transactionId);
115+
}
116+
};
117+
107118
return (
108119
<div>
109120
<h1>Game State</h1>
110-
{entities.map((entity) => (
111-
<div key={entity.entityId}>
112-
<h2>Entity {entity.entityId}</h2>
121+
<button onClick={optimisticUpdate}>update</button>
122+
{Object.entries(entities).map(([entityId, entity]) => (
123+
<div key={entityId}>
124+
<h2>Entity {entityId}</h2>
113125
<h3>Position</h3>
114126
<p>
115127
Player:{" "}
116128
{entity.models.dojo_starter.Position?.player ?? "N/A"}
117129
<br />
118-
X: {entity.models.dojo_starter.Position?.vec.x ?? "N/A"}
130+
X:{" "}
131+
{entity.models.dojo_starter.Position?.vec?.x ?? "N/A"}
119132
<br />
120-
Y: {entity.models.dojo_starter.Position?.vec.y ?? "N/A"}
133+
Y:{" "}
134+
{entity.models.dojo_starter.Position?.vec?.y ?? "N/A"}
121135
</p>
122136
<h3>Moves</h3>
123137
<p>

packages/sdk/package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,25 @@
2222
"./package.json": "./package.json"
2323
},
2424
"devDependencies": {
25+
"@rollup/plugin-commonjs": "^28.0.0",
2526
"@vitest/coverage-v8": "^1.6.0",
2627
"eslint": "^8.57.1",
2728
"prettier": "^2.8.8",
2829
"tsup": "^8.3.0",
2930
"typescript": "^5.6.2",
3031
"vite": "^3.2.11",
31-
"vitest": "^1.6.0"
32+
"vitest": "^1.6.0",
33+
"benchmark": "^2.1.4",
34+
"lodash": "^4.17.21"
3235
},
3336
"peerDependencies": {
3437
"starknet": "6.11.0"
3538
},
3639
"dependencies": {
40+
"@dojoengine/create-burner": "workspace:*",
3741
"@dojoengine/torii-client": "workspace:*",
3842
"axios": "^0.27.2",
39-
"lodash": "^4.17.21",
43+
"immer": "^10.1.1",
4044
"vite-plugin-wasm": "^3.3.0",
4145
"zustand": "^4.5.5"
4246
},

packages/sdk/src/__example__/index.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,20 @@ export interface ItemModel {
2323
durability: number;
2424
}
2525

26+
export interface GalaxyModel {
27+
fieldOrder: string[];
28+
id: string;
29+
name: string;
30+
}
31+
2632
export interface MockSchemaType extends SchemaType {
2733
world: {
2834
player: PlayerModel;
2935
game: GameModel;
3036
item: ItemModel;
3137
};
3238
universe: {
33-
galaxy: {
34-
fieldOrder: string[];
35-
id: string;
36-
name: string;
37-
};
39+
galaxy: GalaxyModel;
3840
};
3941
}
4042

0 commit comments

Comments
 (0)