Skip to content

chore: add sdk token balance example #421

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2025
Merged

Conversation

MartianGreed
Copy link
Collaborator

@MartianGreed MartianGreed commented Mar 17, 2025

Closes #

Introduced changes

Checklist

  • Linked relevant issue
  • Updated relevant documentation
  • Added relevant tests
  • Add a dedicated CI job for new examples
  • Performed self-review of the code

Summary by CodeRabbit

  • New Features

    • Launched a comprehensive project template that includes wallet connectivity and real-time token balance display.
    • Integrated React components for wallet management and token tracking with enhanced SDK subscription capabilities.
  • Documentation

    • Added a detailed setup guide outlining configuration, ESLint guidelines, and integration instructions.
  • Style

    • Introduced modern UI styling and animations for improved responsiveness and visual appeal.
  • Chores

    • Updated configuration files, build scripts, and dependency management to streamline the development workflow.

Copy link

coderabbitai bot commented Mar 17, 2025

Walkthrough

This pull request introduces a new example project for Vite token balance that integrates React, TypeScript, and Dojo SDK. New configuration files, documentation, HTML, styling, and multiple React components (App, Wallet, TokenBalance, StarknetProvider) have been added. In addition, the SDK has been enhanced with updated methods and new hooks for token balance subscriptions, refined type definitions, and dependency modifications.

Changes

Files Change Summary
examples/example-vite-token-balance/{.gitignore, README.md, dojoConfig.ts, eslint.config.js, index.html, package.json} Added new project configuration and documentation files for a React/TypeScript/Vite example that integrates the Dojo SDK.
examples/example-vite-token-balance/src/{App.css, App.tsx, index.css, main.tsx} Introduced the main application entry point, core App component, and associated styling and rendering logic.
examples/example-vite-token-balance/src/components/{starknet-provider.tsx, token-balance.tsx, wallet.tsx} Added new React components for wallet connection, token balance display, and StarkNet provider setup.
examples/example-vite-token-balance/src/typescript/{contracts.gen.ts, models.gen.ts} Provided smart contract interaction functions and model definitions for Dojo smart contract actions.
packages/sdk/{package.json, src/index.ts, src/react/**, src/token.ts, src/types.ts} Enhanced the SDK with new dependencies, refactored token balance methods with structured request objects, introduced a new HOC (WithAccount), added/updated React hooks for entities, events, tokens and state management, and refined type definitions.

Sequence Diagram(s)

sequenceDiagram
  participant M as main.tsx
  participant DSP as DojoSdkProvider
  participant SP as StarknetProvider
  participant App as App Component
  M->>DSP: Initialize Dojo SDK with configuration
  DSP->>SP: Pass SDK context and dojoConfig
  SP->>App: Render App component with provided context
Loading
sequenceDiagram
  participant UI as TokenBalance Component
  participant Hook as useTokens Hook
  participant SDK as Dojo SDK/Torii Client
  UI->>Hook: Request token balances
  Hook->>SDK: Fetch tokens and subscribe for balance updates
  SDK-->>Hook: Return token data and subscription
  Hook-->>UI: Update UI with token balance information
Loading

Possibly related PRs

  • feat: sdk v2 #266: Introduces a similar dojoConfig.ts file that initializes Dojo configuration using a manifest, aligning closely with this PR’s setup.

Suggested reviewers

  • ponderingdemocritus

Poem

In a meadow of code, I happily bound,
New configs and tokens joyfully found,
With wallets that connect in a vibrant display,
I hop through fresh hooks and types all day,
A bunny’s delight in lines profound! 🐰💻

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@MartianGreed MartianGreed force-pushed the example/token-balance branch 6 times, most recently from 7806d69 to 0a81678 Compare March 25, 2025 14:19
@MartianGreed MartianGreed force-pushed the example/token-balance branch from 0a81678 to d30f3e0 Compare March 31, 2025 12:57
@MartianGreed MartianGreed marked this pull request as ready for review March 31, 2025 13:13
@MartianGreed MartianGreed merged commit 4478e79 into main Mar 31, 2025
5 of 6 checks passed
@MartianGreed MartianGreed deleted the example/token-balance branch March 31, 2025 13:20
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 16

🧹 Nitpick comments (35)
examples/example-vite-token-balance/dojoConfig.ts (1)

1-7: LGTM with a note on environment configuration

The configuration is correctly set up with the manifest import and properly exports the Dojo configuration.

Consider making the manifest path more robust by:

  1. Using environment variables for different environments (dev/prod)
  2. Adding error handling for missing or malformed manifest files
- import manifest from "../../worlds/dojo-starter/manifest_dev.json";
+ // Use environment-specific manifest
+ import manifest from process.env.NODE_ENV === "production" 
+   ? "../../worlds/dojo-starter/manifest.json"
+   : "../../worlds/dojo-starter/manifest_dev.json";

export const dojoConfig = createDojoConfig({
    manifest,
});
examples/example-vite-token-balance/src/App.tsx (1)

1-16: LGTM: Simple and focused component structure

The App component has a clean structure that composes the UI from Wallet and TokenBalance components.

Consider these improvements for a more robust implementation:

  1. Add state management context to share wallet data between components
  2. Implement error boundaries for better error handling
  3. Enhance accessibility with semantic HTML
import "./App.css";
import { Wallet } from "./components/wallet";
import TokenBalance from "./components/token-balance";
+import { useState } from "react";
+import { ErrorBoundary } from "react-error-boundary";

function App() {
+   const [walletError, setWalletError] = useState<Error | null>(null);
+   
+   const handleError = (error: Error) => {
+       console.error("Application error:", error);
+       setWalletError(error);
+   };

    return (
        <>
-           <h1>Connect your wallet</h1>
-           <Wallet />
-           <TokenBalance />
+           <main>
+               <h1>Connect your wallet</h1>
+               <ErrorBoundary fallback={<p>Something went wrong with wallet connection</p>} onError={handleError}>
+                   <Wallet />
+                   <TokenBalance />
+               </ErrorBoundary>
+           </main>
        </>
    );
}

export default App;
examples/example-vite-token-balance/tsconfig.app.json (1)

1-27: TSConfig for App is Well-Configured
The TypeScript configuration settings such as target, module, and strict options are appropriately set for a modern React application. Note that inline comments (e.g., at lines 10, 18) are non-standard in pure JSON. However, since tsconfig.json files typically support comments (JSONC style), it should not cause issues with the TypeScript compiler. Still, if any tooling enforces strict JSON compliance, you might consider removing or replacing these comments.

🧰 Tools
🪛 Biome (1.9.4)

[error] 10-10: JSON standard does not allow comments.

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: JSON standard does not allow comments.

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

examples/example-vite-token-balance/tsconfig.node.json (1)

1-25: TSConfig for Node is Correctly Set-Up
The configuration for Node-specific build settings is appropriate with a high ECMAScript target and necessary strict options. Similar to tsconfig.app.json, inline comments (e.g., at lines 9 and 16) are allowed in TypeScript configuration files but may trigger warnings in strict JSON validators. If you encounter issues with JSON parsers, consider removing these comments or using a .jsonc extension if supported by your toolchain.

🧰 Tools
🪛 Biome (1.9.4)

[error] 9-9: JSON standard does not allow comments.

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: JSON standard does not allow comments.

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

examples/example-vite-token-balance/src/main.tsx (2)

16-20: Replace placeholder values with actual configuration values.

The domain configuration is using placeholder values like "WORLD_NAME" and "KATANA". Make sure to replace these with actual values appropriate for your environment before deploying.

- name: "WORLD_NAME",
+ name: "example-token-balance",

23-23: Avoid using non-null assertion.

The non-null assertion (!) on document.getElementById("root") could lead to runtime errors if the element doesn't exist. Consider using a more defensive approach to handle potential null values.

- createRoot(document.getElementById("root")!).render(
+ const rootElement = document.getElementById("root");
+ if (!rootElement) {
+   console.error("Root element not found");
+   return;
+ }
+ createRoot(rootElement).render(
🧰 Tools
🪛 Biome (1.9.4)

[error] 23-23: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

examples/example-vite-token-balance/src/typescript/contracts.gen.ts (2)

19-28: Consider consolidating duplicate error handling logic.

The error handling logic is duplicated in both the actions_move and actions_spawn functions. Consider extracting this pattern into a higher-order function to reduce duplication.

+ const executeWithErrorHandling = async (
+   fn: () => Promise<any>
+ ) => {
+   try {
+     return await fn();
+   } catch (error) {
+     console.error(error);
+     throw error;
+   }
+ };

  const actions_move = async (
    snAccount: Account | AccountInterface,
    direction: CairoCustomEnum
  ) => {
-   try {
-     return await provider.execute(
+   return executeWithErrorHandling(() => 
+     provider.execute(
        snAccount,
        build_actions_move_calldata(direction),
        "dojo_starter"
-     );
-   } catch (error) {
-     console.error(error);
-     throw error;
-   }
+     )
+   );
  };

Also applies to: 39-50


23-23: Consider making the namespace configurable.

The hardcoded "dojo_starter" namespace might need to be configurable for different environments or projects. Consider making it a parameter or retrieving it from configuration.

+ function setupWorld(provider: DojoProvider, namespace: string = "dojo_starter") {
  // ...
      return await provider.execute(
        snAccount,
        build_actions_move_calldata(direction),
-       "dojo_starter"
+       namespace
      );
  // ...
      return await provider.execute(
        snAccount,
        build_actions_spawn_calldata(),
-       "dojo_starter"
+       namespace
      );

Also applies to: 44-44

packages/sdk/src/react/hooks/utils.ts (2)

21-30: Optimize array comparison for better performance.

The current array comparison algorithm has O(n) complexity but could potentially exit early on finding the first unequal element. Also, checking if both are arrays can be optimized.

  // Handle arrays
- if (Array.isArray(a) && Array.isArray(b)) {
+ const aIsArray = Array.isArray(a);
+ const bIsArray = Array.isArray(b);
+ if (aIsArray !== bIsArray) return false;
+ if (aIsArray) {
    if (a.length !== b.length) return false;

    for (let i = 0; i < a.length; i++) {
      if (!deepEqual(a[i], b[i])) return false;
    }

    return true;
  }

50-54: Use a more robust method for checking object property existence.

The current implementation checks if a property exists in b using Object.prototype.hasOwnProperty.call(b, key), which is correct. However, it doesn't handle inherited properties consistently across objects.

  return keysA.every(
    (key) =>
-     Object.prototype.hasOwnProperty.call(b, key) &&
+     Object.hasOwn(b, key) &&
      deepEqual(a[key], b[key])
  );
examples/example-vite-token-balance/src/index.css (1)

1-1: Consider adding a version specification for Tailwind import

The import statement for Tailwind CSS doesn't specify a version. For better maintainability, consider using a versioned import to prevent unexpected changes when Tailwind updates.

-@import "tailwindcss";
+@import "tailwindcss/base";
+@import "tailwindcss/components";
+@import "tailwindcss/utilities";
examples/example-vite-token-balance/README.md (2)

1-9: Customize the README for this specific example

The current README contains generic information about React, TypeScript, and Vite setup. Consider customizing it to include specific information about this token balance example, explaining its purpose, functionality, and how to use it.


10-32: Consider including project-specific ESLint configuration

While the ESLint configuration guidance is helpful, it would be more valuable to include configuration specific to this token balance example project rather than generic examples.

examples/example-vite-token-balance/src/components/token-balance.tsx (2)

4-6: Add error handling for token fetching

The useTokens hook call doesn't include error handling. Consider adding error state management to handle cases when token data can't be retrieved.

-const { tokens, getBalance, toDecimal } = useTokens({
+const { tokens, getBalance, toDecimal, error } = useTokens({
    accountAddresses: [address],
});

+// Add error handling display
+if (error) {
+  return <div>Error loading token data: {error.message}</div>;
+}

14-17: Add loading state and handle empty tokens array

The component doesn't handle the case where tokens array is empty or still loading. Consider adding a loading state and a message for when no tokens are available.

return (
    <div>
        Token Balance: {address}
        <div>
+           {tokens.length === 0 ? (
+               <div>No tokens found for this address</div>
+           ) : (
                {tokens.map((token, idx) => (
                    <div key={idx}>
                        {token.symbol}
                        &nbsp;
                        {toDecimal(token, getBalance(token))}
                    </div>
                ))}
+           )}
        </div>
    </div>
);
examples/example-vite-token-balance/src/components/starknet-provider.tsx (1)

29-40: Add error handling for provider connection

The component doesn't handle potential errors in connecting to the Starknet provider. Consider adding error boundaries or error state handling.

packages/sdk/src/react/hooks/entities.ts (1)

14-14: Avoid using any type in the generic parameter.

The useDojoSDK hook is using any in its generic parameter which defeats the purpose of TypeScript's type safety. Consider using a more specific type constraint if possible.

- const { sdk, useDojoStore } = useDojoSDK<() => any, Schema>();
+ const { sdk, useDojoStore } = useDojoSDK<() => unknown, Schema>();
🧰 Tools
🪛 Biome (1.9.4)

[error] 14-14: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

packages/sdk/src/react/hooks/index.ts (2)

19-24: Replace any type with a more specific constraint.

Using any in type parameters defeats TypeScript's type checking capabilities. Consider using a more specific type or unknown if the exact type cannot be determined.

export function useDojoSDK<
-   Client extends (...args: any) => any,
+   Client extends (...args: unknown[]) => unknown,
    Schema extends SchemaType,
>(): DojoContextType<Client, Schema> {
    return useContext<DojoContextType<Client, Schema>>(DojoContext);
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 20-20: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


32-41: Document the default behavior when no keys are provided.

The function returns BigInt(0) when no keys are provided, but it's not clear if this is a special value or just a default. Consider adding documentation about this behavior.

/**
 * If you know all distinct keys of your model, here is a way to compose it.
 *
+ * Returns BigInt(0) if no keys are provided, which can be used as a default or empty entity ID.
 *
 * @param keys Each keys corresponding to your model keys.
 * @returns Composed entityId
 */
packages/sdk/src/react/hoc/with-account.tsx (1)

9-22: Good implementation of HOC pattern with fallback handling.

The WithAccount HOC follows best practices by:

  1. Properly typing its parameters and return type
  2. Providing a default fallback component
  3. Safely handling the case when no wallet address is available
  4. Correctly merging props

Consider adding a more comprehensive documentation comment to explain how to use this HOC and what happens when a wallet is not connected.

/**
+ * Higher-order component that provides account information to the wrapped component.
+ * If the user has not connected their wallet (no address is available), the fallback component is rendered.
+ *
+ * @example
+ * ```tsx
+ * const AccountAwareComponent = WithAccount(MyComponent);
+ * // In your render:
+ * <AccountAwareComponent additionalProp={value} />
+ * ```
+ *
 * @param Component The component to wrap with account information
 * @param Fallback Component to render when no wallet is connected
 */
packages/sdk/src/react/hooks/events.ts (4)

15-15: Avoid using any in generic type parameters.

Replace any with a more specific type constraint to maintain type safety.

- const { sdk, useDojoStore } = useDojoSDK<() => any, Schema>();
+ const { sdk, useDojoStore } = useDojoSDK<() => unknown, Schema>();
🧰 Tools
🪛 Biome (1.9.4)

[error] 15-15: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


47-47: Avoid using any in type parameters.

Similar to the issue in line 15, use a more specific type constraint rather than any.

- const { sdk } = useDojoSDK<() => any, Schema>();
+ const { sdk } = useDojoSDK<() => unknown, Schema>();
🧰 Tools
🪛 Biome (1.9.4)

[error] 47-47: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


44-70: Consider potential performance implications of array updates.

When frequently adding events to the beginning of an array with setEvents((ev) => [event, ...ev]), performance may degrade as the array grows. Consider using a more efficient data structure or limiting the array size if you expect a large number of historical events.

export function useHistoricalEventsQuery<Schema extends SchemaType>(
    query: ToriiQueryBuilder<Schema>
) {
    const { sdk } = useDojoSDK<() => unknown, Schema>();
    const [events, setEvents] = useState<StandardizedQueryResult<Schema>[]>([]);
+   // Optional: Add a configuration for maximum events to keep
+   const maxEvents = 100; 

    // ... existing code ...

    processUpdateData: (data) => {
        if (!data || data.length === 0) {
            return;
        }
        const event = data.pop();
        if (event && event.entityId !== "0x0") {
-           setEvents((ev) => [event, ...ev]);
+           setEvents((ev) => {
+               const newEvents = [event, ...ev];
+               // Optional: Limit the array size to prevent performance issues
+               return maxEvents ? newEvents.slice(0, maxEvents) : newEvents;
+           });
        }
    },
🧰 Tools
🪛 Biome (1.9.4)

[error] 47-47: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


34-36: Consider returning subscription or status information.

The useEventQuery hook doesn't return anything, while useHistoricalEventsQuery returns events. For consistency and to provide users with more control, consider returning subscription status or other relevant information.

examples/example-vite-token-balance/src/components/wallet.tsx (2)

38-41: Add explicit button type to avoid unintended form submissions.

By default, the button element has type="submit", which may cause unexpected behavior if wrapped in a form. Specify type="button" to ensure the desired behavior.

-<button
+<button
+  type="button"
   onClick={() => disconnect()}
   className="text-white border border-white p-3"
>
  Disconnect
</button>
🧰 Tools
🪛 Biome (1.9.4)

[error] 38-41: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


55-60: Explicitly set button type for each connector button.

Similarly, specify type="button" to avoid default submit behavior inside potential forms.

-<button
+<button
+  type="button"
   key={connector.id}
   onClick={() => connect(connector)}
   disabled={!connector.available()}
   className="text-white border border-white p-3"
>
  {connector.name}
  {isWalletConnecting(connector.id) && "Connecting"}
</button>
🧰 Tools
🪛 Biome (1.9.4)

[error] 55-60: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

packages/sdk/src/react/provider.tsx (1)

16-19: Avoid using any in function type definitions.

Client extends (...args: any) => any disables type checking for function arguments and returns. Consider more specific parameter/return types to enhance maintainability and catch potential errors.

🧰 Tools
🪛 Biome (1.9.4)

[error] 17-17: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 17-17: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

packages/sdk/src/react/hooks/hooks.ts (2)

24-25: Provide a narrower type instead of any.

Using any for the clause parameter disables type checking. A more specific type would help prevent mistakes and clarify usage.

🧰 Tools
🪛 Biome (1.9.4)

[error] 24-24: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


32-32: Avoid any in processUpdateData argument.

To enhance type safety, provide a more specific type or a generic parameter if exact data shape is unknown.

🧰 Tools
🪛 Biome (1.9.4)

[error] 32-32: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

packages/sdk/src/react/hooks/state.ts (1)

15-20: Consider refining the type casting approach.

The comment indicates a temporary solution with "hacktually until I find a proper type input". Using as unknown as type assertion bypasses TypeScript's type checking which could mask potential type errors.

export function createDojoStore<T extends SchemaType>() {
-    // hacktually until I find a proper type input to createDojoStoreFactory
-    return createDojoStoreFactory<T>(create) as unknown as UseBoundStore<
-        StoreApi<GameState<T>>
-    >;
+    // Create a properly typed store
+    return createDojoStoreFactory<T>(create) as UseBoundStore<
+        StoreApi<GameState<T>>
+    >;
}
packages/sdk/src/token.ts (1)

123-161: Comprehensive error handling in callback, but could be improved.

The subscribeTokenBalance function has good error handling in the callback, but doesn't reuse the existing onTokenBalanceUpdated function which would help maintain consistency and reduce code duplication.

export async function subscribeTokenBalance(
    client: torii.ToriiClient,
    request: SubscribeTokenBalanceRequest
): Promise<[torii.TokenBalances, torii.Subscription]> {
    const { contractAddresses, accountAddresses, tokenIds, callback } = request;

    // Get initial token balances
    const initialBalances = await getTokenBalances(client, {
        contractAddresses: contractAddresses ?? [],
        accountAddresses: accountAddresses ?? [],
        tokenIds: tokenIds ?? [],
    });

-    // Create subscription for updates
-    const subscription = client.onTokenBalanceUpdated(
-        contractAddresses ?? [],
-        accountAddresses ?? [],
-        tokenIds ?? [],
-        (res: torii.TokenBalance) => {
-            if (res === defaultTokenBalance) {
-                return;
-            }
-            try {
-                callback({
-                    data: res,
-                    error: undefined,
-                });
-                return;
-            } catch (error) {
-                callback({
-                    data: undefined,
-                    error: error as Error,
-                });
-            }
-        }
-    );
+    // Create subscription for updates - reuse onTokenBalanceUpdated function
+    const wrappedCallback = (res: torii.TokenBalance) => {
+        if (res === defaultTokenBalance) {
+            return;
+        }
+        try {
+            callback({
+                data: res,
+                error: undefined,
+            });
+            return;
+        } catch (error) {
+            callback({
+                data: undefined,
+                error: error as Error,
+            });
+        }
+    };
+
+    const subscription = onTokenBalanceUpdated(client, {
+        contractAddresses,
+        accountAddresses,
+        tokenIds,
+        callback: wrappedCallback,
+    });

    return [initialBalances, subscription];
}
examples/example-vite-token-balance/src/typescript/models.gen.ts (2)

3-3: Use import type for type-only imports.

The static analysis tool correctly flagged this issue. When importing types that are only used for type annotations and not at runtime, it's better to use import type to ensure they're removed by the compiler.

- 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)


85-90: Consider more consistent formatting for enum initialization.

The indentation is inconsistent in the CairoCustomEnum initialization. Also, consider using null instead of undefined for consistency across the codebase.

            directions: [new CairoCustomEnum({ 
-					Left: "",
-				Right: undefined,
-				Up: undefined,
-				Down: undefined, })],
+                Left: "",
+                Right: null,
+                Up: null,
+                Down: null,
+            })],
packages/sdk/src/types.ts (2)

