Skip to content

Commit

Permalink
Merge pull request #293 from dojoengine/fix/readme-1
Browse files Browse the repository at this point in the history
feat: optimistic example
  • Loading branch information
ponderingdemocritus authored Oct 5, 2024
2 parents 94f15c6 + 2fe9c64 commit 31cad93
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 15 deletions.
9 changes: 4 additions & 5 deletions examples/example-vite-react-sdk/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { addAddressPadding } from "starknet";
import { Models, Schema } from "./bindings.ts";
import { useDojo } from "./useDojo.tsx";
import useModel from "./useModel.tsx";
import { useSystemCalls } from "./useSystemCalls.ts";

export const useDojoStore = createDojoStore<Schema>();

Expand All @@ -17,6 +18,8 @@ function App({ db }: { db: SDK<Schema> }) {
const state = useDojoStore((state) => state);
const entities = useDojoStore((state) => state.entities);

const { spawn } = useSystemCalls();

const entityId = useMemo(
() => getEntityIdFromKeys([BigInt(account?.account.address)]),
[account?.account.address]
Expand Down Expand Up @@ -161,11 +164,7 @@ function App({ db }: { db: SDK<Schema> }) {
<div className="col-start-2">
<button
className="h-12 w-12 bg-gray-600 rounded-full shadow-md active:shadow-inner active:bg-gray-500 focus:outline-none text-2xl font-bold text-gray-200"
onClick={async () =>
await client.actions.spawn({
account: account.account,
})
}
onClick={async () => await spawn()}
>
+
</button>
Expand Down
62 changes: 62 additions & 0 deletions examples/example-vite-react-sdk/src/useSystemCalls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { getEntityIdFromKeys } from "@dojoengine/utils";
import { useDojoStore } from "./App";
import { useDojo } from "./useDojo";
import { v4 as uuidv4 } from "uuid";

export const useSystemCalls = () => {
const state = useDojoStore((state) => state);

const {
setup: { client },
account: { account },
} = useDojo();

const generateEntityId = () => {
return getEntityIdFromKeys([BigInt(account?.address)]);
};

const spawn = async () => {
// Generate a unique entity ID
const entityId = generateEntityId();

// Generate a unique transaction ID
const transactionId = uuidv4();

// The value to update the Moves model with
const remainingMoves = 100;

// Apply an optimistic update to the state
// this uses immer drafts to update the state
state.applyOptimisticUpdate(
transactionId,
(draft) =>
(draft.entities[entityId].models.dojo_starter.Moves!.remaining =
remainingMoves)
);

try {
// Execute the spawn action from the client
await client.actions.spawn({ account });

// Wait for the entity to be updated with the new state
await state.waitForEntityChange(entityId, (entity) => {
return (
entity?.models?.dojo_starter?.Moves?.remaining ===
remainingMoves
);
});
} catch (error) {
// Revert the optimistic update if an error occurs
state.revertOptimisticUpdate(transactionId);
console.error("Error executing spawn:", error);
throw error;
} finally {
// Confirm the transaction if successful
state.confirmTransaction(transactionId);
}
};

return {
spawn,
};
};
74 changes: 73 additions & 1 deletion packages/sdk/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,79 @@ const subscription = await sdk.subscribeEntityQuery(
## Optimistic Client Rendering
<!-- TODO -->
We use [immer](https://immerjs.github.io/immer/) for efficient optimistic rendering. This allows instant client-side entity state updates while awaiting blockchain confirmation.
The process:
1. Update entity state optimistically.
2. Wait for condition (e.g., a specific state change).
3. Resolve update, providing immediate user feedback.
This ensures a responsive user experience while maintaining blockchain data integrity.
See our [example project](../../examples/example-vite-react-sdk/src/useSystemCalls.ts) for a real-world implementation.
Note: You will need to have a subscription running in order for the update to resolve.
```typescript
export const useSystemCalls = () => {
const state = useDojoStore((state) => state);
const {
setup: { client },
account: { account },
} = useDojo();
const generateEntityId = () => {
return getEntityIdFromKeys([BigInt(account?.address)]);
};
const spawn = async () => {
// Generate a unique entity ID
const entityId = generateEntityId();
// Generate a unique transaction ID
const transactionId = uuidv4();
// The value to update
const remainingMoves = 100;
// Apply an optimistic update to the state
// this uses immer drafts to update the state
state.applyOptimisticUpdate(
transactionId,
(draft) =>
(draft.entities[entityId].models.dojo_starter.Moves!.remaining =
remainingMoves)
);
try {
// Execute the spawn action
await client.actions.spawn({ account });
// Wait for the entity to be updated with the new state
await state.waitForEntityChange(entityId, (entity) => {
return (
entity?.models?.dojo_starter?.Moves?.remaining ===
remainingMoves
);
});
} catch (error) {
// Revert the optimistic update if an error occurs
state.revertOptimisticUpdate(transactionId);
console.error("Error executing spawn:", error);
throw error;
} finally {
// Confirm the transaction if successful
state.confirmTransaction(transactionId);
}
};
return {
spawn,
};
};
```
# Advanced Usage
Expand Down
18 changes: 9 additions & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ If you are not familiar with Dojo, then you should read the [book](https://book.

- [Quick start in 5 minutes](#quick-start-in-5-minutes)
- [Dojo SDK](#dojo-sdk)
- [Examples](#examples)
- [Examples](#all-examples)
- [All Packages](#all-packages)

## Quick start in 5 minutes
Expand Down Expand Up @@ -70,7 +70,7 @@ pnpm i @dojoengine/sdk
```
> Basic example: [example-vite-react-sdk](./examples/example-vite-react-sdk/)
> More complex: [example-vite-react-sdk](./examples/example-vite-kitchen-sink/)
> More complex: [example-vite-kitchen-sink](./examples/example-vite-kitchen-sink/)
```js
// Create client with your parameters
Expand Down Expand Up @@ -153,13 +153,13 @@ Spin any of these examples locally
npx @dojoengine/create-dojo start
```

- [example-vite-react-sdk](./examples/example-vite-react-sdk/): A React application using Vite and the Dojo SDK
- [example-vite-react-phaser-recs](./examples/example-vite-react-phaser-recs/): A React application using Vite and the Dojo SDK
- [example-vite-react-pwa-recs](./examples/example-vite-react-pwa-recs/): A React application using Vite and the Dojo SDK
- [example-vite-react-threejs-recs](./examples/example-vite-react-threejs-recs/): A React application using Vite and the Dojo SDK
- [example-vue-app-recs](./examples/example-vue-app-recs/): A React application using Vite and the Dojo SDK
- [example-vite-kitchen-sink](./examples/example-vite-kitchen-sink/): A React application using Vite and the Dojo SDK
- [example-nodejs-bot](./examples/example-nodejs-bot/): A React application using Vite and the Dojo SDK
- [example-vite-react-sdk](./examples/example-vite-react-sdk/)
- [example-vite-react-phaser-recs](./examples/example-vite-react-phaser-recs/)
- [example-vite-react-pwa-recs](./examples/example-vite-react-pwa-recs/)
- [example-vite-react-threejs-recs](./examples/example-vite-react-threejs-recs/)
- [example-vue-app-recs](./examples/example-vue-app-recs/)
- [example-vite-kitchen-sink](./examples/example-vite-kitchen-sink/)
- [example-nodejs-bot](./examples/example-nodejs-bot/)

## Contributing to dojo.js

Expand Down

0 comments on commit 31cad93

Please sign in to comment.