-
Notifications
You must be signed in to change notification settings - Fork 54
chore: bump dojo 1.5 #434
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
chore: bump dojo 1.5 #434
Conversation
WalkthroughThis update introduces significant refactoring and feature enhancements across the Dojo SDK and related packages. The core changes include a transition from offset-based to cursor-based pagination in queries, the addition of new utility modules for deep merging Cairo types, and the introduction of improved error handling using the Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant SDK
participant ToriiClient
participant Worker
participant State
App->>SDK: Initialize with config (signer, identity, etc.)
SDK->>ToriiClient: new ToriiClient(config)
App->>SDK: Query or subscribe to entities/events (with cursor-based pagination)
SDK->>ToriiClient: getEntities/getEventMessages({pagination: {cursor, limit, direction}})
ToriiClient-->>SDK: { items: [entities/events], next_cursor }
SDK->>State: parseEntities(items)
App->>Worker: createWorker(callback)
Worker->>SDK: Subscribe to updates
SDK->>Worker: onEntityUpdated callback (array of entities)
Worker->>SDK: publishOffchainPositionCount (if needed)
SDK->>ToriiClient: sendMessage (with typed data, using signer/identity)
ToriiClient-->>SDK: Result<Uint8Array, string>
Worker->>State: update state with merged entities (deepMerge)
Note over Worker: On SIGTERM/SIGINT, Worker frees subscriptions
Possibly related PRs
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
f4758c1
to
eadecf7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 17
🔭 Outside diff range comments (4)
packages/sdk/src/internal/generateTypedData.ts (1)
4-12
: 🛠️ Refactor suggestionUpdate JSDoc to match current function signature
The JSDoc still references a
[domain]
optional parameter (which still exists in the code), but doesn't document the newadditionnalTypes
parameter. Update the documentation to accurately reflect all parameters./** * Generates typed data for any user-defined message. * * * @template M - The message type defined by the schema models. * @param {string} nsModel - Model name prefixed with namespace joined by a hyphen. * @param {M} message - The user-defined message content, must be part of the schema models. * @param {StarknetDomain} [domain] - The domain object. If not provided, uses the default domain from options. + * @param {Array<{ name: string; type: string }>} [modelMapping] - Custom type mapping for message fields. + * @param {Record<string, Array<{ name: string; type: string }>>} [additionalTypes] - Additional types to include in the typed data. * @returns {TypedData} - The generated typed data. */packages/state/src/recs/index.ts (1)
518-554
:⚠️ Potential issue
insertEntitiesInDB
type & logic diverge
The function now acceptsentities: ToriiEntity[]
but still iterates as if it were a map:for (const [entityId, data] of Object.entries(entities)) { … }When
entities
is an array,entityId
becomes"0" | "1" | …
, not the real entity hash, resulting in incorrect primary keys and data corruption.Either:
- for (const [entityId, data] of Object.entries(entities)) { + for (const entity of entities) { + const { id: entityId, ...data } = entity;or revert the parameter back to an object.
packages/sdk/src/web/index.ts (1)
257-283
:⚠️ Potential issueReturn
err()
instead of throwing to stay consistent withResult
API
sendMessage
advertises aResult<Uint8Array, string>
return type, yet thecatch
branch still throws, which will break callers that rely onisOk()/isErr()
handling instead of atry/catch
.- } catch (error) { - console.error("Failed to send message:", error); - throw error; + } catch (error) { + const msg = + error instanceof Error ? error.message : String(error); + console.error("Failed to send message:", msg); + return err(msg); }packages/sdk/src/node/index.ts (1)
240-269
:⚠️ Potential issue
sendMessage
should propagate failures througherr()
instead of exceptionsSame rationale as the web SDK: throwing breaks the
Result
contract.- } catch (error) { - console.error("Failed to send message:", error); - throw error; + } catch (error) { + const msg = + error instanceof Error ? error.message : String(error); + console.error("Failed to send message:", msg); + return err(msg); }
🧹 Nitpick comments (25)
examples/example-vite-react-sdk/src/historical-events.tsx (3)
1-5
: Update imports to use type imports where appropriate.Some named imports are only used as types according to the static analysis hint.
-import { - KeysClause, - ParsedEntity, - HistoricalToriiQueryBuilder, -} from "@dojoengine/sdk"; +import { + KeysClause, + HistoricalToriiQueryBuilder, +} from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
33-35
: Consider addressing TypeScript errors properly.The code contains a
@ts-ignore
comment that suppresses TypeScript errors. Consider addressing the underlying type issue properly instead of ignoring it.Consider providing proper type definitions or using explicit type casting if appropriate:
- {/* @ts-ignore */} - {events.map((e: ParsedEntity<SchemaType>, key) => { + {events.map((e: ParsedEntity<SchemaType>, key: number) => { return <Event event={e} key={key} />; })}Or if necessary, add a more descriptive reason for the type suppression:
- {/* @ts-ignore */} + {/* @ts-ignore - events is correctly typed but TypeScript has issues with the mapping */}🧰 Tools
🪛 Biome (1.9.4)
[error] 34-34: Avoid using the index of an array as key property in an element.
This is the source of the key value.
The order of the items may change, and this also affects performances and component state.
Check the React documentation.(lint/suspicious/noArrayIndexKey)
49-50
: Consider addressing TypeScript errors properly.Similarly, there's another TypeScript error suppression with
@ts-expect-error
. It would be better to fix the underlying type issue or provide a more descriptive comment explaining why the suppression is necessary.- {/* @ts-expect-error type is ok here */} + {/* @ts-expect-error - direction is correctly typed as an enum or string but TypeScript can't infer it */} <div>Direction: {direction}</div>packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Consider using optional chaining instead of non-null assertionsThe formatting change improves readability of the deeply nested property access, but the code still contains non-null assertions that could be replaced with optional chaining for safer access.
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + draft.entities["entity500"].models.world?.item?.durability = 75;Also, you could simplify the computed property access:
- draft.entities[ - "entity500" - ].models.world?.item?.durability = 75; + draft.entities.entity500.models.world?.item?.durability = 75;🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/parseHistoricalEvents.ts (1)
40-42
: Added debug loggingThese additional logging statements will help with debugging but might clutter the console in production environments. Consider adding a more specific debug flag rather than using the general
options?.logging
condition.+ if (options?.debugging) { console.log(model); console.log(entityId, modelName, modelData); + }packages/sdk/src/node/worker.ts (1)
30-43
: Refactor duplicated signal handling codeThe signal handling code for SIGTERM and SIGINT is duplicated. Consider extracting this into a dedicated cleanup function to improve maintainability and reduce duplication.
export async function createWorker( callback: DojoWorkerCallback ): Promise<void> { const sub = await callback(); - process.on("SIGTERM", () => { - for (const s of sub) { - s.free(); - } - - process.exit(0); - }); - - process.on("SIGINT", () => { - for (const s of sub) { - s.free(); - } - process.exit(0); - }); + const cleanup = () => { + for (const s of sub) { + s.free(); + } + process.exit(0); + }; + + process.on("SIGTERM", cleanup); + process.on("SIGINT", cleanup); }packages/sdk/src/internal/generateTypedData.ts (1)
21-21
: Fix typo in parameter name "additionnalTypes"The parameter name contains a spelling error - it should be "additionalTypes" with a single 'n'.
- additionnalTypes?: Record<string, Array<{ name: string; type: string }>> + additionalTypes?: Record<string, Array<{ name: string; type: string }>>Also update the usage at line 31:
- ...additionnalTypes, + ...additionalTypes,packages/sdk/src/web/experimental/index.ts (2)
30-30
: Remove inferrable type annotationThe type annotation on the
historical
parameter is trivially inferred from its initialization. You can safely remove it.- getEvents: async (query: torii.Query, historical: boolean = false) => { + getEvents: async (query: torii.Query, historical = false) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
103-103
: Avoid usingany
type for entity dataThe
entityData
parameter is typed asany
, which bypasses type checking. Consider using a more specific type liketorii.Entity
for consistency with the entity update handler.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 103-103: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/react/hooks/events.ts (1)
70-75
: Consider adding error handling for setEventsWhen updating the events state with new events, you should consider adding error handling in case the filtering or state update operations fail.
processUpdateData: (data) => { if (data) { - const evts = data.filter( - (e) => Number.parseInt(e.entityId, 16) !== 0 - ); - setEvents((ev) => [...evts, ...ev]); + try { + const evts = data.filter( + (e) => Number.parseInt(e.entityId, 16) !== 0 + ); + setEvents((ev) => [...evts, ...ev]); + } catch (error) { + console.error("Error processing event update:", error); + } } },packages/sdk/src/internal/parseEntities.ts (2)
76-77
: Remove stray debug logA hard-coded
console.log(value);
will spam production logs. Gate this behindoptions?.logging
or delete it.- console.log(value); + if (process.env.NODE_ENV !== "production" && options?.logging) { + console.debug(value); + }
58-59
: RedundantObject.values
call
result
is already an array; wrapping it inObject.values
adds an unnecessary copy.- return Object.values(result); + return result;examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-3
: Import unused / type-only symbols withimport type
BigNumberish
,ByteArray
,CairoOption
, and several others are never used at runtime.
Switching toimport type
(and deleting unused names) removes dead code from bundles and appeases Biome.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, CairoCustomEnum } from "starknet";Also delete the now-unused
BigNumberish
,ByteArray
, andCairoOption
imports entirely.🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/state/zustand.ts (1)
14-15
: Useimport type
for type-only symbol
MergedModels
is only used in the type position; importing it as a value keeps unnecessary code.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/types.ts (1)
361-366
: Docs & overload drift –additionalTypes
needs to be reflected in JSDoc and overloads
The signature gained anadditionalTypes
parameter but the surrounding comment block (lines 341-356) still documents the olddomain
parameter and doesn’t mention the new argument. Consumers relying on IntelliSense / typedoc will get stale guidance.- * @param {Array<{ name: string; type: string }>} [modelMapping] - * @param {Record<string, Array<{ name: string; type: string }>>} [additionalTypes] + * @param {Array<{ name: string; type: string }>} [modelMapping] - … + * @param {Record<string, Array<{ name: string; type: string }>>} [additionalTypes] - Extra EIP-712 type groupsPlease update the docblock (and any overloads/implementations) for parity.
packages/sdk/src/internal/models.ts (1)
38-52
: Stale JSDoc & “first entity wins” logic
The docstring repeats the “entityId” parameter even though this overload does not receive one. Additionally,for…of
returns on the very first entity, regardless of whether that entity actually contains the requested model. Consider scanning until a hit is found or usingArray.prototype.find
.- * @param entityId - The ID of the entity.
Also apply the same generic-type fix as above.
examples/example-node-worker/main.ts (1)
120-120
: Useconst
(or mutate) –positionCount
is never reassignedStatic analysis is correct: the variable is declared with
let
but never updated.
Either change it toconst
if it is meant to be immutable, or actually mutate it when events arrive (the commented-out block shows the intent).-let positionCount = defaultPositionCount; +const positionCount = defaultPositionCount;🧰 Tools
🪛 Biome (1.9.4)
[error] 119-120: This let declares a variable that is only assigned once.
'positionCount' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
packages/sdk/src/internal/merge.ts (1)
74-109
: Avoidany
in new enum objects – keeps the strong typing you added elsewhere
newEnumContent
is currently typed asRecord<string, any>
— this silences type-checking and can leak invalid values.-const newEnumContent: Record<string, any> = {}; +const newEnumContent: { [K in keyof typeof target.variant]?: unknown } = {};Repeat the same change in the target-branch block (lines 96-105) and in the generic
deepMerge
result map (line 133).Using precise types improves IntelliSense and prevents accidental insertion of non-serialisable values.
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
3-3
: Mark StarkNet imports that are types withimport type
BigNumberish
is a type-only import, so usingimport type
prevents unnecessary runtime dependency loading and keeps emitted code lean.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import type { BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
70-79
: Consider exporting a union literal instead of a run-time constant for directionsThe current pattern
export const direction = ['Left', 'Right', 'Up', 'Down'] as const; export type Direction = { [key in typeof direction[number]]: string };creates an object-map type rather than a string union (
'Left' | 'Right' | ...
).
If the intention was a simple enum of string literals, a cleaner approach is:export type Direction = 'Left' | 'Right' | 'Up' | 'Down';or leverage
keyof typeof
over a readonly object.Doing so simplifies downstream discriminated-union checks and narrows allowable values at compile time.
packages/sdk/src/web/index.ts (1)
45-49
:await
is redundant when callingnew ToriiClient
new
is a synchronous constructor; the extraawait
just adds an unnecessary micro-task. If the constructor later becomes async, the signature can be revisited, but today this hurts perf slightly and confuses the reader.- return await new torii.ToriiClient(config); + return new torii.ToriiClient(config);packages/sdk/src/internal/toriiQueryBuilder.ts (2)
56-63
: Misleading JSDoc: comment says “Set the maximum number of results” but method sets directionThe copy-paste description for
withDirection
is incorrect and will confuse IDE tooltips & generated docs.
145-158
: DuplicateddefaultToriiOptions()
merge inHistoricalToriiQueryBuilder
ToriiQueryBuilder
already mergesdefaultToriiOptions()
. Re-applying the spread produces an extra object allocation and may accidentally overwrite user-supplied options.- super({ - ...(defaultToriiOptions() as Query), - ...options, - historical: true, - }); + super({ ...options, historical: true });packages/sdk/src/node/index.ts (2)
215-223
: Inconsistent spelling:additionalTypes
vsadditionnalTypes
generateTypedData
expects the 5-th positional argument to beadditionnalTypes
; inadvertent drift in spelling can confuse readers and tooling. Align the variable name with the callee (or better, rename the parameter in the helper to the correct English spelling).- additionalTypes?: Record< + additionnalTypes?: Record<
18-20
: Remove unusedAccount
importThe node variant now relies on
options.signer
and no longer uses anAccount
instance; the leftover import increases bundle size and may mislead maintainers.-import type { Account, TypedData } from "starknet"; +import type { TypedData } from "starknet";
🛑 Comments failed to post (17)
packages/sdk/src/internal/parseHistoricalEvents.ts (1)
19-20:
⚠️ Potential issueMismatched parameter type with function implementation
The parameter type has been updated to accept an array (
torii.Entity[]
) but the function implementation on line 27 still uses afor...in
loop which is designed for iterating over object properties, not array indices. This will cause incorrect behavior.Apply this diff to fix the iteration logic:
export function parseHistoricalEvents<T extends SchemaType>( entities: torii.Entity[], options?: { logging?: boolean } ): StandardizedQueryResult<T> { if (options?.logging) { console.log("Raw historical events", entities); } // Events come from torii flagged as "dojo_starter-Moved-idx" let events: StandardizedQueryResult<T> = []; - for (const entityId in entities) { + for (const entity of entities) { + const entityId = entity.id; // Assuming entity has an id property console.log(entityId); - const entityData = entities[entityId]; + const entityData = entity;Also, update the JSDoc comment on line 10 to match the new parameter type:
- * @param {torii.Entities} entities - The collection of entities to parse. + * @param {torii.Entity[]} entities - The array of entities to parse.📝 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./** * Parses historical events. * @param {torii.Entity[]} entities - The array of entities to parse. * @param {{ logging?: boolean }} [options] - Optional settings. */ export function parseHistoricalEvents<T extends SchemaType>( entities: torii.Entity[], options?: { logging?: boolean } ): StandardizedQueryResult<T> { if (options?.logging) { console.log("Raw historical events", entities); } // Events come from torii flagged as "dojo_starter-Moved-idx" let events: StandardizedQueryResult<T> = []; for (const entity of entities) { const entityId = entity.id; // Assuming entity has an id property console.log(entityId); const entityData = entity; // …rest of your processing logic for each entityData… } return events; }
packages/sdk/src/web/react/hooks/hooks.ts (1)
114-117:
⚠️ Potential issueResource cleanup is commented out
The subscription cleanup code has been commented out, which could lead to memory leaks or unwanted updates after component unmount. Subscriptions should be properly cleaned up when the component unmounts.
Uncomment and update the cleanup code:
return () => { if (subscriptionRef.current) { - // subscriptionRef.current?.free(); - // subscriptionRef.current = null; + subscriptionRef.current?.free(); + subscriptionRef.current = null; } };📝 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.return () => { if (subscriptionRef.current) { subscriptionRef.current?.free(); subscriptionRef.current = null; } };
examples/example-node-worker/package.json (1)
6-9: 🛠️ Refactor suggestion
Security: Hardcoded credentials in scripts
The scripts include hardcoded credentials (
IDENTITY
andSECRET_KEY
) which is a security risk, even for examples. These should be moved to environment variables loaded from a .env file."scripts": { - "bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", - "node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts" + "bun": "bun run main.ts", + "node": "node main.ts" },Then create a
.env.example
file (without real credentials) and document the need to create a.env
file with proper credentials:IDENTITY=your_identity_here SECRET_KEY=your_secret_key_here
📝 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."scripts": { "bun": "bun run main.ts", "node": "node main.ts" },
packages/sdk/src/web/react/hooks/entities.ts (1)
26-35:
⚠️ Potential issueOnly first entity is processed in updates
The update logic now filters out entities with zero entityId (which is good) but then only processes the first entity from the filtered list. This might ignore valid entities if multiple are received in a single update.
Consider processing all valid entities:
if (data) { const entities = data.filter( (e) => Number.parseInt(e.entityId, 16) !== 0 ); - const entity = entities[0]; - if (entity) { - state.updateEntity(entity); - } + // Process all valid entities + for (const entity of entities) { + state.updateEntity(entity); + } }Alternatively, if batch updates are more efficient:
if (data) { const entities = data.filter( (e) => Number.parseInt(e.entityId, 16) !== 0 ); - const entity = entities[0]; - if (entity) { - state.updateEntity(entity); - } + if (entities.length > 0) { + state.updateEntities(entities); + } }📝 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.if (data) { const entities = data.filter( (e) => Number.parseInt(e.entityId, 16) !== 0 ); // Process all valid entities for (const entity of entities) { state.updateEntity(entity); } }
packages/sdk/src/node/worker.ts (1)
2-2: 🛠️ Refactor suggestion
Remove commented-out import or explain why it's kept
There's a commented-out import for
process
fromnode:process
, but your code uses theprocess
object multiple times. This creates ambiguity about whether you're relying on the global Node.jsprocess
object or intending to use an imported one.Either remove the commented code if you're intentionally using the global process object, or uncomment it if you meant to use the explicit import.
-// import process from "node:process"; +import process from "node:process";📝 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.import process from "node:process";
packages/sdk/src/web/experimental/index.ts (1)
41-41: 💡 Verification agent
🧩 Analysis chain
Renamed query flag from
dont_include_hashed_keys
tono_hashed_keys
The query property for excluding hashed keys has been renamed. Ensure this change is documented in the migration guide for users upgrading from previous versions.
Also applies to: 84-84
🏁 Script executed:
#!/bin/bash # Check if both property names are still used in the codebase echo "Checking for usage of old property name 'dont_include_hashed_keys':" rg "dont_include_hashed_keys" --type ts echo -e "\nChecking for usage of new property name 'no_hashed_keys':" rg "no_hashed_keys" --type tsLength of output: 1573
🏁 Script executed:
#!/bin/bash # Locate migration guide markdown files echo "Searching for migration guide files:" rg -l "migration" -g "*.md" # Check for references to old and new flags in markdown echo -e "\nReferences to 'dont_include_hashed_keys' in markdown:" rg "dont_include_hashed_keys" -g "*.md" echo -e "\nReferences to 'no_hashed_keys' in markdown:" rg "no_hashed_keys" -g "*.md"Length of output: 451
Ensure Migration Guide & Tests Updated for Renamed Flag
The query optiondont_include_hashed_keys
has been replaced byno_hashed_keys
, but:• The migration guide (
migration/v1-0-v1-1.md
) doesn’t mention this rename.
• The tests inpackages/sdk/src/__tests__/toriiQueryBuilder.test.ts
still referencedont_include_hashed_keys
.Please:
- Add a note to
migration/v1-0-v1-1.md
describing the rename and its impact on user code.- Update all occurrences of
dont_include_hashed_keys
in your tests and examples tono_hashed_keys
.packages/sdk/src/internal/parseEntities.ts (1)
129-135:
⚠️ Potential issue
u64
should be parsed asBigInt
, notnumber
parsePrimitive
converts everyu64
hex string into a JSnumber
(Number.parseInt
).
Many on-chainu64
values overflowNumber.MAX_SAFE_INTEGER
, so precision will be silently lost.- case "u64": - return Number.parseInt(value.value as string, 16); + case "u64": + // Preserve 64-bit precision + return BigInt(value.value as string);packages/sdk/src/web/state/zustand.ts (1)
71-98:
⚠️ Potential issueIncorrect deep-merge granularity may overwrite sibling models
mergeEntities
iterates over every model inside a namespace and callsmergedModels[namespace] = deepMerge(mergedModels[namespace], namespaceModels);where
namespaceModels
is a single model value, not the whole namespace object.
Each iteration therefore merges the previous namespace object with a scalar, so the final loop pass leaves only the last model, dropping its siblings.Replace the nested loop with a single merge per namespace:
-for (const namespace of Object.keys(entity.models)) { - for (const model of Object.keys(entity.models[namespace])) { - const namespaceModels = entity.models[namespace][model]; - … - mergedModels[typedNamespace] = deepMerge( - mergedModels[typedNamespace] as MergedModels<T>, - namespaceModels // 🛑 only one model! - ) as MergedModels<T>; - } -} +for (const namespace of Object.keys(entity.models)) { + const typedNamespace = namespace as keyof ParsedEntity<T>["models"]; + mergedModels[typedNamespace] = deepMerge( + mergedModels[typedNamespace] as MergedModels<T>, + entity.models[namespace] // ✅ whole namespace object + ) as MergedModels<T>; +}Make the same change in
updateEntity
(lines 126-148) for consistency.packages/sdk/src/internal/types.ts (2)
515-523:
⚠️ Potential issueContractual mismatch – field is documented as “required” but typed as optional
The comment states thatsigner
/identity
will be required when using off-chain messages, yet both properties are declared optional. Either:
- Make them non-optional and supply sensible defaults, or
- Keep them optional but clarify that runtime checks will throw if missing.
Current state risks silent
undefined
access at call-sites.
368-372: 🛠️ Refactor suggestion
Prefer rich errors over plain strings in
Result
sendMessage
now resolves toResult<Uint8Array, string>
. Returning a plain string sacrifices stack traces and makes downstream error-handling brittle (hard to pattern-match reliably).Recommend:
-) => Promise<Result<Uint8Array, string>>; +) => Promise<Result<Uint8Array, Error>>;If a custom error hierarchy exists, expose it here instead of
Error
.📝 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.sendMessage: ( data: TypedData, account?: Account ) => Promise<Result<Uint8Array, Error>>;
packages/sdk/src/internal/models.ts (1)
11-29:
⚠️ Potential issueGeneric type mismatch and unsafe
entityId
comparison
- The generic
Schema
parameter is declared but never used – return type still hard-codesSchemaType[N][M]
, breaking type-safety for consumers with custom schemas.entityId
isBigNumberish
whilev.entityId
is astring
; strict comparison (!==
) will always fail unless caller already stringifies the value.-export function getModelByEntityId< - N extends keyof SchemaType, - M extends keyof SchemaType[N] & string, - Schema extends SchemaType +export function getModelByEntityId< + Schema extends SchemaType, + N extends keyof Schema, + M extends keyof Schema[N] & string >( - entityId: BigNumberish, + entityId: BigNumberish | string, model: `${N}-${M}`, value: StandardizedQueryResult<Schema> -): SchemaType[N][M] | undefined { +): Schema[N][M] | undefined { const [namespace, modelName] = model.split("-") as [N, M]; - for (const v of value) { - if (v.entityId !== entityId) { + const idStr = entityId.toString(); + for (const v of value) { + if (v.entityId !== idStr) { continue; } - return v.models?.[namespace]?.[modelName] as - | SchemaType[N][M] + return v.models?.[namespace]?.[modelName] as + | Schema[N][M] | undefined; } }📝 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.export function getModelByEntityId< Schema extends SchemaType, N extends keyof Schema, M extends keyof Schema[N] & string >( entityId: BigNumberish | string, model: `${N}-${M}`, value: StandardizedQueryResult<Schema> ): Schema[N][M] | undefined { const [namespace, modelName] = model.split("-") as [N, M]; const idStr = entityId.toString(); for (const v of value) { if (v.entityId !== idStr) { continue; } return v.models?.[namespace]?.[modelName] as | Schema[N][M] | undefined; } }
packages/state/src/recs/index.ts (2)
181-190:
⚠️ Potential issue
entities.items
is now an array — update downstream consumers
The new SDK returnsitems: ToriiEntity[]
, yet:setEntities(entities.items, components, logging); // expects object if (Object.keys(entities.items).length < limit) { … } // treating as map
setEntities
and the length check both assume an object keyed byentityId
, causing:• Incorrect entity IDs (array indices)
• Potential loss of data when two entities share the same index across pages
• Misleading size calculationsRefactor
setEntities
to accept an array or convert the array to the expected object shape before passing it along.🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
320-334: 🛠️ Refactor suggestion
Pagination loop never advances – constant
fetchedEntities
InsidegetEntitiesQuery
you fetch once before thewhile
, then keep re-using the samefetchedEntities
object;cursor
is updated but never supplied to a new request, so additional pages are never requested, risking an infinite loop when the first batch size ≥limit
.Move the fetch inside the loop or convert to a
do/while
:- const fetchedEntities = await client.getEntities({ … }); - while (continueFetching) { + while (continueFetching) { + const fetchedEntities = await client.getEntities({ …, cursor });📝 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.while (continueFetching) { const fetchedEntities = await client.getEntities({ …, cursor }); if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); if (Object.keys(fetchedEntities.items).length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } } };
examples/example-node-worker/main.ts (2)
79-98:
⚠️ Potential issue
publishOffchainPositionCount
always sends zeroes – the function uses a stale global instead of live dataInside the payload you pass
position: intoPositionCount(positionCount)but
positionCount
is the module-level default that is never mutated anywhere after its initial declaration.
Hence every message published from this worker will contain only zero counts, regardless of actual moves.Two possible fixes:
- position: intoPositionCount(positionCount), + // TODO: compute the real count from the current `moves` + position: intoPositionCount(calculateNewCount(moves)),or, if you intend to keep the accumulator:
- position: intoPositionCount(positionCount), + position: intoPositionCount(currentPositionCount),where
currentPositionCount
is updated insideonEntityUpdated
.Failing to address this will make off-chain consumers rely on incorrect game state.
21-25: 💡 Verification agent
🧩 Analysis chain
global.Websocket
is probably a typo – useglobal.WebSocket
(capital “S”)Most libraries (including
isomorphic-ws
,websocket
, and the browser spec) expose the constructor asWebSocket
, notWebsocket
.
Setting the wrong global symbol means downstream code that expectsglobal.WebSocket
will silently fall back to the Node TCP socket implementation or crash at runtime.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore – make Ws available globally for SDK internals +// NOTE: the correct global symbol is “WebSocket” with a capital “S”. +global.WebSocket = w3cwebsocket;
🏁 Script executed:
#!/bin/bash set -e echo "Searching for global.Websocket usage..." rg "global\.Websocket" -n echo "Searching for global.WebSocket usage..." rg "global\.WebSocket" -nLength of output: 315
Use the correct global.WebSocket (capital “S”)
The browser spec and most libraries (e.g. isomorphic-ws, websocket) expose the constructor as
WebSocket
, notWebsocket
. Downstream code that looks forglobal.WebSocket
will otherwise break or fall back to a TCP socket at runtime.Locations needing updates:
examples/example-node-worker/main.ts
: replace theglobal.Websocket
assignment-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore – make WebSocket available globally for SDK internals +// NOTE: the correct global symbol is “WebSocket” with a capital “S”. +global.WebSocket = w3cwebsocket;📝 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.// Those lines are require so that websocket works. // @ts-ignore – make WebSocket available globally for SDK internals // NOTE: the correct global symbol is “WebSocket” with a capital “S”. global.WebSocket = w3cwebsocket; // @ts-ignore global.WorkerGlobalScope = global;
examples/example-node-worker/src/typescript/models.gen.ts (1)
38-46:
⚠️ Potential issueTypo:
positition
→position
everywhereThe field is misspelled in the interface, value interface, and default schema:
-positition: Array<[BigNumberish, BigNumberish]>; +position: Array<[BigNumberish, BigNumberish]>;This typo propagates to runtime code (
main.ts
expectsposition
) and will cause type errors as well as undefined fields in JSON serialisation.📝 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.export interface PositionCount { identity: string; position: Array<[BigNumberish, BigNumberish]>; } // Type definition for `dojo_starter::models::PositionCountValue` struct export interface PositionCountValue { position: Array<[BigNumberish, BigNumberish]>; }
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
130-142: 🛠️ Refactor suggestion
Tighten generics & allow
undefined
cursor inwithPagination
Record<string, Record<string, any>>
triggers the noExplicitAny lint error.- Cursor can legitimately be
undefined
(start-from-beginning scenario).-static withPagination<T extends Record<string, Record<string, any>>>( - cursor: string, +static withPagination<T extends SchemaType>( + cursor: string | undefined, limit: number, direction: PaginationDirection ): ToriiQueryBuilder<T> {📝 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.* Create a new builder instance with pagination settings * */ static withPagination<T extends SchemaType>( cursor: string | undefined, limit: number, direction: PaginationDirection ): ToriiQueryBuilder<T> { return new ToriiQueryBuilder<T>() .withLimit(limit) .withCursor(cursor) .withDirection(direction); }
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🔭 Outside diff range comments (2)
packages/sdk/src/web/state/zustand.ts (1)
67-99
: 🛠️ Refactor suggestionNested merge loop can be greatly simplified
The current triple-nested loops plus repeated
Object.assign
make the path easy to break and hard to read. Because you already havedeepMerge
, you can merge the entiremodels
object in one shot:-// Create new models object without spread -const mergedModels: typeof existingEntity.models = Object.assign({}, existingEntity.models); -// Iterate through each namespace … -… deepMerge(…) +const mergedModels = deepMerge( + existingEntity.models as MergedModels<T>, + entity.models as MergedModels<T> +);This removes ~25 lines, eliminates the
@ts-expect-error
s and prevents accidental shadowing ofmodel
/namespace
.packages/state/src/recs/index.ts (1)
516-554
:⚠️ Potential issue
insertEntitiesInDB
iterates an array as an objectWith cursor pagination every batch is
ToriiEntity[]
.
Object.entries(entities)
turns each entity into[index, value]
, soentityId
is the numeric string index, not the actual ID.-for (const [entityId, data] of Object.entries(entities)) { - const entityData = { id: entityId, ...data }; - store.put(entityData); -} +for (const entity of entities) { + store.put(entity); +}Without this fix the IndexedDB store gets incorrect IDs and overwrites rows.
🧹 Nitpick comments (13)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Imports improved with specialized query builderThe import of
HistoricalToriiQueryBuilder
instead ofToriiQueryBuilder
is a good change, making the code more semantically clear about its intention to query historical data.Consider using explicit type imports as suggested by Biome:
import { KeysClause, - ParsedEntity, + type ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/experimental/index.ts (1)
103-103
: Consider replacingany
type with a more specific typeUsing
any
disables type checking, which could lead to potential runtime errors.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 103-103: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (2)
58-58
: Simplify return statementSince
result
is now an array, usingObject.values()
is redundant and could be simplified.- return Object.values(result); + return result;
76-76
: Remove or conditionally execute debug loggingThis
console.log
statement appears to be leftover debug code that should be removed or made conditional based on the options.- console.log(value); + if (options?.logging) { + console.log("Processing enum value:", value); + }examples/example-node-worker/src/typescript/contracts.gen.ts (2)
1-3
: Useimport type
and drop unused symbols
Account
,AccountInterface
, andCairoCustomEnum
are referenced only in type positions, whileBigNumberish
,CairoOption
, andByteArray
are not referenced at all. Importing them as runtime values keeps unnecessary code in the bundle.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { Account, AccountInterface, CairoCustomEnum } from "starknet"; +import { DojoProvider, DojoCall } from "@dojoengine/core";Remove the truly-unused names altogether.
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
15-26
: Return-type annotation improves DX
actions_move
currently has no return type, so the inferred type isPromise<any>
. Explicitly declaring the expected result fromprovider.execute
surfaces errors earlier and helps autocomplete.-const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { +const actions_move = async ( + snAccount: Account | AccountInterface, + direction: CairoCustomEnum +): Promise<Awaited<ReturnType<typeof provider.execute>>> => {(Replace the placeholder with the concrete type if
execute
is generically typed.)packages/sdk/src/web/state/zustand.ts (1)
14-14
: ImportMergedModels
as a type-only symbol
deepMerge
is used at runtime,MergedModels
is not. Switching toimport type
for the latter avoids shipping dead code.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/main.ts (1)
79-118
:positionCount
is never updated after publishing
publishOffchainPositionCount
reads the globalpositionCount
, but neither this function noronEntityUpdated
mutates it for new moves. The payload may therefore become stale and identical messages will be re-sent.Consider incrementing the relevant field before calling
intoPositionCount
, e.g.:-if (!m) { +if (!m) { + positionCount[moves.direction] += 1; // or other logicAlternatively compute the counts on-demand from historical + live data.
packages/state/src/recs/index.ts (1)
185-185
: Unnecessary template literal
"Fetched entities"
is a plain string; the template literal signs are redundant and flagged by Biome.🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/internal/merge.ts (2)
63-113
: Replaceany
with more specific types in CairoCustomEnum handlingThe implementation logic for merging enum variants is solid, but the use of
any
reduces type safety.Consider using more specific types instead of
any
:- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};This change would maintain the flexibility needed while being slightly more type-safe than
any
.🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
123-160
: Improve type safety in deepMerge functionThe
deepMerge
function implementation is comprehensive, handling special Cairo types and regular JavaScript objects recursively. However, it usesany
which could lead to type safety issues.Consider using more specific types:
- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;The function correctly prioritizes special Cairo types handling before general object merging, which is an appropriate approach.
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (1)
1-3
: Use import type for type-only importsSince Cairo types are only used as types in this file, not as values, you should use the
import type
syntax.import type { SchemaType as ISchemaType } from "@dojoengine/sdk"; -import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import type { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet';This helps TypeScript optimize imports that aren't needed at runtime.
🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-142
: Improve type safety in withPagination static methodThe static method has been updated to support cursor-based pagination, but uses
any
in its type signature.- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends Record<string, Record<string, unknown>>>(Using
unknown
instead ofany
would improve type safety while maintaining flexibility.🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (30)
.changeset/thirty-cheetahs-design.md
(1 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)packages/sdk/package.json
(2 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(5 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(3 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(4 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(2 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-wasm/dojo.c
(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- packages/sdk/src/internal/errors.ts
- packages/sdk/package.json
- .changeset/thirty-cheetahs-design.md
- examples/example-node-worker/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (14)
- examples/example-node-worker/dojoConfig.ts
- packages/torii-wasm/dojo.c
- examples/example-node-worker/env.ts
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/sdk/src/node/worker.ts
- packages/sdk/src/internal/parseHistoricalEvents.ts
- packages/sdk/src/internal/generateTypedData.ts
- examples/example-node-worker/package.json
- packages/sdk/src/web/react/hooks/entities.ts
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/web/react/hooks/events.ts
- packages/sdk/src/internal/models.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/web/index.ts
🧰 Additional context used
🧬 Code Graph Analysis (8)
packages/sdk/src/internal/toriiQueryBuilder.ts (3)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)examples/example-node-worker/src/typescript/models.gen.ts (2)
direction
(71-76)SchemaType
(80-94)packages/core/src/provider/DojoProvider.ts (1)
model
(131-140)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/sdk/src/web/experimental/index.ts (3)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/parseHistoricalEvents.ts (1)
parseHistoricalEvents
(18-55)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 103-103: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (34)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: LGTM - Uses specialized historical query builderThe code now uses
HistoricalToriiQueryBuilder
instead of manually configuringToriiQueryBuilder
with a historical flag, which simplifies the code and makes its intent clearer.packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Improved code formatting for readabilityBreaking the property access into separate lines improves readability, especially for deeply nested property paths.
🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/web/experimental/index.ts (5)
24-24
: Standardized client instantiation approachChanged from using a factory method to direct constructor instantiation, which aligns with other client initialization patterns in the SDK.
28-35
: Improved handling of paginated resultsThe code now consistently extracts the
.items
array from paginated results before passing to parsing functions, unifying the approach to data handling across the SDK.🧰 Tools
🪛 Biome (1.9.4)
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
41-42
: Updated query parameter naming for consistencyRenamed
dont_include_hashed_keys
tono_hashed_keys
for consistent terminology across the SDK.Also applies to: 84-85
56-62
: Standardized entity parsing in callbacksUpdated to ignore the entity ID parameter and directly parse an array containing the entity data, aligning with the SDK-wide shift to array-based entity handling.
107-108
: Consistent array-based parsing in event callbacksUpdated the event parsing to work with arrays instead of keyed objects, consistent with the entity subscription handling and overall SDK approach.
packages/sdk/src/internal/parseEntities.ts (5)
10-11
: Updated parameter type to use arrays instead of keyed objectsChanged the function to accept an array of entities rather than a keyed object, which aligns with the SDK's shift toward array-based entity handling.
15-25
: Refactored entity iteration logic for array-based inputModified result container and iteration approach to work with an array of entities instead of a keyed object, maintaining the same parsing logic with updated data access.
47-52
: Updated result building for array-based structureChanged from building a keyed object to pushing entities into an array, consistent with the new function parameter structure.
🧰 Tools
🪛 Biome (1.9.4)
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
91-93
: Added support for 'tuple' type alongside 'array'This enhancement provides better type handling for Cairo data structures, improving the SDK's compatibility with diverse data formats.
129-134
: Enhanced primitive type parsingImproved parsing for various integer types, including BigInt support for large integers and optimized parsing for u64, which will handle Cairo numeric types more accurately.
packages/sdk/src/internal/merge.ts (4)
1-11
: Well-structured Cairo type guardsThe implementation of the
isCairoOption
type guard is clean and well-documented. This approach of creating dedicated type guards improves code readability and supports TypeScript's type inference system.
19-46
: Thorough implementation of Cairo option mergingThe
mergeCairoOption
function handles the expected cases well:
- When source is Some, it correctly prefers the source value
- Otherwise it correctly preserves the target value
- It handles None variants properly
The type casting to
unknown as MergedModels<T>
is necessary due to TypeScript's limitations with complex generics, but be aware this bypasses some type checking.
53-55
: Clear implementation of CairoCustomEnum type guardThis type guard follows the same pattern as the CairoOption guard, maintaining consistency in the codebase.
120-121
: Good type reuseDefining
MergedModels
as a type alias that reusesParsedEntity
types is a clean approach that avoids duplication.examples/example-node-worker/src/typescript/models.gen.ts (4)
70-79
: Well-designed Direction enum type representationThe representation of the Direction enum using both a const tuple and CairoCustomEnum type is a good approach for TypeScript and StarkNet compatibility. This pattern allows for type checking while supporting the Cairo type system.
80-94
: Clean schema type extension patternExtending the imported SchemaType interface is a good approach for maintaining type compatibility with the SDK while adding application-specific models.
95-157
: Consistent schema initialization with proper Cairo type handlingThe schema constant correctly initializes all model types with appropriate default values, including proper instantiation of CairoOption and CairoCustomEnum instances.
Note: The "positition" typo mentioned earlier is also present in the schema initialization and should be fixed consistently.
158-171
: Clean model mapping enum implementationThe ModelsMapping enum provides a convenient way to reference model identifiers. This pattern makes it easy to maintain consistency when referring to models throughout the application.
packages/sdk/src/internal/toriiQueryBuilder.ts (7)
1-6
: Updated imports for new pagination approachThe imports now include
PaginationDirection
type, which supports the new cursor-based pagination approach.
34-37
: Updated withLimit implementation for nested paginationThe method now correctly sets the limit in the pagination object.
47-62
: New cursor-based pagination methodsThe introduction of
withCursor
andwithDirection
methods provides a clean API for the new pagination approach. The implementation is straightforward and matches the new structure.
77-80
: Updated includeHashedKeys for renamed propertyThe method now correctly sets the renamed
no_hashed_keys
property.
90-103
: Updated orderBy methods for nested paginationThe
addOrderBy
andwithOrderBy
methods now correctly set values in the nested pagination object.
110-120
: Updated entity model methods for renamed propertyThe
addEntityModel
andwithEntityModels
methods now correctly use the renamedmodels
property.
145-158
: Good addition of HistoricalToriiQueryBuilderThe new subclass provides a convenient way to create queries with the historical flag set to true by default. This is a cleaner approach than requiring clients to remember to set this flag manually.
packages/sdk/src/node/index.ts (7)
19-36
: Improved imports and additional exportsGood improvements:
- Changed Account to a type import
- Added Result type from neverthrow for better error handling
- Added error constants for consistent error messages
- Additional exports for worker.ts, internal types, and models
These changes enhance the module's API and error handling capabilities.
60-71
: Updated property name in entity query checksUpdated to use the renamed property
no_hashed_keys
instead ofdont_include_hashed_keys
, aligning with changes in ToriiQueryBuilder.
118-130
: Updated property name and event parsingSimilar changes to the entity query handling:
- Updated to use
no_hashed_keys
property- Changed event parsing to handle arrays from
.items
propertyThese changes align with the ToriiQueryBuilder changes and simplify the data structure.
138-144
: Consistent event data parsingUpdated the event callback to parse data consistently with the initial event query, using arrays from
.items
property.
187-190
: Updated getEntities to use items arrayConsistent change to use
.items
property in getEntities method.
201-204
: Updated getEventMessages to use items arrayConsistent change to use
.items
property in getEventMessages method.
240-270
: Improved error handling in sendMessageExcellent improvements to the sendMessage method:
- Now returns Result type from neverthrow instead of throwing errors
- Clear error constants for consistent messages
- Removed explicit Account parameter, using options.signer and options.identity
This is a breaking change for code that explicitly passed an account parameter or relied on thrown errors, but the new approach is much better for error handling.
The use of Result type allows for more predictable error handling patterns in client code. Make sure to document this change in migration guides.
async function onEntityUpdated({ data, error }) { | ||
if (error) { | ||
console.error(error); | ||
return; | ||
} | ||
|
||
console.log(entities); | ||
const entity = data.pop(); | ||
if (entity && entity.entityId !== "0x0") { | ||
// do whatever you need here | ||
const model = entity.models.dojo_starter; | ||
if (model?.Moves) { | ||
await publishOffchainPositionCount(model.Moves); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Potential data loss with data.pop()
data
is already the argument supplied by the subscription.
Calling pop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.
Iterate instead:
for (const entity of data) {
// handle each entity
}
const pc = defaultPositionCount; | ||
for (const e of events) { | ||
const moved = e.models.dojo_starter.Moved; | ||
if (!moved) { | ||
continue; | ||
} | ||
pc[moved.direction] += 1; | ||
} | ||
return pc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
initPositionFromEvent
mutates the shared constant
pc
is an alias of defaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.
-const pc = defaultPositionCount;
+const pc: PositionCount = { ...defaultPositionCount };
This also prevents accidental modification of the default object elsewhere.
📝 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.
const pc = defaultPositionCount; | |
for (const e of events) { | |
const moved = e.models.dojo_starter.Moved; | |
if (!moved) { | |
continue; | |
} | |
pc[moved.direction] += 1; | |
} | |
return pc; | |
const pc: PositionCount = { ...defaultPositionCount }; | |
for (const e of events) { | |
const moved = e.models.dojo_starter.Moved; | |
if (!moved) { | |
continue; | |
} | |
pc[moved.direction] += 1; | |
} | |
return pc; |
// Those lines are require so that websocket works. | ||
// @ts-ignore | ||
global.Websocket = w3cwebsocket; | ||
// @ts-ignore | ||
global.WorkerGlobalScope = global; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong global identifier: use WebSocket
, not Websocket
Browsers (and most polyfills) expose global.WebSocket
(uppercase S).
Assigning to Websocket
leaves libraries that expect WebSocket
undefined.
-// @ts-ignore
-global.Websocket = w3cwebsocket;
+// @ts-ignore
+global.WebSocket = w3cwebsocket;
📝 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.
// Those lines are require so that websocket works. | |
// @ts-ignore | |
global.Websocket = w3cwebsocket; | |
// @ts-ignore | |
global.WorkerGlobalScope = global; | |
// Those lines are require so that websocket works. | |
// @ts-ignore | |
global.WebSocket = w3cwebsocket; | |
// @ts-ignore | |
global.WorkerGlobalScope = global; |
while (continueFetching) { | ||
if (logging) | ||
console.log( | ||
`Fetched ${Object.keys(fetchedEntities).length} entities ${cursor}` | ||
`Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` | ||
); | ||
|
||
setEntities(fetchedEntities, components, logging); | ||
setEntities(fetchedEntities.items, components, logging); | ||
|
||
if (Object.keys(fetchedEntities).length < limit) { | ||
if (Object.keys(fetchedEntities.items).length < limit) { | ||
continueFetching = false; | ||
} else { | ||
cursor += limit; | ||
cursor = fetchedEntities.next_cursor; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Infinite loop in getEntitiesQuery
Inside the while (continueFetching)
loop you never issue a new client.getEntities
call—fetchedEntities
is fetched once outside the loop, so cursor
advances but data doesn’t refresh.
Move the fetch inside the loop:
while (continueFetching) {
const fetchedEntities = await client.getEntities({ …cursor… });
…
}
Otherwise the loop either spins forever or exits immediately depending on the first batch size.
export interface PositionCount { | ||
identity: string; | ||
positition: Array<[BigNumberish, BigNumberish]>; | ||
} | ||
|
||
// Type definition for `dojo_starter::models::PositionCountValue` struct | ||
export interface PositionCountValue { | ||
positition: Array<[BigNumberish, BigNumberish]>; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in "positition" field name
There appears to be a typo in the positition
field name (should be "position").
export interface PositionCount {
identity: string;
- positition: Array<[BigNumberish, BigNumberish]>;
+ position: Array<[BigNumberish, BigNumberish]>;
}
export interface PositionCountValue {
- positition: Array<[BigNumberish, BigNumberish]>;
+ position: Array<[BigNumberish, BigNumberish]>;
}
Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
📝 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.
export interface PositionCount { | |
identity: string; | |
positition: Array<[BigNumberish, BigNumberish]>; | |
} | |
// Type definition for `dojo_starter::models::PositionCountValue` struct | |
export interface PositionCountValue { | |
positition: Array<[BigNumberish, BigNumberish]>; | |
} | |
export interface PositionCount { | |
identity: string; | |
position: Array<[BigNumberish, BigNumberish]>; | |
} | |
// Type definition for `dojo_starter::models::PositionCountValue` struct | |
export interface PositionCountValue { | |
position: Array<[BigNumberish, BigNumberish]>; | |
} |
const client = await new torii.ToriiClient(clientConfig); | ||
return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Client initialization change
Changed from torii.createClient
to directly instantiating new torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.
Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
503223b
to
2cc16f7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 11
🔭 Outside diff range comments (5)
packages/react/package.json (1)
3-3
:⚠️ Potential issueVersion bump needed
The PR title suggests bumping to1.5
, but this package remains at1.4.5
. Please update the version field to1.5.0
.Apply this diff:
- "version": "1.4.5", + "version": "1.5.0",packages/torii-client/package.json (1)
3-3
:⚠️ Potential issueVersion bump needed
This package is still at version1.4.4
. Please update it to1.5.0
to match the PR objective.Apply this diff:
- "version": "1.4.4", + "version": "1.5.0",packages/core/package.json (1)
3-3
:⚠️ Potential issueVersion bump needed
The PR title indicates a bump to1.5
, but this package remains at1.4.4
. Please update the version field to1.5.0
.Apply this diff:
- "version": "1.4.4", + "version": "1.5.0",examples/example-vite-react-sdk/src/historical-events.tsx (1)
13-21
: 🛠️ Refactor suggestionStabilise the
HistoricalToriiQueryBuilder
instance
new HistoricalToriiQueryBuilder()
is created on every render, so the hook sees a different object in its deps each time, forcing an unnecessary re-query.-const events = useHistoricalEventsQuery( - new HistoricalToriiQueryBuilder().withClause( +const builder = React.useMemo( + () => + new HistoricalToriiQueryBuilder().withClause( KeysClause( [], [addAddressPadding(account?.address ?? "0")], "VariableLen" ).build() - ), + ), + [account?.address], +); +const events = useHistoricalEventsQuery(builder);This memoisation avoids redundant network calls and improves performance.
packages/state/src/recs/index.ts (1)
518-553
:⚠️ Potential issue
insertEntitiesInDB
iterates incorrectly over an array
entities
is typed asToriiEntity[]
, yet the code uses
for (const [entityId, data] of Object.entries(entities))
, which yields the
array index ("0"
,"1"
…) instead of the entity’s hashed key.-for (const [entityId, data] of Object.entries(entities)) { +for (const entity of entities) { + const entityId = entity.hashed_keys; + const data = entity;This prevents corrupt keys and preserves original entity data.
♻️ Duplicate comments (13)
packages/sdk/src/internal/merge.ts (1)
96-103
: Replicate the stricter typing for the source-precedence branchThe same
any
/for…in
patterns appear here. Apply the stricter snippet (see previous comment) to keep both branches symmetrical and fully typed.🧰 Tools
🪛 Biome (1.9.4)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/main.ts (3)
22-25
:⚠️ Potential issue
Websocket
should beWebSocket
(duplicate comment)Browsers and most polyfills expose the global with an uppercase S (
WebSocket
).
Re-introducing the lowercase alias re-creates the very issue flagged in earlier reviews.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
125-132
:⚠️ Potential issue
initPositionFromEvent
still mutates the shared constant (duplicate comment)
pc
is an alias ofdefaultPositionCount
; each call accumulates counts into the
constant and leaks state across workers. Spread-clone the default instead:-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };
137-151
: 🛠️ Refactor suggestion
data.pop()
drops all but the last entity (duplicate comment)
data
is already the supplied batch. Iterating is safer and avoids silent data
loss:-const entity = data.pop(); -if (entity && entity.entityId !== "0x0") { - … -} +for (const entity of data) { + if (entity.entityId === "0x0") continue; + … +}packages/state/src/recs/index.ts (2)
189-193
: 🛠️ Refactor suggestionInefficient & incorrect length check on array of entities
entities.items
is an array, soObject.keys(…).length
is both slower and
semantically misleading. It also breaks if the array contains sparse indexes.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) {
307-333
:⚠️ Potential issue
getEntitiesQuery
fetches once, then loops forever (duplicate comment)
fetchedEntities
is obtained before thewhile
loop and never refreshed;
cursor
changes but data doesn’t, so the loop either spins indefinitely or
exits immediately.Move the fetch inside the loop:
-const fetchedEntities = await client.getEntities({ … }); -while (continueFetching) { - … -} +while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { limit, cursor, direction: "Forward", order_by: orderBy }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); + … +}examples/example-node-worker/src/typescript/models.gen.ts (3)
38-46
: Fix typo in "positition" field nameThere appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
129-129
: Schema uses incorrect field name "positition"The schema initialization at line 129 uses the typo "positition" which should be corrected to "position" to match the intended field name.
- positition: [[0, 0]], + position: [[0, 0]],
132-132
: Schema uses incorrect field name "positition"The schema initialization at line 132 also uses the typo "positition" which should be corrected.
- positition: [[0, 0]], + position: [[0, 0]],packages/sdk/src/internal/toriiQueryBuilder.ts (1)
39-45
: Deprecated withOffset method lacks backward compatibilityThe
withOffset
method is now a no-op that returnsthis
without setting any properties. While it's appropriately marked as deprecated, this implementation could silently break existing code that relies on offset-based pagination.Consider maintaining backwards compatibility by mapping offset to an equivalent cursor-based approach, or provide more explicit migration guidance in the deprecation notice.
packages/sdk/src/node/index.ts (3)
50-51
: Client initialization changeChanged from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
215-230
: Modified generateTypedData signatureThe method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
72-85
: Updated entity parsing to use items arrayThe entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This change simplifies the data structure but is a breaking change for existing code.- (await client.getEntities(q)).items + (await client.getEntities(q)).itemsEnsure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
🧹 Nitpick comments (20)
turbo.json (1)
39-42
: Define dependencies for test tasks
Consider adding adependsOn
for the"test"
task so that builds run before tests, improving cache consistency:"test": { -}, + "dependsOn": ["^build"], + "outputs": [], +},This ensures tests always run against fresh builds.
packages/sdk/src/internal/merge.ts (1)
133-155
:deepMerge
silently overwrites arrays & loses type-info
deepMerge
:
- Treats arrays like primitives (
!Array.isArray(source[key])
) → any array onsource
replaces the one ontarget
.
That’s rarely what callers expect from a “deep-merge”.- Falls back to
Record<string, any>
which erases all schema information.- Recurses without runtime cycle protection, which can blow the call-stack if circular refs sneak in.
Consider:
-if ( - source[key] !== null && - typeof source[key] === "object" && - !Array.isArray(source[key]) -) { +if ( + source[key] !== null && + typeof source[key] === "object" +) { // handle Array vs Object separately + if (Array.isArray(source[key]) && Array.isArray(target[key])) { + result[key] = [...(target[key] as unknown[]), ...(source[key] as unknown[])] as typeof source[key]; + continue; + }…and replace the root
Record<string, any>
with a generic helper:function asMutable<T>(v: T): Mutable<T> { return v as Mutable<T>; }This maintains schema types throughout the recursion.
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-vite-react-sdk/src/historical-events.tsx (2)
1-5
: ImportParsedEntity
as a type-only import to trim bundle size
ParsedEntity
is only used for type annotations.
Switching toimport type
lets TS / bundlers tree-shake the symbol:-import { - KeysClause, - ParsedEntity, - HistoricalToriiQueryBuilder, -} from "@dojoengine/sdk"; +import { + KeysClause, + HistoricalToriiQueryBuilder, +} from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
31-35
: Remove@ts-ignore
by refining the hook’s return typeBlindly silencing TypeScript defeats its value.
IfuseHistoricalEventsQuery
returns{ data?: ParsedEntity[] }
, destructure it properly and default to an empty array:const { data: events = [] } = useHistoricalEventsQuery(builder); ... {events.map((e, key) => ( <Event event={e} key={key} /> ))}This eliminates the ignore directive and the unsafe cast.
🧰 Tools
🪛 Biome (1.9.4)
[error] 34-34: Avoid using the index of an array as key property in an element.
This is the source of the key value.
The order of the items may change, and this also affects performances and component state.
Check the React documentation.(lint/suspicious/noArrayIndexKey)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Replace non-null assertions with optional chaining
!.
bypasses runtime checks and the linter rightfully flags it.
Use?.
so the benchmark won’t crash if the path is unexpectedlyundefined
.- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + const item = draft.entities["entity500"]?.models.world?.item; + if (item) item.durability = 75;This keeps the perf test realistic while remaining type-safe.
🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/web/react/hooks/entities.ts (1)
26-35
: Improved entity filtering and update logic.The updated approach to filter zero-value entities and use the first valid entity is more robust. However, there's an opportunity for further optimization:
- If the filter might return an empty array, the direct access to
entities[0]
could be simplified- The check for
data
being truthy could be combined with the filter operationConsider this slightly more concise implementation:
- if (data) { - const entities = data.filter( - (e) => Number.parseInt(e.entityId, 16) !== 0 - ); - - const entity = entities[0]; - if (entity) { - state.updateEntity(entity); - } - } + const validEntity = data?.filter(e => Number.parseInt(e.entityId, 16) !== 0)[0]; + if (validEntity) { + state.updateEntity(validEntity); + }examples/example-node-worker/src/typescript/contracts.gen.ts (3)
1-2
: Import type optimizations neededThe imports are only used as types and should use the
import type
syntax to ensure they're removed by compilers, which improves bundle size and avoids loading unnecessary modules.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
15-26
: Consider refactoring error handlingThe function logs the error and then rethrows it. Consider adding more context to the error message or implementing more specific error handling based on the contract interaction failure.
const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, build_actions_move_calldata(direction), "dojo_starter", ); } catch (error) { - console.error(error); - throw error; + console.error(`Failed to execute move action: ${error}`); + throw new Error(`Move action failed: ${error instanceof Error ? error.message : String(error)}`); } };
5-59
: Exported contract wrapper lacks documentationThe exported function and its methods would benefit from JSDoc documentation explaining their purpose, parameters, and return values, especially since this is likely to be used by developers integrating with the Dojo ecosystem.
+/** + * Sets up the world contract interfaces for interacting with Dojo contracts + * + * @param provider - The Dojo provider used for contract interactions + * @returns Object containing methods to interact with game actions + */ export function setupWorld(provider: DojoProvider) { + /** + * Builds calldata for the move action + * @param direction - A CairoCustomEnum representing the movement direction + * @returns The formatted DojoCall object ready for execution + */ const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { // ... }; // Add similar documentation for other methodspackages/sdk/src/web/state/zustand.ts (1)
14-14
: Import optimization for typesThe
MergedModels
import is only used as a type and should use theimport type
syntax to optimize bundle size.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/parseEntities.ts (1)
58-58
: Unnecessary Object.values callThe function returns
Object.values(result)
, butresult
is already an array. This is unnecessary and could be simplified.- return Object.values(result); + return result;examples/example-node-worker/main.ts (1)
79-98
: Temporal-Dead-Zone risk forpositionCount
reference
positionCount
is declared after this function definition. Although the
function isn’t executed until later, hoisting nuances can be confusing. Moving
the declaration above the function (or passing it as a parameter) improves
readability and avoids TDZ surprises.packages/sdk/src/web/index.ts (1)
83-90
: Guard condition is inverted
q.no_hashed_keys
means hashed keys are not included.
The check should block the subscription when hashed keys are excluded
and no explicitKeys
clause is present.The current logic throws when
no_hashed_keys === true
, which seems correct,
but the variable naming is easy to misinterpret—consider an inline comment or a
helper predicate to avoid future confusion.examples/example-node-worker/src/typescript/models.gen.ts (3)
100-103
: Inconsistent indentation in schema initializationThe indentation in the CairoCustomEnum initialization is inconsistent, with the first option aligned differently than the others.
directions: [new CairoCustomEnum({ - Left: "", + Left: "", Right: undefined, Up: undefined, Down: undefined, })],
1-3
: Useimport type
for type-only importsUse the
import type
syntax for imports that are only used as types to ensure they are removed during compilation.-import type { SchemaType as ISchemaType } from "@dojoengine/sdk"; +import type { SchemaType as ISchemaType } from "@dojoengine/sdk"; -import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; +import type { BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
144-147
: Inconsistent indentation in Moved schema initializationSimilar to the earlier comment, there's inconsistent indentation in the CairoCustomEnum initialization for the Moved schema.
direction: new CairoCustomEnum({ - Left: "", + Left: "", Right: undefined, Up: undefined, Down: undefined, }),packages/sdk/src/internal/toriiQueryBuilder.ts (4)
47-55
: Add parameter documentation for withCursor methodThe
withCursor
method documentation explains what the parameter is for, but doesn't document the parameter itself. Consider adding a@param
tag to match the style of other methods in this class./** * Set the cursor for pagination * undefined is default, fetch from starting point * `next_cursor` is return from queries + * @param {string} cursor - The cursor to paginate from */
57-62
: Fix incorrect JSDoc for withDirection methodThe JSDoc comment for
withDirection
is incorrect - it states "Set the maximum number of results to return" which is a copy of thewithLimit
method's documentation. Update it to correctly describe setting the pagination direction./** - * Set the maximum number of results to return + * Set the direction for pagination + * @param {PaginationDirection} direction - The direction to paginate ("Forward" or "Backward") */
133-142
: Type safety improvement needed in withPagination methodThe static method
withPagination
usesRecord<string, Record<string, any>>
as its generic constraint. This could be improved to use theSchemaType
type for better type safety and to avoid theany
type flagged by the linter.- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends SchemaType>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
145-158
: Add type documentation for HistoricalToriiQueryBuilderOptionsThe new
HistoricalToriiQueryBuilderOptions
type andHistoricalToriiQueryBuilder
class lack documentation explaining their purpose and usage. Consider adding JSDoc comments to clarify that this is specifically for historical queries.+/** + * Options type for HistoricalToriiQueryBuilder, excluding the 'historical' property + * which is always true for historical queries. + */ export type HistoricalToriiQueryBuilderOptions = Omit< Partial<ToriiQueryBuilderOptions>, "historical" >; +/** + * A specialized query builder for historical queries that sets historical:true by default. + * Use this when querying historical event data. + */ export class HistoricalToriiQueryBuilder< T extends SchemaType > extends ToriiQueryBuilder<T> {
🛑 Comments failed to post (11)
packages/react/package.json (1)
38-39: 💡 Verification agent
🧩 Analysis chain
Ensure consistent tooling versions
You’ve addedtypescript@^5.6.2
andvitest@^3.1.2
here—great for React. However,@dojoengine/core
still usesvitest@^1.6.0
. To avoid version drift, please align allvitest
versions across the monorepo.Run this to locate mismatched versions:
🏁 Script executed:
#!/bin/bash rg -A1 '"vitest":' -g 'packages/**/package.json'Length of output: 1077
Align Vitest Versions Across the Monorepo
We currently have three different major Vitest versions in use:
• packages/react & packages/torii-client: ^3.1.2
• packages/utils-wasm & packages/create-dojo: ^2.1.1
• packages/utils, core, state, predeployed-connector, create-burner: ^1.6.x
• packages/sdk: ^1.6.1To avoid confusing test behavior and dependency drift, please pick a single Vitest version (e.g. the latest ^3.1.2) and update all package.json files accordingly:
- packages/utils-wasm/package.json
- packages/utils/package.json
- packages/sdk/package.json
- packages/predeployed-connector/package.json
- packages/state/package.json
- packages/create-burner/package.json
- packages/create-dojo/package.json
- packages/core/package.json
Ensure that each entry under
"devDependencies"
(or"dependencies"
) reads"vitest": "^3.1.2"
.packages/sdk/src/internal/merge.ts (1)
76-83: 🛠️ Refactor suggestion
Avoid
any
and tighten variant-loop typing
newEnumContent
is declared withRecord<string, any>
and the subsequentfor…in
iterates overtarget.variant
.
Both patterns reduce type-safety:
any
disables all compile-time checks.for…in
also enumerates inherited keys; if the underlyingCairoCustomEnum
prototype ever gains enumerable props, they will leak in.-const newEnumContent: Record<string, any> = {}; -for (const key in target.variant) { - newEnumContent[key] = undefined; -} +const newEnumContent = Object.fromEntries( + Object.keys(target.variant as Record<string, unknown>).map((k) => [k, undefined]), +) as { [K in keyof typeof target.variant]?: never };Using
Object.keys
+fromEntries
:
- Filters out prototype keys.
- Preserves the exact variant names via a mapped type instead of
string
.📝 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.const newEnumContent = Object.fromEntries( Object.keys(target.variant as Record<string, unknown>).map((k) => [k, undefined]), ) as { [K in keyof typeof target.variant]?: never }; // Set the active variant from source
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/package.json (1)
6-10:
⚠️ Potential issueAdded helpful scripts for development.
The addition of scripts to run the example with both
bun
andnode
makes it easier for developers to get started with the example. The build script is also useful for TypeScript compilation.Warning: Hardcoded credentials in scripts
The
IDENTITY
andSECRET_KEY
values in the scripts appear to be private keys or identifiers. Although these might be example values, it's generally not recommended to hardcode credentials in scripts that will be committed to a repository.Consider using environment variables from a local
.env
file that is not committed to the repository, like:- "bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", - "node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts", + "bun": "bun run main.ts", + "node": "node main.ts",This would work with the
dotenv
package already included in the dependencies.📝 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."scripts": { "bun": "bun run main.ts", "node": "node main.ts", "build": "tsc -b" },
🧰 Tools
🪛 Gitleaks (8.21.2)
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
36-47: 🛠️ Refactor suggestion
Duplicate error handling pattern
The same error handling pattern is repeated in
actions_spawn
. Consider extracting a common error handling utility to avoid code duplication.+const handleContractError = (action: string, error: unknown) => { + console.error(`Failed to execute ${action} action: ${error}`); + throw new Error(`${action} action failed: ${error instanceof Error ? error.message : String(error)}`); +}; const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, build_actions_move_calldata(direction), "dojo_starter", ); } catch (error) { - console.error(error); - throw error; + handleContractError('move', error); } }; const actions_spawn = async (snAccount: Account | AccountInterface) => { try { return await provider.execute( snAccount, build_actions_spawn_calldata(), "dojo_starter", ); } catch (error) { - console.error(error); - throw error; + handleContractError('spawn', error); } };📝 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.// Add this helper at the top of your file (after imports) const handleContractError = (action: string, error: unknown) => { console.error(`Failed to execute ${action} action:`, error); throw new Error( `${action} action failed: ${ error instanceof Error ? error.message : String(error) }` ); }; const actions_move = async ( snAccount: Account | AccountInterface, direction: CairoCustomEnum ) => { try { return await provider.execute( snAccount, build_actions_move_calldata(direction), "dojo_starter", ); } catch (error) { handleContractError("move", error); } }; const actions_spawn = async (snAccount: Account | AccountInterface) => { try { return await provider.execute( snAccount, build_actions_spawn_calldata(), "dojo_starter", ); } catch (error) { handleContractError("spawn", error); } };
packages/sdk/src/web/state/zustand.ts (1)
92-97: 💡 Verification agent
🧩 Analysis chain
Type casting during deep merge
The code uses multiple type assertions during the merge process, which could be fragile if the structure of the data changes. Consider adding runtime type checks or defensive programming techniques to ensure type safety.
🏁 Script executed:
#!/bin/bash # Check how the deepMerge function is implemented and if it handles type safety # Find the implementation of deepMerge rg -A 10 "export function deepMerge" --type tsLength of output: 864
🏁 Script executed:
#!/bin/bash # Fetch the full implementation of deepMerge to inspect runtime checks and type assertions rg -A100 "export function deepMerge" --type ts packages/sdk/src/internal/merge.tsLength of output: 1495
Ensure runtime type safety when merging models
In packages/sdk/src/web/state/zustand.ts (lines 92–97), we’re casting the result of
deepMerge
—which internally spreads into aRecord<string, any>
—back toMergedModels<T>
:] = deepMerge( mergedModels[typedNamespace as keyof typeof mergedModels] as MergedModels<T>, namespaceModels ) as MergedModels<T>;While TypeScript trusts the cast, at runtime there’s no check that the merged object actually conforms to our schema. To prevent subtle bugs if the input shape changes, we should:
- Add post-merge validation using either:
- Custom type guards that verify required keys/types, or
- A schema-based validator (e.g. Zod, io-ts) to assert the merged output matches
MergedModels<T>
.- Alternatively, enhance
deepMerge
to enforce expected fields and throw or default on unknown/mismatched properties.This defensive step will ensure any divergence between compile-time types and runtime data is caught early.
examples/example-node-worker/main.ts (1)
175-176:
⚠️ Potential issueUnreachable second
return
statementThe empty array returned on line 175 makes the subsequent
return [sub];
dead-code (Biome warning). Return the subscription instead.- return []; - return [sub]; + return [sub];📝 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.return [sub];
🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/web/index.ts (2)
45-49:
⚠️ Potential issue
createClient
need not beasync
orawait
new torii.ToriiClient
is synchronous. Wrapping it inasync/await
adds an
unnecessary micro-task and misleads readers into thinking the constructor is
asynchronous.-export async function createClient( - config: torii.ClientConfig -): Promise<torii.ToriiClient> { - return await new torii.ToriiClient(config); -} +export function createClient( + config: torii.ClientConfig +): torii.ToriiClient { + return new torii.ToriiClient(config); +}📝 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.export function createClient( config: torii.ClientConfig ): torii.ToriiClient { return new torii.ToriiClient(config); }
261-279: 💡 Verification agent
❓ Verification inconclusive
sendMessage
mixesResult
and exceptionsThe function returns
Result<Uint8Array,string>
, except when an internal
error occurs—then itthrow
s, breaking theResult
contract. Prefer returning
err(String(error))
to keep the API consistent.- } catch (error) { - console.error("Failed to send message:", error); - throw error; + } catch (error) { + console.error("Failed to send message:", error); + return err( + error instanceof Error ? error.message : String(error) + ); }
Ensure
sendMessage
consistently returns aResult
on errorsThe catch block currently throws an exception, breaking the
Result<Uint8Array, string>
contract. Convert the caught error into anerr(...)
so callers always receive aResult
.• packages/sdk/src/web/index.ts (around lines 261–279)
} catch (error) { console.error("Failed to send message:", error); - throw error; + return err( + error instanceof Error ? error.message : String(error) + ); }📝 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.if (!account) { return err(NO_ACCOUNT); } try { // Sign the typed data const signature: Signature = await account.signMessage(data); // Stringify typed data for publishing const dataString = JSON.stringify(data); // Publish the signed message return ok( await client.publishMessage( dataString, Array.isArray(signature) ? signature : [signature.r.toString(), signature.s.toString()] ) ); } catch (error) { console.error("Failed to send message:", error); return err( error instanceof Error ? error.message : String(error) ); }
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
9-20:
⚠️ Potential issueBreaking change: Nested pagination structure and renamed properties
The default options structure has significantly changed:
- Pagination parameters are now nested in a
pagination
objectdont_include_hashed_keys
renamed tono_hashed_keys
entity_models
renamed tomodels
These changes will require updates to any code that directly accesses these properties.
Ensure this breaking change is documented in migration guides and update all dependent code, including tests.
packages/sdk/src/node/index.ts (2)
240-265: 🛠️ Refactor suggestion
Enhanced error handling with Result type
The
sendMessage
method now returns aResult
type from neverthrow instead of throwing errors directly. This is a good improvement for error handling but is a breaking change for existing code that expects exceptions.- async (data: TypedData, _account?: Account): Promise<void> + async (data: TypedData, _account?: Account): Promise<Result<Uint8Array, string>>Update callers to handle the Result type appropriately:
const result = await sdk.sendMessage(typedData); if (result.isOk()) { const receipt = result.value; // Handle success } else { const errorMessage = result.error; // Handle error }
127-130:
⚠️ Potential issueHistorical events handling simplified
The handling of historical events has been simplified to always use
parseEntities
on theitems
array. This is consistent with the changes to entity parsing and provides a more unified approach.Ensure that any code relying on the previous historical event parsing behavior is updated accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🔭 Outside diff range comments (1)
packages/state/src/recs/index.ts (1)
516-554
: 🛠️ Refactor suggestion
insertEntitiesInDB
assumes an object, but receives an array
entities
is typed asToriiEntity[]
; iterating withObject.entries
produces numeric indices rather than entity IDs. Iterate the array directly and pick a stable key (e.g.,hashed_keys
).- for (const [entityId, data] of Object.entries(entities)) { - const entityData = { - id: entityId, - ...data, - }; + for (const entity of entities) { + const entityData = { + id: entity.hashed_keys, + ...entity, + }; const request = store.put(entityData);
♻️ Duplicate comments (13)
examples/example-node-worker/src/typescript/models.gen.ts (4)
38-41
: Fix typo in "positition" field nameThere appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }
44-46
: Fix typo in "positition" field nameThe same typo exists in the PositionCountValue interface.
export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }
128-130
: Fix typo in "positition" field name in schema initializationThe same typo exists in the schema initialization for PositionCount.
PositionCount: { identity: "", - positition: [[0, 0]], + position: [[0, 0]], },
132-133
: Fix typo in "positition" field name in schema initializationThe same typo exists in the schema initialization for PositionCountValue.
PositionCountValue: { - positition: [[0, 0]], + position: [[0, 0]], },examples/example-node-worker/main.ts (3)
21-25
: Global identifier typo: useWebSocket
, notWebsocket
Browsers (and most polyfills) exposeglobal.WebSocket
. Re-introducing the lowercaseWebsocket
will break libraries expecting the correct casing.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
120-128
:initPositionFromEvent
still mutates the shared constant
pc
is a direct alias ofdefaultPositionCount
; each update mutates the default object and leaks state across workers/runs.- const pc = defaultPositionCount; + const pc: PositionCount = { ...defaultPositionCount };
136-151
:data.pop()
drops all but the last entityIf multiple entities arrive in one batch, every entity except the final one is silently ignored. Iterate over the array instead.
- const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - … - } + for (const entity of data) { + if (entity.entityId === "0x0") continue; + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } + }packages/state/src/recs/index.ts (2)
323-330
: Infinite loop risk—fetchedEntities
never refreshes
fetchedEntities
is fetched once outside the loop; thewhile
loop re-uses the same data endlessly. Move the fetch inside the loop (or drop the loop if a single page is intended).- const fetchedEntities = await client.getEntities({ … }); - while (continueFetching) { - … - setEntities(fetchedEntities.items, …); - … - cursor = fetchedEntities.next_cursor; + while (continueFetching) { + const page = await client.getEntities({ + pagination: { limit, cursor, direction: "Forward", order_by: orderBy }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); + + setEntities(page.items, components, logging); + + if (page.items.length < limit) { + continueFetching = false; + } else { + cursor = page.next_cursor; + } + }
185-190
: 🛠️ Refactor suggestion
entities.items
is an array—use.length
directlyUsing
Object.keys
on an array is slower and semantically confusing.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) {🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
39-45
:⚠️ Potential issueDeprecated withOffset method lacks backward compatibility.
The
withOffset
method is now a no-op that returnsthis
without setting any properties. While it's appropriately marked as deprecated, this implementation could silently break existing code that relies on offset-based pagination.Consider maintaining backwards compatibility by mapping offset to an equivalent cursor-based approach, or provide more explicit migration guidance in the deprecation notice.
packages/sdk/src/node/index.ts (3)
50-51
:⚠️ Potential issueClient initialization change.
Changed from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
72-85
:⚠️ Potential issueUpdated entity parsing to use items array.
The entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This change simplifies the data structure but is a breaking change for existing code.Ensure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
215-230
:⚠️ Potential issueModified generateTypedData signature.
The method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
🧹 Nitpick comments (12)
examples/example-node-worker/src/typescript/models.gen.ts (2)
1-3
: Consider usingimport type
for type-only importsThe SchemaType import is only used as a type, not as a value. Using
import type
would ensure it's removed during compilation.-import type { SchemaType as ISchemaType } from "@dojoengine/sdk"; +import type { SchemaType as ISchemaType } from "@dojoengine/sdk"; -import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; +import type { BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
100-103
: Improve alignment in enum initializationThe indentation in the CairoCustomEnum initialization is inconsistent. Consider aligning the properties for better readability.
directions: [new CairoCustomEnum({ - Left: "", - Right: undefined, - Up: undefined, - Down: undefined, })], + Left: "", + Right: undefined, + Up: undefined, + Down: undefined, + })],examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Useimport type
for type-only importsThe
ParsedEntity
import is only used as a type, not a value. Usingimport type
would ensure it's removed during compilation.import { KeysClause, - ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Improve property access notation and avoid non-null assertionsThe code was reformatted for better readability, but we can further improve it by using optional chaining instead of non-null assertions to make the code safer.
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + const entity = draft.entities["entity500"]; + if (entity?.models?.world?.item) { + entity.models.world.item.durability = 75; + }🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/web/experimental/index.ts (1)
30-30
: Remove redundant type annotationThe
historical
parameter's boolean type is trivially inferred from its initialization.- getEvents: async (query: torii.Query, historical: boolean = false) => { + getEvents: async (query: torii.Query, historical = false) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
1-3
: Update imports to useimport type
for type-only importsUsing
import type
ensures that type-only imports are removed by the compilers and avoids loading unnecessary modules at runtime.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import { DojoProvider } from "@dojoengine/core"; +import type { DojoCall } from "@dojoengine/core"; +import { Account } from "starknet"; +import type { AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
15-26
: Consider adding retry logic for contract callsContract calls can fail due to network issues or congestion. Consider implementing retry logic with exponential backoff for more robust error handling.
const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { + const maxRetries = 3; + let retries = 0; try { - return await provider.execute( - snAccount, - build_actions_move_calldata(direction), - "dojo_starter", - ); + while (true) { + try { + return await provider.execute( + snAccount, + build_actions_move_calldata(direction), + "dojo_starter", + ); + } catch (error) { + if (retries >= maxRetries || !isRetryableError(error)) { + throw error; + } + retries++; + console.log(`Retrying execution (${retries}/${maxRetries})...`); + await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, retries))); + } + } } catch (error) { console.error(error); throw error; } }; +// Helper to determine if an error is retryable +const isRetryableError = (error: any): boolean => { + // Customize based on the specific error types you want to retry + const errorMessage = String(error); + return errorMessage.includes("network") || + errorMessage.includes("timeout") || + errorMessage.includes("rate limit"); +};packages/sdk/src/web/state/zustand.ts (1)
14-14
: Centralized deep merge utility importedImporting
deepMerge
andMergedModels
from a dedicated module improves code organization and reusability. Useimport type
forMergedModels
if it's only used as a type.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/parseEntities.ts (2)
58-59
: Return the array directly—Object.values
is redundant
result
is already an array. Wrapping it inObject.values
creates an unnecessary shallow copy and slightly obscures intent.- return Object.values(result); + return result;
50-52
: Use a plain string literal to silence Biome warningThere is no interpolation in this template literal; switch to a normal string to remove the linter error.
- console.log(`Parsed entity:`, parsedEntity); + console.log("Parsed entity:", parsedEntity);🧰 Tools
🪛 Biome (1.9.4)
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/internal/merge.ts (2)
57-113
: Consider using more specific type than 'any' for enum content.The implementation for merging Cairo custom enums creates new instances to maintain immutability, but uses
any
type for the enum content.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
123-160
: Consider using a more specific type than 'any' in the deep merge function.The deep merge function is well-implemented with appropriate special case handling for Cairo types, but the result type could be more specific than
any
.- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;Additionally, consider adding more explanatory comments about the merging strategy for nested objects to make the implementation more maintainable.
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (40)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(4 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(2 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/internal/parseHistoricalEvents.ts
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
✅ Files skipped from review due to trivial changes (2)
- .changeset/thirty-cheetahs-design.md
- .github/workflows/ci.yaml
🚧 Files skipped from review as they are similar to previous changes (22)
- examples/example-nodejs-bot/package.json
- packages/react/package.json
- packages/torii-wasm/dojo.c
- examples/example-node-worker/dojoConfig.ts
- packages/core/package.json
- examples/example-node-worker/env.ts
- packages/torii-client/package.json
- packages/sdk/src/internal/errors.ts
- packages/sdk/package.json
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- package.json
- turbo.json
- packages/sdk/src/tests/parseEntities.test.ts
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/src/web/react/hooks/entities.ts
- examples/example-node-worker/tsconfig.json
- packages/sdk/src/node/worker.ts
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/internal/models.ts
- packages/sdk/src/web/index.ts
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
packages/sdk/src/internal/types.ts (2)
ToriiQueryBuilder
(557-557)SchemaType
(50-70)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
🪛 Gitleaks (8.21.2)
examples/example-node-worker/package.json
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (36)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: Updated to use the specialized HistoricalToriiQueryBuilderGood update to use
HistoricalToriiQueryBuilder
which automatically sets the historical flag to true and encapsulates pagination parameters.examples/example-node-worker/package.json (1)
14-18
: Well-structured dependencies for worker functionalityThe added dependencies appropriately support the worker functionality with Torii WASM integration, environment variable handling, Starknet integration, and WebSocket support.
packages/sdk/src/web/experimental/index.ts (4)
24-24
: Client initialization correctly changed to synchronous instantiationThe change from asynchronous to synchronous client creation aligns with similar changes in other SDK modules, providing a more consistent API.
28-28
: Entity and event parsing now correctly extracts items arrayThe updated code properly extracts the
.items
array from query results before passing to parsing functions, aligning with the standardized data handling approach across the SDK.Also applies to: 31-33
39-39
: Query parameter rename for consistencyParameter renamed from
dont_include_hashed_keys
tono_hashed_keys
for consistency with updates in other SDK files.Also applies to: 82-82
54-59
: Entity update callback refactored to process arraysThe callback now correctly processes arrays of entity data rather than objects keyed by entity ID, matching the pattern adopted in other SDK components.
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
5-59
: Well-structured contract interaction helpersThe
setupWorld
function provides a clean API for contract interactions with proper error handling and type safety. The function follows Dojo conventions by providing both execution and calldata building functions.packages/sdk/src/web/react/hooks/events.ts (5)
3-7
: Improved type imports withParsedEntity
The addition of the
ParsedEntity
type import improves type safety throughout the file.
27-29
: State update logic simplifiedChanged from a return statement to a direct state update call, which is cleaner and more explicit.
31-39
: Event filtering logic enhancedNow filters out events with zero entityId and updates state with the first valid event instead of the last. This is a better approach for most use cases.
58-58
: Historical events state properly typedThe state is now explicitly typed as an array of
ParsedEntity<Schema>
and the processing function is simplified.Also applies to: 66-68
70-75
: Historical events update improvedNow prepends all filtered events rather than a single event, providing more complete historical data.
packages/sdk/src/web/state/zustand.ts (2)
71-99
: Enhanced nested model mergingThe entity merging logic is improved with a more granular nested loop approach that properly handles namespace and model hierarchies. The use of
deepMerge
ensures proper handling of Cairo-specific types.
140-149
: Consistent use of deepMerge in updateEntityThe
updateEntity
method now uses the samedeepMerge
utility asmergeEntities
, ensuring consistent merging behavior across the store.packages/sdk/src/internal/merge.ts (4)
1-11
: Well-structured type checking utility for CairoOption.The implementation properly uses the type guard pattern to safely check if a value is a CairoOption instance, with good documentation.
13-46
: Merge strategy for CairoOption implements proper immutability.The function creates new instances of CairoOption rather than modifying existing ones, which maintains immutability. The merging logic prioritizes "Some" values from the source, falling back to the target when needed.
48-55
: Appropriate type guard implementation for CairoCustomEnum.The implementation is clean and follows the same pattern as the CairoOption type guard.
115-121
: Clean utility type definition for merged models.The type effectively extracts model types from the schema, which will be useful for type-checking throughout the codebase.
packages/sdk/src/internal/toriiQueryBuilder.ts (8)
10-20
: Refactored structure to use nested pagination object.The default options now use a nested pagination object that contains limit, cursor, direction, and order_by properties, aligning with a cursor-based pagination approach. The property names have been updated from
dont_include_hashed_keys
tono_hashed_keys
and fromentity_models
tomodels
for consistency.
35-36
: Updated method to use nested pagination property.The
withLimit
method has been updated to set the limit within the pagination object.
47-63
: Added new cursor-based pagination methods.The new
withCursor
andwithDirection
methods support cursor-based pagination, which is a more scalable approach for large datasets. These methods provide building blocks for the new pagination strategy.
78-79
: Updated property name for consistency.The
includeHashedKeys
method now modifiesno_hashed_keys
rather thandont_include_hashed_keys
, reflecting the renamed property.
90-103
: Updated order methods to use nested pagination structure.The order-related methods now modify properties within the pagination object rather than directly on the query object.
110-119
: Updated entity model methods to use renamed property.The entity model related methods now use the
models
property instead ofentity_models
for consistency.
133-142
: Updated pagination static method to use cursor-based approach.The static
withPagination
method now uses cursor, limit, and direction parameters instead of page and pageSize, reflecting the transition to cursor-based pagination.Consider using a more specific type than
any
for the Record generic:- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends Record<string, Record<string, unknown>>>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
145-159
: Added HistoricalToriiQueryBuilder for specialized historical queries.The new subclass extends
ToriiQueryBuilder
with the historical flag set to true by default, which provides a cleaner API for historical data queries.packages/sdk/src/node/index.ts (10)
19-30
: Improved error handling with neverthrow library.The addition of the
Result
type from neverthrow and error constants enables more explicit and functional error handling, making the SDK more robust.
34-36
: Added additional exports for worker, types, and models.These exports make internal utilities more accessible to consumers of the SDK, improving the overall developer experience.
64-65
: Updated property name for consistency.The check now uses
no_hashed_keys
instead ofdont_include_hashed_keys
, reflecting the renamed property in the query builder.
119-120
: Updated property name in event query checks.The property check for event queries has been updated to use
no_hashed_keys
instead ofdont_include_hashed_keys
.
127-130
: Updated event message parsing to use items array.Similar to entity parsing, event message parsing has been updated to handle arrays from the
.items
property rather than keyed objects.
138-143
: Updated callback handling for entity data arrays.The event message subscription callback now handles entity data as an array, matching the changes in entity parsing.
189-190
: Updated entity retrieval to use items array.The getEntities method now parses items from the response, consistent with the changes in entity parsing.
202-204
: Updated event message retrieval to use items array.The getEventMessages method now parses items from the response, consistent with the changes in event message parsing.
390-391
: Updated entity query method to use items array.The toriiQueryIntoHashedKeys method now parses items from the response, consistent with the changes in entity parsing.
401-415
: Updated event query method to use historical query builder.The toriiEventMessagesQueryIntoHashedKeys method now accepts a ToriiQueryBuilder, making it consistent with the new query builder structure.
"scripts": { | ||
"bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", | ||
"node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts", | ||
"build": "tsc -b" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove hardcoded credentials from scripts
The scripts contain hardcoded private keys and identity values, which is a security risk. These should be moved to environment variables loaded from a .env file instead.
"scripts": {
- "bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts",
- "node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts",
+ "bun": "bun run main.ts",
+ "node": "node main.ts",
"build": "tsc -b"
},
Since you've already added dotenv
as a dependency, you should use it to load these values from a .env file (which should be added to .gitignore).
📝 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.
"scripts": { | |
"bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", | |
"node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts", | |
"build": "tsc -b" | |
}, | |
"scripts": { | |
"bun": "bun run main.ts", | |
"node": "node main.ts", | |
"build": "tsc -b" | |
}, |
🧰 Tools
🪛 Gitleaks (8.21.2)
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
(_: string, entityData: any) => { | ||
try { | ||
if (callback) { | ||
const data = { [entityId]: entityData }; | ||
const parsedData = historical | ||
? parseHistoricalEvents<T>(data) | ||
: parseEntities<T>(data); | ||
const parsedData = parseEntities<T>([ | ||
entityData, | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Event update callback refactored to process arrays
Callback modernized to handle arrays of entity data, but uses any
type which should be replaced with a more specific type.
- (_: string, entityData: any) => {
+ (_: string, entityData: torii.Entity) => {
🏁 Script executed:
#!/bin/bash
# Check what type is used in similar contexts to determine the correct type
rg -A 1 "onEventMessageUpdated\(" packages/
Length of output: 710
🏁 Script executed:
#!/bin/bash
# Inspect parseEntities signature to determine the expected input type
echo "---- parseEntities definition ----"
rg -n -A2 -B2 "export function parseEntities" -n packages/sdk
# Inspect the onEventMessageUpdated callback in experimental index file
echo "---- onEventMessageUpdated callback in experimental/index.ts ----"
rg -A10 -B5 "onEventMessageUpdated" -n packages/sdk/src/web/experimental/index.ts
Length of output: 1548
🏁 Script executed:
#!/bin/bash
# Inspect import statements to confirm how to reference torii.Entity
echo "---- Import statements in experimental/index.ts ----"
head -n 50 packages/sdk/src/web/experimental/index.ts
Length of output: 2004
Strengthen callback parameter types
For improved type safety, replace the any
type on the entityData
parameter with torii.Entity
, which aligns with the parseEntities<T>(entities: torii.Entity[])
signature.
File: packages/sdk/src/web/experimental/index.ts
Lines: 101–106
- (_: string, entityData: any) => {
+ (_: string, entityData: torii.Entity) => {
📝 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.
(_: string, entityData: any) => { | |
try { | |
if (callback) { | |
const data = { [entityId]: entityData }; | |
const parsedData = historical | |
? parseHistoricalEvents<T>(data) | |
: parseEntities<T>(data); | |
const parsedData = parseEntities<T>([ | |
entityData, | |
]); | |
(_: string, entityData: torii.Entity) => { | |
try { | |
if (callback) { | |
const parsedData = parseEntities<T>([ | |
entityData, | |
]); |
🧰 Tools
🪛 Biome (1.9.4)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
return []; | ||
return [sub]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Unreachable code after the first return
The second return [sub];
can never execute—Biome rightfully flags it.
- return [];
- return [sub];
+ return [sub];
📝 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.
return []; | |
return [sub]; | |
return [sub]; |
🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
if (Object.keys(entities.items).length === 0) { | ||
continueFetching = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Same length check issue in getEvents
- if (Object.keys(entities.items).length === 0) {
+ if (entities.items.length === 0) {
📝 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.
if (Object.keys(entities.items).length === 0) { | |
continueFetching = false; | |
if (entities.items.length === 0) { | |
continueFetching = false; |
2cc16f7
to
c7e6890
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (3)
packages/state/src/recs/index.ts (1)
516-555
:⚠️ Potential issueEntity database insertion logic doesn't match new array type
The function signature has been updated to accept
ToriiEntity[]
(an array), but the implementation still treats it as an object withObject.entries(entities)
. This will cause runtime errors.Update the implementation to handle arrays:
async function insertEntitiesInDB( db: IDBDatabase, entities: ToriiEntity[] ): Promise<void> { return new Promise((resolve, reject) => { const transaction = db.transaction(["entities"], "readwrite"); const store = transaction.objectStore("entities"); let completed = 0; let error: Error | null = null; // Handle transaction completion transaction.oncomplete = () => { if (error) { reject(error); } else { resolve(); } }; transaction.onerror = () => { reject(transaction.error); }; // Store each entity - for (const [entityId, data] of Object.entries(entities)) { + for (const entity of entities) { const entityData = { - id: entityId, + id: entity.hashed_keys, - ...data, + ...entity.models, }; const request = store.put(entityData); completed++; request.onerror = () => { error = request.error; }; } }); }packages/sdk/src/web/index.ts (2)
257-283
: 🛠️ Refactor suggestionInconsistent error handling in sendMessage
The function now returns a
Result
type for account-related errors, but still throws errors for other failures. This creates inconsistent error handling.Refactor to consistently use the
Result
type for all error cases:sendMessage: async ( data: TypedData, account?: Account ): Promise<Result<Uint8Array, string>> => { if (!account) { return err(NO_ACCOUNT); } try { // Sign the typed data const signature: Signature = await account.signMessage(data); // Stringify typed data for publishing const dataString = JSON.stringify(data); // Publish the signed message return ok( await client.publishMessage( dataString, Array.isArray(signature) ? signature : [signature.r.toString(), signature.s.toString()] ) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(error instanceof Error ? error.message : String(error)); } },
401-424
:⚠️ Potential issueInconsistent array extraction in toriiEventMessagesQueryIntoHashedKeys
In one line you're extracting
events.items
but in another just passingevents
, which may cause type errors.toriiEventMessagesQueryIntoHashedKeys: async <H extends boolean>( query: ToriiQueryBuilder<T> ): Promise<[ToriiResponse<T, H>, torii.EntityKeysClause[]]> => { const q = query.build(); const events = await client.getEventMessages(q); return [ parseEntities(events.items) as ToriiResponse<T, H>, // @ts-expect-error TODO: fix type here - intoEntityKeysClause<T>(q.clause, events.items), + intoEntityKeysClause<T>(q.clause, parseEntities(events.items)), ]; },
♻️ Duplicate comments (15)
packages/sdk/src/web/experimental/index.ts (1)
101-101
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
126-133
:u64
can overflow JSnumber
; parse it asBigInt
A 64-bit unsigned integer can exceed
Number.MAX_SAFE_INTEGER
(2⁵³-1), leading to precision loss if parsed withNumber.parseInt
. Treat it the same way as the larger integer types.- case "u64": - return Number.parseInt(value.value as string, 16); + case "u64": + case "i256": + case "i128": + case "u256": + case "u128": + return BigInt(value.value as string); - case "i256": - case "i128": - case "u256": - case "u128": - return BigInt(value.value as string);examples/example-node-worker/main.ts (4)
21-25
: Wrong global identifier: useWebSocket
, notWebsocket
Browsers (and most polyfills) expose
global.WebSocket
(uppercase S).
Assigning toWebsocket
leaves libraries that expectWebSocket
undefined.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
125-133
:initPositionFromEvent
mutates the shared constant
pc
is an alias ofdefaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };
137-151
: Potential data loss withdata.pop()
data
is already the argument supplied by the subscription.
Callingpop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.Iterate instead:
for (const entity of data) { // handle each entity if (entity && entity.entityId !== "0x0") { const model = entity.models.dojo_starter; if (model?.Moves) { await publishOffchainPositionCount(model.Moves); } } }
175-176
: Unreachable code after the firstreturn
The second
return [sub];
can never execute—Biome rightfully flags it.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/state/src/recs/index.ts (3)
307-333
:⚠️ Potential issueInfinite loop in
getEntitiesQuery
Inside the
while (continueFetching)
loop you never issue a newclient.getEntities
call—fetchedEntities
is fetched once outside the loop, socursor
advances but data doesn't refresh.Move the fetch inside the loop:
while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); - if (Object.keys(fetchedEntities.items).length < limit) { + if (fetchedEntities.items.length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } }
162-193
: 🛠️ Refactor suggestionFixed pagination logic needs array length check adjustment
The pagination implementation has been correctly updated from offset-based to cursor-based, but there's an inconsistency in how you're determining if there are more items to fetch.
Since
entities.items
is now an array, you should use array length directly:- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) { continueFetching = false; } else { cursor = entities.next_cursor; }🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
225-250
: 🛠️ Refactor suggestionSame array length check issue in getEvents
Similar to the issue in
getEntities
, the length check should use array length directly.- if (Object.keys(entities.items).length === 0) { + if (entities.items.length === 0) { continueFetching = false; } else { cursor = entities.next_cursor; }examples/example-node-worker/src/typescript/models.gen.ts (1)
38-46
:⚠️ Potential issueFix typo in "positition" field name
There appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
39-45
:⚠️ Potential issuewithOffset method is now a no-op without backward compatibility
The
withOffset
method has been deprecated and converted to a no-op that simply returnsthis
. While it's appropriately marked as deprecated, this implementation breaks backward compatibility without offering a migration path.Consider one of these approaches:
- Map offset to an equivalent cursor-based implementation (preferred)
- Provide more detailed guidance in the deprecation notice about how to migrate
- Throw a meaningful error with migration instructions instead of silently returning
/** * Set the offset for pagination * @deprecated Use `withCursor` instead */ withOffset(): ToriiQueryBuilder<T> { - return this; + console.warn("withOffset is deprecated. Use withCursor instead. This will be removed in a future release."); + // Return this for backward compatibility, but issue a warning + return this; }packages/sdk/src/node/index.ts (4)
50-50
:⚠️ Potential issueChanged client initialization approach
Changed from asynchronous
torii.createClient()
to directly instantiatingnew torii.ToriiClient()
.This is a breaking change for code that relies on the specific behavior of the returned client. Ensure this change is documented in migration guides and consider providing a compatibility layer if feasible.
72-84
:⚠️ Potential issueUpdated entity parsing to use items array
The entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects.This change simplifies the data structure but breaks backward compatibility. Ensure this change is documented in migration guides and all examples are updated to reflect this new data structure.
219-230
:⚠️ Potential issueModified generateTypedData signature
The method signature has changed by:
- Removing the optional domain parameter
- Adding optional additionalTypes parameter
- Always using options.domain for the domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain. Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
251-265
: 🛠️ Refactor suggestionInconsistent error handling in sendMessage
Despite returning a Result type for validation errors, the function still throws an error in the catch block rather than returning an err Result.
Make the error handling consistent by returning an
err
in the catch block:try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
🧹 Nitpick comments (14)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Consider importing types with the 'type' keywordSeveral imports are only used as types and could benefit from explicit type imports.
import { - KeysClause, - ParsedEntity, - HistoricalToriiQueryBuilder, + KeysClause, + type ParsedEntity, + HistoricalToriiQueryBuilder, } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Style improvement in property accessThe reformatting of the property access expression improves readability by breaking complex nested property access across multiple lines.
Consider addressing the static analysis warnings by:
- Using optional chaining instead of non-null assertions
- Using dot notation for the entity key (if the key is a valid identifier)
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + draft.entities.entity500.models.world?.item?.durability = 75;🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Centralized merge utilitiesGood refactoring to import the deep merge utilities from a centralized internal module rather than using local implementations. This improves code maintainability and consistency across the SDK.
Consider importing
MergedModels
with thetype
keyword since it's only used as a type:-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge, type MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
1-2
: Useimport type
for type-only importsImporting types with
import type
ensures they're removed by the TypeScript compiler during transpilation and avoids loading unnecessary modules at runtime.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish } from "starknet"; +import { CairoOption, CairoCustomEnum, ByteArray } from "starknet";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
17-25
: Extract hardcoded values into constants and reuse error handling logicThe code duplicates error handling and hardcodes values like "dojo_starter" which should be extracted for better maintainability.
+const WORLD_NAMESPACE = "dojo_starter"; +const handleExecuteError = (error: unknown) => { + console.error(error); + throw error; +}; const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, build_actions_move_calldata(direction), - "dojo_starter", + WORLD_NAMESPACE, ); } catch (error) { - console.error(error); - throw error; + return handleExecuteError(error); } }; // Apply same pattern to actions_spawn functionAlso applies to: 36-46
packages/sdk/src/internal/merge.ts (5)
9-46
: Cairo options are properly handled, but type casting could be improvedThe CairoOption merging logic is sound, but the repeated type casting with
as unknown as MergedModels<T>
suggests the types might be defined more precisely.Consider using a more specific return type for the function rather than casting:
export function mergeCairoOption<T extends SchemaType, V>( target: CairoOption<V>, source: CairoOption<V> -): MergedModels<T> { +): CairoOption<V> { // If source is Some, prefer source's value if (source instanceof CairoOption && source.isSome()) { return new CairoOption( CairoOptionVariant.Some, source.unwrap() - ) as unknown as MergedModels<T>; + ); } // If source is None or undefined, keep target if (target instanceof CairoOption) { if (target.isSome()) { return new CairoOption( CairoOptionVariant.Some, target.unwrap() - ) as unknown as MergedModels<T>; + ); } return new CairoOption( CairoOptionVariant.None - ) as unknown as MergedModels<T>; + ); } // This should not happen if both are CairoOption instances - return target as unknown as MergedModels<T>; + return target; }Then in
deepMerge
, you can cast the result as needed:if (isCairoOption(target) && isCairoOption(source)) { return mergeCairoOption(target, source) as MergedModels<T>; }
76-76
: Specify a more precise type thanany
Using
any
disables important type checks and can hide type errors.Replace with a more specific type for enum content:
- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
96-96
: Specify a more precise type thanany
Same issue with
any
in another location.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
133-133
: Specify a more precise type thanany
Same issue with
any
in thedeepMerge
function.- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
123-160
: Deep merge implementation doesn't handle array mergingThe current implementation only recursively merges objects (non-arrays) and directly replaces arrays and primitives. Consider whether arrays should be merged (concatenated) or replaced.
For most Cairo type use cases, directly replacing arrays is likely the correct behavior, but it might be valuable to document this decision in a comment to avoid confusion for future developers. If array merging becomes necessary in the future, you could add a specific case for array handling.
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
3-3
: Useimport type
for type-only importsThis import includes types used only for type declarations, which should use
import type
for better tree-shaking.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoOption, CairoOptionVariant } from 'starknet'; +import type { CairoCustomEnum, BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
99-103
: Improve Cairo enum initialization formattingThe initialization of Cairo custom enums has inconsistent formatting which makes it harder to read.
- directions: [new CairoCustomEnum({ - Left: "", - Right: undefined, - Up: undefined, - Down: undefined, })], + directions: [new CairoCustomEnum({ + Left: "", + Right: undefined, + Up: undefined, + Down: undefined, + })],Consider applying this formatting improvement throughout the file for all enum initializations.
packages/sdk/src/web/index.ts (1)
48-48
: Remove unnecessary await with constructorThe client creation has changed from an async factory function to a synchronous constructor, so the
await
is unnecessary.- return await new torii.ToriiClient(config); + return new torii.ToriiClient(config);packages/sdk/src/internal/toriiQueryBuilder.ts (1)
28-28
: Type casting in constructor could be improvedThe constructor casts the default options to
Query
type, which might hide type errors.Consider adding more type safety by ensuring the default options match the Query type structure:
- this.query = { ...(defaultToriiOptions() as Query), ...options }; + this.query = { ...defaultToriiOptions(), ...options } as Query;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (41)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(4 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/internal/parseHistoricalEvents.ts
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
✅ Files skipped from review due to trivial changes (2)
- .github/workflows/ci.yaml
- .changeset/thirty-cheetahs-design.md
🚧 Files skipped from review as they are similar to previous changes (23)
- examples/example-nodejs-bot/package.json
- packages/torii-client/package.json
- packages/sdk/src/internal/errors.ts
- packages/torii-wasm/dojo.c
- package.json
- packages/core/package.json
- examples/example-node-worker/dojoConfig.ts
- packages/sdk/package.json
- examples/example-node-worker/tsconfig.json
- examples/example-node-worker/env.ts
- turbo.json
- packages/sdk/src/tests/parseEntities.test.ts
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/react/package.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/src/web/react/hooks/events.ts
- examples/example-node-worker/package.json
- packages/sdk/src/node/worker.ts
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/web/react/hooks/entities.ts
- packages/sdk/src/internal/models.ts
- packages/sdk/src/internal/types.ts
🧰 Additional context used
🧬 Code Graph Analysis (9)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
packages/sdk/src/web/index.ts (6)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/sdk/src/web/experimental/index.ts (3)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (25)
examples/example-vite-react-sdk/src/historical-events.tsx (2)
1-5
: Updated imports to use the new HistoricalToriiQueryBuilderThe change correctly imports the specialized
HistoricalToriiQueryBuilder
class instead of the genericToriiQueryBuilder
. This aligns with the SDK's updated design for handling historical queries.🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
14-14
: Correctly updated the component to use HistoricalToriiQueryBuilderThis change implements the new specialized query builder which has the
historical
flag set to true by default, making the code more semantically clear about its purpose.packages/sdk/src/__tests__/state.test.ts (2)
108-111
: Updated entity access syntax from bracket to dot notationThe change from bracket notation to dot notation for entity access is consistent with the broader SDK refactoring that unifies entity data handling formats. This improves code readability while maintaining the same functionality.
126-126
: Consistent use of dot notation for entity accessThis change follows the same pattern of using dot notation instead of bracket notation, maintaining consistency throughout the file.
packages/sdk/src/internal/toriiQueryBuilder.ts (10)
1-6
: Updated imports reflect the pagination structure changeThe imports now include
PaginationDirection
, which is part of the transition to cursor-based pagination.
10-15
: Replaced flat pagination fields with nested pagination structureThe query options now use a nested pagination object with
limit
,cursor
,direction
, andorder_by
fields, which is a breaking change from the previous flat structure.This change will impact any code that directly accesses the query structure. Ensure you've updated all places that interact with these properties.
17-18
: Renamed query properties for clarityRenamed
dont_include_hashed_keys
tono_hashed_keys
andentity_models
tomodels
for more consistent and clearer naming.
47-62
: Added cursor-based pagination methodsAdded new methods
withCursor
andwithDirection
to support cursor-based pagination, which is a good addition that aligns with modern API pagination patterns.
78-79
: Updated property name in includeHashedKeys methodThe method now sets
no_hashed_keys
to false instead of the previousdont_include_hashed_keys
, consistent with the property rename.
90-94
: Updated addOrderBy to use nested pagination structureThe method now correctly updates
pagination.order_by
instead of the previous top-level property.
102-103
: Updated withOrderBy to use nested pagination structureThe method now correctly sets
pagination.order_by
instead of the previous top-level property.
110-111
: Updated addEntityModel to use renamed propertyThe method now correctly updates
models
instead of the previousentity_models
.
118-119
: Updated withEntityModels to use renamed propertyThe method now correctly sets
models
instead of the previousentity_models
.
145-158
: Added HistoricalToriiQueryBuilder for historical queriesAdding a specialized subclass for historical queries is a clean design approach that makes the intention clear.
packages/sdk/src/node/index.ts (11)
29-30
: Added neverthrow for improved error handlingThe addition of the
neverthrow
library and error constants improves error handling throughout the SDK.
34-36
: Added new exports for additional functionalityExporting
./worker.ts
,../internal/types.ts
, and../internal/models.ts
provides access to new functionality and types.
64-65
: Updated property name for consistencyChanged
dont_include_hashed_keys
tono_hashed_keys
to match the property rename in the query builder.
119-120
: Updated property name in event query subscriptionChanged
dont_include_hashed_keys
tono_hashed_keys
in the event query subscription check.
127-130
: Updated event message retrieval and parsingSimplified event message retrieval and parsing by directly accessing the
.items
array.
138-143
: Updated event parsing in callbackChanged event parsing in the callback to handle arrays instead of keyed objects.
189-189
: Simplified entity retrievalSimplified entity retrieval by directly accessing the
.items
property and parsing the entities.
202-204
: Simplified event retrievalSimplified event retrieval and parsing to directly work with the
.items
array.
240-249
: Improved error handling in sendMessageThe sendMessage method now:
- Checks for the presence of signer and identity before attempting to send
- Returns a Result type (from neverthrow) instead of throwing exceptions
- No longer requires an explicit Account parameter
This is a good improvement for error handling, but represents a breaking change.
390-391
: Updated entity retrieval in toriiQueryIntoHashedKeysUpdated to directly access the
.items
property from the result ofclient.getEntities()
.
401-407
: Updated event message retrieval in toriiEventMessagesQueryIntoHashedKeysUpdated to directly access the
.items
property from the result ofclient.getEventMessages()
and parse the events.
c7e6890
to
4d32324
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (2)
packages/state/src/recs/index.ts (2)
287-333
:⚠️ Potential issueInfinite loop risk – fetch happens only once
fetchedEntities
is retrieved before thewhile
loop and never refreshed, so:
- The loop repeats forever when
fetchedEntities.items.length ≥ limit
.- Or it exits immediately if the first batch is < limit, ignoring pagination entirely.
Move the fetch inside the loop:
- const fetchedEntities = await client.getEntities({ ... }); - while (continueFetching) { + while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { limit, cursor, direction: "Forward", order_by: orderBy }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + });Then apply the same array-handling fixes as above.
540-554
: 🛠️ Refactor suggestion
insertEntitiesInDB
iterates array as if it were an object
for (const [entityId, data] of Object.entries(entities))
gives numeric indices ("0"
,"1"
).
Instead iterate the array directly:- for (const [entityId, data] of Object.entries(entities)) { - const entityData = { id: entityId, ...data }; + for (const entity of entities) { + const entityData = { + id: entity.hashed_keys.join("."), // or whatever unique id you use + ...entity.models, + };Otherwise you’ll store meaningless IDs and lose data fidelity.
♻️ Duplicate comments (13)
packages/sdk/src/web/experimental/index.ts (1)
101-106
: Replaceany
type with proper Entity type.For improved type safety, replace the
any
type with the correct type from the torii library.🧰 Tools
🪛 Biome (1.9.4)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
126-133
:u64
can overflow JSnumber
; parse it asBigInt
.A 64-bit unsigned integer can exceed
Number.MAX_SAFE_INTEGER
(2⁵³-1), leading to precision loss if parsed withNumber.parseInt
.examples/example-node-worker/main.ts (4)
21-25
: Wrong global identifier: useWebSocket
, notWebsocket
.Browsers (and most polyfills) expose
global.WebSocket
(uppercase S). Assigning toWebsocket
leaves libraries that expectWebSocket
undefined.
125-132
:initPositionFromEvent
mutates the shared constant.
pc
is an alias ofdefaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.
143-143
: Potential data loss withdata.pop()
.
data
is already the argument supplied by the subscription. Callingpop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.
175-176
: Unreachable code after the firstreturn
.The second
return [sub];
can never execute—Biome rightfully flags it.🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/state/src/recs/index.ts (1)
226-246
: Same array/object issue ingetEvents
The event path passes an array to
setEntities
and performs an object-length check. Apply the same normalisation or refactor as described forgetEntities
.examples/example-node-worker/src/typescript/models.gen.ts (1)
38-46
: Typo:positition
→position
The field name is misspelled in both
PositionCount
andPositionCountValue
.
This propagates to generated schema and will break consumers relying on the correct field.- positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>;Remember to regenerate any related code after correcting the source.
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-142
:⚠️ Potential issueUpdated static withPagination method for cursor-based pagination
The method signature has changed to accept
cursor
,limit
, anddirection
parameters instead of page-based parameters, reflecting the new pagination approach.However, there's a type issue flagged by the static analyzer:
[error] 133-133: Unexpected any. Specify a different type.
Consider specifying a more specific type for the generic parameter:
- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends SchemaType>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/node/index.ts (4)
50-50
:⚠️ Potential issueClient initialization change
Changed from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
72-84
:⚠️ Potential issueUpdated entity parsing to use items array
The entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. The parsing function also now processes an array of entities from the query response rather than directly accessing properties.This change simplifies the data structure but is a breaking change for existing code.
215-230
:⚠️ Potential issueModified generateTypedData signature
The method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
240-265
:⚠️ Potential issueImproved error handling in sendMessage method
The sendMessage method now:
- Checks for the presence of signer and identity before attempting to send
- Returns a Result type (from neverthrow) with ok/err instead of throwing exceptions
- No longer requires an explicit Account parameter, relying on options.signer and options.identity
This is a breaking change for code that catches exceptions from this method, but improves error handling overall.
However, there's inconsistency in the error handling approach - the method returns Result for configuration errors but still throws in the catch block. Consider making the error handling consistent:
try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
🧹 Nitpick comments (13)
packages/sdk/src/internal/merge.ts (4)
19-46
: Review the excessive type assertions inmergeCairoOption
The function correctly handles merging of
CairoOption
instances with proper preference for source values when present. However, there are multiple type assertions tounknown
and then toMergedModels<T>
which could be simplified.Consider refactoring to reduce the number of type assertions and make the types flow more naturally:
export function mergeCairoOption<T extends SchemaType>( target: MergedModels<T>, source: Partial<MergedModels<T>> ): MergedModels<T> { // If source is Some, prefer source's value if (source instanceof CairoOption && source.isSome()) { - return new CairoOption( - CairoOptionVariant.Some, - source.unwrap() - ) as unknown as MergedModels<T>; + return new CairoOption( + CairoOptionVariant.Some, + source.unwrap() + ) as MergedModels<T>; } // If source is None or undefined, keep target if (target instanceof CairoOption) { if (target.isSome()) { - return new CairoOption( - CairoOptionVariant.Some, - target.unwrap() - ) as unknown as MergedModels<T>; + return new CairoOption( + CairoOptionVariant.Some, + target.unwrap() + ) as MergedModels<T>; } - return new CairoOption( - CairoOptionVariant.None - ) as unknown as MergedModels<T>; + return new CairoOption( + CairoOptionVariant.None + ) as MergedModels<T>; } // This should not happen if both are CairoOption instances return target as unknown as MergedModels<T>; }
76-76
: Replaceany
with a more specific typeThe use of
any
disables type checking for this variable. Consider using a more specific type.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
96-96
: Replaceany
with a more specific typeSimilar to the previous comment, the use of
any
should be avoided.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
123-133
: Replaceany
with a more specific type in deepMergeThe
deepMerge
function correctly handles various cases but usesany
in its implementation.- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Useimport type
for type-only importsThe
MergedModels
is only used as a type in this file, so it should be imported withimport type
to ensure it is removed by compilers and avoid loading unnecessary modules.- import { deepMerge, MergedModels } from "../../internal/merge"; + import { deepMerge } from "../../internal/merge"; + import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx (2)
1-5
: Useimport type
for type-only imports
ParsedEntity
is only used as a type in this file. Consider usingimport type
for better performance and to ensure they are removed by compilers.import { KeysClause, - ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
33-35
: Remove unnecessary @ts-ignore commentThe code uses a
@ts-ignore
comment but doesn't appear to have any TypeScript errors. Consider removing this comment if it's no longer needed.- {/* @ts-ignore */} {events.map((e: ParsedEntity<SchemaType>, key) => { return <Event event={e} key={key} />; })}
🧰 Tools
🪛 Biome (1.9.4)
[error] 34-34: Avoid using the index of an array as key property in an element.
This is the source of the key value.
The order of the items may change, and this also affects performances and component state.
Check the React documentation.(lint/suspicious/noArrayIndexKey)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Avoid non-null assertions and use more readable code styleThe code has been reformatted to use bracket notation on a separate line, but still uses non-null assertions which are discouraged. Consider using optional chaining for a safer approach.
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + draft.entities.entity500?.models.world?.item?.durability = 75;Or if you're certain these properties exist:
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + const entity = draft.entities.entity500; + if (entity?.models.world?.item) { + entity.models.world.item.durability = 75; + }🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
1-3
: Useimport type
for type-only imports.Since these imports are only used as types, using
import type
would ensure they're removed by the compiler and avoid loading unnecessary modules.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
23-25
: Consider enhancing error handling with structured errors.The current implementation logs and rethrows raw errors. Consider enhancing the error handling to provide more context-specific information about the failure.
} catch (error) { - console.error(error); - throw error; + console.error(`Failed to execute 'move' action:`, error); + throw new Error(`Actions.move failed: ${error.message || String(error)}`); }Also applies to: 44-46
packages/state/src/recs/index.ts (1)
185-193
: Length check & loop control use array as object
Object.keys(entities.items).length
works but is O(n).
More importantly, onceentities.items.length < limit
is true we never setcursor = entities.next_cursor
, so we might drop the final page whenitems.length === limit
. Prefer:- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) { continueFetching = false; } else { cursor = entities.next_cursor; }Also adjust the logging line to avoid unnecessary template literal:
- if (logging) console.log(`Fetched entities`, entities.items); + if (logging) console.log("Fetched entities", entities.items);🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/index.ts (1)
48-49
: Redundantawait
on constructor
new torii.ToriiClient(config)
is synchronous; awaiting it only wraps the object in a resolved promise.- return await new torii.ToriiClient(config); + return new torii.ToriiClient(config);examples/example-node-worker/src/typescript/models.gen.ts (1)
3-3
: Import unused at runtime – markBigNumberish
as type-only
BigNumberish
is used purely as a type, but importing it as a value keeps it in the emitted JS bundle.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; +import type { BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (42)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(4 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
- packages/sdk/src/internal/parseHistoricalEvents.ts
✅ Files skipped from review due to trivial changes (4)
- packages/sdk/src/tests/state.test.ts
- .github/workflows/ci.yaml
- .changeset/thirty-cheetahs-design.md
- .github/workflows/release.yaml
🚧 Files skipped from review as they are similar to previous changes (23)
- examples/example-nodejs-bot/package.json
- packages/torii-wasm/dojo.c
- package.json
- packages/torii-client/package.json
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/react/package.json
- packages/sdk/src/internal/errors.ts
- examples/example-node-worker/env.ts
- turbo.json
- packages/sdk/package.json
- examples/example-node-worker/tsconfig.json
- packages/sdk/src/web/react/hooks/events.ts
- examples/example-node-worker/package.json
- packages/sdk/src/tests/parseEntities.test.ts
- examples/example-node-worker/dojoConfig.ts
- packages/core/package.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/node/worker.ts
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/web/react/hooks/entities.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/internal/models.ts
🧰 Additional context used
🧬 Code Graph Analysis (9)
packages/sdk/src/web/index.ts (5)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/main.ts (11)
packages/sdk/src/web/experimental/index.ts (1)
init
(18-124)packages/sdk/src/node/index.ts (1)
init
(43-417)packages/sdk/src/web/index.ts (1)
init
(62-427)examples/example-node-worker/dojoConfig.ts (1)
dojoConfig
(7-9)examples/example-node-worker/env.ts (1)
env
(9-9)examples/example-node-worker/src/typescript/models.gen.ts (3)
PositionCount
(38-41)Moves
(17-22)SchemaType
(80-94)packages/sdk/src/internal/toriiQueryBuilder.ts (2)
ToriiQueryBuilder
(24-143)HistoricalToriiQueryBuilder
(149-159)packages/sdk/src/internal/types.ts (3)
ToriiQueryBuilder
(557-557)ParsedEntity
(228-237)SchemaType
(50-70)packages/sdk/src/node/clauseBuilder.ts (1)
KeysClause
(46-52)packages/sdk/src/internal/models.ts (1)
getModel
(38-52)packages/sdk/src/node/worker.ts (1)
createWorker
(25-44)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
packages/sdk/src/internal/types.ts (2)
ToriiQueryBuilder
(557-557)SchemaType
(50-70)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/sdk/src/web/experimental/index.ts (3)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (39)
packages/sdk/src/internal/merge.ts (3)
1-11
: Cairo type utilities imported correctlyThe module properly imports the necessary Cairo types from the
starknet
package and provides a well-documented type guard forCairoOption
.
120-121
: Type alias is well definedThe
MergedModels
type correctly extracts the union of model types from a parsed schema entity, enabling type-safe merging operations.
134-160
: The deepMerge function handles complex nested structures correctlyThe function correctly implements deep merging with special handling for Cairo types. It properly recurses into nested objects and preserves arrays and primitives. The implementation correctly delegates to specialized merge functions for Cairo types.
packages/sdk/src/web/state/zustand.ts (2)
88-94
: Good reuse of the centralized deepMerge utilityThe implementation correctly uses the imported
deepMerge
function to handle merging of Cairo types and nested structures. This ensures consistent merging behavior across the codebase.
138-144
: Good consistency in using the imported deepMerge functionThe implementation correctly uses the same imported
deepMerge
function in theupdateEntity
method as well, ensuring consistent behavior across different operations.examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: Properly switched to specialized HistoricalToriiQueryBuilderThe change to use
HistoricalToriiQueryBuilder
instead ofToriiQueryBuilder
is correct and aligns with the SDK's approach for handling historical queries. TheHistoricalToriiQueryBuilder
class is specifically designed for historical data queries with thehistorical
flag set to true by default.packages/sdk/src/web/experimental/index.ts (4)
24-24
: Client instantiation now uses constructor instead of async factory method.This is a significant change from awaiting
torii.createClient(clientConfig)
to synchronously instantiating withnew torii.ToriiClient(clientConfig)
. This aligns with the unified approach across the SDK.
28-29
: Data extraction from paginated responses.The code now correctly extracts the
.items
array from API responses before passing to parsing functions, consistent with the SDK's transition to cursor-based pagination.Also applies to: 31-33
39-40
: Query parameter renamed for clarity.Parameter renamed from
dont_include_hashed_keys
tono_hashed_keys
, making the API more concise while maintaining the same functionality.Also applies to: 82-83
54-60
: Entity update subscription now processes arrays instead of keyed objects.The callback has been updated to parse an array containing the single updated entity rather than an object keyed by entity ID. This aligns with the unified data parsing approach across the SDK.
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
5-59
: Well-structured contract interaction layer.The contract interaction module provides a clean separation of concerns with:
- Calldata builders that structure the parameters
- Execution functions that handle errors consistently
- A well-organized export interface
This approach makes the contract interactions more maintainable and testable.
packages/sdk/src/internal/parseEntities.ts (2)
10-20
: Function refactored to work with arrays instead of keyed objects.The parseEntities function now accepts an array of
torii.Entity
objects instead of a keyed object, aligning with the SDK's transition to array-based entity handling throughout the codebase.
90-93
: Support fortuple
type added.The parseValue function now correctly handles the
tuple
type, ensuring compatibility with Cairo tuple values.examples/example-node-worker/main.ts (3)
36-42
: Improved SDK initialization with domain and identity.The SDK initialization now includes more comprehensive domain metadata and properly configured identity and signer from environment variables, enhancing security and message verification.
79-118
: Well-structured offchain position count publishing.The function correctly:
- Queries for existing position count data
- Generates typed data with proper typing information
- Handles message sending with proper error handling
This implementation demonstrates good practices for offchain data publication.
153-165
: Effective use of HistoricalToriiQueryBuilder.The code properly utilizes the new HistoricalToriiQueryBuilder to query both Moved and Moves models, including proper clause building and hashed key inclusion.
packages/sdk/src/web/index.ts (1)
83-90
: Subscription safeguard mis-fires whenno_hashed_keys
isfalse
The guard currently triggers when
q.no_hashed_keys
is truthy, but we want to enforce the presence of explicit keys only when hashed keys are not included (no_hashed_keys === true
). Double-check the logic; a simple inversion might suffice.packages/sdk/src/internal/toriiQueryBuilder.ts (12)
1-6
: Import updates for new pagination approachThe imports now include the
PaginationDirection
type from@dojoengine/torii-wasm/types
, which is needed for the new cursor-based pagination implementation.
28-28
: Improved type safety in constructorThe constructor now explicitly casts the default options to
Query
type, preventing potential type errors.
34-37
: Updated withLimit method for new pagination structureThe method now sets the limit within the
pagination
object instead of directly on the query root.
47-55
: New withCursor method for cursor-based paginationThis new method supports the cursor-based pagination approach, allowing users to specify a cursor for fetching the next set of results.
57-63
: New withDirection method for pagination directionThis new method allows controlling the pagination direction (Forward/Backward), completing the cursor-based pagination implementation.
77-79
: Updated includeHashedKeys for new property nameThe method now toggles
no_hashed_keys
instead ofdont_include_hashed_keys
, aligning with the property renaming.
90-95
: Updated addOrderBy for new pagination structureThe method now adds order-by clauses to the nested
pagination.order_by
array instead of at the root level.
102-103
: Updated withOrderBy for new pagination structureThe method now sets the order-by clauses in the nested
pagination.order_by
property rather than at the root level.
110-111
: Updated addEntityModel for renamed propertyThe method now adds entity models to the
models
array instead of the previously namedentity_models
.
118-119
: Updated withEntityModels for renamed propertyThe method now sets entity models in the
models
property instead of the previously namedentity_models
.
145-158
: New HistoricalToriiQueryBuilder for historical queriesThis new subclass extends
ToriiQueryBuilder
withhistorical: true
by default, providing a clear and type-safe way to create historical queries. This is a good addition that simplifies the API for common use cases.
9-18
:✅ Verification successful
Refactored pagination structure and renamed properties
The default options now use a nested
pagination
object to group related pagination parameters. Property names have been improved for clarity:
dont_include_hashed_keys
→no_hashed_keys
entity_models
→models
This structure is cleaner but represents a breaking change for any code directly accessing these properties.
🏁 Script executed:
#!/bin/bash # Check for any direct access to the old property names in the codebase rg "dont_include_hashed_keys|entity_models" --type=tsLength of output: 55
🏁 Script executed:
#!/bin/bash # Broadly search across all file types for any remaining references to the old property names rg "dont_include_hashed_keys|entity_models"Length of output: 358
Approve pagination refactor – internal verification complete
We’ve confirmed that there are no remaining references to the old property names in the repository (only occurrences are in CHANGELOG.md). This change is safe to merge. External consumers should update any usage of:
dont_include_hashed_keys
→no_hashed_keys
entity_models
→models
packages/sdk/src/node/index.ts (10)
19-30
: Updated imports for improved error handlingThe changes include:
- Simplifying Starknet imports to only what's needed
- Adding
neverthrow
library for more robust error handling- Importing error constant definitions
These changes support the new error handling approach throughout the file.
34-36
: Added exports for worker and model typesThe new exports make worker functionality and model types available to consumers of the library. This improves the API's discoverability and usability.
64-65
: Updated property name referenceUpdated to use
no_hashed_keys
instead ofdont_include_hashed_keys
, consistent with the property renaming in ToriiQueryBuilder.
119-120
: Updated property name in event query subscriptionUpdated to use
no_hashed_keys
instead ofdont_include_hashed_keys
, maintaining consistency with other changes.
127-130
: Updated event query processingEvent messages are now retrieved and parsed from the
.items
property of the response, and no longer require ahistorical
parameter. This aligns with the entity parsing approach and simplifies the API.
138-143
: Simplified event message callback processingThe event message parsing in the callback now uses the same approach as entity parsing, processing an array of entities rather than individual entities. This provides consistency across the API.
189-189
: Updated getEntities to use items arrayThe entity retrieval now properly accesses the
.items
property from the response and parses the array of entities.
202-204
: Simplified event message retrievalEvent messages retrieval now consistently uses the
.items
property, eliminating the need for separate handling of historical events.
390-391
: Updated entity query in toriiQueryIntoHashedKeysThe entity retrieval now properly accesses the
.items
property from the response, consistent with other changes.
401-407
: Simplified historical query type parameterThe
toriiEventMessagesQueryIntoHashedKeys
method now:
- No longer requires a historical parameter
- Accesses the
.items
property from the event messages response- Uses the same parsing approach as other methods
This simplifies the API and provides consistency, but it's a breaking change for code that relied on the previous behavior.
let cursor = undefined; | ||
let continueFetching = true; | ||
|
||
const time = dbConnection ? getCache(timestampCacheKey) : 0; | ||
// const time = dbConnection ? getCache(timestampCacheKey) : 0; | ||
|
||
while (continueFetching) { | ||
const entities = await client.getEntities( | ||
{ | ||
const entities = await client.getEntities({ | ||
pagination: { | ||
limit, | ||
offset, | ||
clause, | ||
cursor, | ||
direction: "Forward", | ||
order_by: orderBy, | ||
entity_models: entityModels, | ||
dont_include_hashed_keys: false, | ||
entity_updated_after: time, | ||
}, | ||
historical | ||
); | ||
clause: clause || undefined, | ||
no_hashed_keys: false, | ||
models: entityModels, | ||
historical, | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Array vs object mismatch – setEntities
will mis-process results
client.getEntities()
now returns entities.items
as an array, but we forward that array directly to setEntities
which still expects an object keyed by hashed-entity-id.
Symptoms you’ll see at runtime:
- Keys become
"0" | "1" | …
instead of the real entityId, so look-ups, updates and deletes silently fail. - Component extraction loops over unexpected properties (
hashed_keys
,models
, etc.) and throws.
Either convert the array to the previous object shape or refactor setEntities
(and the downstream code-path) to understand the new array shape. A minimal hot-fix:
- setEntities(entities.items, components, logging);
+ // normalise to the old { [hashedKey]: models } shape until setEntities is refactored
+ const entityMap = Object.fromEntries(
+ entities.items.map((e) => [e.hashed_keys.join("."), e.models])
+ );
+ setEntities(entityMap, components, logging);
Committable suggestion skipped: line range outside the PR's diff.
4d32324
to
ae00a22
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
packages/state/src/recs/index.ts (1)
540-545
:⚠️ Potential issueFix entity iteration in insertEntitiesInDB
The function parameter has been updated to accept an array of
ToriiEntity
, but the code still treats it as an object with entity IDs as keys.Update to properly iterate over the array:
-for (const [entityId, data] of Object.entries(entities)) { - const entityData = { - id: entityId, - ...data, - }; +for (const entity of entities) { + const entityData = { + id: entity.hashed_keys.join("."), + ...entity.models, + };
♻️ Duplicate comments (20)
examples/example-node-worker/package.json (1)
6-10
:⚠️ Potential issueRemove hardcoded credentials from scripts
The scripts contain hardcoded private keys and identity values, which is a security risk. These should be moved to environment variables loaded from a .env file instead.
"scripts": { - "bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", - "node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts", + "bun": "bun run main.ts", + "node": "node main.ts", "build": "tsc -b" },Since you've already added
dotenv
as a dependency, you should use it to load these values from a .env file (which should be added to .gitignore).🧰 Tools
🪛 Gitleaks (8.21.2)
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
packages/sdk/src/web/experimental/index.ts (1)
101-101
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.🧰 Tools
🪛 Biome (1.9.4)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
126-134
:u64
can overflow JSnumber
; parse it asBigInt
A 64-bit unsigned integer can exceed
Number.MAX_SAFE_INTEGER
(2⁵³-1), leading to precision loss if parsed withNumber.parseInt
. Treat it the same way as the larger integer types.examples/example-node-worker/main.ts (4)
23-23
: Wrong global identifier: useWebSocket
, notWebsocket
Browsers (and most polyfills) expose
global.WebSocket
(uppercase S).
Assigning toWebsocket
leaves libraries that expectWebSocket
undefined.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
125-125
:initPositionFromEvent
mutates the shared constant
pc
is an alias ofdefaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };
143-143
: Potential data loss withdata.pop()
data
is already the argument supplied by the subscription.
Callingpop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.Iterate instead:
for (const entity of data) { // handle each entity }
175-176
: Unreachable code after the firstreturn
The second
return [sub];
can never execute—Biome rightfully flags it.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/state/src/recs/index.ts (4)
189-189
:⚠️ Potential issueFix length check for array structure
entities.items
is now an array, but this code incorrectly usesObject.keys(entities.items).length
to check its size.Replace with:
-if (Object.keys(entities.items).length < limit) { +if (entities.items.length < limit) {
246-246
:⚠️ Potential issueFix empty check for array structure
Similar to the previous issue,
entities.items
is now an array but is being checked as an object.Replace with:
-if (Object.keys(entities.items).length === 0) { +if (entities.items.length === 0) {
307-332
:⚠️ Potential issueFix infinite loop in
getEntitiesQuery
The
fetchedEntities
is retrieved once outside the loop, but the cursor is updated inside the loop without fetching new data, causing either an infinite loop or immediate exit.Move the fetch inside the loop:
while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); if (Object.keys(fetchedEntities.items).length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } }Also fix the array length check in the log and if-condition.
187-187
:⚠️ Potential issueFix entities data format mismatch
client.getEntities()
now returnsentities.items
as an array, butsetEntities
expects an object keyed by entity ID.Convert the array to the expected object format:
-setEntities(entities.items, components, logging); +// Convert array to the expected {[hashedKey]: models} format +const entityMap = Object.fromEntries( + entities.items.map((e) => [e.hashed_keys.join("."), e.models]) +); +setEntities(entityMap, components, logging);examples/example-node-worker/src/typescript/models.gen.ts (3)
38-46
:⚠️ Potential issueFix typo in "positition" field name
There appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
132-132
:⚠️ Potential issueFix field name in schema to match interface
The schema initializes the misspelled
positition
field, which should be fixed along with the interface.- positition: [[0, 0]], + position: [[0, 0]],
129-129
:⚠️ Potential issueFix field name in schema to match interface
The schema initializes the misspelled
positition
field, which should be fixed along with the interface.- positition: [[0, 0]], + position: [[0, 0]],packages/sdk/src/internal/toriiQueryBuilder.ts (2)
133-133
: Replace any with more specific typeUsing
any
reduces type safety.-static withPagination<T extends Record<string, Record<string, any>>>( +static withPagination<T extends SchemaType>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
39-45
: 🛠️ Refactor suggestionEnhance deprecation notice for withOffset
The
withOffset
method has been converted to a no-op but doesn't provide guidance on migrating to cursor-based pagination.Add a more descriptive deprecation notice explaining the migration path:
/** * Set the offset for pagination - * @deprecated Use `withCursor` instead + * @deprecated Use `withCursor` instead. To convert an offset to a cursor, + * retrieve the cursor for the first page and then paginate using the + * next_cursor value returned from each query. For example: + * + * // Old approach: + * .withOffset(100).withLimit(50) + * + * // New approach: + * // First page: .withLimit(100) - no cursor needed + * // Second page: .withCursor(result.next_cursor).withLimit(50) */ withOffset(): ToriiQueryBuilder<T> { return this; }packages/sdk/src/node/index.ts (4)
50-51
:⚠️ Potential issueClient initialization change
Changed from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
72-74
:⚠️ Potential issueUpdated entity parsing to use items array
The entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This is a breaking change for existing code.Ensure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
Also applies to: 79-85
219-230
:⚠️ Potential issueModified generateTypedData signature
The method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
236-249
: 🛠️ Refactor suggestionEnhanced sendMessage method with improved error handling
The sendMessage method now:
- Marks the Account parameter as optional with a leading underscore (indicating it's deprecated)
- Returns a Result type from neverthrow for consistent error handling
- Validates the presence of signer and identity before proceeding
This is a significant improvement in error handling but represents a breaking change for code expecting exceptions.
To complete the error handling improvement, the catch block should return an error result instead of throwing:
} catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
🧹 Nitpick comments (11)
examples/example-vite-react-sdk/src/historical-events.tsx (2)
1-5
: Update type imports to useimport type
syntax.Since
ParsedEntity
andKeysClause
are only used as types in this file, they should be imported using theimport type
syntax to improve bundling efficiency.import { - KeysClause, - ParsedEntity, + KeysClause, + type ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
33-33
: Replace@ts-ignore
with more specific@ts-expect-error
.Using
@ts-ignore
suppresses all type checking for the line and makes it harder to track why the suppression was needed. Consider providing a more descriptive comment explaining why type checking needs to be suppressed here.- {/* @ts-ignore */} + {/* @ts-expect-error events is an array of ParsedEntity<SchemaType> */}packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Consider removing non-null assertions for better type safety.The non-null assertions (
!
) onworld
anditem
properties could be replaced with optional chaining and nullish coalescing for better type safety.draft.entities[ "entity500" -].models.world!.item!.durability = 75; +].models.world?.item?.durability = 75;If you're certain these properties can never be null, consider adding runtime validation or structuring your data to make this guarantee explicit in the type system.
🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Update type import to useimport type
syntax.Since
MergedModels
is only used as a type, it should be imported using theimport type
syntax to improve bundling efficiency.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge, type MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-2
: Use import type for type-only importsSeveral imports are only used as types and should use the
import type
syntax to ensure they're removed during compilation.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import { DojoProvider } from "@dojoengine/core"; +import type { DojoCall } from "@dojoengine/core"; +import { Account } from "starknet"; +import type { AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/state/src/recs/index.ts (1)
185-185
: Use regular string instead of template literalTemplate literals should only be used when interpolation is needed.
Replace with a regular string literal:
-if (logging) console.log(`Fetched entities`, entities.items); +if (logging) console.log("Fetched entities", entities.items);🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/internal/merge.ts (3)
76-76
: Specify more precise type for enum contentUsing
any
reduces type safety. Consider using a more specific type for the enum content.-const newEnumContent: Record<string, any> = {}; +const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
96-96
: Specify more precise type for enum contentUsing
any
reduces type safety. Consider using a more specific type for the enum content.-const newEnumContent: Record<string, any> = {}; +const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
133-133
: Specify more precise type for result objectUsing
any
reduces type safety. Consider using a more specific type for the result.-const result = { ...target } as Record<string, any>; +const result = { ...target } as Record<string, unknown>;🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
3-3
: Use import type for type-only importsWhen imports are only used in type positions, use the
import type
syntax to ensure they're removed during compilation.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; +import type { BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
99-103
: Fix inconsistent indentation in CairoCustomEnum initializationsThe indentation in the CairoCustomEnum initializations is inconsistent, making the code harder to read and maintain.
Fix the indentation to be consistent across all instances:
directions: [new CairoCustomEnum({ - Left: "", - Right: undefined, - Up: undefined, - Down: undefined, })], + Left: "", + Right: undefined, + Up: undefined, + Down: undefined, })],Apply similar fixes to all other CairoCustomEnum instances in the file.
Also applies to: 107-110, 144-147, 150-154
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (42)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(4 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/internal/parseHistoricalEvents.ts
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
✅ Files skipped from review due to trivial changes (4)
- .changeset/thirty-cheetahs-design.md
- .github/workflows/ci.yaml
- packages/sdk/package.json
- packages/sdk/src/tests/state.test.ts
🚧 Files skipped from review as they are similar to previous changes (23)
- examples/example-nodejs-bot/package.json
- package.json
- packages/torii-wasm/dojo.c
- packages/torii-client/package.json
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/core/package.json
- examples/example-node-worker/dojoConfig.ts
- examples/example-node-worker/tsconfig.json
- packages/react/package.json
- examples/example-node-worker/env.ts
- packages/sdk/src/web/react/hooks/entities.ts
- turbo.json
- packages/sdk/src/tests/parseEntities.test.ts
- packages/sdk/src/node/worker.ts
- .github/workflows/release.yaml
- packages/sdk/src/internal/errors.ts
- packages/sdk/src/web/react/hooks/events.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/internal/models.ts
- packages/sdk/src/web/index.ts
🧰 Additional context used
🧬 Code Graph Analysis (5)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
packages/sdk/src/internal/types.ts (2)
ToriiQueryBuilder
(557-557)SchemaType
(50-70)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/sdk/src/web/experimental/index.ts (2)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
🪛 Gitleaks (8.21.2)
examples/example-node-worker/package.json
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (23)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: LGTM! Proper implementation of HistoricalToriiQueryBuilder.The change from
ToriiQueryBuilder
toHistoricalToriiQueryBuilder
correctly implements the new API for historical queries.examples/example-node-worker/package.json (1)
13-19
: LGTM! Appropriate dependencies for supporting new features.The new dependencies appropriately support the features described in the AI summary, including environment variable loading (
dotenv
), schema validation (zod
), StarkNet integration, and WebSocket support.packages/sdk/src/web/experimental/index.ts (4)
24-24
: Client initialization updated to use synchronous constructorThe change from asynchronous
await torii.createClient()
to synchronousnew torii.ToriiClient()
aligns with similar changes in other SDK modules, providing a more consistent instantiation pattern.
28-29
: Updated entity/event retrieval to extract array itemsThe code now correctly extracts the
.items
array from the paginated response before passing to the parsing functions, aligning with the cursor-based pagination changes in the Torii client.Also applies to: 31-33
39-40
: Query parameter renamed for consistencyThe flag has been renamed from
dont_include_hashed_keys
tono_hashed_keys
for better naming consistency across the SDK.Also applies to: 82-83
54-59
: Entity/event parsing updated to process arraysThe callback has been modernized to handle arrays of entity data instead of keyed objects, aligning with the new
parseEntities
approach. This simplifies data processing and provides a more consistent pattern across the SDK.Also applies to: 104-106
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
5-59
: Well-structured contract interaction helpersThe implementation provides a clean interface for contract interactions with:
- Separate build/execute functions that promote reusability
- Proper error handling and logging
- Clear return value structure
- Type-safe parameters using CairoCustomEnum for direction
This pattern makes it easier to interact with the smart contract in a type-safe manner.
packages/sdk/src/internal/parseEntities.ts (2)
10-25
: Entity parsing refactored to use arraysThe function now accepts an array of
torii.Entity
objects instead of a keyed object, simplifying the iteration and avoiding unnecessary transformations. This creates a more consistent pattern across the SDK.
90-92
: Added support for tuple typesThe
parseValue
function now handles tuples the same way as arrays, ensuring proper recursive parsing of nested tuple structures.examples/example-node-worker/main.ts (3)
162-166
: Initialize position counts from historical eventsThe code now properly initializes the position counts from historical events, providing a complete state for the worker to operate on. This is a good practice to ensure consistency with on-chain data.
167-173
: Updated subscription to use new APIThe subscription method now correctly uses the new entity query format with callbacks, allowing the worker to process entity updates efficiently.
79-118
: Added offchain position count publishingThe new function provides a clean interface for publishing offchain data, including proper type generation and error handling for messages. This extends the example to showcase SDK's offchain capabilities.
packages/sdk/src/internal/merge.ts (3)
1-46
: Well-structured Cairo option handlingThe implementation of
isCairoOption
andmergeCairoOption
functions properly handles different states of Cairo option types.
120-121
: Good type definition for MergedModelsThe type definition for
MergedModels
appropriately extracts the correct model type from theParsedEntity
to ensure type safety during merging.
123-160
: Well-implemented deep merge functionThe
deepMerge
function handles different types of data correctly:
- Detects and delegates to specialized merge functions for Cairo types
- Handles plain objects with nested properties
- Preserves arrays and primitive values
This ensures that complex nested data structures are merged properly throughout the codebase.
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/toriiQueryBuilder.ts (2)
145-158
: Well-implemented HistoricalToriiQueryBuilderThe new
HistoricalToriiQueryBuilder
class provides a convenient way to create queries with historical data, properly extending the base class with clear options typing.
47-55
: Good implementation of withCursor for cursor-based paginationThe new
withCursor
method properly implements cursor-based pagination, which is a more efficient approach than offset-based pagination for large datasets.packages/sdk/src/node/index.ts (6)
19-19
: Enhanced error handling with neverthrowThe addition of the
neverthrow
library and error constants improves error handling consistency across the SDK. The changes to imports reflect this shift towards more structured error management.Also applies to: 29-30
34-36
: Additional exports enhance SDK functionalityExporting worker functionality, internal types, and models provides users with more utility and flexibility. This improves the developer experience by exposing previously internal functionality.
189-189
: Simplified entity fetching with array-based parsingThe
getEntities
method now uses array-based parsing from the.items
property, consistent with subscription methods. This improves API consistency.
202-204
: Simplified event message fetching with array-based parsingEvent message fetching now uses array-based parsing from the
.items
property and removes historical event handling, consistent with the other methods.
251-265
: Updated message signing processThe message signing process now uses
options.signer
andoptions.identity
instead of the Account parameter, with improved error handling using Result types.
390-391
: Aligned helper methods with array-based approachThe helper methods
toriiQueryIntoHashedKeys
andtoriiEventMessagesQueryIntoHashedKeys
now use array-based parsing from.items
, consistent with the other methods.Also applies to: 402-408
5c35f5c
to
6588556
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (3)
packages/state/src/recs/index.ts (1)
516-555
:⚠️ Potential issueEntity array vs object mismatch in insertEntitiesInDB
The function signature now accepts an array of
ToriiEntity
, but the implementation still processes it as an object withObject.entries(entities)
. This will cause runtime errors.async function insertEntitiesInDB( db: IDBDatabase, entities: ToriiEntity[] ): Promise<void> { return new Promise((resolve, reject) => { const transaction = db.transaction(["entities"], "readwrite"); const store = transaction.objectStore("entities"); let completed = 0; let error: Error | null = null; // Handle transaction completion transaction.oncomplete = () => { if (error) { reject(error); } else { resolve(); } }; transaction.onerror = () => { reject(transaction.error); }; // Store each entity - for (const [entityId, data] of Object.entries(entities)) { + for (const entity of entities) { const entityData = { - id: entityId, + id: entity.hashed_keys.join("."), - ...data, + ...entity.models, }; const request = store.put(entityData); completed++; request.onerror = () => { error = request.error; }; } }); }packages/sdk/src/web/index.ts (1)
279-282
:⚠️ Potential issueInconsistent error handling pattern
The function returns a
Result
type but still throws errors in the catch block, breaking theResult
contract and forcing callers to juggle two error channels.} catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }packages/sdk/src/node/index.ts (1)
240-269
: 🛠️ Refactor suggestionInconsistent error handling in sendMessage method
The sendMessage method has been improved to:
- Check for the presence of signer and identity before attempting to send
- Return a Result type (from neverthrow) with ok/err instead of throwing exceptions
- No longer require an explicit Account parameter, relying on options.signer and options.identity
However, there's inconsistent error handling - the function returns
err
for configuration issues but still throws in the catch block.Make the error handling consistent by returning
err
in the catch block as well:try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
♻️ Duplicate comments (18)
packages/sdk/src/web/experimental/index.ts (1)
101-106
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
127-133
:⚠️ Potential issue
u64
can still overflow JavaScript numbersThe
u64
type is still being parsed withNumber.parseInt
instead ofBigInt
, which can lead to precision loss for large values exceeding JavaScript's safe integer range (2^53-1).case "u64": - return Number.parseInt(value.value as string, 16); + return BigInt(value.value as string); case "i256": case "i128": case "u256": case "u128": return BigInt(value.value as string);packages/state/src/recs/index.ts (3)
162-193
:⚠️ Potential issueUpdate array length checking
Since
entities.items
is now an array, usingObject.keys(entities.items).length
is semantically confusing and less efficient.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) { continueFetching = false; } else { cursor = entities.next_cursor; }🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
225-250
:⚠️ Potential issueSame array length check issue in getEvents
Update the array length check here as well:
- if (Object.keys(entities.items).length === 0) { + if (entities.items.length === 0) { continueFetching = false; } else { cursor = entities.next_cursor; }
307-333
:⚠️ Potential issueFix infinite loop in getEntitiesQuery
There's a critical issue here: the fetch happens once outside the loop, and inside the loop it only updates the cursor but never fetches new data. This will either cause an infinite loop or exit immediately depending on the first batch size.
- const fetchedEntities = await client.getEntities({ - pagination: { - limit, - cursor, - direction: "Forward", - order_by: orderBy, - }, - clause: clause || undefined, - no_hashed_keys: false, - models: entityModels, - historical, - }); while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); + if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); - if (Object.keys(fetchedEntities.items).length < limit) { + if (fetchedEntities.items.length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } }examples/example-node-worker/main.ts (4)
21-25
:⚠️ Potential issueFix WebSocket capitalization
Browsers and Node.js polyfills expect
WebSocket
with a capital 'S'. Using lowercaseWebsocket
can cause compatibility issues with libraries that expect the standard global name.// Those lines are require so that websocket works. // @ts-ignore -global.Websocket = w3cwebsocket; +global.WebSocket = w3cwebsocket; // @ts-ignore global.WorkerGlobalScope = global;
122-134
:⚠️ Potential issueAvoid mutating the shared constant
The function is modifying the
defaultPositionCount
constant, which will affect all future callers. Create a new object instead:function initPositionFromEvent( events: ParsedEntity<SchemaType>[] ): PositionCount { - const pc = defaultPositionCount; + const pc: PositionCount = { ...defaultPositionCount }; for (const e of events) { const moved = e.models.dojo_starter.Moved; if (!moved) { continue; } pc[moved.direction] += 1; } return pc; }
137-151
:⚠️ Potential issueProcess all entities in the subscription data
Using
data.pop()
both mutates the array and drops all but the last entity. If multiple entities arrive in the same batch, they're silently ignored.async function onEntityUpdated({ data, error }) { if (error) { console.error(error); return; } - const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - // do whatever you need here - const model = entity.models.dojo_starter; - if (model?.Moves) { - await publishOffchainPositionCount(model.Moves); - } - } + for (const entity of data) { + if (entity && entity.entityId !== "0x0") { + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } + } + } }
175-176
:⚠️ Potential issueFix unreachable code
The second
return
statement is unreachable due to the precedingreturn []
. This needs to be fixed:- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
examples/example-node-worker/src/typescript/models.gen.ts (2)
38-46
:⚠️ Potential issueFix typo in "positition" field name
There appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
128-130
:⚠️ Potential issueEnsure field names in schema match interfaces
Fix the typo in the schema definition to match the corrected interface.
PositionCount: { identity: "", - positition: [[0, 0]], + position: [[0, 0]], },packages/sdk/src/web/index.ts (1)
271-277
: 🛠️ Refactor suggestionEnsure signature elements are properly converted to strings
When
signature
is an array ofbigint
s, they should be explicitly converted to strings aspublishMessage
expects string array.return ok( await client.publishMessage( dataString, - Array.isArray(signature) - ? signature - : [signature.r.toString(), signature.s.toString()] + Array.isArray(signature) + ? signature.map(s => s.toString()) + : [signature.r.toString(), signature.s.toString()] ) );packages/sdk/src/internal/toriiQueryBuilder.ts (1)
39-45
: 🛠️ Refactor suggestionEnhance deprecation notice for withOffset method
The
withOffset
method is now a no-op, which could silently break existing code that relies on offset-based pagination. Consider adding a more descriptive notice explaining the migration path./** * Set the offset for pagination - * @deprecated Use `withCursor` instead + * @deprecated Use `withCursor` instead. For migration, you can convert your offset to a cursor: + * - For initial pagination, use undefined cursor to start from the beginning + * - For subsequent pages, use the next_cursor value returned from the previous query + * - To roughly approximate old offset behavior: fetch with undefined cursor and skip offset records */ withOffset(): ToriiQueryBuilder<T> { return this; }packages/sdk/src/node/index.ts (5)
50-50
: Client initialization changeChanged from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
64-65
: Renamed query parameter for improved clarityParameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in both entity and event query subscriptions. This is a breaking change but improves naming consistency.Ensure this change is documented in migration guides and update all examples to use the new parameter name.
72-74
: Updated entity parsing to use items arrayThe entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This change simplifies the data structure but is a breaking change for existing code.Ensure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
127-130
: Updated event parsing to use items arraySimilar to the entity parsing changes, event parsing now uses arrays from the
.items
property. This aligns event and entity parsing approaches for better consistency.Update all documentation and examples to reflect this structural change in event data handling.
215-230
: Modified generateTypedData signatureThe method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
🧹 Nitpick comments (15)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Optimize imports to useimport type
for type-only importsSome of the imported symbols are only used as types and should be imported using
import type
syntax for better build performance.-import { - KeysClause, - ParsedEntity, - HistoricalToriiQueryBuilder, -} from "@dojoengine/sdk"; +import { + KeysClause, + HistoricalToriiQueryBuilder, +} from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Improved code readability with line breaksBreaking the nested property access into multiple lines improves readability and makes the test code easier to understand and maintain.
Consider replacing the non-null assertions (
!
) with optional chaining (?.
) for safer property access:draft.entities[ "entity500" -].models.world!.item!.durability = 75; +].models.world?.item?.durability = 75;🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Excellent refactoring: Centralizing merge utilitiesReplacing local implementations with a centralized module improves maintainability and ensures consistent handling of Cairo-specific types across the codebase.
Consider using
import type
for theMergedModels
type since it's only used as a type:-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-4
: Optimize imports withimport type
for type-only importsSeveral of these imports are only used as types in the file. Consider using the
import type
syntax to ensure they're properly removed during compilation.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import { DojoProvider } from "@dojoengine/core"; +import type { DojoCall } from "@dojoengine/core"; +import { Account, AccountInterface } from "starknet"; +import type { BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/merge.ts (4)
75-77
: Avoid usingany
type for enhanced type safetyReplace the generic
any
type with a more specific type fornewEnumContent
.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
95-97
: Avoid usingany
type for enhanced type safetyReplace the generic
any
type with a more specific type fornewEnumContent
.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
133-133
: Avoid usingany
type for enhanced type safetyReplace the generic
any
type with a more specific type forresult
.- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
9-11
: Consider enhancing the type guard for broader compatibilityThe current implementation checks if the value is an instance of CairoOption, but it might not handle all possible Cairo option formats or serialized forms.
Consider enhancing the type guard to handle both instance checks and structural checks:
export function isCairoOption(value: unknown): value is CairoOption<unknown> { - return value instanceof CairoOption; + return ( + value instanceof CairoOption || + (typeof value === 'object' && + value !== null && + ('variant' in value || 'isSome' in value)) + ); }examples/example-node-worker/src/typescript/models.gen.ts (1)
3-3
: Useimport type
for type-only importsSince these imports are only used as types, it's better to use the
import type
syntax to ensure they're removed during compilation.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import type { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/index.ts (2)
236-239
: Fix typo in parameter nameThe parameter name "additionnalTypes" contains a spelling error (extra 'n').
- additionnalTypes?: Record< + additionalTypes?: Record< string, Array<{ name: string; type: string }> >
245-246
: Fix typo in argument nameEnsure the argument name matches the corrected parameter name.
options.domain, modelMapping, - additionnalTypes + additionalTypespackages/sdk/src/internal/toriiQueryBuilder.ts (2)
133-133
: Replaceany
with more specific type constraintUsing
any
in type constraints disables many type checking rules. Consider using a more specific type.- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends SchemaType>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
152-158
: Add documentation for the HistoricalToriiQueryBuilder classThis new class lacks documentation explaining its purpose and how it differs from the base class.
export class HistoricalToriiQueryBuilder< T extends SchemaType > extends ToriiQueryBuilder<T> { + /** + * Creates a ToriiQueryBuilder instance with historical flag set to true + * Used for querying historical events in the system + * + * @param options - Optional query builder configuration + */ constructor(options?: ToriiQueryBuilderOptions) { super({ ...(defaultToriiOptions() as Query), ...options, historical: true, }); } }packages/sdk/src/node/index.ts (2)
34-36
: New module exports addedSeveral new modules are now exported:
- worker.ts: likely for worker thread management
- types.ts: SDK type definitions
- models.ts: model management utilities
Ensure these new modules are documented with examples showing how they should be used.
401-415
: Removed historical parameter from event query conversionThe historical parameter has been removed from the toriiEventMessagesQueryIntoHashedKeys method, but the method still uses a generic type parameter H (presumably for Historical). This could lead to confusion.
Since historical events support has been removed, consider updating the method signature for clarity:
- toriiEventMessagesQueryIntoHashedKeys: async <H extends boolean>( + toriiEventMessagesQueryIntoHashedKeys: async ( query: ToriiQueryBuilder<T> - ): Promise<[ToriiResponse<T, H>, torii.EntityKeysClause[]]> => { + ): Promise<[ToriiResponse<T, false>, torii.EntityKeysClause[]]> => { const q = query.build(); const events = await client.getEventMessages(q); const parsedEvents = parseEntities(events.items); return [ - parsedEvents as ToriiResponse<T, H>, + parsedEvents as ToriiResponse<T, false>, intoEntityKeysClause<T>( q.clause, parsedEvents as StandardizedQueryResult<T> ), ]; },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (42)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(4 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/internal/parseHistoricalEvents.ts
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
✅ Files skipped from review due to trivial changes (2)
- packages/sdk/src/tests/state.test.ts
- .changeset/thirty-cheetahs-design.md
🚧 Files skipped from review as they are similar to previous changes (25)
- examples/example-node-worker/dojoConfig.ts
- examples/example-nodejs-bot/package.json
- packages/react/package.json
- .github/workflows/ci.yaml
- packages/torii-wasm/dojo.c
- packages/torii-client/package.json
- examples/example-node-worker/env.ts
- packages/core/package.json
- package.json
- .github/workflows/release.yaml
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/sdk/src/tests/parseEntities.test.ts
- turbo.json
- packages/sdk/src/node/worker.ts
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/package.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- examples/example-node-worker/tsconfig.json
- packages/sdk/src/web/react/hooks/events.ts
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/internal/errors.ts
- packages/sdk/src/web/react/hooks/entities.ts
- packages/sdk/src/internal/models.ts
- examples/example-node-worker/package.json
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/sdk/src/web/index.ts (5)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
packages/sdk/src/internal/types.ts (2)
ToriiQueryBuilder
(557-557)SchemaType
(50-70)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (13)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
4-4
: Great improvement: Using specialized query builderThe switch from
ToriiQueryBuilder
toHistoricalToriiQueryBuilder
makes the code more semantically clear, as it communicates the intent to query historical data directly through the class name.Also applies to: 14-14
packages/sdk/src/web/experimental/index.ts (2)
24-24
: Good refactor: Consistent client initialization and data handlingThe switch to synchronous client initialization and consistent extraction of
.items
from client responses improves code consistency across the SDK.Also applies to: 28-28, 31-32, 48-48, 92-92, 95-95
39-39
: Property rename:dont_include_hashed_keys
tono_hashed_keys
The query property name has been updated for better clarity and consistency.
Also applies to: 82-82
examples/example-node-worker/src/typescript/contracts.gen.ts (5)
7-13
: LGTM! Clear implementation for move calldataThe function correctly constructs calldata for the
move
action with the direction parameter.
15-26
: Good implementation with proper error handlingThe function implementation follows best practices by including error logging and propagation.
28-34
: LGTM! Clear implementation for spawn calldataThe function correctly constructs calldata for the
spawn
action with empty parameters.
36-47
: Good implementation with proper error handlingThe function implementation follows best practices by including error logging and propagation.
51-58
: Clean API interface designThe return object provides a well-structured API for contract interactions, exposing both the action functions and the calldata builders.
packages/sdk/src/internal/parseEntities.ts (3)
10-15
: Good refactoring to work with entity arraysThe function signature has been updated to accept an array of entities rather than a keyed object, which aligns with changes in the broader codebase.
17-20
: Clear adaptation of entity extractionThe logic has been updated to correctly extract entity ID and data from the array structure.
90-93
: Support for tuple type addedAdding support for the "tuple" type is a good enhancement to handle more complex data structures.
packages/state/src/recs/index.ts (1)
15-15
: Type import updated to reflect new entity structureThe type import has been changed from
Entities
toEntity as ToriiEntity
, correctly aligning with the shift to array-based entity representation.packages/sdk/src/node/index.ts (1)
29-30
: Improved error handling with neverthrow libraryThe addition of the neverthrow library for Result-based error handling is a good practice and improves error handling throughout the SDK.
Make sure to document this pattern in the SDK documentation so consumers understand how to properly handle errors from the SDK functions.
export function deepMerge<T extends SchemaType>( | ||
target: MergedModels<T>, | ||
source: Partial<MergedModels<T>> | ||
): MergedModels<T> { | ||
if (isCairoOption(target) && isCairoOption(source)) { | ||
return mergeCairoOption(target, source); | ||
} | ||
if (isCairoCustomEnum(target) && isCairoCustomEnum(source)) { | ||
return mergeCairoCustomEnum(target, source); | ||
} | ||
const result = { ...target } as Record<string, any>; | ||
for (const key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
if ( | ||
source[key] !== null && | ||
typeof source[key] === "object" && | ||
!Array.isArray(source[key]) | ||
) { | ||
// If the property is an object in both source and target, recursively merge | ||
if ( | ||
key in target && | ||
typeof target[key] === "object" && | ||
!Array.isArray(target[key]) | ||
) { | ||
result[key] = deepMerge(target[key], source[key]); | ||
} else { | ||
// If the key doesn't exist in target or isn't an object, just assign | ||
result[key] = source[key]; | ||
} | ||
} else { | ||
// For non-objects (primitives, arrays, null), just assign | ||
result[key] = source[key]; | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Add unit tests for the deepMerge function
This is a critical utility function that handles complex merging logic for Cairo types. Ensure it has comprehensive test coverage for various edge cases.
Let's verify if there are existing tests for this function:
🏁 Script executed:
#!/bin/bash
# Check for tests related to the deepMerge function
rg "deepMerge" --type=ts -A 5 -B 5 "packages/sdk/src/__tests__" || echo "No tests found"
Length of output: 100
Add unit tests for deepMerge in packages/sdk/src/internal/merge.ts
No tests currently cover this function. Please add a new test suite (e.g. packages/sdk/src/internal/tests/merge.test.ts) that verifies:
- Merging of primitive values (overwrites correctly)
- Recursive merging of nested objects
- Handling of arrays (should be overwritten, not deep-merged)
- Treatment of
null
and undefined properties - Behavior with custom Cairo types (
CairoOption
,CairoCustomEnum
)
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
positition: [[0, 0]], | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure field names in schema match interfaces
Fix the typo in the schema definition to match the corrected interface.
PositionCountValue: {
- positition: [[0, 0]],
+ position: [[0, 0]],
},
📝 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.
positition: [[0, 0]], | |
}, | |
PositionCountValue: { | |
position: [[0, 0]], | |
}, |
4f22735
to
8fef149
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
🔭 Outside diff range comments (2)
packages/state/src/recs/index.ts (1)
516-554
:⚠️ Potential issueInconsistent parameter type and usage in
insertEntitiesInDB
The parameter type is changed to
ToriiEntity[]
(array), but the function still treats it as an object withObject.entries(entities)
. This mismatch will cause runtime errors.async function insertEntitiesInDB( db: IDBDatabase, entities: ToriiEntity[] ): Promise<void> { return new Promise((resolve, reject) => { const transaction = db.transaction(["entities"], "readwrite"); const store = transaction.objectStore("entities"); let completed = 0; let error: Error | null = null; // Handle transaction completion transaction.oncomplete = () => { if (error) { reject(error); } else { resolve(); } }; transaction.onerror = () => { reject(transaction.error); }; // Store each entity - for (const [entityId, data] of Object.entries(entities)) { + for (const entity of entities) { const entityData = { - id: entityId, + id: entity.hashed_keys, - ...data, + ...entity.models, }; const request = store.put(entityData); completed++; request.onerror = () => { error = request.error; }; } }); }packages/sdk/src/web/index.ts (1)
257-282
:⚠️ Potential issue
sendMessage
should returnResult.err
, not throwThe method has been updated to use the
neverthrow
Result type for error handling, but inconsistently throws in the catch block instead of returning an error result.This breaks the
Result
contract and forces callers to handle both the Result pattern and try/catch, which defeats the purpose of usingneverthrow
.try { // Sign the typed data const signature: Signature = await account.signMessage(data); // Stringify typed data for publishing const dataString = JSON.stringify(data); // Publish the signed message return ok( await client.publishMessage( dataString, Array.isArray(signature) ? signature : [signature.r.toString(), signature.s.toString()] ) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }
♻️ Duplicate comments (18)
packages/sdk/src/internal/merge.ts (1)
123-160
: Add unit tests for the deepMerge function.This is a critical utility function that handles complex merging logic for Cairo types. Currently, there are no tests covering its functionality.
Please add a new test suite (e.g. packages/sdk/src/internal/tests/merge.test.ts) that verifies:
- Merging of primitive values (overwrites correctly)
- Recursive merging of nested objects
- Handling of arrays (should be overwritten, not deep-merged)
- Treatment of
null
and undefined properties- Behavior with custom Cairo types (
CairoOption
,CairoCustomEnum
)🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/experimental/index.ts (2)
30-32
: Remove unused historical parameterThe
historical
parameter is declared but never used in the implementation.- getEvents: async (query: torii.Query, historical: boolean = false) => { + getEvents: async (query: torii.Query) => { const events = await client.getEventMessages(query); return parseEntities(events.items); },🧰 Tools
🪛 Biome (1.9.4)
[error] 30-30: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
101-106
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 101-101: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
126-133
: 🛠️ Refactor suggestionRisk of numeric precision loss for u64 values
A 64-bit unsigned integer can exceed JavaScript's Number.MAX_SAFE_INTEGER (2^53-1), leading to precision loss. Consider parsing u64 with BigInt like the other large integer types.
function parsePrimitive(value: torii.Ty): any { switch (value.type_name) { - case "u64": - return Number.parseInt(value.value as string, 16); case "i256": case "i128": case "u256": case "u128": + case "u64": return BigInt(value.value as string); default: return value.value; } }packages/state/src/recs/index.ts (3)
246-246
: Same length check issue ingetEvents
- if (Object.keys(entities.items).length === 0) { + if (entities.items.length === 0) {
189-189
:⚠️ Potential issueArray length check uses incorrect method
Since
entities.items
is now an array, use.length
directly instead ofObject.keys().length
.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) { continueFetching = false; } else {
320-333
:⚠️ Potential issueInfinite loop in
getEntitiesQuery
Inside the
while (continueFetching)
loop you never issue a newclient.getEntities
call—fetchedEntities
is fetched once outside the loop, socursor
advances but data doesn't refresh.- const fetchedEntities = await client.getEntities({ - pagination: { - limit, - cursor, - direction: "Forward", - order_by: orderBy, - }, - clause: clause || undefined, - no_hashed_keys: false, - models: entityModels, - historical, - }); while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); + if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); - if (Object.keys(fetchedEntities.items).length < limit) { + if (fetchedEntities.items.length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } }examples/example-node-worker/main.ts (4)
21-25
: Wrong global identifier: useWebSocket
, notWebsocket
Browsers and Node.js polyfills expect
global.WebSocket
(uppercase 'S'). Using lowercaseWebsocket
will leave libraries that expect the standardWebSocket
identifier undefined.// Those lines are require so that websocket works. // @ts-ignore -global.Websocket = w3cwebsocket; +global.WebSocket = w3cwebsocket; // @ts-ignore global.WorkerGlobalScope = global;
125-133
:initPositionFromEvent
mutates the shared constantUsing
const pc = defaultPositionCount
creates a reference to the shared constant. Each call to this function will mutate the same object, creating cumulative side-effects for future callers.function initPositionFromEvent( events: ParsedEntity<SchemaType>[] ): PositionCount { - const pc = defaultPositionCount; + const pc: PositionCount = { ...defaultPositionCount }; for (const e of events) { const moved = e.models.dojo_starter.Moved; if (!moved) { continue; } pc[moved.direction] += 1; } return pc; }
143-151
: Potential data loss withdata.pop()
Using
data.pop()
both mutates the array and only processes the last entity. If multiple entities arrive in the same batch, all but the last will be silently ignored.async function onEntityUpdated({ data, error }) { if (error) { console.error(error); return; } - const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - // do whatever you need here - const model = entity.models.dojo_starter; - if (model?.Moves) { - await publishOffchainPositionCount(model.Moves); + for (const entity of data) { + if (entity && entity.entityId !== "0x0") { + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } } } }
175-176
: Unreachable code after the firstreturn
The second return statement can never execute because the function will always exit at the first return.
- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
examples/example-node-worker/src/typescript/models.gen.ts (2)
38-46
:⚠️ Potential issueFix typo in "positition" field name
There appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }
129-133
:⚠️ Potential issueEnsure field names in schema match interfaces
Fix the typo in the schema definition to match the corrected interface.
PositionCount: { identity: "", - positition: [[0, 0]], + position: [[0, 0]], }, PositionCountValue: { - positition: [[0, 0]], + position: [[0, 0]], },packages/sdk/src/node/index.ts (5)
50-50
: Client initialization changeChanged from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.
64-64
: Renamed query parameter for improved clarityParameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in both entity and event query subscriptions. This is a breaking change but improves naming consistency.Also applies to: 119-119
73-74
: Updated entity and event parsing to use items arrayThe entity and event parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This change simplifies the data structure but is a breaking change for existing code.Also applies to: 82-84, 141-143, 189-189, 204-204, 390-391
215-230
: Modified generateTypedData signatureThe method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
240-265
: 🛠️ Refactor suggestionError handling inconsistency in sendMessage method
While the method now uses
Result
type from neverthrow for early returns, it still throws an error in the catch block instead of returning an error result.Apply this fix to make error handling consistent:
try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
🧹 Nitpick comments (9)
packages/sdk/src/internal/merge.ts (3)
76-76
: Consider using a more specific type instead ofany
.Using
any
reduces type safety and can lead to runtime errors.- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
96-96
: Replaceany
with a more specific type.Similarly to the previous occurrence, using a more specific type would improve type safety.
- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};🧰 Tools
🪛 Biome (1.9.4)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
133-133
: Replaceany
withunknown
for better type safety.The
any
type bypasses TypeScript's type checking, whileunknown
forces proper type checking before use.- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Useimport type
for type imports.
MergedModels
is only used as a type, so it should be imported withimport type
to ensure they are removed by compilers.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Useimport type
for type-only imports.
ParsedEntity
is only used as a type, so it should be imported withimport type
.import { KeysClause, - ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Consider using optional chaining instead of non-null assertions.The current implementation uses non-null assertions (
!
) which might cause runtime errors if the values are null or undefined.- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + draft.entities["entity500"].models.world?.item?.durability = 75;🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-2
: Useimport type
for better bundle optimizationThe imports are only used for type information, not at runtime. Using
import type
helps optimize bundle size and clarifies intent.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import { Account, type AccountInterface, type BigNumberish, type CairoOption, type CairoCustomEnum, type ByteArray } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts (1)
3-3
: Useimport type
for type-only importsSince
CairoCustomEnum
,CairoOption
,CairoOptionVariant
, andBigNumberish
are only used as types in this file, you should use theimport type
syntax to ensure they're removed during compilation.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import type { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-133
: Removeany
type from static withPagination methodThe static method uses
Record<string, Record<string, any>>
which includesany
. This violates type safety principles and can lead to runtime errors.-static withPagination<T extends Record<string, Record<string, any>>>( +static withPagination<T extends SchemaType>( cursor: string, limit: number, direction: PaginationDirection ): ToriiQueryBuilder<T> {🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
🛑 Comments failed to post (2)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
39-45: 💡 Verification agent
🧩 Analysis chain
Enhance deprecation notice for withOffset
The
withOffset
method has been converted to a no-op that returnsthis
without setting any properties. While it's marked as deprecated, this silent change could break existing code that relies on offset-based pagination.Provide a more descriptive deprecation notice in the JSDoc explaining the migration path to cursor-based pagination:
/** * Set the offset for pagination - * @deprecated Use `withCursor` instead + * @deprecated Offset-based pagination is no longer supported. Use `withCursor` instead. + * To migrate from offset to cursor pagination: + * 1. For initial page, use `withCursor(undefined)` instead of `withOffset(0)` + * 2. For subsequent pages, use the `next_cursor` value returned from the previous query */ withOffset(): ToriiQueryBuilder<T> { return this; }Also consider adding a compatibility helper method to assist with migration:
/** * Compatibility helper for migrating from offset-based pagination * @deprecated Use `withCursor` directly when possible */ withOffsetCompat(offset: number): ToriiQueryBuilder<T> { // If offset is 0, leave cursor undefined to start from the beginning if (offset > 0) { console.warn('Offset-based pagination is deprecated. Using approximation for cursor.'); // Apply some cursor approximation logic here if possible } return this; }Let me search for usages of withOffset to assess impact:
🏁 Script executed:
#!/bin/bash # Check for usage of withOffset in the codebase rg "\.withOffset\(" --type=tsLength of output: 31
🏁 Script executed:
#!/bin/bash # Search for all usages of withOffset across the repo rg '\.withOffset\(' -n . # Inspect the withOffset declaration in the SDK internals rg 'withOffset' -n packages/sdk/src/internal/toriiQueryBuilder.tsLength of output: 136
Improve deprecation notice for withOffset
No internal usages of
withOffset
were detected, so this change won’t break existing SDK calls—but it’s still part of the public API, and we should help consumers migrate.Please update the JSDoc in packages/sdk/src/internal/toriiQueryBuilder.ts to something like:
/** * Set the offset for pagination - * @deprecated Use `withCursor` instead + * @deprecated Offset-based pagination is no longer supported. Use `withCursor` instead. + * To migrate: + * 1. For the first page, replace `withOffset(0)` with `withCursor(undefined)`. + * 2. For subsequent pages, pass the `next_cursor` from the previous response. */ withOffset(): ToriiQueryBuilder<T> { return this; }Optionally, add a helper for smoother migration:
/** * Compatibility helper for migrating from offset-based pagination. * @deprecated Use `withCursor` directly when possible. */ withOffsetCompat(offset: number): ToriiQueryBuilder<T> { if (offset > 0) { console.warn( 'Offset-based pagination is deprecated. Using approximate cursor fallback.' ); // TODO: implement fallback or document limitations } return this; }
- File: packages/sdk/src/internal/toriiQueryBuilder.ts
- Lines: 39–45
packages/sdk/src/node/index.ts (1)
401-407: 💡 Verification agent
🧩 Analysis chain
Simplified historical event handling
The
toriiEventMessagesQueryIntoHashedKeys
method has been simplified to work with the updated event parsing structure. Thehistorical
parameter is still in the type signature but no longer affects implementation behavior.Check if any documentation or migration guides need to be updated to reflect this change:
🏁 Script executed:
#!/bin/bash # Search for uses of the historical parameter in code or docs rg -A 3 -B 3 "historical\s*[:=]" --type tsx --type tsLength of output: 83
🏁 Script executed:
#!/bin/bash # Search for 'historical' references in code and documentation rg -n "historical" --glob "*.{ts,tsx,md}"Length of output: 6473
🏁 Script executed:
#!/bin/bash # Display lines 330-430 in packages/sdk/src/node/index.ts for context sed -n '330,430p' packages/sdk/src/node/index.tsLength of output: 3280
Update documentation for deprecated historical flag
The SDK helper no longer acts on the
historical
parameter even though it remains in the type signature. We should align all docs and JSDoc with this simplification:• packages/sdk/src/node/index.ts
– Remove the obsolete@param {boolean} historical
from updateEventMessageSubscription’s JSDoc.
– In toriiEventMessagesQueryIntoHashedKeys, correct the@returns
annotation to use the genericH
(not hard-codedfalse
) and drop any description implying historical has behavioral effect.• README.md
– Update or remove the “If you want to index historical events” section so users don’t expect the helper to change behavior based on a historical flag.• CHANGELOG.md (and any Migration guide)
– Add a note thathistorical
is now a no-op in event‐query helpers and point toquery.historical
for clarity.
8347ca5
to
a0ed096
Compare
dd6f140
to
b104036
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🔭 Outside diff range comments (2)
packages/sdk/src/web/index.ts (1)
279-282
: 🛠️ Refactor suggestion
sendMessage
should returnResult.err
, not throwInside the
catch
wethrow
, breaking theResult
contract and forcing callers to juggle two error channels.catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }This ensures consistent error handling using the Result type pattern throughout the codebase.
packages/sdk/src/node/index.ts (1)
266-269
:⚠️ Potential issueInconsistent error handling pattern.
While Result types from neverthrow are used to handle errors in the initial checks, the function still throws errors in the catch block instead of returning an
err
Result. This inconsistency could confuse developers and make error handling more difficult.Apply this diff to make error handling consistent:
catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
♻️ Duplicate comments (20)
packages/sdk/src/internal/merge.ts (1)
123-160
: Add unit tests for the deepMerge function.This function handles complex merging logic but lacks test coverage. Comprehensive tests should be added to verify its behavior with different Cairo types and nested objects.
Also, consider improving type safety by replacing
any
with a more specific type:- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/experimental/index.ts (1)
95-95
: 🛠️ Refactor suggestionStill using
any
type for entity dataA previous review comment suggested replacing the
any
type withtorii.Entity
for improved type safety, but this hasn't been addressed.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
127-133
:⚠️ Potential issueInconsistent handling of integer types
The code treats
u64
as a regular number (usingNumber.parseInt
), while handling larger integer types (i256
,i128
,u256
,u128
) asBigInt
. Since au64
can also exceed JavaScript's safe integer range, it should also useBigInt
for consistency and to prevent precision loss.function parsePrimitive(value: torii.Ty): any { switch (value.type_name) { case "u64": - return Number.parseInt(value.value as string, 16); + return BigInt(value.value as string); case "i256": case "i128": case "u256": case "u128": return BigInt(value.value as string); default: return value.value; } }packages/state/src/recs/index.ts (3)
242-246
:⚠️ Potential issueEvent handling inconsistency with array vs object
Similar to the entity handling, the code expects
entities.items
to be an array but usesObject.keys(entities.items).length
to check the length.-if (logging) console.log("entities", entities.items); +if (logging) console.log("events", entities.items); setEntities(entities.items, components, logging); -if (Object.keys(entities.items).length === 0) { +if (entities.items.length === 0) {
516-519
:⚠️ Potential issueUpdated parameter type but function implementation not updated
The
insertEntitiesInDB
function now expects an array ofToriiEntity
objects but still processes them as a keyed object withObject.entries(entities)
in line 541. This will lead to unexpected behavior.async function insertEntitiesInDB( db: IDBDatabase, entities: ToriiEntity[] ): Promise<void> { return new Promise((resolve, reject) => { const transaction = db.transaction(["entities"], "readwrite"); const store = transaction.objectStore("entities"); let completed = 0; let error: Error | null = null; // Handle transaction completion transaction.oncomplete = () => { if (error) { reject(error); } else { resolve(); } }; transaction.onerror = () => { reject(transaction.error); }; // Store each entity - for (const [entityId, data] of Object.entries(entities)) { + for (const entity of entities) { const entityData = { - id: entityId, + id: entity.hashed_keys.join('.'), - ...data, + ...entity.models, }; const request = store.put(entityData); completed++; request.onerror = () => { error = request.error; }; } }); }
307-318
:⚠️ Potential issueUpdated entity query parameters in getEntitiesQuery
The parameters for
getEntitiesQuery
have been updated to use cursor-based pagination, but there's a critical issue: thefetchedEntities
variable is defined outside the loop but never updated inside it.This is likely to cause an infinite loop or incorrect behavior, as the cursor updates but the entity data doesn't refresh. Move the fetch inside the loop:
-const fetchedEntities = await client.getEntities({ - pagination: { - limit, - cursor, - direction: "Forward", - order_by: orderBy, - }, - clause: clause || undefined, - no_hashed_keys: false, - models: entityModels, - historical, -}); while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); + if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); if (Object.keys(fetchedEntities.items).length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } }examples/example-node-worker/main.ts (4)
21-25
: Wrong global identifier: useWebSocket
, notWebsocket
Browsers (and most polyfills) expose
global.WebSocket
(uppercase S).
Assigning toWebsocket
leaves libraries that expectWebSocket
undefined.// @ts-ignore -global.Websocket = w3cwebsocket; +global.WebSocket = w3cwebsocket;
125-133
:initPositionFromEvent
mutates the shared constant
pc
is an alias ofdefaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };This also prevents accidental modification of the default object elsewhere.
137-151
: Potential data loss withdata.pop()
data
is already the argument supplied by the subscription.
Callingpop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.Iterate instead:
- const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - // do whatever you need here - const model = entity.models.dojo_starter; - if (model?.Moves) { - await publishOffchainPositionCount(model.Moves); - } - } + for (const entity of data) { + if (entity && entity.entityId !== "0x0") { + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } + } + }
175-176
: Unreachable code after the firstreturn
The second
return [sub];
can never execute—Biome rightfully flags it.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
examples/example-node-worker/src/typescript/models.gen.ts (2)
38-46
: Fix typo in "positition" field nameThere appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
129-133
: Ensure field names in schema match interfacesFix the typo in the schema definition to match the corrected interface.
PositionCount: { identity: "", - positition: [[0, 0]], + position: [[0, 0]], }, PositionCountValue: { - positition: [[0, 0]], + position: [[0, 0]], },packages/sdk/src/node/index.ts (8)
50-50
: Client initialization change.Changed from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
64-65
: Renamed query parameter for improved clarity.Parameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in entity query subscriptions. This is a breaking change but improves naming consistency.Ensure this change is documented in migration guides and update all examples to use the new parameter name.
72-74
: Updated entity parsing to use items array.The entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This change simplifies the data structure but is a breaking change for existing code.Ensure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
119-120
: Renamed query parameter for improved clarity.Parameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in event query subscriptions. This is a breaking change but improves naming consistency.Ensure this change is documented in migration guides and update all examples to use the new parameter name.
127-130
: Updated event parsing to use items array.Similar to the entity parsing changes, event parsing now uses arrays from the
.items
property. This aligns event and entity parsing approaches for better consistency.Update all documentation and examples to reflect this structural change in event data handling.
138-143
: Updated event parsing to use items array.Similar to the entity parsing changes, event parsing now uses arrays from the
.items
property. This aligns event and entity parsing approaches for better consistency.Update all documentation and examples to reflect this structural change in event data handling.
219-230
: Modified generateTypedData signature.The method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
242-265
: 🛠️ Refactor suggestionImproved error handling in sendMessage method.
The sendMessage method now:
- Checks for the presence of signer and identity before attempting to send
- Returns a Result type (from neverthrow) with ok/err instead of throwing exceptions
- No longer requires an explicit Account parameter, relying on options.signer and options.identity
This is a breaking change for code that catches exceptions from this method, but improves error handling overall.
However, there's still inconsistency in error handling. The function uses Result for initial checks but throws an error in the catch block:
try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
🧹 Nitpick comments (13)
packages/sdk/src/internal/merge.ts (2)
19-46
: Improve type safety inmergeCairoOption
function.The function correctly handles the merging logic for CairoOption instances, but it contains multiple
as unknown as MergedModels<T>
type assertions which are unsafe and could be improved.Consider refactoring to make better use of generics to avoid these type assertions:
-export function mergeCairoOption<T extends SchemaType>( - target: MergedModels<T>, - source: Partial<MergedModels<T>> -): MergedModels<T> { +export function mergeCairoOption<T extends SchemaType, V>( + target: CairoOption<V>, + source: CairoOption<V> +): CairoOption<V> { // If source is Some, prefer source's value - if (source instanceof CairoOption && source.isSome()) { + if (source.isSome()) { return new CairoOption( CairoOptionVariant.Some, source.unwrap() - ) as unknown as MergedModels<T>; + ); } // If source is None or undefined, keep target - if (target instanceof CairoOption) { - if (target.isSome()) { - return new CairoOption( - CairoOptionVariant.Some, - target.unwrap() - ) as unknown as MergedModels<T>; - } - return new CairoOption( - CairoOptionVariant.None - ) as unknown as MergedModels<T>; + if (target.isSome()) { + return new CairoOption( + CairoOptionVariant.Some, + target.unwrap() + ); } + return new CairoOption(CairoOptionVariant.None); // This should not happen if both are CairoOption instances - return target as unknown as MergedModels<T>; }Then update the calling code to handle the type conversion.
63-113
: Improve type safety and remove usage ofany
inmergeCairoCustomEnum
.While the function correctly handles merging CairoCustomEnum instances, it uses
any
type in the Record definitions which could lead to type safety issues.Consider using a more specific type instead of
any
:- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};Make the same change at line 96.
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Good refactoring: Import utilities from centralized module.Importing
deepMerge
andMergedModels
from the centralized module improves code maintainability and reduces duplication. Consider usingimport type
forMergedModels
since it's only used as a type.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Update import with type annotations.Since
ParsedEntity
is only used as a type, consider usingimport type
to improve build optimization.import { KeysClause, - ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-2
: Useimport type
for type-only importsThe imports are only used as type annotations. Using
import type
ensures they're removed during compilation, improving bundle size and avoiding unnecessary module loading.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, CairoCustomEnum } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/state/src/recs/index.ts (4)
165-165
: Commented out timestamp caching codeThe timestamp caching functionality appears to be disabled but not completely removed. Consider removing it entirely if it's no longer needed or documenting why it's being kept for future reference.
323-323
: Array length check uses inefficient methodThe code is using
Object.keys(fetchedEntities.items).length
instead offetchedEntities.items.length
to get the array length.- `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` + `Fetched ${fetchedEntities.items.length} entities ${fetchedEntities.next_cursor}`
326-328
: Array length check uses inefficient methodSimilar to previous instances, the code uses
Object.keys(...).length
instead of.length
for an array.-if (Object.keys(fetchedEntities.items).length < limit) { +if (fetchedEntities.items.length < limit) {
512-514
: Commented out code should be removedThe
getCache
function is commented out but not removed. If it's no longer needed, remove it completely to improve code clarity.-// const getCache = (timestampCacheKey: string) => { -// return Number(localStorage.getItem(timestampCacheKey) || 0); -// };examples/example-node-worker/src/typescript/models.gen.ts (1)
3-3
: Useimport type
for type-only imports-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import type { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet';This helps the compiler optimize the code by excluding imports that aren't needed at runtime.
🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/index.ts (1)
274-277
: Convert bigint signatures to stringsWhen
signature
is an array ofbigint
s they're forwarded as-is;publishMessage
expectsstring[]
.return ok( await client.publishMessage( dataString, - Array.isArray(signature) - ? signature - : [signature.r.toString(), signature.s.toString()] + Array.isArray(signature) + ? signature.map((x) => x.toString()) + : [signature.r.toString(), signature.s.toString()] ) );This ensures the signature is properly converted to strings regardless of the input format.
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-133
: Avoidany
in generic type parameterUsing
any
in type parameters disables important type checking rules.-static withPagination<T extends Record<string, Record<string, any>>>( +static withPagination<T extends SchemaType>(This makes the method type-safe and consistent with the rest of the class implementation.
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Consider optional chaining instead of non-null assertions for safer access.The code uses non-null assertions (
!
) twice, which can lead to runtime errors if the properties are unexpectedly null or undefined. Consider using optional chaining for safer property access.-draft.entities[ - "entity500" -].models.world!.item!.durability = 75; +draft.entities["entity500"].models.world?.item?.durability = 75;Additionally, note that the static analyzer suggests using a literal key instead of a string literal for "entity500", but this is primarily a style preference and both approaches are valid.
🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (42)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(3 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
- packages/sdk/src/internal/parseHistoricalEvents.ts
✅ Files skipped from review due to trivial changes (1)
- .changeset/thirty-cheetahs-design.md
🚧 Files skipped from review as they are similar to previous changes (26)
- packages/sdk/src/internal/errors.ts
- examples/example-nodejs-bot/package.json
- examples/example-node-worker/dojoConfig.ts
- examples/example-node-worker/env.ts
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/react/package.json
- packages/torii-wasm/dojo.c
- packages/core/package.json
- packages/sdk/src/web/react/hooks/hooks.ts
- packages/sdk/src/tests/state.test.ts
- .github/workflows/ci.yaml
- examples/example-node-worker/tsconfig.json
- packages/torii-client/package.json
- package.json
- packages/sdk/package.json
- .github/workflows/release.yaml
- packages/sdk/src/web/react/hooks/entities.ts
- packages/sdk/src/tests/parseEntities.test.ts
- examples/example-node-worker/package.json
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/src/web/react/hooks/events.ts
- turbo.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/node/worker.ts
- packages/sdk/src/internal/models.ts
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/sdk/src/web/index.ts (5)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
packages/sdk/src/internal/types.ts (2)
ToriiQueryBuilder
(557-557)SchemaType
(50-70)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (29)
packages/sdk/src/internal/merge.ts (3)
9-11
: Looks good! Well-documented type guard function.The type guard for CairoOption is correctly implemented and includes clear JSDoc comments explaining its purpose.
53-55
: Looks good! Well-documented type guard function.The type guard for CairoCustomEnum is correctly implemented and includes clear JSDoc comments explaining its purpose.
120-122
: Good type definition with export.The MergedModels type alias is properly defined and exported, making it available for use throughout the codebase.
packages/sdk/src/web/state/zustand.ts (2)
84-94
: Good implementation: Using the imported deepMerge utility.The imported
deepMerge
utility is used correctly to merge models within namespaces.
134-144
: Good implementation: Consistent usage of deepMerge across methods.The imported
deepMerge
utility is consistently used in theupdateEntity
method, matching the implementation inmergeEntities
.examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: Good migration to HistoricalToriiQueryBuilder.Switching to the
HistoricalToriiQueryBuilder
aligns with the SDK's updated approach to handling historical events with cursor-based pagination.packages/sdk/src/web/experimental/index.ts (6)
23-23
: Client initialization changed from async to syncThe initialization of the Torii client has been changed from an asynchronous factory method to a synchronous constructor. This is a significant change in usage pattern that should be documented in release notes.
27-27
: Improved entity extraction and parsingThe function now explicitly extracts the
items
array from the client response before parsing, which provides a more consistent data handling approach across the codebase.
29-31
: Simplified event retrieval without historical parameterThe
getEvents
function has been simplified by removing the unusedhistorical
parameter, addressing a previous review comment. The implementation now consistently uses theitems
array from the response.
38-38
: Query flag renamed for clarityThe query flag was renamed from
dont_include_hashed_keys
tono_hashed_keys
, which is clearer and more concise.
53-58
: Updated entity data parsing in subscription callbackThe callback now correctly parses entity data as an array instead of a keyed object, aligning with the changes in the
parseEntities
function.
98-100
: Updated event data parsing in subscription callbackThe callback now correctly parses the event data as an array, which aligns with the changes in the
parseEntities
function.packages/sdk/src/internal/parseEntities.ts (5)
10-15
: Updated parseEntities to accept an array instead of a keyed objectThe function now accepts an array of
torii.Entity
objects instead of a keyed object. This is a significant API change that should be documented for users.
17-20
: Refactored entity processing for array inputThe entity processing loop now iterates over an array of entities rather than object keys, extracting
hashed_keys
andmodels
directly from each entity.
25-25
: Updated model loop to reference entity's models propertyThe inner loop now correctly references
entity.models
to match the array-based entity structure.
47-47
: Changed result collection method for array-based approachInstead of setting values in an object by key, the result is now built using
push()
to maintain the array structure.
90-90
: Added support for "tuple" type in parseValueThe
parseValue
function now handles the "tuple" type, treating it the same way as "array" by mapping over the values and parsing each one.packages/state/src/recs/index.ts (4)
15-15
: Updated import to use the renamed Entity typeThe import has been updated to use
Entity as ToriiEntity
from@dojoengine/torii-client
, aligning with the new entity handling approach.
162-162
: Switched from offset to cursor-based paginationThe code now uses cursor-based pagination instead of offset-based pagination, which is a significant change in how pagination works.
168-179
: Updated query parameters for cursor-based paginationThe query parameters now use a nested
pagination
object with cursor and direction properties instead of the previous flat structure. This is a breaking change that should be documented.
229-240
: Updated event query parameters for cursor-based paginationSimilar to the entity query, the event query parameters now use a nested
pagination
object and have updated field names.packages/sdk/src/internal/toriiQueryBuilder.ts (1)
145-159
: Good implementation of HistoricalToriiQueryBuilderThe new
HistoricalToriiQueryBuilder
class is well-designed, extending the base query builder while fixing thehistorical
flag totrue
. This ensures consistent behavior for historical queries.packages/sdk/src/node/index.ts (7)
19-19
: Import refinement improved type safety.The import statement has been refined to only import the necessary types, removing unused imports like
StarknetDomain
. This helps prevent potential confusion and bloat in the codebase.
29-30
: Added robust error handling with neverthrow.Integration of the
neverthrow
library and standardized error constants provides better error handling patterns throughout the SDK.
34-36
: New module exports enhance SDK capabilities.The additional exports from worker.ts, types.ts, and models.ts modules expand the SDK's functionality and provide more tools for developers.
189-189
: Entity query results access updated.Entity query results now consistently access the
.items
property before parsing.
202-204
: Event query results access updated.Event query results now consistently access the
.items
property before parsing.
390-391
: Entity query results access updated.Query results now consistently access the
.items
property before parsing.
406-407
: Event query results access updated.Event query results now consistently access the
.items
property before parsing.
const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { | ||
return { | ||
contractName: "actions", | ||
entrypoint: "move", | ||
calldata: [direction], | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Function uses inconsistent naming style
The function uses snake_case (build_actions_move_calldata
) instead of camelCase which is the TypeScript convention. This is inconsistent with the exported function names in line 52-57 which use camelCase (buildMoveCalldata
).
-const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => {
+const buildActionsMoveCalldata = (direction: CairoCustomEnum): DojoCall => {
return {
contractName: "actions",
entrypoint: "move",
calldata: [direction],
};
};
📝 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.
const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { | |
return { | |
contractName: "actions", | |
entrypoint: "move", | |
calldata: [direction], | |
}; | |
}; | |
const buildActionsMoveCalldata = (direction: CairoCustomEnum): DojoCall => { | |
return { | |
contractName: "actions", | |
entrypoint: "move", | |
calldata: [direction], | |
}; | |
}; |
const build_actions_spawn_calldata = (): DojoCall => { | ||
return { | ||
contractName: "actions", | ||
entrypoint: "spawn", | ||
calldata: [], | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Function uses inconsistent naming style
Similar to the previous function, this uses snake_case instead of the conventional camelCase in TypeScript.
-const build_actions_spawn_calldata = (): DojoCall => {
+const buildActionsSpawnCalldata = (): DojoCall => {
return {
contractName: "actions",
entrypoint: "spawn",
calldata: [],
};
};
📝 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.
const build_actions_spawn_calldata = (): DojoCall => { | |
return { | |
contractName: "actions", | |
entrypoint: "spawn", | |
calldata: [], | |
}; | |
}; | |
const buildActionsSpawnCalldata = (): DojoCall => { | |
return { | |
contractName: "actions", | |
entrypoint: "spawn", | |
calldata: [], | |
}; | |
}; |
const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { | ||
try { | ||
return await provider.execute( | ||
snAccount, | ||
build_actions_move_calldata(direction), | ||
"dojo_starter", | ||
); | ||
} catch (error) { | ||
console.error(error); | ||
throw error; | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Function follows inconsistent naming and could use better error handling
The function uses snake_case which is inconsistent with TypeScript conventions. Additionally, the error handling could benefit from more specific error messages to aid debugging.
-const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => {
+const actionsMove = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => {
try {
return await provider.execute(
snAccount,
- build_actions_move_calldata(direction),
+ buildActionsMoveCalldata(direction),
"dojo_starter",
);
} catch (error) {
- console.error(error);
+ console.error(`Error executing move action: ${error}`);
throw error;
}
};
📝 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.
const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { | |
try { | |
return await provider.execute( | |
snAccount, | |
build_actions_move_calldata(direction), | |
"dojo_starter", | |
); | |
} catch (error) { | |
console.error(error); | |
throw error; | |
} | |
}; | |
const actionsMove = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { | |
try { | |
return await provider.execute( | |
snAccount, | |
buildActionsMoveCalldata(direction), | |
"dojo_starter", | |
); | |
} catch (error) { | |
console.error(`Error executing move action: ${error}`); | |
throw error; | |
} | |
}; |
actions: { | ||
move: actions_move, | ||
buildMoveCalldata: build_actions_move_calldata, | ||
spawn: actions_spawn, | ||
buildSpawnCalldata: build_actions_spawn_calldata, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Inconsistency between function definitions and exports
The exported function names use camelCase but reference functions defined with snake_case. This inconsistency should be resolved.
return {
actions: {
- move: actions_move,
- buildMoveCalldata: build_actions_move_calldata,
- spawn: actions_spawn,
- buildSpawnCalldata: build_actions_spawn_calldata,
+ move: actionsMove,
+ buildMoveCalldata: buildActionsMoveCalldata,
+ spawn: actionsSpawn,
+ buildSpawnCalldata: buildActionsSpawnCalldata,
},
};
Committable suggestion skipped: line range outside the PR's diff.
const actions_spawn = async (snAccount: Account | AccountInterface) => { | ||
try { | ||
return await provider.execute( | ||
snAccount, | ||
build_actions_spawn_calldata(), | ||
"dojo_starter", | ||
); | ||
} catch (error) { | ||
console.error(error); | ||
throw error; | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Function follows inconsistent naming and could use better error handling
Similar to actions_move
, this function uses snake_case and has minimal error information in the error handling.
-const actions_spawn = async (snAccount: Account | AccountInterface) => {
+const actionsSpawn = async (snAccount: Account | AccountInterface) => {
try {
return await provider.execute(
snAccount,
- build_actions_spawn_calldata(),
+ buildActionsSpawnCalldata(),
"dojo_starter",
);
} catch (error) {
- console.error(error);
+ console.error(`Error executing spawn action: ${error}`);
throw error;
}
};
Committable suggestion skipped: line range outside the PR's diff.
if (logging) console.log(`Fetched entities`, entities.items); | ||
|
||
setEntities(entities, components, logging); | ||
setEntities(entities.items, components, logging); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Entity handling inconsistency with array vs object
The code now expects entities.items
to be an array, but then uses Object.keys(entities.items).length
in line 189 to check the length, which is inefficient for an array. Additionally, setEntities
might expect a different shape than what's being passed.
-if (logging) console.log(`Fetched entities`, entities.items);
+if (logging) console.log("Fetched entities", entities.items);
setEntities(entities.items, components, logging);
-if (Object.keys(entities.items).length < limit) {
+if (entities.items.length < limit) {
📝 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.
if (logging) console.log(`Fetched entities`, entities.items); | |
setEntities(entities, components, logging); | |
setEntities(entities.items, components, logging); | |
if (logging) console.log("Fetched entities", entities.items); | |
setEntities(entities.items, components, logging); | |
if (entities.items.length < limit) { |
🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
b104036
to
ff82d6f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (3)
packages/state/src/recs/index.ts (1)
516-554
:⚠️ Potential issueType mismatch in insertEntitiesInDB function
The function parameter type has been updated to
ToriiEntity[]
, but the implementation still treatsentities
as an object with entries. This will cause runtime errors.async function insertEntitiesInDB( db: IDBDatabase, entities: ToriiEntity[] ): Promise<void> { return new Promise((resolve, reject) => { const transaction = db.transaction(["entities"], "readwrite"); const store = transaction.objectStore("entities"); let completed = 0; let error: Error | null = null; // Handle transaction completion transaction.oncomplete = () => { if (error) { reject(error); } else { resolve(); } }; transaction.onerror = () => { reject(transaction.error); }; // Store each entity - for (const [entityId, data] of Object.entries(entities)) { - const entityData = { - id: entityId, - ...data, - }; + for (const entity of entities) { + const entityData = { + id: entity.hashed_keys, + ...entity, + }; const request = store.put(entityData); completed++; request.onerror = () => { error = request.error; }; } }); }packages/sdk/src/web/index.ts (1)
257-283
:⚠️ Potential issueImprove error handling in sendMessage method
The method returns a
Result
type but still throws an error in the catch block rather than returning an error result. This defeats the purpose of using theResult
type for proper error handling.sendMessage: async ( data: TypedData, account?: Account ): Promise<Result<Uint8Array, string>> => { if (!account) { return err(NO_ACCOUNT); } try { // Sign the typed data const signature: Signature = await account.signMessage(data); // Stringify typed data for publishing const dataString = JSON.stringify(data); // Publish the signed message return ok( await client.publishMessage( dataString, Array.isArray(signature) ? signature : [signature.r.toString(), signature.s.toString()] ) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); } },packages/sdk/src/internal/toriiQueryBuilder.ts (1)
90-103
:⚠️ Potential issueUpdated OrderBy methods to use nested pagination structure
Both
addOrderBy
andwithOrderBy
now operate on the nestedpagination.order_by
property instead of a root-level property. This is a breaking change that aligns with the new pagination structure.
♻️ Duplicate comments (22)
examples/example-node-worker/src/typescript/contracts.gen.ts (5)
7-13
: Function uses inconsistent naming styleThe function uses snake_case (
build_actions_move_calldata
) instead of camelCase which is the TypeScript convention. This is inconsistent with the exported function names in line 52-57 which use camelCase (buildMoveCalldata
).-const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { +const buildActionsMoveCalldata = (direction: CairoCustomEnum): DojoCall => { return { contractName: "actions", entrypoint: "move", calldata: [direction], }; };
15-26
: Function follows inconsistent naming and could use better error handlingThe function uses snake_case which is inconsistent with TypeScript conventions. Additionally, the error handling could benefit from more specific error messages to aid debugging.
-const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { +const actionsMove = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, - build_actions_move_calldata(direction), + buildActionsMoveCalldata(direction), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing move action: ${error}`); throw error; } };
28-34
: Function uses inconsistent naming styleSimilar to the previous function, this uses snake_case instead of the conventional camelCase in TypeScript.
-const build_actions_spawn_calldata = (): DojoCall => { +const buildActionsSpawnCalldata = (): DojoCall => { return { contractName: "actions", entrypoint: "spawn", calldata: [], }; };
36-47
: Function follows inconsistent naming and could use better error handlingSimilar to
actions_move
, this function uses snake_case and has minimal error information in the error handling.-const actions_spawn = async (snAccount: Account | AccountInterface) => { +const actionsSpawn = async (snAccount: Account | AccountInterface) => { try { return await provider.execute( snAccount, - build_actions_spawn_calldata(), + buildActionsSpawnCalldata(), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing spawn action: ${error}`); throw error; } };
52-57
: Inconsistency between function definitions and exportsThe exported function names use camelCase but reference functions defined with snake_case. This inconsistency should be resolved.
return { actions: { - move: actions_move, - buildMoveCalldata: build_actions_move_calldata, - spawn: actions_spawn, - buildSpawnCalldata: build_actions_spawn_calldata, + move: actionsMove, + buildMoveCalldata: buildActionsMoveCalldata, + spawn: actionsSpawn, + buildSpawnCalldata: buildActionsSpawnCalldata, }, };packages/sdk/src/web/experimental/index.ts (1)
95-101
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
126-133
: 🛠️ Refactor suggestionInconsistent handling of numeric types
u64
is parsed asNumber.parseInt
, but it can exceed JavaScript's safe integer range (2^53-1). For consistency with other large integer types, consider converting it toBigInt
.function parsePrimitive(value: torii.Ty): any { switch (value.type_name) { - case "u64": - return Number.parseInt(value.value as string, 16); case "i256": case "i128": case "u256": case "u128": + case "u64": return BigInt(value.value as string); default: return value.value; } }packages/state/src/recs/index.ts (1)
307-333
:⚠️ Potential issueInfinite loop in getEntitiesQuery
The
fetchedEntities
is only retrieved once outside the loop, but the cursor is updated inside the loop. This will lead to an infinite loop or immediate exit because you're not fetching new data on each iteration.- const fetchedEntities = await client.getEntities({ - pagination: { - limit, - cursor, - direction: "Forward", - order_by: orderBy, - }, - clause: clause || undefined, - no_hashed_keys: false, - models: entityModels, - historical, - }); - while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + }); + if (logging) console.log( `Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` ); setEntities(fetchedEntities.items, components, logging); if (Object.keys(fetchedEntities.items).length < limit) { continueFetching = false; } else { cursor = fetchedEntities.next_cursor; } }examples/example-node-worker/main.ts (4)
21-23
:⚠️ Potential issueFix the case in WebSocket global assignment
The code is using
Websocket
(lowercase 'S') when it should beWebSocket
(capital 'S'). This can cause compatibility issues with libraries that expect the standard global name.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
125-132
:⚠️ Potential issueAvoid mutating the shared constant
The function
initPositionFromEvent
modifiesdefaultPositionCount
via thepc
reference, introducing side effects that affect all future callers.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };
136-151
: 🛠️ Refactor suggestionUse iteration instead of
data.pop()
to process multiple entitiesUsing
data.pop()
both mutates the array and processes only the last entity, silently ignoring any others that might have arrived in the same batch.async function onEntityUpdated({ data, error }) { if (error) { console.error(error); return; } - const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - // do whatever you need here - const model = entity.models.dojo_starter; - if (model?.Moves) { - await publishOffchainPositionCount(model.Moves); - } - } + for (const entity of data) { + if (entity && entity.entityId !== "0x0") { + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } + } + } }
175-176
:⚠️ Potential issueRemove unreachable code
The second
return [sub];
statement will never execute because of the precedingreturn [];
statement.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/merge.ts (1)
123-160
: Add unit tests for the deepMerge functionThis is a critical utility function that handles complex merging logic for Cairo types, but it appears to lack test coverage.
Let's verify if there are tests for this function:
#!/bin/bash # Check for tests related to the deepMerge function rg "deepMerge" --type=ts -A 5 -B 5 "packages/sdk/src/__tests__" || echo "No tests found"A comprehensive test suite should include:
- Merging primitive values (overwrites correctly)
- Recursive merging of nested objects
- Handling of arrays (should be overwritten, not merged)
- Treatment of
null
andundefined
properties- Behavior with
CairoOption
andCairoCustomEnum
types🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
38-46
:⚠️ Potential issueFix typo in "positition" field name
There is a typo in the
positition
field name (should be "position"). Since this affects the interface structure, it should be fixed in all occurrences.export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }
128-133
:⚠️ Potential issueEnsure field names in schema match interfaces
The schema definition needs to be updated to match the corrected interface.
PositionCount: { identity: "", - positition: [[0, 0]], + position: [[0, 0]], }, PositionCountValue: { - positition: [[0, 0]], + position: [[0, 0]], },packages/sdk/src/web/index.ts (1)
271-278
: 🛠️ Refactor suggestionEnsure signature array elements are strings
When
signature
is an array ofbigint
s, they're forwarded as-is, butpublishMessage
expectsstring[]
. Convert numeric values to strings.return ok( await client.publishMessage( dataString, - Array.isArray(signature) - ? signature - : [signature.r.toString(), signature.s.toString()] + Array.isArray(signature) + ? signature.map(s => s.toString()) + : [signature.r.toString(), signature.s.toString()] ) );packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-142
:⚠️ Potential issueUpdated static pagination helper method signature
The
withPagination
static method now acceptscursor
,limit
, anddirection
parameters instead of page-based parameters, reflecting the new pagination approach.There's a type issue flagged by the static analyzer:
[error] 133-133: Unexpected any. Specify a different type.
Consider specifying a more specific type for the generic parameter:
- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends SchemaType>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/node/index.ts (5)
50-51
:⚠️ Potential issueClient initialization change
Changed from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
64-65
:⚠️ Potential issueUpdated entity parsing to use items array
The entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects. This change simplifies the data structure but is a breaking change for existing code.Renamed parameter from
dont_include_hashed_keys
tono_hashed_keys
for improved naming consistency.Ensure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
Also applies to: 72-85
119-130
:⚠️ Potential issueUpdated event parsing to use items array
Similar to the entity parsing changes, event parsing now uses arrays from the
.items
property. This aligns event and entity parsing approaches for better consistency.Update all documentation and examples to reflect this structural change in event data handling.
215-230
:⚠️ Potential issueModified generateTypedData signature
The method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain.
Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
240-265
: 🛠️ Refactor suggestionImproved error handling in sendMessage method
The method now:
- Checks for the presence of signer and identity before attempting to send
- Returns a Result type (from neverthrow) with ok/err instead of throwing exceptions
- No longer requires an explicit Account parameter, relying on options.signer and options.identity
This is a breaking change for code that catches exceptions from this method, but improves error handling overall.
However, there's an inconsistency - the function still throws an error in the catch block despite using Result for other error cases. Consider making the error handling consistent:
try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
🧹 Nitpick comments (8)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-3
: Update imports to useimport type
for type-only importsThe imports are only used as types in this file, not as values. Using
import type
ensures they're removed during compilation, resulting in a smaller bundle size.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/state/src/recs/index.ts (2)
189-189
: Inefficient array length checkWhen checking the length of an array,
entities.items.length
is more appropriate thanObject.keys(entities.items).length
.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) {
246-246
: Inefficient array length check in getEventsSame as the previous comment, use direct array length property instead of Object.keys().length.
- if (Object.keys(entities.items).length === 0) { + if (entities.items.length === 0) {examples/example-node-worker/main.ts (1)
110-114
: Use Result handling pattern for error managementThe function uses a try-catch that logs the error and then rethrows it, but the SDK now supports the
Result
pattern fromneverthrow
. Consider handling the error without throwing.try { - await sdk.sendMessage(data); + const result = await sdk.sendMessage(data); + if (result.isErr()) { + console.error(result.error); + } } catch (err) { console.error(err); }packages/sdk/src/internal/merge.ts (2)
76-76
: Avoid the use ofany
typeThe code uses
any
types in multiple places, which disables TypeScript's type checking. This can lead to runtime errors that could have been caught at compile time.-const newEnumContent: Record<string, any> = {}; +const newEnumContent: Record<string, unknown> = {}; -const newEnumContent: Record<string, any> = {}; +const newEnumContent: Record<string, unknown> = {}; -const result = { ...target } as Record<string, any>; +const result = { ...target } as Record<string, unknown>;Also applies to: 96-96, 133-133
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
127-156
: Consider adding specific handling fornull
in comparison logicThe current comparison checks for
source[key] !== null
before checking if it's an object. This might cause issues if you intend to treatnull
as a special case differently from other primitives.if ( - source[key] !== null && typeof source[key] === "object" && !Array.isArray(source[key]) ) {
Or if you want to preserve the current behavior but make it more explicit:
if ( source[key] !== null && typeof source[key] === "object" && !Array.isArray(source[key]) ) { // If the property is an object in both source and target, recursively merge if ( key in target && + target[key] !== null && typeof target[key] === "object" && !Array.isArray(target[key]) ) {
🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (1)
1-3
: Useimport type
for type-only importsUse
import type
syntax for imports that are only used as types to help optimize the compiled output.import type { SchemaType as ISchemaType } from "@dojoengine/sdk"; -import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; +import type { BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
39-45
: Deprecated withOffset is now a no-opThe
withOffset
method has been deprecated and converted to a no-op that returns the builder instance without making any changes. This supports the transition from offset-based to cursor-based pagination.Consider adding more details to the deprecation notice to guide users toward using the new cursor-based pagination methods.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (43)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(3 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(4 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)worlds/onchain-dash
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
- packages/sdk/src/internal/parseHistoricalEvents.ts
✅ Files skipped from review due to trivial changes (3)
- worlds/onchain-dash
- packages/sdk/src/tests/state.test.ts
- .changeset/thirty-cheetahs-design.md
🚧 Files skipped from review as they are similar to previous changes (24)
- examples/example-nodejs-bot/package.json
- packages/torii-client/package.json
- packages/torii-wasm/dojo.c
- packages/sdk/package.json
- packages/core/package.json
- examples/example-node-worker/env.ts
- turbo.json
- packages/sdk/src/internal/errors.ts
- packages/sdk/src/node/worker.ts
- packages/react/package.json
- packages/sdk/src/web/react/hooks/hooks.ts
- .github/workflows/release.yaml
- examples/example-node-worker/dojoConfig.ts
- .github/workflows/ci.yaml
- package.json
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- packages/sdk/src/tests/parseEntities.test.ts
- packages/sdk/src/web/react/hooks/events.ts
- examples/example-node-worker/package.json
- examples/example-node-worker/tsconfig.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/internal/types.ts
- packages/sdk/src/internal/generateTypedData.ts
- packages/sdk/src/internal/models.ts
🧰 Additional context used
🧬 Code Graph Analysis (8)
packages/sdk/src/web/react/hooks/entities.ts (2)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)packages/sdk/src/web/queryBuilder.ts (2)
entity
(72-80)entity
(100-105)
packages/sdk/src/web/index.ts (5)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/sdk/src/web/experimental/index.ts (2)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (21)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Style change for better code formattingThe code change maintains the same functionality while breaking the property access across multiple lines for better readability in complex nested expressions.
Note: There are two static analysis warnings about non-null assertions on line 133. While not introduced by this change, you might consider using optional chaining (
?.
) instead of non-null assertions (!
) in the future for better type safety.🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
examples/example-vite-react-sdk/src/historical-events.tsx (2)
4-5
: Updated import to use specialized HistoricalToriiQueryBuilderThe specialized
HistoricalToriiQueryBuilder
is now imported instead of the genericToriiQueryBuilder
, which aligns with the SDK's architectural changes.Consider using
import type { ParsedEntity }
for type-only imports to optimize bundling:import { KeysClause, - ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
14-14
: Updated to use HistoricalToriiQueryBuilderThe implementation now uses the specialized
HistoricalToriiQueryBuilder
which automatically sets thehistorical
flag to true, improving code clarity and intent.packages/sdk/src/web/state/zustand.ts (1)
14-14
: Improved code organization by centralizing merge utilitiesThe previous local implementation of Cairo type merging functions has been replaced with imports from a centralized utility module. This improves maintainability by keeping all merging logic in one place.
Consider using
import type
for theMergedModels
type to optimize bundling:-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/react/hooks/entities.ts (2)
22-24
: Improved function body clarityChanged from implicit return to explicit block statement for the
processInitialData
callback, which better represents that this function performs an action without returning a meaningful value.
26-35
:✅ Verification successful
Enhanced entity filtering logic and update behavior
The updated implementation improves how entities with zero IDs are filtered:
- Uses
Number.parseInt(e.entityId, 16) !== 0
which is more robust than string comparison- Uses the first entity (
entities[0]
) instead of the last one (entities.pop()
)This change aligns with the SDK's unified approach to entity and event data processing.
Verify that using the first entity instead of the last one in the array doesn't cause any issues with your application logic:
🏁 Script executed:
#!/bin/bash # Look for patterns where multiple entities are expected in update data rg -A 5 "updateEntity" --no-ignore-vcsLength of output: 12707
No issues with first-entity selection
I’ve verified that across the SDK and example code,
updateEntity
is always called with the first filtered element. There are no patterns where downstream logic expects the last element:• examples/example-vite-phaser-sdk/src/scenes/Game.ts uses
data[0]
• No occurrences of multiple-entity handling rely on.pop()
or the last itemThis change is consistent with the unified entity/event processing and can be approved.
packages/sdk/src/web/experimental/index.ts (4)
27-32
: Updated entity and event fetching to handle paginated resultsThe code now correctly extracts the
.items
array from client responses, aligning with the new cursor-based pagination approach.
53-59
: Update entity data handling in callbackThe callback now correctly parses a single entity from an array, matching the changes in the
parseEntities
function that now expects an array of entities.
98-100
: Update event data handling in callbackSimilar to the entity callback, this correctly adapts to the new array-based entity parsing.
23-23
:✅ Verification successful
Changed client creation from async to sync
The client initialization has been updated from using an asynchronous factory method to a synchronous constructor. Make sure to verify this doesn't affect callers expecting a Promise.
🏁 Script executed:
#!/bin/bash # Check for any usages of createClient that might need updating echo "Searching for usages of createClient that might need updating" rg -A 2 "createClient" --type tsLength of output: 13516
🏁 Script executed:
#!/bin/bash # Search for any imports or references to the experimental module rg -n "experimental" --type tsLength of output: 427
🏁 Script executed:
#!/bin/bash # Display the contents of the experimental index file to inspect exports sed -n '1,200p' packages/sdk/src/web/experimental/index.tsLength of output: 4431
Client instantiation remains async to consumers
We still exportinit
as anasync
function returning a Promise of the SDK methods. Although we now callnew ToriiClient(...)
synchronously under the hood, callers continue toawait init(...)
with no change to their code.No further updates required.
packages/sdk/src/internal/parseEntities.ts (3)
10-13
: Updated function signature for array-based entity handlingThe function now accepts an array of entities rather than an object, aligning with the new cursor-based pagination approach that returns items as arrays.
17-25
: Refactored entity parsing for array inputsThe entity parsing logic has been updated to iterate over an array of entities rather than object keys, which is more efficient and aligns with the changes in the API response format.
90-93
: Added support for tuple type parsingTuple type support has been added to the
parseValue
function, ensuring that tuple types in Cairo are correctly handled. This is handled similarly to arrays by mapping over the value elements.packages/state/src/recs/index.ts (1)
168-179
: Updated pagination to use cursor-based approachThe pagination logic has been updated to use cursor-based pagination (with
cursor
anddirection: "Forward"
) instead of offset-based pagination. The query parameterdont_include_hashed_keys
has been renamed tono_hashed_keys
for clarity.packages/sdk/src/internal/toriiQueryBuilder.ts (3)
47-55
: Added new withCursor method for cursor-based paginationGood addition! This method allows setting the cursor for pagination, which is essential for the new cursor-based pagination approach.
57-63
: Added new withDirection method for pagination directionThis method properly implements the ability to set pagination direction, completing the cursor-based pagination API.
145-158
: Added HistoricalToriiQueryBuilder for historical queriesGood addition! This subclass extends ToriiQueryBuilder with the
historical
flag set to true by default, making it easier to create historical queries without having to set this flag manually.packages/sdk/src/node/index.ts (4)
19-37
: Improved imports and exports for better error handling and type safetyThe changes:
- Removed unnecessary imports from "starknet"
- Added Result, err, ok from "neverthrow" for better error handling
- Added NO_IDENTITY and NO_SIGNER constants for consistent error messages
- Added exports for worker.ts, internal types, and models
These changes improve error handling and support new worker-based usage patterns.
138-143
: Consistent event callback data parsingThe event callback now parses a single entity into an array using
parseEntities([entityData])
, consistent with the entity callback approach. This ensures uniformity in how entity data is parsed throughout the SDK.
189-204
: Simplified entity and event queryingThe entity and event querying methods now access
.items
before parsing, consistent with the updated data structure. This matches the subscription callback approach and ensures data is processed uniformly throughout the SDK.
385-392
: Updated query conversion methods to use consistent item parsingThe methods
toriiQueryIntoHashedKeys
andtoriiEventMessagesQueryIntoHashedKeys
have been updated to:
- Use
.items
before parsing, consistent with other methods- Use the same parsing approach for entities and events
The
historical
parameter has been removed fromtoriiEventMessagesQueryIntoHashedKeys
, simplifying the API.These changes ensure consistency across the SDK and align with the cursor-based pagination model.
Also applies to: 401-414
sendMessage: async ( | ||
data: TypedData, | ||
account: Account | ||
): Promise<void> => { | ||
account?: Account | ||
): Promise<Result<Uint8Array, string>> => { | ||
if (!account) { | ||
return err(NO_ACCOUNT); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use configured signer and identity when account is not provided
The method checks if an account is provided and returns an error if not, but it should utilize the configured signer and identity from the SDK initialization.
sendMessage: async (
data: TypedData,
account?: Account
): Promise<Result<Uint8Array, string>> => {
- if (!account) {
- return err(NO_ACCOUNT);
- }
+ // Try to use provided account, fall back to configured signer and identity
+ if (!account && options.signer && options.identity) {
+ // Use the configured signer and identity
+ try {
+ // Implementation details depend on how your signer works,
+ // but you would need to create or use a signing mechanism
+ // with the configured signer and identity
+ // e.g., something like:
+ // const signature = options.signer.sign(data, options.identity);
+ // ...
+ } catch (error) {
+ return err(`Failed to sign with configured signer: ${String(error)}`);
+ }
+ } else if (!account) {
+ return err(NO_ACCOUNT);
+ }
Committable suggestion skipped: line range outside the PR's diff.
includeHashedKeys(): ToriiQueryBuilder<T> { | ||
this.query.dont_include_hashed_keys = false; | ||
this.query.no_hashed_keys = false; | ||
return this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed flag for hashed keys inclusion
The property was renamed from dont_include_hashed_keys
to no_hashed_keys
for improved naming consistency.
This is a breaking change that should be documented in the migration guide.
this.query.models.push(model); | ||
return this; | ||
} | ||
|
||
/** | ||
* Set multiple entity models at once | ||
*/ | ||
withEntityModels(models: (keyof T & string)[]): ToriiQueryBuilder<T> { | ||
this.query.entity_models = models; | ||
return this; | ||
} | ||
|
||
/** | ||
* Set the minimum timestamp for entity updates | ||
*/ | ||
updatedAfter(timestamp: number): ToriiQueryBuilder<T> { | ||
this.query.entity_updated_after = timestamp; | ||
this.query.models = models; | ||
return this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed entity models property
The property was renamed from entity_models
to models
for consistency and clarity.
This is a breaking change that should be documented in the migration guide.
ff82d6f
to
34c97ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🔭 Outside diff range comments (2)
packages/sdk/src/web/index.ts (1)
279-282
:⚠️ Potential issueError handling inconsistency
The method returns a Result type to handle errors in a structured way, but still throws errors in the catch block instead of returning
err()
.Fix the inconsistency by returning an error result instead of throwing:
} catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }packages/sdk/src/node/index.ts (1)
267-269
:⚠️ Potential issueError handling inconsistency
The method returns a Result type but still throws errors in the catch block instead of returning
err()
.Fix the inconsistency by returning an error result instead of throwing:
} catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }
♻️ Duplicate comments (17)
examples/example-node-worker/src/typescript/contracts.gen.ts (5)
7-13
: Function uses inconsistent naming styleThe function uses snake_case (
build_actions_move_calldata
) instead of camelCase which is the TypeScript convention. This is inconsistent with the exported function names in line 52-57 which use camelCase (buildMoveCalldata
).-const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { +const buildActionsMoveCalldata = (direction: CairoCustomEnum): DojoCall => { return { contractName: "actions", entrypoint: "move", calldata: [direction], }; };
15-26
: Function follows inconsistent naming and could use better error handlingThe function uses snake_case which is inconsistent with TypeScript conventions. Additionally, the error handling could benefit from more specific error messages to aid debugging.
-const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { +const actionsMove = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, - build_actions_move_calldata(direction), + buildActionsMoveCalldata(direction), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing move action: ${error}`); throw error; } };
28-34
: Function uses inconsistent naming styleSimilar to the previous function, this uses snake_case instead of the conventional camelCase in TypeScript.
-const build_actions_spawn_calldata = (): DojoCall => { +const buildActionsSpawnCalldata = (): DojoCall => { return { contractName: "actions", entrypoint: "spawn", calldata: [], }; };
36-47
: Function follows inconsistent naming and could use better error handlingSimilar to
actions_move
, this function uses snake_case and has minimal error information in the error handling.-const actions_spawn = async (snAccount: Account | AccountInterface) => { +const actionsSpawn = async (snAccount: Account | AccountInterface) => { try { return await provider.execute( snAccount, - build_actions_spawn_calldata(), + buildActionsSpawnCalldata(), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing spawn action: ${error}`); throw error; } };
51-58
: Inconsistency between function definitions and exportsThe exported function names use camelCase but reference functions defined with snake_case. This inconsistency should be resolved.
return { actions: { - move: actions_move, - buildMoveCalldata: build_actions_move_calldata, - spawn: actions_spawn, - buildSpawnCalldata: build_actions_spawn_calldata, + move: actionsMove, + buildMoveCalldata: buildActionsMoveCalldata, + spawn: actionsSpawn, + buildSpawnCalldata: buildActionsSpawnCalldata, }, };packages/sdk/src/web/experimental/index.ts (1)
95-95
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
127-133
: 🛠️ Refactor suggestionPotential precision loss with u64 values
The function parses "u64" values as
Number.parseInt
which may cause precision loss for large values. JavaScript's Number type can safely represent integers up to 2^53-1, but u64 can go up to 2^64-1.switch (value.type_name) { case "u64": - return Number.parseInt(value.value as string, 16); + return BigInt(value.value as string); case "i256": case "i128": case "u256": case "u128": return BigInt(value.value as string);examples/example-node-worker/main.ts (4)
21-25
: Wrong global identifier: useWebSocket
, notWebsocket
Browsers (and most polyfills) expose
global.WebSocket
(uppercase S).
Assigning toWebsocket
leaves libraries that expectWebSocket
undefined.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
125-134
:initPositionFromEvent
mutates the shared constant
pc
is an alias ofdefaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };
175-176
: Unreachable code after the firstreturn
The second
return [sub];
can never execute—Biome rightfully flags it.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
137-151
: 🛠️ Refactor suggestionPotential data loss with
data.pop()
data
is already the argument supplied by the subscription.
Callingpop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.- const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - // do whatever you need here - const model = entity.models.dojo_starter; - if (model?.Moves) { - await publishOffchainPositionCount(model.Moves); - } - } + for (const entity of data) { + if (entity && entity.entityId !== "0x0") { + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } + } + }packages/state/src/recs/index.ts (3)
307-333
:⚠️ Potential issueInfinite pagination loop – fetch happens outside the
while
fetchedEntities
is requested once before the loop; inside the loop no new page is fetched, socursor
advances without fresh data, causing either an immediate exit or an infinite loop.Move the
client.getEntities
call inside thewhile
block (mirroring the pattern used ingetEntities
andgetEvents
).
246-247
:⚠️ Potential issueSame array-length issue in getEvents
Replicate the fix applied above:
- if (Object.keys(entities.items).length === 0) { + if (entities.items.length === 0) {
189-190
:⚠️ Potential issueIncorrect length check for an array
entities.items
is an array; usingObject.keys
is slower and semantically wrong.
Switch to.length
directly.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) {examples/example-node-worker/src/typescript/models.gen.ts (1)
40-46
:⚠️ Potential issueFix typo
positition
→position
The misspelled field propagates to interfaces, schema defaults and any generated clients, breaking type-safe access.
- positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>;Apply the same correction in
PositionCountValue
and theschema
object.Also applies to: 128-133
packages/sdk/src/web/index.ts (1)
271-278
: 🛠️ Refactor suggestionPotential type mismatch in signature handling
The code handles both array and non-array signature formats, but doesn't convert array elements to strings when signature is an array.
Ensure consistent string conversion for all signature formats:
return ok( await client.publishMessage( dataString, Array.isArray(signature) - ? signature + ? signature.map((x) => x.toString()) : [signature.r.toString(), signature.s.toString()] ) );packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-142
:⚠️ Potential issueUpdated static pagination helper method signature
The
withPagination
static method now acceptscursor
,limit
, anddirection
parameters instead of page-based parameters, reflecting the new pagination approach.There's a type issue flagged by the static analyzer:
[error] 133-133: Unexpected any. Specify a different type.
Consider specifying a more specific type for the generic parameter:
- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends SchemaType>(🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
🧹 Nitpick comments (10)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Code readability improvement with multi-line property accessThe refactoring improves readability by breaking the long property access chain into multiple lines, making it easier to understand the nested structure.
However, there are some issues that should be addressed:
- The code uses non-null assertions (
!
), which can lead to runtime errors if the properties are unexpectedly null.- The string literal in bracket notation could be simplified if "entity500" is a valid identifier.
Consider replacing the non-null assertions with optional chaining and potentially simplify the bracket notation:
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + draft.entities["entity500"]?.models.world?.item?.durability = 75;Or even better, if you want to handle the potential nullish values safely:
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + const entity = draft.entities["entity500"]; + if (entity?.models.world?.item) { + entity.models.world.item.durability = 75; + }🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Updated import to use specialized HistoricalToriiQueryBuilderGood update to use the specialized
HistoricalToriiQueryBuilder
which better reflects the historical querying intent of this component.Consider using
import type
for type-only imports to improve compilation efficiency:-import { - KeysClause, - ParsedEntity, - HistoricalToriiQueryBuilder, -} from "@dojoengine/sdk"; +import { + KeysClause, + HistoricalToriiQueryBuilder, +} from "@dojoengine/sdk"; +import type { ParsedEntity } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Centralized merge utilities for improved maintainabilityGood refactoring to import centralized merge utilities instead of using local implementations. This promotes code reuse and maintainability.
Since
MergedModels
is only used as a type, consider using theimport type
syntax:-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-3
: Consider usingimport type
for type-only importsFor better tree-shaking and to ensure imported types are removed during compilation, consider using the
import type
syntax for type imports.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import type { DojoProvider, DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; import * as models from "./models.gen";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/state/src/recs/index.ts (1)
185-185
: Avoid unnecessary template literal
console.log
does not interpolate any variables here, so a simple string literal is clearer and avoids the Biome warning.- if (logging) console.log(`Fetched entities`, entities.items); + if (logging) console.log("Fetched entities", entities.items);🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/internal/merge.ts (2)
76-83
: Avoidany
in new enum constructionUsing
Record<string, any>
loses type safety and is flagged by Biome.
Since variant keys come fromCairoCustomEnum["variant"]
, you can preserve types:-const newEnumContent: Record<string, any> = {}; +const newEnumContent: { [K in keyof typeof target.variant]?: typeof sourceValue } = {};Also applies to: 96-103
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
133-155
: Recursive merge mutates nested object type
result[key] = deepMerge(target[key], source[key]);
The recursive call returnsMergedModels<T>
butresult
is typed asRecord<string, any>
, losing compile-time safety and raisingany
warnings downstream.Introduce a generic helper and tighten the result type:
-const result = { ...target } as Record<string, any>; +const result: typeof target = { ...target };🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (1)
3-3
: Import only types where possible
BigNumberish
is a type-only import; switch toimport type
to reduce bundle size.-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; +import type { BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/index.ts (1)
236-247
: Updated generateTypedData signatureThe method signature has changed to:
- Remove the optional domain parameter
- Add an optional additionnalTypes parameter
- Always use options.domain as the domain value
This is more consistent but could be a breaking change for code that explicitly passed a different domain.
Consider fixing the typo in the parameter name:
- additionnalTypes?: Record< + additionalTypes?: Record<packages/sdk/src/node/index.ts (1)
242-242
: Unused account parameterThe
_account
parameter is accepted but unused (indicated by the underscore prefix), as the method now relies onoptions.signer
andoptions.identity
.Consider removing the parameter entirely or clarifying its purpose through better documentation, since it's confusing to accept a parameter that's not used.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (43)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(3 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(6 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)worlds/onchain-dash
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
- packages/sdk/src/internal/parseHistoricalEvents.ts
✅ Files skipped from review due to trivial changes (1)
- .changeset/thirty-cheetahs-design.md
🚧 Files skipped from review as they are similar to previous changes (26)
- package.json
- worlds/onchain-dash
- packages/torii-wasm/dojo.c
- packages/sdk/package.json
- examples/example-node-worker/dojoConfig.ts
- packages/torii-client/package.json
- examples/example-node-worker/env.ts
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- .github/workflows/ci.yaml
- packages/react/package.json
- turbo.json
- packages/core/package.json
- packages/sdk/src/node/worker.ts
- packages/sdk/src/tests/parseEntities.test.ts
- packages/sdk/src/internal/errors.ts
- packages/sdk/src/web/react/hooks/entities.ts
- packages/sdk/src/tests/state.test.ts
- .github/workflows/release.yaml
- packages/sdk/src/internal/generateTypedData.ts
- examples/example-node-worker/tsconfig.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- examples/example-nodejs-bot/package.json
- packages/sdk/src/web/react/hooks/events.ts
- examples/example-node-worker/package.json
- packages/sdk/src/internal/types.ts
- packages/sdk/src/internal/models.ts
🧰 Additional context used
🧬 Code Graph Analysis (8)
examples/example-node-worker/main.ts (9)
packages/sdk/src/node/index.ts (1)
init
(43-417)examples/example-node-worker/dojoConfig.ts (1)
dojoConfig
(7-9)examples/example-node-worker/env.ts (1)
env
(9-9)examples/example-node-worker/src/typescript/models.gen.ts (3)
PositionCount
(38-41)Moves
(17-22)SchemaType
(80-94)packages/sdk/src/internal/toriiQueryBuilder.ts (2)
ToriiQueryBuilder
(24-143)HistoricalToriiQueryBuilder
(149-159)packages/sdk/src/internal/types.ts (3)
ToriiQueryBuilder
(557-557)ParsedEntity
(228-237)SchemaType
(50-70)packages/sdk/src/node/clauseBuilder.ts (1)
KeysClause
(46-52)packages/sdk/src/internal/models.ts (1)
getModel
(38-52)packages/sdk/src/node/worker.ts (1)
createWorker
(25-44)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/web/index.ts (5)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
packages/sdk/src/web/experimental/index.ts
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/react/hooks/hooks.ts
[error] 72-72: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (30)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: Using HistoricalToriiQueryBuilder instead of ToriiQueryBuilderThe component now correctly uses the specialized
HistoricalToriiQueryBuilder
which has thehistorical
flag set to true by default, simplifying the query building process.packages/sdk/src/web/react/hooks/hooks.ts (4)
7-7
: Added ParsedEntity to importsGood addition of the
ParsedEntity
type to the imports, necessary for the type changes in the component.
18-18
: Added trailing comma after type parameterMinor stylistic change that helps with cleaner git diffs for future changes to type parameters.
32-33
: Updated callback types to handle arrays of ParsedEntityThis is a significant change that aligns with the SDK's shift towards handling arrays of parsed entities rather than objects keyed by entity IDs.
65-67
: Updated data processing to cast to ParsedEntity arraysThe changes ensure that data is properly cast to the expected
ParsedEntity<Schema>[]
type in the callbacks.Also applies to: 75-77, 90-92
packages/sdk/src/web/experimental/index.ts (4)
27-27
: Client response structure changeThe code now extracts
.items
from the response before parsing. This indicates a change in the return structure ofclient.getEntities
. Ensure all client usage is updated consistently.
38-38
: Changed query property nameThe property name has changed from
dont_include_hashed_keys
tono_hashed_keys
. Ensure all client code is updated to use the new property name.
53-59
: Changed entity update callback to handle arraysThe callback now processes arrays of entities instead of objects keyed by entity ID. This is a breaking change that affects how developers handle entity updates in their code.
23-23
:❓ Verification inconclusive
Client initialization changed from async to sync
The client initialization was changed from asynchronous to synchronous, which is a significant change. Make sure this is intentional and that no initialization logic that requires awaiting is lost.
🏁 Script executed:
#!/bin/bash # Check for any potential async initialization in ToriiClient that might be bypassed rg -B5 -A2 "ToriiClient" --multiline packages/Length of output: 10696
Confirm synchronous ToriiClient initialization
The experimental Web SDK now instantiates the Torii client without
await
:// packages/sdk/src/web/experimental/index.ts:23 const client = new torii.ToriiClient(clientConfig);However, the existing Web (
packages/sdk/src/web/index.ts
) and Node (packages/sdk/src/node/index.ts
) entrypoints use:const client = await new torii.ToriiClient(config);Please verify that the
ToriiClient
constructor does not perform any asynchronous setup (i.e., it doesn’t return a Promise requiringawait
). If it does, restore theawait
to ensure all initialization logic completes before use.packages/sdk/src/internal/parseEntities.ts (3)
17-20
: Updated iteration logic for entity arraysThe function now iterates over an array of entities instead of a keyed object, extracting
entityId
fromhashed_keys
andentityData
frommodels
. This change reflects a fundamental shift in how entity data is structured.
90-93
: Added support for tuple typeThe function now handles the "tuple" type similar to "array" when parsing values. This enhances compatibility with Cairo types.
10-13
:❌ Incorrect review comment
Function signature change impacts all callers
The function now accepts an array of
torii.Entity
objects instead of a keyed object. This is a major API change that affects all callers of this function.
🏁 Script executed:
#!/bin/bash # Check how widespread the usage of parseEntities is echo "=== Searching for parseEntities calls ===" rg "parseEntities\(" --no-ignore packages/ examples/ -B2 -A2Length of output: 4182
No breaking change detected for parseEntities
All callers already pass arrays of torii.Entity to parseEntities, so the updated signature aligns with existing usage. You can disregard the previous API-impact concern.• Usage locations confirmed:
– packages/sdk/src/node/index.ts
– packages/sdk/src/web/index.ts
– packages/sdk/src/web/experimental/index.ts
– packages/sdk/src/tests/parseEntities.test.tsLikely an incorrect or invalid review comment.
examples/example-node-worker/main.ts (1)
27-42
: Comprehensive SDK initialization with identity and signerThe SDK initialization now includes domain metadata, identity, and signer configuration. This is a good practice for proper authentication and message signing.
packages/state/src/recs/index.ts (1)
168-179
:❓ Verification inconclusive
Verify
order_by
nestingThe Torii client previously accepted
order_by
at the root level, not insidepagination
. Placing it underpagination
may be ignored by the API.Run the following quick check against the client types:
Also applies to: 230-240
🏁 Script executed:
#!/bin/bash # Inspect ToriiClient method signature to confirm pagination shape grep -R --line-number "interface Pagination" $(npm root)/@dojoengine/torii-client | headLength of output: 212
Verify placement of
order_by
in getEntities callThe Torii client’s
getEntities
API may expect theorder_by
parameter at the top level of the request rather than nested insidepagination
. If it’s nested, it could be silently ignored. Please confirm the request shape in the Torii client type definitions and adjust accordingly:- await client.getEntities({ - pagination: { - limit, - cursor, - direction: "Forward", - order_by: orderBy, - }, - clause: clause || undefined, - no_hashed_keys: false, - models: entityModels, - historical, - }); + await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + }, + order_by: orderBy, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + });Also applies to lines 230–240.
packages/sdk/src/internal/merge.ts (1)
127-132
: Type guard ordering indeepMerge
The function first checks for Cairo-specific types, but when only one side is a
CairoOption
/CairoCustomEnum
the merge falls through to generic object logic, returning an object instead of the expected wrapped type, potentially violating invariants.Consider early-returning the target when the wrappers differ:
if (isCairoOption(target) !== isCairoOption(source) || isCairoCustomEnum(target) !== isCairoCustomEnum(source)) { return target; }packages/sdk/src/web/index.ts (5)
30-31
: Good addition of error handling utilitiesAdded error handling using the
neverthrow
library for functional error handling withResult
types, and imported error constants from a centralized location.
257-263
: Improved error handling in sendMessageThe method now accepts an optional account parameter and returns a Result type instead of throwing errors directly when no account is provided. This is a good improvement for error handling consistency.
92-94
: Updated entity and event parsing to use items arrayEntity and event parsing now consistently access the
.items
property of the response before parsing. This aligns with changes in response data structure from the Torii client.Also applies to: 147-149, 206-206, 219-221
99-104
: Updated subscription callbacks to parse single entitiesSubscription callbacks now parse arrays containing a single entity instead of objects keyed by ID, reflecting the updated data shape returned by the client.
Also applies to: 158-160
48-48
:✅ Verification successful
Client initialization now uses direct instantiation
Changed from
torii.createClient(config)
to direct instantiation withnew torii.ToriiClient(config)
. This aligns with similar changes in the node SDK and experimental web SDK.
🏁 Script executed:
#!/bin/bash # Check if all client initializations are consistent across the codebase rg -A 2 -B 2 "torii\.ToriiClient" --glob "*.ts"Length of output: 5797
Client instantiation consistency verified
All client initializations across the SDKs and example apps now use direct instantiation via
new torii.ToriiClient(config)
, matching the node SDK and experimental web SDK. No further changes required.packages/sdk/src/internal/toriiQueryBuilder.ts (3)
43-55
: Transition from offset to cursor-based paginationThe
withOffset
method is now deprecated in favor of the newwithCursor
method, reflecting a shift to cursor-based pagination which is more efficient for large datasets.
57-62
: Added direction support for paginationNew
withDirection
method supports specifying the traversal direction in cursor-based pagination, which is useful for implementing infinite scrolling in both directions.
145-159
: Added HistoricalToriiQueryBuilder classNew specialized class that extends ToriiQueryBuilder with the historical flag set to true by default, making it more convenient to work with historical queries.
packages/sdk/src/node/index.ts (7)
50-50
: Client initialization now uses direct instantiationChanged from
torii.createClient(config)
to direct instantiation withnew torii.ToriiClient(config)
. This aligns with similar changes in the web SDK.
34-36
: Added exports for worker module and other utilitiesNew exports for worker, types, and models modules enhance the SDK's functionality and make it easier to use these modules from external code.
244-249
: Improved error handling in sendMessageNow checks for the presence of
options.signer
andoptions.identity
and returns a Result type instead of throwing errors. This is a significant improvement for error handling.
251-265
: Updated message signing approachNow uses
torii.TypedData
encoding with the configured identity and signer, which provides a more streamlined approach to message signing.
72-74
: Updated entity and event parsing to use items arrayEntity and event parsing now consistently access the
.items
property of the response before parsing, reflecting changes in the Torii client response structure.Also applies to: 127-130, 189-189, 202-204
79-84
: Updated subscription callbacks to parse single entitiesSubscription callbacks now parse arrays containing a single entity instead of objects keyed by ID, reflecting the updated data shape returned by the client.
Also applies to: 138-143
219-230
: Updated generateTypedData signatureThe method signature has changed to:
- Remove the optional domain parameter
- Add an optional additionalTypes parameter
- Always use options.domain as the domain value
This is more consistent with the web SDK implementation.
// subscriptionRef.current?.free(); | ||
// subscriptionRef.current = null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleanup function is commented out
The cleanup function that should free the subscription reference is commented out, which could lead to memory leaks.
Uncomment and fix the cleanup function to properly free resources:
- // subscriptionRef.current?.free();
- // subscriptionRef.current = null;
+ subscriptionRef.current.free();
+ subscriptionRef.current = null;
getEvents: async (query: torii.Query) => { | ||
const events = await client.getEventMessages(query); | ||
return parseEntities(events.items); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Removed historical parameter in getEvents
The historical
parameter has been removed from the getEvents
function. Make sure this change is intentional and documented, as it may affect backward compatibility.
🏁 Script executed:
#!/bin/bash
# Check for usages of getEvents with historical parameter that might break
rg "getEvents.*historical.*true" -B1 -A1 --exclude="*.ts.old" examples/ | grep -v "^binary file"
Length of output: 510
🏁 Script executed:
#!/bin/bash
# Search for getEvents calls with multiple parameters (potential historical flag usage)
echo "=== Multi-argument getEvents calls ==="
rg -n "getEvents\(" . | grep "," || echo "None found"
# Search specifically for 'historical' coupled with getEvents
echo -e "\n=== 'historical' in getEvents contexts ==="
rg -n "historical" . | grep "getEvents" || echo "None found"
Length of output: 326
Document removal of historical
parameter in getEvents
We’ve confirmed there are no internal calls passing a historical
flag to getEvents
, but its removal is a breaking change for consumers. Please update your public-facing documentation and release notes to reflect this.
• File: packages/sdk/src/web/experimental/index.ts (lines 29–32)
getEvents(query: torii.Query)
no longer accepts ahistorical
argument.
• Action: Add a note in CHANGELOG.md and the SDK migration guide about the removedhistorical
parameter.
if (dbConnection) { | ||
await insertEntitiesInDB(dbConnection, entities); | ||
await insertEntitiesInDB(dbConnection, entities.items); | ||
} | ||
|
||
if (logging) console.log(`Fetched entities`, entities); | ||
if (logging) console.log(`Fetched entities`, entities.items); | ||
|
||
setEntities(entities, components, logging); | ||
setEntities(entities.items, components, logging); | ||
|
||
if (Object.keys(entities).length < limit) { | ||
if (Object.keys(entities.items).length < limit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Database insert treats entity array as object
insertEntitiesInDB
receives an array but iterates with Object.entries
, producing numeric indices instead of real entity IDs.
Store the actual hashed_keys
(or another stable ID) and iterate directly:
-for (const [entityId, data] of Object.entries(entities)) {
- const entityData = { id: entityId, ...data };
+for (const entity of entities) {
+ const entityId = entity.hashed_keys?.join(".") ?? crypto.randomUUID();
+ const entityData = { id: entityId, ...entity };
const request = store.put(entityData);
Also applies to: 541-553
🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
@@ -49,7 +75,7 @@ | |||
* HashedKeys represent internal torii entity id. | |||
*/ | |||
includeHashedKeys(): ToriiQueryBuilder<T> { | |||
this.query.dont_include_hashed_keys = false; | |||
this.query.no_hashed_keys = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed properties for improved clarity
Properties were renamed for consistency and clarity:
dont_include_hashed_keys
→no_hashed_keys
entity_models
→models
These changes make the API more intuitive but are breaking changes.
Ensure these breaking changes are documented in the migration guide.
Also applies to: 110-110, 118-118
34c97ec
to
b159d72
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (3)
packages/state/src/recs/index.ts (1)
541-553
:⚠️ Potential issueDatabase insert treats entity array as object
insertEntitiesInDB
receives an array but iterates withObject.entries
, producing numeric indices instead of real entity IDs.
Store the actualhashed_keys
(or another stable ID) and iterate directly:-for (const [entityId, data] of Object.entries(entities)) { - const entityData = { - id: entityId, - ...data, - }; +for (const entity of entities) { + const entityId = entity.hashed_keys?.join(".") ?? crypto.randomUUID(); + const entityData = { + id: entityId, + ...entity, + }; const request = store.put(entityData);packages/sdk/src/web/index.ts (1)
257-282
:⚠️ Potential issueHandle errors consistently with Result in
sendMessage
The function returns a
Result
type but still throws in the catch block, which defeats the purpose of usingResult
for error handling. Ensure consistency by always returningerr
instead of throwing.} catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }packages/sdk/src/node/index.ts (1)
240-270
: 🛠️ Refactor suggestionImproved error handling in sendMessage method
The sendMessage method now:
- Checks for the presence of signer and identity before attempting to send
- Returns a Result type (from neverthrow) with ok/err instead of throwing exceptions
- No longer requires an explicit Account parameter, relying on options.signer and options.identity
The function still throws an error in the catch block despite using Result for other error cases. Consider making the error handling consistent by returning
err
in the catch block as well:try { const td = new torii.TypedData(JSON.stringify(data)).encode( options.identity ); const sig = options.signer.sign(td); const dataString = JSON.stringify(data); return ok( await client.publishMessage(dataString, [ sig.r.toString(), sig.s.toString(), ]) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
♻️ Duplicate comments (23)
examples/example-node-worker/package.json (1)
6-10
:⚠️ Potential issueRemove hardcoded credentials from scripts
The scripts contain hardcoded private keys and identity values, which is a security risk. These should be moved to environment variables loaded from a .env file instead.
"scripts": { - "bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", - "node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts", + "bun": "bun run main.ts", + "node": "node main.ts", "build": "tsc -b" },Since
dotenv
is already added as a dependency (line 15), use it to load these values from a .env file instead, which should be added to .gitignore.🧰 Tools
🪛 Gitleaks (8.21.2)
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
packages/sdk/src/web/react/hooks/hooks.ts (1)
121-123
:⚠️ Potential issueCleanup function is still commented out
The cleanup function that should free the subscription reference remains commented out, which could lead to memory leaks.
Uncomment and fix the cleanup function to properly free resources:
- // subscriptionRef.current?.free(); - // subscriptionRef.current = null; + subscriptionRef.current?.free(); + subscriptionRef.current = null;examples/example-node-worker/src/typescript/contracts.gen.ts (5)
7-13
: Function uses inconsistent naming styleThe function uses snake_case (
build_actions_move_calldata
) instead of camelCase, which is the TypeScript convention. This is inconsistent with the exported function names in line 52-57 which use camelCase (buildMoveCalldata
).-const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { +const buildActionsMoveCalldata = (direction: CairoCustomEnum): DojoCall => { return { contractName: "actions", entrypoint: "move", calldata: [direction], }; };
15-26
: Function follows inconsistent naming and could use better error handlingThe function uses snake_case which is inconsistent with TypeScript conventions. Additionally, the error handling could benefit from more specific error messages to aid debugging.
-const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { +const actionsMove = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, - build_actions_move_calldata(direction), + buildActionsMoveCalldata(direction), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing move action: ${error}`); throw error; } };
28-34
: Function uses inconsistent naming styleSimilar to the previous function, this uses snake_case instead of the conventional camelCase in TypeScript.
-const build_actions_spawn_calldata = (): DojoCall => { +const buildActionsSpawnCalldata = (): DojoCall => { return { contractName: "actions", entrypoint: "spawn", calldata: [], }; };
36-47
: Function follows inconsistent naming and could use better error handlingSimilar to
actions_move
, this function uses snake_case and has minimal error information in the error handling.-const actions_spawn = async (snAccount: Account | AccountInterface) => { +const actionsSpawn = async (snAccount: Account | AccountInterface) => { try { return await provider.execute( snAccount, - build_actions_spawn_calldata(), + buildActionsSpawnCalldata(), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing spawn action: ${error}`); throw error; } };
52-57
: Inconsistency between function definitions and exportsThe exported function names use camelCase but reference functions defined with snake_case. This inconsistency should be resolved to improve maintainability.
return { actions: { - move: actions_move, - buildMoveCalldata: build_actions_move_calldata, - spawn: actions_spawn, - buildSpawnCalldata: build_actions_spawn_calldata, + move: actionsMove, + buildMoveCalldata: buildActionsMoveCalldata, + spawn: actionsSpawn, + buildSpawnCalldata: buildActionsSpawnCalldata, }, };packages/sdk/src/web/experimental/index.ts (2)
29-32
: Removedhistorical
parameter fromgetEvents
The
historical
parameter has been removed from thegetEvents
function, which is a breaking change for API consumers.This change should be documented in the CHANGELOG.md and migration guide. Please verify if there are any existing calls that might be affected:
#!/bin/bash # Check for usages of getEvents with historical parameter grep -r "getEvents.*historical" --include="*.ts" --include="*.tsx" examples/
95-95
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts (1)
126-133
:⚠️ Potential issue
u64
can overflow JSnumber
; parse it asBigInt
A 64-bit unsigned integer can exceed
Number.MAX_SAFE_INTEGER
(2⁵³-1), leading to precision loss if parsed withNumber.parseInt
. It should be treated the same way as the larger integer types.- case "u64": - return Number.parseInt(value.value as string, 16); - case "i256": - case "i128": - case "u256": - case "u128": - return BigInt(value.value as string); + case "u64": + case "i256": + case "i128": + case "u256": + case "u128": + return BigInt(value.value as string);examples/example-node-worker/main.ts (4)
21-25
: Wrong global identifier: useWebSocket
, notWebsocket
Browsers (and most polyfills) expose
global.WebSocket
(uppercase S).
Assigning toWebsocket
leaves libraries that expectWebSocket
undefined.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
125-133
:initPositionFromEvent
mutates the shared constant
pc
is an alias ofdefaultPositionCount
, so every call mutates the constant and all future callers see cumulative side-effects.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };This also prevents accidental modification of the default object elsewhere.
143-151
: Potential data loss withdata.pop()
data
is already the argument supplied by the subscription.
Callingpop()
both mutates the array and drops all but the last entity; if multiple entities arrive in the same batch they are silently ignored.- const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - // do whatever you need here - const model = entity.models.dojo_starter; - if (model?.Moves) { - await publishOffchainPositionCount(model.Moves); - } - } + for (const entity of data) { + if (entity.entityId !== "0x0") { + // do whatever you need here + const model = entity.models.dojo_starter; + if (model?.Moves) { + await publishOffchainPositionCount(model.Moves); + } + } + }
175-176
: Unreachable code after the firstreturn
The second
return [sub];
can never execute—Biome rightfully flags it.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/state/src/recs/index.ts (1)
307-333
:⚠️ Potential issueInfinite loop in
getEntitiesQuery
Inside the
while (continueFetching)
loop you never issue a newclient.getEntities
call—fetchedEntities
is fetched once outside the loop, socursor
advances but data doesn't refresh.- const fetchedEntities = await client.getEntities({ - pagination: { - limit, - cursor, - direction: "Forward", - order_by: orderBy, - }, - clause: clause || undefined, - no_hashed_keys: false, - models: entityModels, - historical, - }); - - while (continueFetching) { + while (continueFetching) { + const fetchedEntities = await client.getEntities({ + pagination: { + limit, + cursor, + direction: "Forward", + order_by: orderBy, + }, + clause: clause || undefined, + no_hashed_keys: false, + models: entityModels, + historical, + });packages/sdk/src/internal/merge.ts (1)
123-160
: 🛠️ Refactor suggestionAdd unit tests for deepMerge in packages/sdk/src/internal/merge.ts
No tests currently cover this function. Please add a new test suite (e.g. packages/sdk/src/internal/tests/merge.test.ts) that verifies:
- Merging of primitive values (overwrites correctly)
- Recursive merging of nested objects
- Handling of arrays (should be overwritten, not deep-merged)
- Treatment of
null
and undefined properties- Behavior with custom Cairo types (
CairoOption
,CairoCustomEnum
)🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
38-46
: Fix typo in "positition" field nameThere appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
129-133
: Fix typo in schema definition to match interfacesThe schema definition contains the same typo as found in the interfaces.
PositionCount: { identity: "", - positition: [[0, 0]], }, PositionCountValue: { - positition: [[0, 0]], + position: [[0, 0]], },packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-137
: 🛠️ Refactor suggestionSpecify a more specific type for the generic parameter
The
any
type in the generic parameter ofwithPagination
disables many type checking rules and should be replaced with a more specific type.-static withPagination<T extends Record<string, Record<string, any>>>( +static withPagination<T extends SchemaType>( cursor: string, limit: number, direction: PaginationDirection ): ToriiQueryBuilder<T> {🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/node/index.ts (4)
50-51
: Breaking change: Client initialization changedChanged from
torii.createClient
to directly instantiatingnew torii.ToriiClient
.This is a breaking change for anyone directly using the returned client. Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
64-65
: Renamed query parameter for improved clarityParameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in both entity and event query subscriptions.This is a breaking change but improves naming consistency. Ensure this change is documented in migration guides and update all examples to use the new parameter name.
72-85
: Updated entity parsing to use items arrayThe entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects.This change simplifies the data structure but is a breaking change for existing code. Ensure this change is documented in migration guides and make sure that all examples and documentation are updated to reflect this new data structure.
215-230
: Modified generateTypedData signatureThe method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain. Ensure this change is documented in migration guides and consider if there are cases where passing a different domain was useful functionality.
🧹 Nitpick comments (12)
packages/sdk/src/__tests__/zustand.perf.test.ts (1)
131-133
: Consider replacing non-null assertions and string literal keyThe code uses non-null assertions (
!
) which could be unsafe ifworld
oritem
is null or undefined. Additionally, using a string literal for the entity key could be simplified.- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + const entity = draft.entities["entity500"]; + if (entity?.models?.world?.item) { + entity.models.world.item.durability = 75; + }This change adds null-checking to prevent potential runtime errors and improves readability.
🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Consider usingimport type
for type-only importsSome imports are only used as types. Using
import type
would ensure they're removed by compilers, potentially optimizing the bundle size.import { - KeysClause, - ParsedEntity, + KeysClause, HistoricalToriiQueryBuilder, + type ParsedEntity, } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Consider usingimport type
for MergedModelsThe
MergedModels
import is only used as a type. Usingimport type
would ensure it's removed by compilers and potentially optimize bundle size.-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge } from "../../internal/merge"; +import type { MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-2
: Useimport type
for type-only importsThe imports from
@dojoengine/core
andstarknet
include types that are only used as types and not as values.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import { DojoProvider } from "@dojoengine/core"; +import type { DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/state/src/recs/index.ts (2)
189-189
: Use array length property instead ofObject.keys().length
Since
entities.items
is now an array, use the direct.length
property instead of converting to object keys first.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) {
246-247
: Use array length check for empty array- if (Object.keys(entities.items).length === 0) { + if (entities.items.length === 0) {packages/sdk/src/internal/merge.ts (2)
76-76
: Improve type safety by avoidingany
typeThe codebase uses
any
in several Record type declarations, which weakens type safety. Consider using more specific types where possible:- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};And similarly for other occurrences.
Also applies to: 96-96, 133-133
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
127-156
: Handle circular references in deepMergeThe current implementation doesn't check for circular references, which could lead to stack overflow errors. Consider adding a WeakMap to track objects being merged and detect cycles.
export function deepMerge<T extends SchemaType>( target: MergedModels<T>, source: Partial<MergedModels<T>> ): MergedModels<T> { + // Use WeakMap to detect circular references + const seen = new WeakMap(); + + function merge(target: any, source: any): any { + // Check for circular references + if (typeof source === 'object' && source !== null) { + if (seen.has(source)) { + return seen.get(source); + } + seen.set(source, target); + } + + if (isCairoOption(target) && isCairoOption(source)) { + return mergeCairoOption(target, source); + } + if (isCairoCustomEnum(target) && isCairoCustomEnum(source)) { + return mergeCairoCustomEnum(target, source); + } + // Rest of the implementation... + } + + return merge(target, source);🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/index.ts (2)
259-264
: Consider using configured signer and identity when account is not providedThe SDK has configured identity and signer at initialization, but
sendMessage
doesn't use them when an account isn't provided directly.sendMessage: async ( data: TypedData, account?: Account ): Promise<Result<Uint8Array, string>> => { if (!account) { + // Try to use configured signer and identity if available + if (options.signer && options.identity) { + try { + const signature = await options.signer.signMessage(data); + const dataString = JSON.stringify(data); + const sigArray = Array.isArray(signature) + ? signature.map(s => s.toString()) + : [signature.r.toString(), signature.s.toString()]; + + return ok(await client.publishMessage(dataString, sigArray)); + } catch (error) { + console.error("Failed to sign with configured signer:", error); + return err(`Failed to sign with configured signer: ${String(error)}`); + } + } return err(NO_ACCOUNT); }
272-277
: Convert bigint signature elements to stringsWhen signature is an array of
bigint
s they're forwarded as-is, butpublishMessage
likely expectsstring[]
. Ensure all signature elements are properly converted to strings.return ok( await client.publishMessage( dataString, - Array.isArray(signature) - ? signature - : [signature.r.toString(), signature.s.toString()] + Array.isArray(signature) + ? signature.map(s => s.toString()) + : [signature.r.toString(), signature.s.toString()] ) );examples/example-node-worker/src/typescript/models.gen.ts (2)
3-3
: Add a type import to improve type safety.The import statement includes types that are only used as types and not as runtime values.
-import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; +import type { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet';🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
99-103
: Inconsistent indentation in CairoCustomEnum initializationThe indentation is inconsistent in the CairoCustomEnum initialization, making the code harder to read.
directions: [new CairoCustomEnum({ - Left: "", - Right: undefined, - Up: undefined, - Down: undefined, })], + Left: "", + Right: undefined, + Up: undefined, + Down: undefined, })],Apply the same fix to all similar occurrences in the file (lines 106-111, 143-148, and 150-155).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (44)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(3 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(6 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)worlds/dojo-starter
(1 hunks)worlds/onchain-dash
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
- packages/sdk/src/internal/parseHistoricalEvents.ts
✅ Files skipped from review due to trivial changes (4)
- packages/sdk/src/tests/state.test.ts
- .changeset/thirty-cheetahs-design.md
- worlds/dojo-starter
- packages/sdk/src/node/worker.ts
🚧 Files skipped from review as they are similar to previous changes (23)
- packages/torii-wasm/dojo.c
- worlds/onchain-dash
- examples/example-node-worker/dojoConfig.ts
- packages/react/package.json
- packages/core/package.json
- examples/example-node-worker/env.ts
- packages/sdk/package.json
- packages/sdk/src/tests/parseEntities.test.ts
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- examples/example-node-worker/tsconfig.json
- turbo.json
- examples/example-nodejs-bot/package.json
- packages/sdk/src/internal/errors.ts
- package.json
- packages/sdk/src/web/react/hooks/entities.ts
- packages/torii-client/package.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/internal/generateTypedData.ts
- .github/workflows/release.yaml
- packages/sdk/src/web/react/hooks/events.ts
- packages/sdk/src/internal/models.ts
- .github/workflows/ci.yaml
- packages/sdk/src/internal/types.ts
🧰 Additional context used
🧬 Code Graph Analysis (9)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/web/index.ts (6)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/sdk/src/internal/parseEntities.ts (2)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)packages/sdk/src/internal/types.ts (2)
StandardizedQueryResult
(193-195)ParsedEntity
(228-237)
packages/sdk/src/web/experimental/index.ts (2)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)
packages/sdk/src/web/react/hooks/hooks.ts (2)
packages/sdk/src/internal/types.ts (1)
ParsedEntity
(228-237)examples/example-vite-react-sql/src/components/playground/schema.tsx (1)
Schema
(48-66)
🪛 Biome (1.9.4)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/experimental/index.ts
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/web/react/hooks/hooks.ts
[error] 72-72: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
🪛 Gitleaks (8.21.2)
examples/example-node-worker/package.json
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: check
- GitHub Check: build
🔇 Additional comments (16)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-14
: Great upgrade to the specialized HistoricalToriiQueryBuilderThe change to
HistoricalToriiQueryBuilder
aligns with the SDK's internal refactor where query builders were enhanced to support cursor-based pagination and historical querying.examples/example-node-worker/package.json (2)
13-19
: Good dependency updates for the enhanced SDK implementationThe additions of Torii WASM, dotenv, starknet, websocket, and zod dependencies align well with the new environment configuration and enhanced SDK usage in this example.
21-22
: Appropriate type definitions for developmentAdding the type definitions for Node.js and WebSocket is appropriate for TypeScript development.
packages/sdk/src/web/react/hooks/hooks.ts (2)
32-33
: Type signature updated to use array-based entitiesThe parameter types for
processInitialData
andprocessUpdateData
have been updated from handling the generalToriiResponse
to specifically working with arrays ofParsedEntity<Schema>
. This aligns with the broader SDK changes moving from keyed objects to arrays of entities.
65-67
: Updated data casting to match new type signaturesThe function calls have been updated to cast the data to
ParsedEntity<Schema>[]
, ensuring type compatibility with the updated callback signatures. This maintains type safety throughout the data flow.Also applies to: 75-77, 90-92
packages/sdk/src/web/experimental/index.ts (2)
53-59
: Updated entity parsing to handle arrays instead of keyed objectsThe callback now processes entity data as an array, matching the updated
parseEntities
function signature. This approach is more consistent with the rest of the SDK.
98-100
: Updated event parsing to handle arrays instead of keyed objectsThe callback now processes event data as an array, matching the updated
parseEntities
function signature. This approach is more consistent with the rest of the SDK.packages/sdk/src/internal/parseEntities.ts (2)
10-23
: Function refactored to work with entity arrays instead of keyed objectsThe
parseEntities
function has been refactored to accept an array oftorii.Entity
objects instead of a keyed object. This aligns with the broader SDK changes to handle entities as arrays.
90-90
: Added support for tuple type in parseValueThe function now handles the "tuple" case, which was previously missing. This improves the robustness of the parser.
packages/sdk/src/internal/toriiQueryBuilder.ts (4)
9-20
: Breaking change: Pagination structure refactoredThe pagination parameters are now nested within a
pagination
object instead of being at the root level. This structural change aligns with the transition from offset-based to cursor-based pagination.This is a breaking change that should be documented in the migration guide for users upgrading from previous versions.
39-45
: Deprecated method now returns a no-opThe
withOffset
method is now deprecated and returnsthis
without performing any action, which is appropriate for a smooth transition to the new pagination model.
47-63
: New cursor-based pagination methods addedThe new
withCursor
andwithDirection
methods provide better support for cursor-based pagination, allowing for more flexible and efficient data retrieval.
145-159
: New HistoricalToriiQueryBuilder class for historical queriesThe new
HistoricalToriiQueryBuilder
class provides a convenient way to create queries for historical data by extendingToriiQueryBuilder
with thehistorical
flag set to true by default.packages/sdk/src/node/index.ts (3)
29-30
: Added neverthrow for improved error handlingThe addition of
neverthrow
for Result types provides a more robust error handling approach.
34-36
: New exports for worker, types, and modelsThe additional exports make worker functionality, internal types, and models available to consumers of the SDK.
401-414
: Simplified toriiEventMessagesQueryIntoHashedKeys methodThe
toriiEventMessagesQueryIntoHashedKeys
method signature has been simplified by removing thehistorical
parameter and always parsing events uniformly on.items
.
}, | ||
subscribeEntities: async ( | ||
query: torii.Query, | ||
callback: ToriiSubscriptionCallback<T> | ||
) => { | ||
if ( | ||
query.dont_include_hashed_keys && | ||
query.no_hashed_keys && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Changed property name from dont_include_hashed_keys
to no_hashed_keys
The property name used in conditions has changed from dont_include_hashed_keys
to no_hashed_keys
, which is a breaking change for API consumers.
Let's check if this change is consistent across the codebase:
Also applies to: 80-80
🏁 Script executed:
#!/bin/bash
# Check for usages of both property names
grep -r "dont_include_hashed_keys" --include="*.ts" packages/
grep -r "no_hashed_keys" --include="*.ts" packages/
Length of output: 1289
Action Required: Address Breaking Change for dont_include_hashed_keys
→ no_hashed_keys
We’ve confirmed that the old dont_include_hashed_keys
key has been fully removed and replaced by no_hashed_keys
across the SDK (no references to the old name were found). This will break any consumers still passing dont_include_hashed_keys
.
Affected SDK surfaces:
- packages/sdk/src/internal/toriiQueryBuilder.ts
- packages/sdk/src/web/index.ts
- packages/sdk/src/web/experimental/index.ts
- packages/sdk/src/node/index.ts
- packages/state/src/recs/index.ts
Please choose one of the following:
- Add a deprecated alias: if
query.dont_include_hashed_keys
is set, map it internally toquery.no_hashed_keys
. - Treat this as a true breaking change: document it in the CHANGELOG, bump to a new major version, and call out the renamed property in upgrade notes.
@@ -21,24 +20,22 @@ | |||
...options.client, | |||
} as torii.ClientConfig; | |||
|
|||
const client = await torii.createClient(clientConfig); | |||
const client = new torii.ToriiClient(clientConfig); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Client instantiation changed from async to sync
The client creation has been changed from using await torii.createClient(clientConfig)
to a synchronous instantiation with new torii.ToriiClient(clientConfig)
. This is a breaking change if consumers are awaiting the client creation.
Is this change consistent across the codebase? Let's check other client initializations:
🏁 Script executed:
#!/bin/bash
# Search for client initialization patterns in the SDK
grep -r "createClient" --include="*.ts" packages/sdk/
grep -r "new torii.ToriiClient" --include="*.ts" packages/sdk/
Length of output: 611
🏁 Script executed:
#!/bin/bash
# Show the surrounding code for context in experimental/index.ts
sed -n '1,50p' packages/sdk/src/web/experimental/index.ts
Length of output: 1810
🏁 Script executed:
#!/bin/bash
sed -n '1,50p' packages/sdk/src/web/index.ts
Length of output: 1607
🏁 Script executed:
#!/bin/bash
# Show the surrounding code in node/index.ts for client instantiation
sed -n '1,50p' packages/sdk/src/node/index.ts
Length of output: 1630
Inconsistent ToriiClient instantiation across entrypoints
We’re now instantiating the ToriiClient synchronously in web/experimental
but still using await new ToriiClient()
in other async entrypoints. While this isn’t a breaking change for consumers (all public APIs remain async functions that return a promise), it can be confusing and looks inconsistent.
Locations to harmonize:
- packages/sdk/src/web/experimental/index.ts
const client = new torii.ToriiClient(clientConfig);
- packages/sdk/src/web/index.ts
return await new torii.ToriiClient(config);
- packages/sdk/src/node/index.ts
const client = await new torii.ToriiClient(clientConfig);
Recommendation: pick one pattern—either drop all redundant await
or add await
everywhere—and apply it across all init/createClient functions for clarity.
b159d72
to
cb2f3ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (2)
packages/sdk/src/web/index.ts (1)
257-282
:⚠️ Potential issueFix inconsistent error handling in sendMessage
While the function now returns a Result type, the catch block still throws errors instead of returning them as Err.
try { // Sign the typed data const signature: Signature = await account.signMessage(data); // Stringify typed data for publishing const dataString = JSON.stringify(data); // Publish the signed message return ok( await client.publishMessage( dataString, Array.isArray(signature) ? signature : [signature.r.toString(), signature.s.toString()] ) ); } catch (error) { console.error("Failed to send message:", error); - throw error; + return err(String(error)); }Additionally, when
signature
is an array ofbigint
s, they should be converted to strings:return ok( await client.publishMessage( dataString, Array.isArray(signature) - ? signature + ? signature.map(s => s.toString()) : [signature.r.toString(), signature.s.toString()] ) );packages/sdk/src/node/index.ts (1)
267-269
: 🛠️ Refactor suggestionInconsistent error handling in catch block
While the function has been refactored to use Result for normal error cases, it still throws an exception in the catch block, which is inconsistent with the new pattern.
Make the error handling consistent by returning
err
in the catch block:catch (error) { console.error("Failed to send message:", error); - throw error; + return err(`Failed to send message: ${error instanceof Error ? error.message : String(error)}`); }
♻️ Duplicate comments (28)
examples/example-node-worker/package.json (1)
6-10
:⚠️ Potential issueRemove hardcoded credentials from scripts
The scripts contain hardcoded private keys and identity values, which is a security risk. These should be moved to environment variables loaded from a .env file instead.
"scripts": { - "bun": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 bun run main.ts", - "node": "IDENTITY=0x0127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec SECRET_KEY=0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 node main.ts", + "bun": "bun run main.ts", + "node": "node main.ts", "build": "tsc -b" },Since you've already added
dotenv
as a dependency, you should use it to load these values from a .env file (which should be added to .gitignore).🧰 Tools
🪛 Gitleaks (8.21.2)
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
packages/sdk/src/web/react/hooks/hooks.ts (1)
121-123
:⚠️ Potential issueUncomment and fix the cleanup function
The cleanup function that should free the subscription reference is commented out, which could lead to memory leaks.
return () => { if (subscriptionRef.current) { - // subscriptionRef.current?.free(); - // subscriptionRef.current = null; + subscriptionRef.current.free(); + subscriptionRef.current = null; } };examples/example-node-worker/src/typescript/contracts.gen.ts (5)
7-13
: Function uses inconsistent naming styleThe function uses snake_case (
build_actions_move_calldata
) instead of camelCase which is the TypeScript convention. This is inconsistent with the exported function names in line 52-57 which use camelCase.-const build_actions_move_calldata = (direction: CairoCustomEnum): DojoCall => { +const buildActionsMoveCalldata = (direction: CairoCustomEnum): DojoCall => { return { contractName: "actions", entrypoint: "move", calldata: [direction], }; };
15-26
: Function follows inconsistent naming and could use better error handlingThe function uses snake_case which is inconsistent with TypeScript conventions. Additionally, the error handling could benefit from more specific error messages to aid debugging.
-const actions_move = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { +const actionsMove = async (snAccount: Account | AccountInterface, direction: CairoCustomEnum) => { try { return await provider.execute( snAccount, - build_actions_move_calldata(direction), + buildActionsMoveCalldata(direction), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing move action: ${error}`); throw error; } };
28-34
: Function uses inconsistent naming styleSimilar to the previous function, this uses snake_case instead of the conventional camelCase in TypeScript.
-const build_actions_spawn_calldata = (): DojoCall => { +const buildActionsSpawnCalldata = (): DojoCall => { return { contractName: "actions", entrypoint: "spawn", calldata: [], }; };
36-47
: Function follows inconsistent naming and could use better error handlingSimilar to
actions_move
, this function uses snake_case and has minimal error information in the error handling.-const actions_spawn = async (snAccount: Account | AccountInterface) => { +const actionsSpawn = async (snAccount: Account | AccountInterface) => { try { return await provider.execute( snAccount, - build_actions_spawn_calldata(), + buildActionsSpawnCalldata(), "dojo_starter", ); } catch (error) { - console.error(error); + console.error(`Error executing spawn action: ${error}`); throw error; } };
52-57
: Inconsistency between function definitions and exportsThe exported function names use camelCase but reference functions defined with snake_case. This inconsistency should be resolved.
return { actions: { - move: actions_move, - buildMoveCalldata: build_actions_move_calldata, - spawn: actions_spawn, - buildSpawnCalldata: build_actions_spawn_calldata, + move: actionsMove, + buildMoveCalldata: buildActionsMoveCalldata, + spawn: actionsSpawn, + buildSpawnCalldata: buildActionsSpawnCalldata, }, };packages/sdk/src/web/experimental/index.ts (4)
95-95
: Strengthen callback parameter typesFor improved type safety, replace the
any
type on theentityData
parameter withtorii.Entity
, which aligns with theparseEntities<T>(entities: torii.Entity[])
signature.- (_: string, entityData: any) => { + (_: string, entityData: torii.Entity) => {🧰 Tools
🪛 Biome (1.9.4)
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
29-32
: Document removal ofhistorical
parameter in getEventsWe've confirmed there are no internal calls passing a
historical
flag togetEvents
, but its removal is a breaking change for consumers. Please update your public-facing documentation and release notes to reflect this.• File: packages/sdk/src/web/experimental/index.ts (lines 29–32)
getEvents(query: torii.Query)
no longer accepts ahistorical
argument.
• Action: Add a note in CHANGELOG.md and the SDK migration guide about the removedhistorical
parameter.
38-38
: Action Required: Address Breaking Change fordont_include_hashed_keys
→no_hashed_keys
We've confirmed that the old
dont_include_hashed_keys
key has been fully removed and replaced byno_hashed_keys
across the SDK. This will break any consumers still passingdont_include_hashed_keys
.Please choose one of the following:
- Add a deprecated alias: if
query.dont_include_hashed_keys
is set, map it internally toquery.no_hashed_keys
.- Treat this as a true breaking change: document it in the CHANGELOG, bump to a new major version, and call out the renamed property in upgrade notes.
23-23
: Inconsistent ToriiClient instantiation across entrypointsWe're now instantiating the ToriiClient synchronously in
web/experimental
but still usingawait new ToriiClient()
in other async entrypoints. While this isn't a breaking change for consumers (all public APIs remain async functions that return a promise), it can be confusing and looks inconsistent.Recommendation: pick one pattern—either drop all redundant
await
or addawait
everywhere—and apply it across all init/createClient functions for clarity.packages/sdk/src/internal/parseEntities.ts (1)
126-134
:⚠️ Potential issueParse
u64
(and larger) asBigInt
to avoid precision loss
Number.parseInt
cannot safely represent allu64
values – anything above2**53-1
will silently lose precision.
Please parse all 64-bit and wider integers asBigInt
(and prepend0x
when the string is hexadecimal).- case "u64": - return Number.parseInt(value.value as string, 16); - case "i256": - case "i128": - case "u256": - case "u128": - return BigInt(value.value as string); + case "u64": + case "i256": + case "i128": + case "u256": + case "u128": + // Use BigInt to keep full precision. The `0x` prefix lets BigInt + // parse the hex string correctly. + return BigInt(`0x${value.value as string}`);examples/example-node-worker/main.ts (4)
21-25
: Still assigning the wrong global – useWebSocket
, notWebsocket
Same issue was raised previously; the browser (and most polyfills) exposeWebSocket
with a capital S.-// @ts-ignore -global.Websocket = w3cwebsocket; +// @ts-ignore +global.WebSocket = w3cwebsocket;
123-131
:initPositionFromEvent
mutates the shared default object
pc
is just an alias ofdefaultPositionCount
, so every call permanently mutates the constant.-const pc = defaultPositionCount; +const pc: PositionCount = { ...defaultPositionCount };
137-150
:data.pop()
drops entities & mutates the batchIf multiple entities arrive in one notification all but the last are ignored.
Iterate instead:- const entity = data.pop(); - if (entity && entity.entityId !== "0x0") { - … - } + for (const entity of data) { + if (entity.entityId === "0x0") continue; + … + }
175-176
: Unreachable code after the firstreturn
The second
return [sub];
can never execute.- return []; - return [sub]; + return [sub];🧰 Tools
🪛 Biome (1.9.4)
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/state/src/recs/index.ts (3)
185-190
: Array length check usesObject.keys
– inefficient & misleading
entities.items
is an array; use.length
directly.- if (Object.keys(entities.items).length < limit) { + if (entities.items.length < limit) {🧰 Tools
🪛 Biome (1.9.4)
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
246-247
:setEntities
still receives an array although it expects an objectPassing the raw array causes keys to become
"0" | "1" | …
, breaking look-ups.
Convert the array into an object keyed by the realentityId
, or refactorsetEntities
to understand arrays.Also applies to: 328-329
541-553
: Iterating over an array withObject.entries
loses entity IDs
entities
is an array;Object.entries
returns numeric indices, so the storedid
is"0"
,"1"
, … instead of the hashed key. Iterate directly:-for (const [entityId, data] of Object.entries(entities)) { - const entityData = { id: entityId, ...data }; +for (const entity of entities) { + const entityId = entity.hashed_keys?.join(".") ?? crypto.randomUUID(); + const entityData = { id: entityId, ...entity };packages/sdk/src/internal/merge.ts (1)
123-160
: 🛠️ Refactor suggestionAdd unit tests for deepMerge and fix
any
usageThis is a critical utility function that handles complex merging logic for Cairo types. Ensure it has comprehensive test coverage for various edge cases.
- const result = { ...target } as Record<string, any>; + const result = { ...target } as Record<string, unknown>;Add tests that verify:
- Merging of primitive values (overwrites correctly)
- Recursive merging of nested objects
- Handling of arrays (should be overwritten, not deep-merged)
- Treatment of
null
and undefined properties- Behavior with custom Cairo types (
CairoOption
,CairoCustomEnum
)🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
38-46
: Fix typo in "positition" field nameThere appears to be a typo in the
positition
field name (should be "position").export interface PositionCount { identity: string; - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; } export interface PositionCountValue { - positition: Array<[BigNumberish, BigNumberish]>; + position: Array<[BigNumberish, BigNumberish]>; }Since this affects the interface structure and is reflected in the schema initialization, this typo should be fixed in the generator if possible.
128-133
: Fix typo in schema field name to match interfacesFix the typo in the schema definition to match the corrected interface.
PositionCount: { identity: "", - positition: [[0, 0]], + position: [[0, 0]], }, PositionCountValue: { - positition: [[0, 0]], + position: [[0, 0]], },packages/sdk/src/node/index.ts (6)
50-50
: Client initialization changeChanged from
torii.createClient
to directly instantiatingnew torii.ToriiClient
. This is a breaking change for anyone directly using the returned client.Ensure this change is documented in migration guides and potentially consider providing a compatibility layer if feasible.
64-65
: Renamed query parameter for improved clarityParameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in entity query subscriptions.Ensure this change is documented in migration guides and update all examples to use the new parameter name.
72-74
: Updated entity parsing to use items arrayThe entity parsing has been updated to handle arrays from the
.items
property rather than keyed objects.Ensure this change is documented in migration guides. Make sure that all examples and documentation are updated to reflect this new data structure.
119-120
: Renamed query parameter for improved clarityParameter renamed from
dont_include_hashed_keys
tono_hashed_keys
in event query subscriptions.Ensure this change is documented in migration guides and update all examples to use the new parameter name.
127-130
: Updated event parsing to use items arraySimilar to the entity parsing changes, event parsing now uses arrays from the
.items
property.Update all documentation and examples to reflect this structural change in event data handling.
219-230
: Modified generateTypedData signatureThe method signature has changed:
- Removed optional domain parameter
- Added optional additionalTypes parameter
- Domain is now always taken from options.domain
This is a breaking change for code that explicitly passed a domain parameter different from options.domain. Ensure this change is documented in migration guides.
🧹 Nitpick comments (10)
packages/sdk/src/__tests__/zustand.perf.test.ts (2)
131-133
: Consider addressing non-null assertionsWhile the code formatting change is fine, the static analysis tools flag two concerns:
- The use of non-null assertions (
!
) is discouraged as they bypass TypeScript's type checking- The string literal key could be simplified
- draft.entities[ - "entity500" - ].models.world!.item!.durability = 75; + draft.entities.entity500?.models.world?.item?.durability = 75;This change replaces non-null assertions with optional chaining operators for safer access, and simplifies the property access syntax.
🧰 Tools
🪛 Biome (1.9.4)
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
151-151
: Consider addressing non-null assertions here tooFor consistency with the above change, this line should also be updated to use optional chaining.
- draft.entities["entity500"].models.world!.item!.durability = 75; + draft.entities.entity500?.models.world?.item?.durability = 75;🧰 Tools
🪛 Biome (1.9.4)
[error] 151-151: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 151-151: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 151-151: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
1-5
: Consider usingimport type
for type-only importsThe static analysis tools suggest that some imports are only used as types and should be marked as such with
import type
.import { KeysClause, - ParsedEntity, + type ParsedEntity, HistoricalToriiQueryBuilder, } from "@dojoengine/sdk";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/web/state/zustand.ts (1)
14-14
: Good refactor: Using centralized merge utilitiesImporting the
deepMerge
andMergedModels
from a central utility module helps reduce code duplication and ensures consistent handling of Cairo types across the SDK.Consider using
import type
for type-only imports:-import { deepMerge, MergedModels } from "../../internal/merge"; +import { deepMerge, type MergedModels } from "../../internal/merge";🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
examples/example-node-worker/src/typescript/contracts.gen.ts (1)
1-2
: Useimport type
for type-only importsImporting the types with
import type
ensures they are removed by the compilers and avoids loading unnecessary modules.-import { DojoProvider, DojoCall } from "@dojoengine/core"; -import { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet"; +import { DojoProvider } from "@dojoengine/core"; +import type { DojoCall } from "@dojoengine/core"; +import type { Account, AccountInterface, BigNumberish, CairoOption, CairoCustomEnum, ByteArray } from "starknet";🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
packages/sdk/src/internal/parseEntities.ts (1)
55-59
: RedundantObject.values
on an array
result
is already an array (ParsedEntity<T>[]
). Wrapping it withObject.values
just allocates a shallow copy for no benefit.- return Object.values(result); + return result;packages/sdk/src/internal/merge.ts (1)
63-113
: Replaceany
with more specific typesThe merging logic is correct, properly handling active variants. However, there are untyped
any
usages in the implementation.Replace the untyped Records with more specific types:
- const newEnumContent: Record<string, any> = {}; + const newEnumContent: Record<string, unknown> = {};Same for line 96.
🧰 Tools
🪛 Biome (1.9.4)
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/models.gen.ts (2)
3-3
: Useimport type
for type-only imports- import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet'; + import { CairoCustomEnum, CairoOption, CairoOptionVariant } from 'starknet'; + import type { BigNumberish } from 'starknet';Since
BigNumberish
is only used as a type, not as a value, it's better to useimport type
for it.🧰 Tools
🪛 Biome (1.9.4)
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.(lint/style/useImportType)
99-104
: Improve code indentation for enum initializationThe indentation is inconsistent in the CairoCustomEnum initialization, making it harder to read.
directions: [new CairoCustomEnum({ - Left: "", + Left: "", - Right: undefined, + Right: undefined, - Up: undefined, + Up: undefined, - Down: undefined, })], + Down: undefined +})],Apply similar formatting improvements to other CairoCustomEnum initializations in the file.
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
133-142
: Update the generic type parameter in withPaginationReplace the generic Record type with the more specific SchemaType:
- static withPagination<T extends Record<string, Record<string, any>>>( + static withPagination<T extends SchemaType>( cursor: string, limit: number, direction: PaginationDirection ): ToriiQueryBuilder<T> {This aligns with how the class is used elsewhere and eliminates the
any
type warning.🧰 Tools
🪛 Biome (1.9.4)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
⛔ Files ignored due to path filters (5)
examples/example-vite-react-phaser-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-pwa-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vite-react-threejs-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
examples/example-vue-app-recs/src/dojo/generated/setup.ts
is excluded by!**/generated/**
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (45)
.changeset/thirty-cheetahs-design.md
(1 hunks).github/workflows/ci.yaml
(1 hunks).github/workflows/release.yaml
(6 hunks)examples/example-node-worker/dojoConfig.ts
(1 hunks)examples/example-node-worker/env.ts
(1 hunks)examples/example-node-worker/main.ts
(1 hunks)examples/example-node-worker/package.json
(1 hunks)examples/example-node-worker/src/typescript/contracts.gen.ts
(1 hunks)examples/example-node-worker/src/typescript/models.gen.ts
(1 hunks)examples/example-node-worker/tsconfig.json
(1 hunks)examples/example-nodejs-bot/package.json
(1 hunks)examples/example-vite-experimental-sdk/src/main.ts
(1 hunks)examples/example-vite-react-app-recs/src/dojo/setup.ts
(2 hunks)examples/example-vite-react-sdk/src/historical-events.tsx
(2 hunks)package.json
(1 hunks)packages/core/package.json
(1 hunks)packages/react/package.json
(2 hunks)packages/sdk/package.json
(3 hunks)packages/sdk/src/__tests__/parseEntities.test.ts
(7 hunks)packages/sdk/src/__tests__/parseHistoricalEvents.test.ts
(0 hunks)packages/sdk/src/__tests__/state.test.ts
(3 hunks)packages/sdk/src/__tests__/toriiQueryBuilder.test.ts
(6 hunks)packages/sdk/src/__tests__/zustand.perf.test.ts
(1 hunks)packages/sdk/src/internal/errors.ts
(1 hunks)packages/sdk/src/internal/generateTypedData.ts
(2 hunks)packages/sdk/src/internal/merge.ts
(1 hunks)packages/sdk/src/internal/models.ts
(1 hunks)packages/sdk/src/internal/parseEntities.ts
(4 hunks)packages/sdk/src/internal/parseHistoricalEvents.ts
(0 hunks)packages/sdk/src/internal/toriiQueryBuilder.ts
(6 hunks)packages/sdk/src/internal/types.ts
(5 hunks)packages/sdk/src/node/index.ts
(12 hunks)packages/sdk/src/node/worker.ts
(1 hunks)packages/sdk/src/web/experimental/index.ts
(3 hunks)packages/sdk/src/web/index.ts
(11 hunks)packages/sdk/src/web/react/hooks/entities.ts
(1 hunks)packages/sdk/src/web/react/hooks/events.ts
(3 hunks)packages/sdk/src/web/react/hooks/hooks.ts
(6 hunks)packages/sdk/src/web/state/zustand.ts
(1 hunks)packages/state/src/recs/index.ts
(6 hunks)packages/torii-client/package.json
(2 hunks)packages/torii-wasm/dojo.c
(1 hunks)turbo.json
(1 hunks)worlds/dojo-starter
(1 hunks)worlds/onchain-dash
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/sdk/src/internal/parseHistoricalEvents.ts
- packages/sdk/src/tests/parseHistoricalEvents.test.ts
✅ Files skipped from review due to trivial changes (4)
- packages/react/package.json
- .changeset/thirty-cheetahs-design.md
- packages/sdk/src/tests/state.test.ts
- turbo.json
🚧 Files skipped from review as they are similar to previous changes (23)
- examples/example-node-worker/dojoConfig.ts
- examples/example-nodejs-bot/package.json
- worlds/dojo-starter
- packages/torii-client/package.json
- examples/example-vite-react-app-recs/src/dojo/setup.ts
- package.json
- packages/torii-wasm/dojo.c
- packages/sdk/src/internal/errors.ts
- examples/example-node-worker/env.ts
- packages/sdk/package.json
- packages/core/package.json
- packages/sdk/src/tests/parseEntities.test.ts
- packages/sdk/src/web/react/hooks/entities.ts
- examples/example-node-worker/tsconfig.json
- packages/sdk/src/tests/toriiQueryBuilder.test.ts
- packages/sdk/src/node/worker.ts
- .github/workflows/ci.yaml
- .github/workflows/release.yaml
- packages/sdk/src/web/react/hooks/events.ts
- worlds/onchain-dash
- packages/sdk/src/internal/types.ts
- packages/sdk/src/internal/models.ts
- packages/sdk/src/internal/generateTypedData.ts
🧰 Additional context used
🧬 Code Graph Analysis (7)
packages/sdk/src/web/index.ts (5)
packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (1)
NO_ACCOUNT
(3-3)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
packages/sdk/src/node/index.ts (6)
packages/sdk/src/internal/convertClauseToEntityKeysClause.ts (1)
intoEntityKeysClause
(4-36)packages/sdk/src/internal/parseEntities.ts (1)
parseEntities
(10-59)packages/sdk/src/internal/types.ts (2)
ToriiResponse
(248-253)ToriiQueryBuilder
(557-557)packages/sdk/src/internal/generateTypedData.ts (1)
generateTypedData
(13-48)packages/sdk/src/internal/errors.ts (2)
NO_SIGNER
(1-1)NO_IDENTITY
(2-2)packages/sdk/src/internal/toriiQueryBuilder.ts (1)
ToriiQueryBuilder
(24-143)
examples/example-node-worker/src/typescript/contracts.gen.ts (2)
examples/example-node-worker/src/typescript/models.gen.ts (1)
direction
(71-76)packages/core/src/types/index.ts (1)
DojoCall
(130-134)
examples/example-node-worker/src/typescript/models.gen.ts (1)
packages/sdk/src/internal/types.ts (1)
SchemaType
(50-70)
examples/example-vite-react-sdk/src/historical-events.tsx (1)
packages/sdk/src/internal/toriiQueryBuilder.ts (1)
HistoricalToriiQueryBuilder
(149-159)
packages/sdk/src/internal/merge.ts (3)
packages/sdk/src/web/queryBuilder.ts (1)
value
(191-193)examples/example-node-worker/src/typescript/models.gen.ts (1)
SchemaType
(80-94)packages/sdk/src/internal/types.ts (2)
SchemaType
(50-70)ParsedEntity
(228-237)
packages/state/src/recs/index.ts (1)
packages/core/src/provider/DojoProvider.ts (1)
entities
(104-123)
🪛 Biome (1.9.4)
examples/example-node-worker/main.ts
[error] 176-176: This code is unreachable
... because this statement will return from the function beforehand
(lint/correctness/noUnreachable)
packages/sdk/src/web/experimental/index.ts
[error] 95-95: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/toriiQueryBuilder.ts
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
examples/example-node-worker/src/typescript/contracts.gen.ts
[error] 1-1: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
This import is only used as a type.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-node-worker/src/typescript/models.gen.ts
[error] 3-3: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
examples/example-vite-react-sdk/src/historical-events.tsx
[error] 1-5: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/sdk/src/__tests__/zustand.perf.test.ts
[error] 131-133: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
[error] 131-133: Forbidden non-null assertion.
Unsafe fix: Replace with optional chain operator ?. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator
(lint/style/noNonNullAssertion)
[error] 132-132: The computed expression can be simplified without the use of a string literal.
Unsafe fix: Use a literal key instead.
(lint/complexity/useLiteralKeys)
packages/sdk/src/internal/merge.ts
[error] 76-76: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 96-96: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
[error] 133-133: Unexpected any. Specify a different type.
any disables many type checking rules. Its use should be avoided.
(lint/suspicious/noExplicitAny)
packages/sdk/src/internal/parseEntities.ts
[error] 50-50: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
packages/sdk/src/web/react/hooks/hooks.ts
[error] 72-72: Forbidden non-null assertion.
(lint/style/noNonNullAssertion)
packages/sdk/src/web/state/zustand.ts
[error] 14-14: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
packages/state/src/recs/index.ts
[error] 185-185: Do not use template literals if interpolation and special-character handling are not needed.
Unsafe fix: Replace with string literal
(lint/style/noUnusedTemplateLiteral)
🪛 Gitleaks (8.21.2)
examples/example-node-worker/package.json
7-7: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: build
- GitHub Check: check
🔇 Additional comments (24)
examples/example-vite-experimental-sdk/src/main.ts (1)
34-38
: Update looks good: Removed unnecessary "historical" parameterThe removal of the second parameter to
sdk.getEvents()
aligns with SDK-wide changes where the historical event handling was unified, removing the distinction between historical and non-historical events.examples/example-vite-react-sdk/src/historical-events.tsx (1)
14-20
: Good update: Using specialized query builder for historical eventsThe change from
ToriiQueryBuilder
toHistoricalToriiQueryBuilder
is appropriate as it leverages the specialized builder that setshistorical: true
by default. This makes the code more explicit about its intent and leverages the dedicated API.packages/sdk/src/internal/merge.ts (2)
9-11
: Looks good: Type guard for CairoOptionClean and straightforward implementation of the type guard for Cairo's Option type.
53-55
: Looks good: Type guard for CairoCustomEnumClean implementation of the type guard for Cairo's custom enum type.
packages/sdk/src/web/index.ts (5)
30-31
: LGTM: Added Result type from neverthrow for error handlingGood addition of error handling using the Result type from neverthrow library and centralizing error messages.
48-48
: API change: direct instantiation of ToriiClientChanged from using a factory function to direct class instantiation. This appears to be an intentional API change in the underlying library.
92-94
: Updated to access items property from pagination responseThe SDK now expects responses to include an items array property, consistent with a move to cursor-based pagination.
232-247
: Updated typed data generation interfaceThe signature was updated to use the domain from options and add support for additional types. This provides more flexibility for custom type definitions.
414-424
: Fixed array handling in toriiEventMessagesQueryIntoHashedKeysThe function now properly handles the items array from the query result and passes it to intoEntityKeysClause.
Though there's still a TODO comment about fixing the type. You might want to address this in a future update.
packages/sdk/src/internal/toriiQueryBuilder.ts (3)
39-45
: Deprecated offset-based pagination in favor of cursor-basedGood approach to maintain backward compatibility by keeping the deprecated method as a no-op while directing users to the new method through JSDoc.
47-62
: Added new cursor-based pagination methodsThe new
withCursor
andwithDirection
methods support the transition to cursor-based pagination, which is more efficient for large datasets.
145-158
: LGTM: New HistoricalToriiQueryBuilder classGood addition of a specialized class for historical queries, extending the base query builder with the historical flag set to true by default.
packages/sdk/src/node/index.ts (12)
19-19
: Import cleanup for Starknet typesThe import has been simplified to only include the actually used types from the Starknet package.
29-30
: Added Result type and error constantsAdded imports from neverthrow for error handling and imported constants for common error messages. This is a good improvement for standardized error handling.
34-36
: Additional exports for worker and modelsNew exports for worker, types, and models will enable more flexible SDK usage patterns.
79-85
: Updated subscription callback to use array-based parsingThe entity update callback now parses a single entity into an array structure, consistent with the new array-based approach throughout the codebase.
138-143
: Updated event callback to use array-based parsingThe event update callback now parses a single entity into an array structure, consistent with the new array-based approach throughout the codebase.
189-189
: Unified entity retrieval and parsingThe entity retrieval has been simplified to access the items array directly and parse it.
202-204
: Simplified event retrieval and parsingEvent retrieval and parsing have been simplified by removing special handling for historical events and directly accessing the items array.
242-249
: Improved error handling with Result typeThe sendMessage method now returns a Result type with proper error handling when signer or identity is missing, which is more robust than throwing exceptions.
251-265
: Refactored message sending for better reliabilityMessage sending now:
- Uses options.signer and options.identity instead of explicit account parameter
- Returns a Result type for successful operations
- Uses proper error handling for missing configuration
390-390
: Updated entity array access in toriiQueryIntoHashedKeysEntity access pattern has been updated to use the items array property, consistent with other changes throughout the file.
402-402
: Simplified toriiEventMessagesQueryIntoHashedKeys signatureRemoved the historical parameter from the method signature, simplifying the API.
406-407
: Updated event parsing in toriiEventMessagesQueryIntoHashedKeysEvent parsing has been updated to use the items array property, consistent with other changes throughout the file.
const fetchedEntities = await client.getEntities({ | ||
pagination: { | ||
limit, | ||
offset: cursor, | ||
clause: clause || undefined, | ||
cursor, | ||
direction: "Forward", | ||
order_by: orderBy, | ||
entity_models: entityModels, | ||
dont_include_hashed_keys: false, | ||
entity_updated_after: 0, | ||
}, | ||
historical | ||
); | ||
clause: clause || undefined, | ||
no_hashed_keys: false, | ||
models: entityModels, | ||
historical, | ||
}); | ||
|
||
while (continueFetching) { | ||
if (logging) | ||
console.log( | ||
`Fetched ${Object.keys(fetchedEntities).length} entities ${cursor}` | ||
`Fetched ${Object.keys(fetchedEntities.items).length} entities ${fetchedEntities.next_cursor}` | ||
); | ||
|
||
setEntities(fetchedEntities, components, logging); | ||
setEntities(fetchedEntities.items, components, logging); | ||
|
||
if (Object.keys(fetchedEntities).length < limit) { | ||
if (Object.keys(fetchedEntities.items).length < limit) { | ||
continueFetching = false; | ||
} else { | ||
cursor += limit; | ||
cursor = fetchedEntities.next_cursor; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Potential infinite/incorrect loop – fetch performed only once
fetchedEntities
is retrieved before entering the while
loop and never refreshed, so:
- the loop may spin forever if
entities.items.length ≥ limit
, or - it processes only the first page and exits.
Move the client.getEntities
call inside the loop or convert the loop to do … while
.
export function mergeCairoOption<T extends SchemaType>( | ||
target: MergedModels<T>, | ||
source: Partial<MergedModels<T>> | ||
): MergedModels<T> { | ||
// If source is Some, prefer source's value | ||
if (source instanceof CairoOption && source.isSome()) { | ||
return new CairoOption( | ||
CairoOptionVariant.Some, | ||
source.unwrap() | ||
) as unknown as MergedModels<T>; | ||
} | ||
|
||
// If source is None or undefined, keep target | ||
if (target instanceof CairoOption) { | ||
if (target.isSome()) { | ||
return new CairoOption( | ||
CairoOptionVariant.Some, | ||
target.unwrap() | ||
) as unknown as MergedModels<T>; | ||
} | ||
return new CairoOption( | ||
CairoOptionVariant.None | ||
) as unknown as MergedModels<T>; | ||
} | ||
|
||
// This should not happen if both are CairoOption instances | ||
return target as unknown as MergedModels<T>; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding unit tests for this critical merge functionality
The implementation looks correct, handling the different cases (Some vs None) for CairoOption merging. The function properly preserves the source value when present or falls back to the target.
This is a core function that will impact entity state management throughout the application. Please add test coverage for various merge scenarios, including:
- When source is Some and target is Some
- When source is None and target is Some
- When source is Some and target is None
- When source is None and target is None
const defaultToriiOptions = () => ({ | ||
limit: 100, // default limit | ||
offset: 0, | ||
pagination: { | ||
limit: 100, | ||
cursor: undefined, | ||
direction: "Forward", | ||
order_by: [], | ||
}, | ||
clause: undefined, | ||
dont_include_hashed_keys: true, | ||
order_by: [], | ||
entity_models: [], | ||
entity_updated_after: 0, | ||
no_hashed_keys: true, | ||
models: [], | ||
historical: false, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Breaking change: Restructured pagination options
The pagination parameters are now nested within a pagination
object instead of being at the root level, and no_hashed_keys
replaces dont_include_hashed_keys
.
Please ensure these breaking changes are documented in the migration guide for users upgrading from previous versions.
🏁 Script executed:
#!/bin/bash
# Check if there's a migration guide or documentation for these breaking changes
fd -t f "migration|upgrade|changelog|BREAKING" --exec grep -l "pagination" {} \;
Length of output: 83
Add missing migration guide entry for pagination restructure and key rename
It looks like the breaking changes to defaultToriiOptions
haven’t been documented yet. Please add/update your migration guide or changelog to cover:
- Moving pagination fields (
limit
,cursor
,direction
,order_by
) under a top-levelpagination
object - Renaming
dont_include_hashed_keys
→no_hashed_keys
- Any examples or code snippets showing the before/after usage
Closes #
Introduced changes
Checklist
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores