Skip to content

feat: deprecate QueryBuilder -- Default to ToriiQueryBuilder #392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .changeset/tidy-toys-compare.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
---

Default to ToriiQueryBuilder for queries with Clause
2 changes: 1 addition & 1 deletion examples/example-vite-experimental-sdk/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src", "vite.config.ts"]
"include": ["src"]
}
49 changes: 24 additions & 25 deletions examples/example-vite-kitchen-sink/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,52 @@
"preview": "vite preview"
},
"dependencies": {
"@cartridge/connector": "^0.3.46",
"@dojoengine/core": "workspace:*",
"@dojoengine/sdk": "workspace:*",
"@dojoengine/predeployed-connector": "workspace:*",
"@dojoengine/sdk": "workspace:*",
"@dojoengine/torii-client": "workspace:*",
"@dojoengine/torii-wasm": "workspace:*",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tooltip": "^1.1.8",
"@starknet-react/chains": "catalog:",
"@starknet-react/core": "catalog:",
"@t3-oss/env-core": "^0.11.1",
"@t3-oss/env-nextjs": "^0.11.1",
"class-variance-authority": "^0.7.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dotenv": "^16.4.5",
"jiti": "^1.21.6",
"dotenv": "^16.4.7",
"jiti": "^1.21.7",
"lucide-react": "^0.441.0",
"next": "14.2.12",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.0",
"react-hook-form": "^7.54.2",
"starknet": "catalog:",
"tailwind-merge": "^2.5.2",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.9",
"zod": "^3.23.8"
"zod": "^3.24.1"
},
"devDependencies": {
"@types/node": "^20.16.10",
"@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.2",
"@types/node": "^20.17.17",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^8.57.1",
"eslint-config-next": "14.2.12",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.13",
"typescript": "^5.6.2",
"vite": "^5.4.8",
"postcss": "^8.5.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
"vite": "^6.1.0",
"vite-plugin-mkcert": "^1.17.6",
"vite-plugin-top-level-await": "^1.4.4",
"vite-plugin-wasm": "^3.3.0",
"vite-plugin-wasm": "^3.4.1",
"vite-preset-react": "^2.3.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useCallback, useEffect, useState } from "react";

import { ParsedEntity, QueryBuilder, SDK } from "@dojoengine/sdk";
import {
KeysClause,
ParsedEntity,
SDK,
ToriiQueryBuilder,
} from "@dojoengine/sdk";
import { useDojoSDK } from "@dojoengine/sdk/react";
import { Subscription } from "@dojoengine/torii-wasm";
import { SchemaType } from "@/typescript/models.gen";
Expand Down Expand Up @@ -32,47 +37,22 @@ export default function CallerCounter() {
}, [incrementCallerCounter, setIsLoading]);

const { sdk } = useDojoSDK<typeof setupWorld, SchemaType>();
useEffect(() => {
async function getEntity(db: SDK<SchemaType>, address: string) {
const entity = await db.getEntities({
query: new QueryBuilder<SchemaType>()
.namespace("onchain_dash", (n) =>
n.entity("CallerCounter", (e) =>
e.eq("caller", addAddressPadding(address))
)
)
.build(),
callback: () => {},
});
const counter = entity.pop() as ParsedEntity<SchemaType>;
if (!counter) {
return 0;
}
const count = counter.models.onchain_dash?.CallerCounter?.counter;
if (undefined === count) {
return 0;
}

return parseInt(count.toString(), 16);
}
if (address && sdk) {
getEntity(sdk, address).then(setCount).catch(console.error);
}
}, [address, sdk]);