401-403: Simplified method signature for onTokenBalanceUpdated.

The method signature is updated to use the new request object pattern, which is more maintainable than separate parameters. The JSDoc comments need to be updated to reflect this change.

Consider updating the JSDoc comments to reflect that the method now takes a single request object rather than separate parameters:

/**
 * Subscribes to token balance updates
 *
 * # Parameters
- * @param {string[]} contract_addresses - Array of contract addresses to filter (empty for all)
- * @param {string[]} account_addresses - Array of account addresses to filter (empty for all)
- * @param {string[]} token_ids - Array of token ids to filter (empty for all)
- * @param {Funtion} callback - JavaScript function to call on updates
+ * @param {SubscribeTokenBalanceRequest} request - Request object containing filters and callback
 *
 * # Returns
 * Result containing subscription handle or error
 * @returns torii.Subscription
 */

418-420: Simplified method signature for updateTokenBalanceSubscription.

The method signature is updated to use the new request object pattern, which is more maintainable than separate parameters. The JSDoc comments need to be updated to reflect this change.

Consider updating the JSDoc comments to reflect that the method now takes a single request object rather than separate parameters:

/**
 * Updates an existing token balance subscription
 *
 * # Parameters
- * @param {torii.Subscription} subscription - Existing subscription to update
- * @param {string[]} contract_addresses - New array of contract addresses to filter
- * @param {string[]} account_addresses - New array of account addresses to filter
- * @param {string[]} token_ids - New array of token ids to filter
+ * @param {UpdateTokenBalanceSubscriptionRequest} request - Request object containing subscription and filters
 *
 * # Returns
 * Result containing unit or error
 * @returns {Promise<void>}
 */
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04dd181 and d30f3e0.