useEffect(() => {
async function subscribeToEntityUpdates(
db: SDK<SchemaType>,
address: string
) {
const sub = await db.subscribeEntityQuery({
query: new QueryBuilder<SchemaType>()
.namespace("onchain_dash", (n) =>
n.entity("CallerCounter", (e) =>
e.eq("caller", addAddressPadding(address))
)
const [initialEntities, sub] = await db.subscribeEntityQuery({
query: new ToriiQueryBuilder()
.withClause(
KeysClause(
["onchain_dash-CallerCounter"],
[addAddressPadding(address)],
"FixedLen"
).build()
)
.build(),
.includeHashedKeys(),
callback: ({ data, error }) => {
if (data) {
const entity = data.pop() as ParsedEntity<SchemaType>;
Expand Down Expand Up @@ -101,6 +81,13 @@ export default function CallerCounter() {
},
});
setSub(sub);
const count =
initialEntities[0]?.models.onchain_dash?.CallerCounter?.counter;
if (!count) {
setCount(0);
} else {
setCount(parseInt(count.toString(), 16));
}
Comment on lines +84 to +90
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check for initialEntities[0].

The code directly accesses initialEntities[0] without checking if the array is empty, which could lead to runtime errors.

Apply this diff to add the necessary check:

+            if (!initialEntities.length) {
+                setCount(0);
+                return;
+            }
             const count =
                 initialEntities[0]?.models.onchain_dash?.CallerCounter?.counter;
             if (!count) {
                 setCount(0);
             } else {
                 setCount(parseInt(count.toString(), 16));
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const count =
initialEntities[0]?.models.onchain_dash?.CallerCounter?.counter;
if (!count) {
setCount(0);
} else {
setCount(parseInt(count.toString(), 16));
}
if (!initialEntities.length) {
setCount(0);
return;
}
const count =
initialEntities[0]?.models.onchain_dash?.CallerCounter?.counter;
if (!count) {
setCount(0);
} else {
setCount(parseInt(count.toString(), 16));
}

}
if (address && sdk && sub === null) {
subscribeToEntityUpdates(sdk, address)
Expand Down
61 changes: 28 additions & 33 deletions examples/example-vite-kitchen-sink/src/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { useCallback, useEffect, useRef, useState, KeyboardEvent } from "react";
import { useForm } from "react-hook-form";
import { useAccount } from "@starknet-react/core";
import { toValidAscii } from "@/lib/utils";
import { ParsedEntity, SDK } from "@dojoengine/sdk";
import {
KeysClause,
ParsedEntity,
SDK,
ToriiQueryBuilder,
} from "@dojoengine/sdk";
import { Subscription } from "@dojoengine/torii-wasm";
import { shortAddress } from "@/lib/utils";
import { Message, SchemaType } from "@/typescript/models.gen";
Expand Down Expand Up @@ -61,40 +66,18 @@ export default function Chat() {
[db, account, reset]
);

useEffect(() => {
async function getEntity(db: SDK<SchemaType>) {
const entity = await db.getEntities({
query: {
onchain_dash: { Message: { $: {} } },
},
callback: () => {},
});

return (
entity
.map((e) => e.models.onchain_dash.Message)
.filter(Boolean)
// @ts-expect-error a & b are not undefined as they are filtered out with `filer(Boolean)`
.sort((a: Message, b: Message): number =>
parseInt(a.timestamp.toString(), 16) <
parseInt(b.timestamp.toString(), 16)
? -1
: 1
)
);
}
if (db && messages.length === 0 && sub === null) {
// @ts-expect-error ts is getting drunk there
getEntity(db).then(setMessages).catch(console.error);
}
}, [db, messages, sub]);

useEffect(() => {
async function subscribeToEntityUpdates(db: SDK<SchemaType>) {
const sub = await db.subscribeEntityQuery({
query: {
onchain_dash: { Message: { $: {} } },
},
const [initialMessages, sub] = await db.subscribeEntityQuery({
query: new ToriiQueryBuilder()
.withClause(
KeysClause(
["onchain_dash-Message"],
[undefined],
"FixedLen"
).build()
)
.includeHashedKeys(),
callback: ({ data }) => {
if (data) {
const entity = data.pop() as ParsedEntity<SchemaType>;
Expand All @@ -113,6 +96,18 @@ export default function Chat() {
},
});
setSub(sub);

setMessages(
initialMessages
.map((e) => e.models.onchain_dash.Message as MessageItem)
.filter(Boolean)
.sort((a: Message, b: Message): number =>
parseInt(a.timestamp.toString(), 16) <
parseInt(b.timestamp.toString(), 16)
? -1
: 1
)
);
Comment on lines +100 to +110
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check for initialMessages.

The code directly processes initialMessages without checking if it's empty, which could lead to runtime errors.

Apply this diff to add the necessary check:

+            if (!initialMessages.length) {
+                setMessages([]);
+                return;
+            }
             setMessages(
                 initialMessages
                     .map((e) => e.models.onchain_dash.Message as MessageItem)
                     .filter(Boolean)
                     .sort((a: Message, b: Message): number =>
                         parseInt(a.timestamp.toString(), 16) <
                         parseInt(b.timestamp.toString(), 16)
                             ? -1
                             : 1
                     )
             );

}
if (db && sub === null) {
subscribeToEntityUpdates(db).then().catch(console.error);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { useCallback, useEffect, useState } from "react";
import { Button } from "./ui/button";
import { useSendTransaction } from "@starknet-react/core";
import { ParsedEntity, QueryBuilder, SDK } from "@dojoengine/sdk";
import {
KeysClause,
ParsedEntity,
SDK,
ToriiQueryBuilder,
} from "@dojoengine/sdk";
import { Subscription } from "@dojoengine/torii-wasm";
import { dojoConfig } from "@/../dojoConfig";
import { SchemaType } from "@/typescript/models.gen";
Expand All @@ -28,45 +33,19 @@ export default function GlobalCOunter() {

const { sdk: db } = useDojoSDK<typeof setupWorld, SchemaType>();

useEffect(() => {
async function getEntity(db: SDK<SchemaType>) {
const entity = await db.getEntities({
query: new QueryBuilder<SchemaType>()
.namespace("onchain_dash", (n) =>
n.entity("GlobalCounter", (e) =>
e.eq("global_counter_key", 9999999)
)
)
.build(),
callback: ({ data, error }) => {},
});

const counter = entity.pop() as ParsedEntity<SchemaType>;
if (!counter) {
return 0;
}
const count = counter.models.onchain_dash?.GlobalCounter?.counter;
if (undefined === count) {
return 0;
}
return parseInt(count.toString(), 16);
}

if (db) {
getEntity(db).then(setCount).catch(console.error);
}
}, [db]);

useEffect(() => {
async function subscribeToEntityUpdates(db: SDK<SchemaType>) {
const sub = await db.subscribeEntityQuery({
query: new QueryBuilder<SchemaType>()
.namespace("onchain_dash", (n) =>
n.entity("GlobalCounter", (e) =>
e.eq("global_counter_key", 9999999)
)
const [initialEntities, sub] = await db.subscribeEntityQuery({
// Here it is important to includeHashedKeys as subscription requires hasedKeys to query entityIds
query: new ToriiQueryBuilder()
.withClause(
KeysClause(
["onchain_dash-GlobalCounter"],
["9999999"],
"VariableLen"
).build()
)
.build(),
.includeHashedKeys(),
Comment on lines +40 to +48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the hardcoded values in KeysClause.

The hardcoded values "onchain_dash-GlobalCounter" and "9999999" should be constants or configuration values.


🏁 Script executed:

#!/bin/bash
# Search for other occurrences of these hardcoded values
rg "9999999|onchain_dash-GlobalCounter"

Length of output: 812


Hardcoded Value Extraction Recommended

The search confirms that the literal values "onchain_dash-GlobalCounter" and "9999999" are used in multiple parts of the codebase:

  • In the auto‑generated models file (models.gen.ts)
  • In the global-counter.tsx and theme-switch.tsx components
  • In test files (parseEntities.test.ts)

Given their repeated usage, it would be beneficial to extract these as constants or configuration values to improve maintainability and consistency.

callback: ({ data, error }) => {
if (data) {
const entity = data.pop() as ParsedEntity<SchemaType>;
Expand Down Expand Up @@ -95,6 +74,14 @@ export default function GlobalCOunter() {
},
});
setSub(sub);

const count =
initialEntities[0]?.models.onchain_dash?.GlobalCounter?.counter;
if (undefined === count) {
setCount(0);
} else {
setCount(parseInt(count.toString(), 16));
}
}
if (db && sub === null) {
subscribeToEntityUpdates(db)
Expand Down
Loading