⛔ Files ignored due to path filters (3)
  • examples/example-vite-token-balance/public/vite.svg is excluded by !**/*.svg
  • examples/example-vite-token-balance/src/assets/react.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (36)
  • examples/example-vite-token-balance/.gitignore (1 hunks)
  • examples/example-vite-token-balance/README.md (1 hunks)
  • examples/example-vite-token-balance/dojoConfig.ts (1 hunks)
  • examples/example-vite-token-balance/eslint.config.js (1 hunks)
  • examples/example-vite-token-balance/index.html (1 hunks)
  • examples/example-vite-token-balance/package.json (1 hunks)
  • examples/example-vite-token-balance/src/App.css (1 hunks)
  • examples/example-vite-token-balance/src/App.tsx (1 hunks)
  • examples/example-vite-token-balance/src/components/starknet-provider.tsx (1 hunks)
  • examples/example-vite-token-balance/src/components/token-balance.tsx (1 hunks)
  • examples/example-vite-token-balance/src/components/wallet.tsx (1 hunks)
  • examples/example-vite-token-balance/src/index.css (1 hunks)
  • examples/example-vite-token-balance/src/main.tsx (1 hunks)
  • examples/example-vite-token-balance/src/typescript/contracts.gen.ts (1 hunks)
  • examples/example-vite-token-balance/src/typescript/models.gen.ts (1 hunks)
  • examples/example-vite-token-balance/src/vite-env.d.ts (1 hunks)
  • examples/example-vite-token-balance/tsconfig.app.json (1 hunks)
  • examples/example-vite-token-balance/tsconfig.json (1 hunks)
  • examples/example-vite-token-balance/tsconfig.node.json (1 hunks)
  • examples/example-vite-token-balance/vite.config.ts (1 hunks)
  • package.json (2 hunks)
  • packages/sdk/package.json (1 hunks)
  • packages/sdk/src/index.ts (5 hunks)
  • packages/sdk/src/react/hoc/with-account.tsx (1 hunks)
  • packages/sdk/src/react/hooks.ts (0 hunks)
  • packages/sdk/src/react/hooks/entities.ts (1 hunks)
  • packages/sdk/src/react/hooks/events.ts (1 hunks)
  • packages/sdk/src/react/hooks/hooks.ts (1 hunks)
  • packages/sdk/src/react/hooks/index.ts (1 hunks)
  • packages/sdk/src/react/hooks/state.ts (1 hunks)
  • packages/sdk/src/react/hooks/token.ts (1 hunks)
  • packages/sdk/src/react/hooks/utils.ts (1 hunks)
  • packages/sdk/src/react/index.ts (1 hunks)
  • packages/sdk/src/react/provider.tsx (2 hunks)
  • packages/sdk/src/token.ts (1 hunks)
  • packages/sdk/src/types.ts (7 hunks)
💤 Files with no reviewable changes (1)
  • packages/sdk/src/react/hooks.ts
🧰 Additional context used
🧬 Code Definitions (11)
examples/example-vite-token-balance/src/App.tsx (1)
examples/example-vite-token-balance/src/components/wallet.tsx (1)
  • Wallet (9-68)
examples/example-vite-token-balance/src/components/starknet-provider.tsx (1)
examples/example-vite-token-balance/dojoConfig.ts (1)
  • dojoConfig (5-7)
examples/example-vite-token-balance/src/main.tsx (4)
examples/example-vite-token-balance/dojoConfig.ts (1)
  • dojoConfig (5-7)
packages/sdk/src/react/provider.tsx (1)
  • DojoSdkProvider (46-80)
examples/example-vite-token-balance/src/typescript/contracts.gen.ts (1)
  • setupWorld (4-60)
examples/example-vite-token-balance/src/components/starknet-provider.tsx (1)
  • StarknetProvider (18-41)
packages/sdk/src/react/hooks/index.ts (3)
examples/example-vite-token-balance/src/typescript/models.gen.ts (1)
  • SchemaType (68-80)
packages/sdk/src/types.ts (1)
  • SchemaType (51-71)
packages/sdk/src/react/provider.tsx (2)
  • DojoContextType (16-30)
  • DojoContext (37-37)
examples/example-vite-token-balance/src/components/token-balance.tsx (2)
packages/sdk/src/react/hooks/token.ts (1)
  • useTokens (17-78)
packages/sdk/src/react/hoc/with-account.tsx (1)
  • WithAccount (9-22)
packages/sdk/src/react/hooks/token.ts (3)
packages/sdk/src/types.ts (3)
  • GetTokenRequest (261-264)
  • GetTokenBalanceRequest (266-268)
  • SubscriptionCallbackArgs (280-280)
packages/sdk/src/react/hooks/index.ts (1)
  • useDojoSDK (19-24)
packages/sdk/src/react/hooks/utils.ts (1)
  • deepEqual (7-55)
packages/sdk/src/react/hooks/hooks.ts (3)
examples/example-vite-token-balance/src/typescript/models.gen.ts (1)
  • SchemaType (68-80)
packages/sdk/src/types.ts (5)
  • SchemaType (51-71)
  • SubscribeParams (524-534)
  • SubscribeResponse (256-259)
  • ToriiQueryBuilder (545-545)
  • ToriiResponse (249-254)
packages/sdk/src/react/hooks/utils.ts (2)
  • sleep (62-64)
  • deepEqual (7-55)
packages/sdk/src/index.ts (2)
packages/sdk/src/types.ts (4)
  • SubscribeTokenBalanceRequest (287-289)
  • GetTokenRequest (261-264)
  • GetTokenBalanceRequest (266-268)
  • UpdateTokenBalanceSubscriptionRequest (291-293)
packages/sdk/src/token.ts (5)
  • subscribeTokenBalance (123-161)
  • getTokens (40-46)
  • getTokenBalances (52-63)
  • onTokenBalanceUpdated (75-87)
  • updateTokenBalanceSubscription (100-112)
examples/example-vite-token-balance/src/typescript/models.gen.ts (1)
packages/sdk/src/types.ts (1)
  • SchemaType (51-71)
packages/sdk/src/token.ts (1)
packages/sdk/src/types.ts (4)
  • GetTokenRequest (261-264)
  • GetTokenBalanceRequest (266-268)
  • SubscribeTokenBalanceRequest (287-289)
  • UpdateTokenBalanceSubscriptionRequest (291-293)
packages/sdk/src/types.ts (2)
examples/example-vite-react-sdk/src/typescript/models.gen.ts (1)
  • SchemaType (75-87)
examples/example-vite-token-balance/src/typescript/models.gen.ts (1)
  • SchemaType (68-80)
🪛 Biome (1.9.4)
packages/sdk/src/react/hooks/utils.ts

[error] 7-7: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 7-7: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

examples/example-vite-token-balance/tsconfig.node.json

[error] 9-9: JSON standard does not allow comments.

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 10-10: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: JSON standard does not allow comments.

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 17-17: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

examples/example-vite-token-balance/tsconfig.app.json

[error] 10-10: JSON standard does not allow comments.

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 11-11: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 12-12: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 13-13: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 14-14: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 15-15: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-16: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 16-18: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 18-18: JSON standard does not allow comments.

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 19-19: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 20-20: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 21-21: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 22-22: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 23-23: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 24-24: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-25: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 25-26: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

packages/sdk/src/react/hooks/entities.ts

[error] 14-14: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

examples/example-vite-token-balance/src/components/wallet.tsx

[error] 1-6: 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)


[error] 38-41: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)


[error] 55-60: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

examples/example-vite-token-balance/src/main.tsx

[error] 23-23: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

packages/sdk/src/react/hooks/index.ts

[error] 20-20: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 20-20: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

packages/sdk/src/react/hooks/events.ts

[error] 15-15: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 47-47: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

examples/example-vite-token-balance/src/components/token-balance.tsx

[error] 13-13: 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/react/hooks/token.ts

[error] 54-54: This hook does not specify all of its dependencies: fetchTokenBalances

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 54-54: This hook does not specify all of its dependencies: fetchTokens

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)

packages/sdk/src/react/hooks/state.ts

[error] 32-32: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 32-32: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 59-59: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 59-59: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

packages/sdk/src/react/hooks/hooks.ts

[error] 24-24: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 32-32: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 55-55: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)


[error] 68-68: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)


[error] 44-44: This hook does not specify all of its dependencies: config.getErrorPrefix

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.processInitialData

This dependency is not specified in the hook dependency list.

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.subscribeMethod

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.updateSubscriptionMethod

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.queryToHashedKeysMethod

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.historical

This dependency is not specified in the hook dependency list.

This dependency is not specified in the hook dependency list.

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.processUpdateData

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 88-88: This hook does not specify all of its dependencies: config.getErrorPrefix

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)

examples/example-vite-token-balance/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)

🔇 Additional comments (47)
examples/example-vite-token-balance/src/vite-env.d.ts (1)

1-1: LGTM: Standard TypeScript declaration for Vite

This is the standard TypeScript declaration file for Vite projects that allows TypeScript to recognize Vite-specific types.

examples/example-vite-token-balance/tsconfig.json (1)

1-7: LGTM: Standard TypeScript project references configuration

This TypeScript configuration properly uses project references to organize compilation for different parts of the project.

packages/sdk/src/react/index.ts (1)

3-3: Clean addition of the HOC export

The export statement follows the established pattern and properly exposes the with-account HOC module for external use. This will make the account-related functionality available to consumers of the SDK.

package.json (2)

6-6: LGTM: New WebAssembly build script

This new script provides a dedicated command for building WebAssembly components, which aligns with the WASM support in the token balance example.


15-15:

❓ Verification inconclusive

Verify if increased concurrency is necessary

The concurrency parameter was increased from 15 to 20. While this likely accommodates the additional workload from the new example, ensure this won't cause performance issues on average development machines.


🏁 Script executed:

#!/bin/bash
# Check how many packages/examples are in the project that might run in dev mode
echo "Number of potential packages/examples that may run concurrently:"
find packages examples -type f -name "package.json" | grep -v "node_modules" | wc -l

# List them for reference
echo -e "\nList of packages/examples:"
find packages examples -type f -name "package.json" | grep -v "node_modules"

Length of output: 1498


Review Action: Verify Impact of Increased Concurrency

Based on the analysis, there are 27 packages/examples that could potentially run concurrently in dev mode. Increasing the concurrency from 15 to 20 appears to be a deliberate attempt to better accommodate the additional workload (including the new example). However, since running 20 processes concurrently could strain lower-end development machines, please verify on a typical development setup that this change does not lead to performance issues. If any performance concerns arise, consider providing an override option or documentation for environments with limited resources.

packages/sdk/package.json (1)

77-78:

✅ Verification successful

Added StarkNet React dependencies

These dependencies will support the StarkNet blockchain integration for the token balance example. The use of "catalog:" versioning is consistent with other dependencies in the project.

However, consider whether these should be peer dependencies instead if they're primarily used in example projects rather than core SDK functionality.


🏁 Script executed:

#!/bin/bash
# Check if these dependencies are used in core SDK code or just in examples
echo "Checking for @starknet-react usage in SDK core code:"
rg -l "@starknet-react" packages/sdk/src --glob "!*.d.ts" | grep -v "examples" || echo "Not found in core SDK"

echo -e "\nChecking for @starknet-react usage in examples:"
rg -l "@starknet-react" examples/ || echo "Not found in examples"

Length of output: 1916


StarkNet React Dependency Integration Verified

After verifying the usage across the repository, it’s clear that although many occurrences appear in the examples, there is a direct usage in the core SDK (notably in packages/sdk/src/react/hoc/with-account.tsx). This indicates that the added dependencies are not used solely for example projects. Keeping them as direct dependencies is therefore justified. If the core usage is intentional and essential, no change to peer dependencies is necessary. Please confirm that this aligns with the intended design.

  • Usage in core SDK: packages/sdk/src/react/hoc/with-account.tsx
  • Widespread usage across example projects
examples/example-vite-token-balance/vite.config.ts (1)

1-10:

✅ Verification successful

Well-structured Vite configuration for the example

The configuration includes all necessary plugins for a modern React+WASM+Tailwind setup. The comment with documentation link is helpful for developers who might be less familiar with Vite.

Make sure all these plugins are listed as dependencies in the example project's package.json.


🏁 Script executed:

#!/bin/bash
# Check if the required plugins are listed in the example project's package.json
EXAMPLE_DIR="examples/example-vite-token-balance"
echo "Checking for Vite plugins in ${EXAMPLE_DIR}/package.json:"

# Check each plugin
for plugin in "@vitejs/plugin-react" "vite-plugin-wasm" "vite-plugin-top-level-await" "@tailwindcss/vite"; do
  if cat "${EXAMPLE_DIR}/package.json" 2>/dev/null | grep -q "\"$plugin\""; then
    echo "$plugin is present"
  else
    echo "$plugin may be missing"
  fi
done

Length of output: 1316


Vite Configuration and Dependencies Verified
The Vite configuration in examples/example-vite-token-balance/vite.config.ts is well-structured for a modern React+WASM+Tailwind setup. All listed plugins (i.e., @vitejs/plugin-react, vite-plugin-wasm, vite-plugin-top-level-await, and @tailwindcss/vite) have been confirmed to be present as dependencies in the example project's package.json.

No further action is required.

examples/example-vite-token-balance/index.html (1)

1-14: HTML Structure Looks Excellent
The HTML document is well-formed with the correct doctype, meta tags for charset and viewport settings, and a clear mounting point for the application. The inclusion of the module script (/src/main.tsx) is also correctly implemented.

examples/example-vite-token-balance/.gitignore (1)

1-25: .gitignore Covers Essential Patterns
The ignore rules comprehensively cover logs, build artifacts, node_modules, and common editor or OS-specific files. This setup will help maintain a clean repository and prevent unnecessary files from being committed.

examples/example-vite-token-balance/src/App.css (1)

1-43: CSS Styles are Clear and Targeted
The CSS establishes a clear layout for the app container and defines effective visual enhancements for logo hover effects and animations. The use of media queries for reducing motion shows good accessibility awareness. Overall, the styling is clean and well-scoped to the components.

examples/example-vite-token-balance/src/main.tsx (1)

1-38: The initialization and setup look good.

The file properly initializes the Dojo SDK and sets up the component hierarchy with appropriate providers. The error handling is also well-implemented with the catch for the main function.

🧰 Tools
🪛 Biome (1.9.4)

[error] 23-23: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

examples/example-vite-token-balance/src/typescript/contracts.gen.ts (1)

4-60: Well-structured contract interaction patterns.

The setupWorld function follows a consistent pattern for building calldata and executing contract calls, with proper error handling. This organization makes it easy to add new actions in the future while maintaining a consistent interface.

examples/example-vite-token-balance/eslint.config.js (1)

1-28: Well-configured ESLint setup for a React TypeScript project.

The ESLint configuration is appropriately set up with recommended rules for JavaScript, TypeScript, and React. The inclusion of React hooks and React refresh plugins is particularly useful for a React application.

packages/sdk/src/react/hooks/utils.ts (2)

32-40: Strong handling of special object types.

The implementation correctly handles special object types like Date and RegExp, providing specific comparison logic for each. This is a good practice for deep equality comparison.


57-64: Solid implementation of the sleep utility.

The sleep function is well-implemented using a Promise wrapped around setTimeout, which is the standard pattern for creating a delay in asynchronous code.

examples/example-vite-token-balance/src/index.css (2)

27-33: LGTM: Proper responsive layout setup

The body styling correctly sets up a responsive layout with flex display and minimum dimensions, ensuring proper rendering across different device sizes.


59-70: LGTM: Well-implemented media query for color scheme preferences

The media query implementation for light mode preferences is well structured, making appropriate adjustments to colors and backgrounds based on user preferences.

examples/example-vite-token-balance/src/components/token-balance.tsx (2)

1-2: LGTM: Clean import statement

The import statement correctly imports the required components from the SDK.


24-24: LGTM: Proper use of HOC pattern

The WithAccount HOC correctly wraps the component to provide the necessary account information.

examples/example-vite-token-balance/src/components/starknet-provider.tsx (1)

19-23: LGTM: Proper configuration of predeployed accounts

The usePredeployedAccounts hook is configured correctly with appropriate RPC URL and chain identifier.

packages/sdk/src/react/hooks/entities.ts (1)

1-35: Good implementation of the entity query subscription hook.

The hook design effectively leverages reusable subscription logic through createSubscriptionHook and properly handles entity updates in the store.

🧰 Tools
🪛 Biome (1.9.4)

[error] 14-14: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

packages/sdk/src/react/hooks/index.ts (1)

7-11: Well-organized exports structure.

The file has a clean organization, exporting related functionality from separate modules, which makes the codebase more maintainable and the imports clearer for consumers.

packages/sdk/src/react/hoc/with-account.tsx (1)

4-7: Well-typed interface for account props.

The WithAccountProps interface properly types the account and address properties, making it clear what properties are being injected into the wrapped component.

packages/sdk/src/react/hooks/events.ts (1)

12-36: Well-structured subscription hook implementation.

The implementation of useEventQuery properly sets up the subscription and handles updates to entities when events are received.

🧰 Tools
🪛 Biome (1.9.4)

[error] 15-15: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

examples/example-vite-token-balance/src/components/wallet.tsx (1)

1-6: False positive regarding type-only imports.

Static analysis suggests converting these to import type, but the hooks and Connector interface appear to be used as runtime objects (e.g., calling connector.available()). Therefore, importing them as types could break functionality. This warning can be safely ignored in this case.

🧰 Tools
🪛 Biome (1.9.4)

[error] 1-6: 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/react/provider.tsx (1)

46-80: Implementation check.

Overall, the provider logic looks correct. The context is properly set up, and the single-instantiation guard for DojoProvider helps prevent multiple context collisions. No concerns here.

🧰 Tools
🪛 Biome (1.9.4)

[error] 54-54: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)

packages/sdk/src/token.ts (3)

19-35: LGTM! Function handles address padding correctly.

The parseTokenRequest function correctly handles padding for both contract and account addresses, ensuring consistent formatting for the Starknet ecosystem.


40-46: Well-structured function with good null handling.

The getTokens function properly handles optional parameters with the null coalescing operator, ensuring that empty arrays are passed when parameters are undefined.


52-63: Function follows consistent pattern with good error handling.

The getTokenBalances function maintains consistency with the other token-related functions and properly handles optional parameters.

examples/example-vite-token-balance/package.json (1)

23-24:

✅ Verification successful

Verify React 19 compatibility with dependencies.

React 19 is very recent, and some dependencies might not be fully compatible yet. Ensure that all dependencies work well with this version.


🌐 Web query:

Is React 19 stable for production use? What's the current stable version?

💡 Result:

React 19 is stable and recommended for production use as of its official release on December 5, 2024. The current stable version is 19.0.0, which includes significant improvements to asynchronous handling, component architecture, and performance optimization.

Key Production-Ready Features

  • Server Components: Now stable in the main release channel, enabling server-side rendering optimizations for faster initial page loads and SEO improvements[4][9]
  • Actions API: Simplifies async operations like form submissions with built-in pending states, error handling, and optimistic updates[1][7][9]
  • Enhanced error handling via onCaughtError and onUncaughtError hooks for granular error reporting[3][6]
  • Native Asset Management: Built-in support for <title>, <meta> tags, stylesheets, and async scripts in component trees[1][9]

Stability & Support Status

  • Actively maintained with bug/security fixes[2]
  • Backward compatibility maintained through React 18.3 transition warnings[6]
  • Major frameworks like Next.js and React Native 0.78+ already support React 19 features[5][14]

Upgrade Considerations

  1. Required Migration Steps:
    • New JSX transform mandated
    • UMD builds discontinued (use ESM via CDNs like esm.sh)[6]
    • Deprecated API removals (e.g., propTypes in React Native)[5]
  2. Recommended path:
    npm install react@19 react-dom@19
    npm install @types/react@19 @types/react-dom@19 # TypeScript

While React 19 introduces breaking changes, the React team provides codemods and detailed upgrade guides to simplify migration[6][9]. Production apps using modern React patterns can safely adopt v19, though projects relying on deprecated APIs may require refactoring.

Citations:


React 19 is confirmed as stable and production-ready

Based on the latest information:

  • React 19 (v19.0.0) is officially stable and recommended for production use.
  • The package.json upgrade to "react": "^19.0.0", "react-dom": "^19.0.0" is consistent with the current stable release.
  • While React 19 introduces some breaking changes (e.g., new JSX transform requirements), the core dependencies should work as long as they don't rely on deprecated APIs. Please double-check any custom or third-party libraries for compatibility with these new changes.
examples/example-vite-token-balance/src/typescript/models.gen.ts (1)

138-148: LGTM! Good use of enum for mapping models.

Using an enum for model mapping provides type safety and centralized management of model references, which is a good practice.

packages/sdk/src/index.ts (8)

5-17: Imports are well-organized.

The added imports for token balance functionality are logically grouped together. The types are correctly imported from ./types, and the implementation functions are imported from ./token.


102-105: Improved error handling consistency.

Good enhancement to explicitly set error: undefined in the success case, making the callback response structure more consistent and predictable.


172-173: Consistent error handling pattern.

This change follows the same pattern of explicitly setting error: undefined in success cases that was applied to the entity query callbacks, maintaining consistency throughout the codebase.


190-201: Well-implemented token balance subscription method.

The subscribeTokenBalance method is properly implemented following the same pattern as other subscription methods in the SDK. The method delegates to the imported function while maintaining the SDK's interface contract.


288-290: API simplification for getTokens.

Good refactoring to use a single request object parameter instead of separate parameters, which improves maintainability and allows for easier future extensions.


296-300: API simplification for getTokenBalances.

The method now accepts a structured request object which improves code readability and maintainability, following the same pattern used for other token-related methods.


313-317: API simplification for onTokenBalanceUpdated.

Refactoring to use a single request object parameter maintains consistency with other token-related methods in the SDK.


329-333: API simplification for updateTokenBalanceSubscription.

Consistent pattern of using a structured request object instead of multiple parameters, which enhances maintainability.

packages/sdk/src/types.ts (8)

261-268: Well-structured token request interfaces.

The GetTokenRequest and GetTokenBalanceRequest interfaces are cleanly designed with optional fields, allowing for flexible querying patterns. The extension pattern (having GetTokenBalanceRequest extend GetTokenRequest) reduces duplication and maintains a logical relationship between the types.


270-279: Good pattern for success/failure response typing.

The Success<T> and Failure<E> types create a clear separation between successful and failed operations, which improves type safety and makes error handling more explicit.


280-285: Well-designed subscription callback type.

The SubscriptionCallbackArgs and SubscriptionCallback types provide a type-safe way to handle both successful updates and errors in subscription callbacks, enhancing the robustness of the SDK.


287-293: Good composition of token balance subscription types.

Using type composition (extending existing types) for SubscribeTokenBalanceRequest and UpdateTokenBalanceSubscriptionRequest is a clean approach that maintains consistency and reduces duplication.


330-339: Complete SDK interface for token balance subscription.

The SDK interface is properly extended with the new subscribeTokenBalance method, maintaining consistency with the implementation in index.ts. The JSDoc comments are thorough and helpful.


376-376: Simplified method signature for getTokens.

The method signature is updated to use the new request object pattern, which is more maintainable than separate parameters.


384-386: Simplified method signature for getTokenBalances.

The method signature is updated to use the new request object pattern, which is more maintainable than separate parameters.


531-531: Updated subscription callback type.

The callback type is updated to use the new SubscriptionCallback type, which provides a more consistent and type-safe way to handle subscription updates across the SDK.

* @param b Second value to compare
* @returns True if the values are equivalent, false otherwise
*/
export function deepEqual(a: any, b: any): boolean {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace any types with more specific types.

Using any disables TypeScript's type checking, which can lead to type safety issues. Consider using unknown or a generic type parameter with constraints.

- export function deepEqual(a: any, b: any): boolean {
+ export function deepEqual<T>(a: unknown, b: unknown): boolean {
📝 Committable suggestion

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

Suggested change
export function deepEqual(a: any, b: any): boolean {
export function deepEqual<T>(a: unknown, b: unknown): boolean {
🧰 Tools
🪛 Biome (1.9.4)

[error] 7-7: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 7-7: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

Comment on lines +34 to +54
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default tseslint.config({
plugins: {
// Add the react-x and react-dom plugins
'react-x': reactX,
'react-dom': reactDom,
},
rules: {
// other rules...
// Enable its recommended typescript rules
...reactX.configs['recommended-typescript'].rules,
...reactDom.configs.recommended.rules,
},
})
```
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add installation and usage instructions

The README lacks instructions on how to install dependencies and run the example. Consider adding sections for:

  • Prerequisites
  • Installation
  • Running the example
  • Expected functionality

Comment on lines +12 to +13
{tokens.map((token, idx) => (
<div key={idx}>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid using array index as key in React lists

Using array indices as keys can lead to rendering issues if the order of items changes. Consider using a more stable unique identifier like token.contract_address as the key.

-{tokens.map((token, idx) => (
-    <div key={idx}>
+{tokens.map((token) => (
+    <div key={token.contract_address}>

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: 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)

Comment on lines +9 to +16
const controller = new ControllerConnector({
chains: [
{
rpcUrl: "http://localhost:5050",
},
],
defaultChainId: shortString.encodeShortString("KATANA"),
});
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid hardcoding RPC URL in the controller configuration

The RPC URL is hardcoded to "http://localhost:5050". Consider using the URL from dojoConfig for consistency with the rest of the application.

const controller = new ControllerConnector({
    chains: [
        {
-            rpcUrl: "http://localhost:5050",
+            rpcUrl: dojoConfig.rpcUrl as string,
        },
    ],
    defaultChainId: shortString.encodeShortString("KATANA"),
});
📝 Committable suggestion

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

Suggested change
const controller = new ControllerConnector({
chains: [
{
rpcUrl: "http://localhost:5050",
},
],
defaultChainId: shortString.encodeShortString("KATANA"),
});
const controller = new ControllerConnector({
chains: [
{
rpcUrl: dojoConfig.rpcUrl as string,
},
],
defaultChainId: shortString.encodeShortString("KATANA"),
});

Comment on lines +37 to +38
{/* @ts-ignore react version mismatch */}
{children}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Remove TypeScript ignore comment and fix type issue properly

The code uses a TypeScript ignore comment to suppress a React version mismatch error. Instead of ignoring the error, consider addressing the underlying issue by ensuring compatible versions of dependencies.

-        {/* @ts-ignore react version mismatch */}
         {children}

Then update your package.json to ensure compatible versions of React dependencies.


🏁 Script executed:

#!/bin/bash
# Check React versions in package.json
grep -r "\"react\":" examples/example-vite-token-balance/package.json
grep -r "\"@starknet-react" examples/example-vite-token-balance/package.json

Length of output: 265


Fix dependency mismatches and remove the TS ignore directive

  • Action Required:

    • Remove the @ts-ignore comment in examples/example-vite-token-balance/src/components/starknet-provider.tsx (lines 37–38) so that TypeScript can catch the version mismatch issues.
    • Update your dependency versions in examples/example-vite-token-balance/package.json. The output shows "react": "^19.0.0", which likely isn’t what your @starknet-react packages expect. Adjust React (and, if needed, the @starknet-react/* dependencies) so they are compatible—for example, consider downgrading React to a version that aligns with the expectations of your other packages.
  • Diff Suggestion:

    -        {/* @ts-ignore react version mismatch */}
             {children}
📝 Committable suggestion

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

Suggested change
{/* @ts-ignore react version mismatch */}
{children}
{children}

Comment on lines +44 to +86
const fetchData = useCallback(async () => {
// Wait until lock is released
while (isUpdating.current) {
await sleep(50);
}

// Lock function
isUpdating.current = true;

if (subscriptionRef.current) {
const [results, clause] = await config.queryToHashedKeysMethod(
fetchingRef.current!,
config.historical
);
await config.updateSubscriptionMethod(
subscriptionRef.current,
clause,
config.historical
);
config.processInitialData(results);
return null;
}

const [initialData, subscription] = await config.subscribeMethod({
query: fetchingRef.current!,
callback: ({ data, error }) => {
if (data) {
config.processUpdateData(data);
}
if (error) {
console.error(
`${config.getErrorPrefix()} - error subscribing with query: `,
query.toString()
);
console.error(error);
}
},
historical: config.historical,
});

config.processInitialData(initialData);
return subscription;
}, [query]);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Include all config function references in the dependency array.

Each function or variable referenced from config within fetchData (e.g. queryToHashedKeysMethod, processInitialData, etc.) should be included in useCallback's or the effect's dependency array to avoid stale references or unintentional behavior.

🧰 Tools
🪛 Biome (1.9.4)

[error] 55-55: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)


[error] 68-68: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)


[error] 44-44: This hook does not specify all of its dependencies: config.getErrorPrefix

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.processInitialData

This dependency is not specified in the hook dependency list.

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.subscribeMethod

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.updateSubscriptionMethod

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.queryToHashedKeysMethod

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.historical

This dependency is not specified in the hook dependency list.

This dependency is not specified in the hook dependency list.

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)


[error] 44-44: This hook does not specify all of its dependencies: config.processUpdateData

This dependency is not specified in the hook dependency list.

(lint/correctness/useExhaustiveDependencies)

Comment on lines +55 to +56
fetchingRef.current!,
config.historical
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove non-null assertion if possible.

Using ! can mask potential null or undefined issues at runtime. Consider adding a guard or default value to ensure safety if fetchingRef.current or subscriptionRef.current might be null.

Also applies to: 68-68

🧰 Tools
🪛 Biome (1.9.4)

[error] 55-55: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

Comment on lines +29 to +48
export function useModel<
N extends keyof SchemaType,
M extends keyof SchemaType[N] & string,
Client extends (...args: any) => any,
Schema extends SchemaType,
>(entityId: BigNumberish, model: `${N}-${M}`): SchemaType[N][M] | undefined {
const [namespace, modelName] = model.split("-") as [N, M];
const { useDojoStore } =
useContext<DojoContextType<Client, Schema>>(DojoContext);

// Select only the specific model data for the given entityId
const modelData = useDojoStore(
(state) =>
state.entities[entityId.toString()]?.models?.[namespace]?.[
modelName
] as SchemaType[N][M] | undefined
);

return modelData;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace any with more specific types.

Using any in the generic type constraints reduces type safety. The static analysis tool correctly flagged this as a potential issue.

export function useModel<
    N extends keyof SchemaType,
    M extends keyof SchemaType[N] & string,
-    Client extends (...args: any) => any,
+    Client extends (...args: unknown[]) => unknown,
    Schema extends SchemaType,
>(entityId: BigNumberish, model: `${N}-${M}`): SchemaType[N][M] | undefined {
    const [namespace, modelName] = model.split("-") as [N, M];
    const { useDojoStore } =
        useContext<DojoContextType<Client, Schema>>(DojoContext);

    // Select only the specific model data for the given entityId
    const modelData = useDojoStore(
        (state) =>
            state.entities[entityId.toString()]?.models?.[namespace]?.[
                modelName
            ] as SchemaType[N][M] | undefined
    );

    return modelData;
}
📝 Committable suggestion

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

Suggested change
export function useModel<
N extends keyof SchemaType,
M extends keyof SchemaType[N] & string,
Client extends (...args: any) => any,
Schema extends SchemaType,
>(entityId: BigNumberish, model: `${N}-${M}`): SchemaType[N][M] | undefined {
const [namespace, modelName] = model.split("-") as [N, M];
const { useDojoStore } =
useContext<DojoContextType<Client, Schema>>(DojoContext);
// Select only the specific model data for the given entityId
const modelData = useDojoStore(
(state) =>
state.entities[entityId.toString()]?.models?.[namespace]?.[
modelName
] as SchemaType[N][M] | undefined
);
return modelData;
}
export function useModel<
N extends keyof SchemaType,
M extends keyof SchemaType[N] & string,
Client extends (...args: unknown[]) => unknown,
Schema extends SchemaType,
>(entityId: BigNumberish, model: `${N}-${M}`): SchemaType[N][M] | undefined {
const [namespace, modelName] = model.split("-") as [N, M];
const { useDojoStore } =
useContext<DojoContextType<Client, Schema>>(DojoContext);
// Select only the specific model data for the given entityId
const modelData = useDojoStore(
(state) =>
state.entities[entityId.toString()]?.models?.[namespace]?.[
modelName
] as SchemaType[N][M] | undefined
);
return modelData;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 32-32: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 32-32: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

Comment on lines +56 to +73
export function useModels<
N extends keyof SchemaType,
M extends keyof SchemaType[N] & string,
Client extends (...args: any) => any,
Schema extends SchemaType,
>(model: `${N}-${M}`): { [entityId: string]: SchemaType[N][M] | undefined } {
const [namespace, modelName] = model.split("-") as [N, M];
const { useDojoStore } =
useContext<DojoContextType<Client, Schema>>(DojoContext);

const modelData = useDojoStore((state) =>
state.getEntitiesByModel(namespace, modelName).map((entity) => ({
[entity.entityId]: entity.models?.[namespace]?.[modelName],
}))
) as unknown as { [entityId: string]: SchemaType[N][M] | undefined };

return modelData;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace any with more specific types.

Similar to the previous function, using any in type constraints should be replaced with more specific types to improve type safety.

export function useModels<
    N extends keyof SchemaType,
    M extends keyof SchemaType[N] & string,
-    Client extends (...args: any) => any,
+    Client extends (...args: unknown[]) => unknown,
    Schema extends SchemaType,
>(model: `${N}-${M}`): { [entityId: string]: SchemaType[N][M] | undefined } {
    const [namespace, modelName] = model.split("-") as [N, M];
    const { useDojoStore } =
        useContext<DojoContextType<Client, Schema>>(DojoContext);

    const modelData = useDojoStore((state) =>
        state.getEntitiesByModel(namespace, modelName).map((entity) => ({
            [entity.entityId]: entity.models?.[namespace]?.[modelName],
        }))
    ) as unknown as { [entityId: string]: SchemaType[N][M] | undefined };

    return modelData;
}
📝 Committable suggestion

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

Suggested change
export function useModels<
N extends keyof SchemaType,
M extends keyof SchemaType[N] & string,
Client extends (...args: any) => any,
Schema extends SchemaType,
>(model: `${N}-${M}`): { [entityId: string]: SchemaType[N][M] | undefined } {
const [namespace, modelName] = model.split("-") as [N, M];
const { useDojoStore } =
useContext<DojoContextType<Client, Schema>>(DojoContext);
const modelData = useDojoStore((state) =>
state.getEntitiesByModel(namespace, modelName).map((entity) => ({
[entity.entityId]: entity.models?.[namespace]?.[modelName],
}))
) as unknown as { [entityId: string]: SchemaType[N][M] | undefined };
return modelData;
}
export function useModels<
N extends keyof SchemaType,
M extends keyof SchemaType[N] & string,
Client extends (...args: unknown[]) => unknown,
Schema extends SchemaType,
>(model: `${N}-${M}`): { [entityId: string]: SchemaType[N][M] | undefined } {
const [namespace, modelName] = model.split("-") as [N, M];
const { useDojoStore } =
useContext<DojoContextType<Client, Schema>>(DojoContext);
const modelData = useDojoStore((state) =>
state.getEntitiesByModel(namespace, modelName).map((entity) => ({
[entity.entityId]: entity.models?.[namespace]?.[modelName],
}))
) as unknown as { [entityId: string]: SchemaType[N][M] | undefined };
return modelData;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 59-59: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)


[error] 59-59: Unexpected any. Specify a different type.

any disables many type checking rules. Its use should be avoided.

(lint/suspicious/noExplicitAny)

Comment on lines +20 to +25
"@starknet-react/chains": "catalog:",
"@starknet-react/core": "catalog:",
"@tailwindcss/vite": "^4.0.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"starknet": "catalog:",
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Specify exact versions instead of using "catalog:" references.

Using "catalog:" for version references may lead to unpredictable behavior if the catalog version changes. It's generally better to pin specific versions for production code.

    "@dojoengine/sdk": "workspace:*",
    "@dojoengine/torii-client": "workspace:*",
    "@dojoengine/utils": "workspace:*",
-    "@starknet-react/chains": "catalog:",
-    "@starknet-react/core": "catalog:",
+    "@starknet-react/chains": "^0.2.2",
+    "@starknet-react/core": "^2.1.0",
    "@tailwindcss/vite": "^4.0.1",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
-    "starknet": "catalog:",
+    "starknet": "^5.24.3",
    "tailwindcss": "^4.0.14"

🌐 Web query:

What are the latest versions of @starknet-react/chains, @starknet-react/core, and starknet packages?

💡 Result:

As of March 2025, the latest versions are:

@starknet-react/chains: 3.1.2
@starknet-react/core: 3.7.2
starknet (JS library): 6.24.1

Key details from sources:

  • @starknet-react/core 3.7.2 was last published 2 months ago (January 2025)[2][6]
  • starknet 6.24.1 received an update 10 days before the current date[12]
  • The types-js package (related to Starknet React) uses version 0.7.X alignment with JSON RPC 0.8[5]
  • Starknet React V3 requires Starknet.js v6[17], which matches the latest 6.24.1 version[12]

These versions support Starknet network upgrades up to v0.13.3[3][5], including new features like optimistic parallelization and applicative recursion[3]. When installing, ensure compatibility between package versions as shown in the Starknet React documentation[19].

Citations:


Update the version references to the latest stable releases in package.json

Please change the version references for the @starknet-react and starknet dependencies from "catalog:" to specific versions. Based on the recent query, the following versions should be used:

  • @starknet-react/chains: ^3.1.2
  • @starknet-react/core: ^3.7.2
  • starknet: ^6.24.1

Below is the updated diff snippet for the file examples/example-vite-token-balance/package.json (lines 20-25):

    "@dojoengine/sdk": "workspace:*",
    "@dojoengine/torii-client": "workspace:*",
    "@dojoengine/utils": "workspace:*",
-    "@starknet-react/chains": "catalog:",
-    "@starknet-react/core": "catalog:",
+    "@starknet-react/chains": "^3.1.2",
+    "@starknet-react/core": "^3.7.2",
    "@tailwindcss/vite": "^4.0.1",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
-    "starknet": "catalog:",
+    "starknet": "^6.24.1",
    "tailwindcss": "^4.0.14"

Using specific version numbers will help avoid unpredictable behavior if the catalog versions change. Please update accordingly.

📝 Committable suggestion

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

Suggested change
"@starknet-react/chains": "catalog:",
"@starknet-react/core": "catalog:",
"@tailwindcss/vite": "^4.0.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"starknet": "catalog:",
{
"dependencies": {
"@dojoengine/sdk": "workspace:*",
"@dojoengine/torii-client": "workspace:*",
"@dojoengine/utils": "workspace:*",
"@starknet-react/chains": "^3.1.2",
"@starknet-react/core": "^3.7.2",
"@tailwindcss/vite": "^4.0.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"starknet": "^6.24.1",
"tailwindcss": "^4.0.14"
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant