diff --git a/examples/example-vite-token-balance/.gitignore b/examples/example-vite-token-balance/.gitignore
new file mode 100644
index 00000000..a547bf36
--- /dev/null
+++ b/examples/example-vite-token-balance/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/example-vite-token-balance/README.md b/examples/example-vite-token-balance/README.md
new file mode 100644
index 00000000..40ede56e
--- /dev/null
+++ b/examples/example-vite-token-balance/README.md
@@ -0,0 +1,54 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default tseslint.config({
+ extends: [
+ // Remove ...tseslint.configs.recommended and replace with this
+ ...tseslint.configs.recommendedTypeChecked,
+ // Alternatively, use this for stricter rules
+ ...tseslint.configs.strictTypeChecked,
+ // Optionally, add this for stylistic rules
+ ...tseslint.configs.stylisticTypeChecked,
+ ],
+ languageOptions: {
+ // other options...
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+})
+```
+
+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,
+ },
+})
+```
diff --git a/examples/example-vite-token-balance/dojoConfig.ts b/examples/example-vite-token-balance/dojoConfig.ts
new file mode 100644
index 00000000..e45ee85a
--- /dev/null
+++ b/examples/example-vite-token-balance/dojoConfig.ts
@@ -0,0 +1,7 @@
+import { createDojoConfig } from "@dojoengine/core";
+
+import manifest from "../../worlds/dojo-starter/manifest_dev.json";
+
+export const dojoConfig = createDojoConfig({
+ manifest,
+});
diff --git a/examples/example-vite-token-balance/eslint.config.js b/examples/example-vite-token-balance/eslint.config.js
new file mode 100644
index 00000000..092408a9
--- /dev/null
+++ b/examples/example-vite-token-balance/eslint.config.js
@@ -0,0 +1,28 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+
+export default tseslint.config(
+ { ignores: ['dist'] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ['**/*.{ts,tsx}'],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ 'react-hooks': reactHooks,
+ 'react-refresh': reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+ },
+)
diff --git a/examples/example-vite-token-balance/index.html b/examples/example-vite-token-balance/index.html
new file mode 100644
index 00000000..2c65c8f1
--- /dev/null
+++ b/examples/example-vite-token-balance/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Example SDK Tokens
+
+
+
+
+
+
diff --git a/examples/example-vite-token-balance/package.json b/examples/example-vite-token-balance/package.json
new file mode 100644
index 00000000..bf089c1c
--- /dev/null
+++ b/examples/example-vite-token-balance/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "example-vite-token-balance",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@cartridge/connector": "^0.7.6",
+ "@cartridge/controller": "^0.7.6",
+ "@dojoengine/core": "workspace:*",
+ "@dojoengine/predeployed-connector": "workspace:*",
+ "@dojoengine/sdk": "workspace:*",
+ "@dojoengine/torii-client": "workspace:*",
+ "@dojoengine/utils": "workspace:*",
+ "@starknet-react/chains": "catalog:",
+ "@starknet-react/core": "catalog:",
+ "@tailwindcss/vite": "^4.0.1",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "starknet": "catalog:",
+ "tailwindcss": "^4.0.14"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.21.0",
+ "@types/react": "^19.0.10",
+ "@types/react-dom": "^19.0.4",
+ "@vitejs/plugin-react": "^4.3.4",
+ "eslint": "^9.21.0",
+ "eslint-plugin-react-hooks": "^5.1.0",
+ "eslint-plugin-react-refresh": "^0.4.19",
+ "globals": "^15.15.0",
+ "typescript": "~5.7.2",
+ "typescript-eslint": "^8.24.1",
+ "vite": "^6.2.0",
+ "vite-plugin-top-level-await": "^1.5.0",
+ "vite-plugin-wasm": "^3.4.1"
+ }
+}
diff --git a/examples/example-vite-token-balance/public/vite.svg b/examples/example-vite-token-balance/public/vite.svg
new file mode 100644
index 00000000..e7b8dfb1
--- /dev/null
+++ b/examples/example-vite-token-balance/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/example-vite-token-balance/src/App.css b/examples/example-vite-token-balance/src/App.css
new file mode 100644
index 00000000..b9d355df
--- /dev/null
+++ b/examples/example-vite-token-balance/src/App.css
@@ -0,0 +1,42 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/examples/example-vite-token-balance/src/App.tsx b/examples/example-vite-token-balance/src/App.tsx
new file mode 100644
index 00000000..a008dbb1
--- /dev/null
+++ b/examples/example-vite-token-balance/src/App.tsx
@@ -0,0 +1,15 @@
+import "./App.css";
+import { Wallet } from "./components/wallet";
+import TokenBalance from "./components/token-balance";
+
+function App() {
+ return (
+ <>
+ Connect your wallet
+
+
+ >
+ );
+}
+
+export default App;
diff --git a/examples/example-vite-token-balance/src/assets/react.svg b/examples/example-vite-token-balance/src/assets/react.svg
new file mode 100644
index 00000000..6c87de9b
--- /dev/null
+++ b/examples/example-vite-token-balance/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/example-vite-token-balance/src/components/starknet-provider.tsx b/examples/example-vite-token-balance/src/components/starknet-provider.tsx
new file mode 100644
index 00000000..2aa3f629
--- /dev/null
+++ b/examples/example-vite-token-balance/src/components/starknet-provider.tsx
@@ -0,0 +1,41 @@
+import type { PropsWithChildren } from "react";
+import { mainnet } from "@starknet-react/chains";
+import { jsonRpcProvider, StarknetConfig, voyager } from "@starknet-react/core";
+import { dojoConfig } from "../../dojoConfig";
+import { usePredeployedAccounts } from "@dojoengine/predeployed-connector/react";
+import { ControllerConnector } from "@cartridge/connector";
+import { shortString } from "starknet";
+
+const controller = new ControllerConnector({
+ chains: [
+ {
+ rpcUrl: "http://localhost:5050",
+ },
+ ],
+ defaultChainId: shortString.encodeShortString("KATANA"),
+});
+
+export default function StarknetProvider({ children }: PropsWithChildren) {
+ const { connectors } = usePredeployedAccounts({
+ rpc: dojoConfig.rpcUrl as string,
+ id: "katana",
+ name: "Katana",
+ });
+
+ const provider = jsonRpcProvider({
+ rpc: () => ({ nodeUrl: dojoConfig.rpcUrl as string }),
+ });
+
+ return (
+
+ {/* @ts-ignore react version mismatch */}
+ {children}
+
+ );
+}
diff --git a/examples/example-vite-token-balance/src/components/token-balance.tsx b/examples/example-vite-token-balance/src/components/token-balance.tsx
new file mode 100644
index 00000000..bae93c94
--- /dev/null
+++ b/examples/example-vite-token-balance/src/components/token-balance.tsx
@@ -0,0 +1,24 @@
+import { useTokens, WithAccount } from "@dojoengine/sdk/react";
+
+function TokenBalance({ address }: { address: `0x${string}` }) {
+ const { tokens, getBalance, toDecimal } = useTokens({
+ accountAddresses: [address],
+ });
+
+ return (
+
+ Token Balance: {address}
+
+ {tokens.map((token, idx) => (
+
+ {token.symbol}
+
+ {toDecimal(token, getBalance(token))}
+
+ ))}
+
+
+ );
+}
+
+export default WithAccount(TokenBalance);
diff --git a/examples/example-vite-token-balance/src/components/ui/button.tsx b/examples/example-vite-token-balance/src/components/ui/button.tsx
new file mode 100644
index 00000000..e69de29b
diff --git a/examples/example-vite-token-balance/src/components/wallet.tsx b/examples/example-vite-token-balance/src/components/wallet.tsx
new file mode 100644
index 00000000..1adc6269
--- /dev/null
+++ b/examples/example-vite-token-balance/src/components/wallet.tsx
@@ -0,0 +1,68 @@
+import {
+ Connector,
+ useAccount,
+ useConnect,
+ useDisconnect,
+} from "@starknet-react/core";
+import { useCallback, useState } from "react";
+
+export function Wallet() {
+ const { connectAsync, connectors } = useConnect();
+ const { address } = useAccount();
+ const { disconnect } = useDisconnect();
+ const [pendingConnectorId, setPendingConnectorId] = useState<
+ string | undefined
+ >(undefined);
+
+ const connect = useCallback(
+ async (connector: Connector) => {
+ setPendingConnectorId(connector.id);
+ try {
+ await connectAsync({ connector });
+ } catch (error) {
+ console.error(error);
+ }
+ setPendingConnectorId(undefined);
+ },
+ [connectAsync]
+ );
+
+ function isWalletConnecting(connectorId: string) {
+ return pendingConnectorId === connectorId;
+ }
+
+ if (address) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
Connect Wallet
+
+ {}
+ {connectors.map((connector) => (
+
+ ))}
+
+
+ );
+}
diff --git a/examples/example-vite-token-balance/src/index.css b/examples/example-vite-token-balance/src/index.css
new file mode 100644
index 00000000..d6457264
--- /dev/null
+++ b/examples/example-vite-token-balance/src/index.css
@@ -0,0 +1,70 @@
+@import "tailwindcss";
+
+:root {
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/examples/example-vite-token-balance/src/main.tsx b/examples/example-vite-token-balance/src/main.tsx
new file mode 100644
index 00000000..beff7e36
--- /dev/null
+++ b/examples/example-vite-token-balance/src/main.tsx
@@ -0,0 +1,38 @@
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import "./index.css";
+import App from "./App.tsx";
+
+import { init } from "@dojoengine/sdk";
+import { dojoConfig } from "../dojoConfig";
+import { DojoSdkProvider } from "@dojoengine/sdk/react";
+import { setupWorld } from "./typescript/contracts.gen";
+import StarknetProvider from "./components/starknet-provider.tsx";
+
+async function main() {
+ const sdk = await init({
+ client: { worldAddress: dojoConfig.manifest.world.address },
+ domain: {
+ name: "WORLD_NAME",
+ version: "1.0",
+ chainId: "KATANA",
+ revision: "1",
+ },
+ });
+
+ createRoot(document.getElementById("root")!).render(
+
+
+
+
+
+
+
+ );
+}
+
+main().catch(console.error);
diff --git a/examples/example-vite-token-balance/src/typescript/contracts.gen.ts b/examples/example-vite-token-balance/src/typescript/contracts.gen.ts
new file mode 100644
index 00000000..aa4700cf
--- /dev/null
+++ b/examples/example-vite-token-balance/src/typescript/contracts.gen.ts
@@ -0,0 +1,60 @@
+import type { DojoProvider, DojoCall } from "@dojoengine/core";
+import type { Account, AccountInterface, CairoCustomEnum } from "starknet";
+
+export function setupWorld(provider: DojoProvider) {
+ const build_actions_move_calldata = (
+ direction: CairoCustomEnum
+ ): DojoCall => {
+ return {
+ contractName: "actions",
+ entrypoint: "move",
+ calldata: [direction],
+ };
+ };
+
+ const actions_move = async (
+ snAccount: Account | AccountInterface,
+ direction: CairoCustomEnum
+ ) => {
+ try {
+ return await provider.execute(
+ snAccount,
+ build_actions_move_calldata(direction),
+ "dojo_starter"
+ );
+ } catch (error) {
+ console.error(error);
+ throw error;
+ }
+ };
+
+ const build_actions_spawn_calldata = (): DojoCall => {
+ return {
+ contractName: "actions",
+ entrypoint: "spawn",
+ calldata: [],
+ };
+ };
+
+ const actions_spawn = async (snAccount: Account | AccountInterface) => {
+ try {
+ return await provider.execute(
+ snAccount,
+ build_actions_spawn_calldata(),
+ "dojo_starter"
+ );
+ } catch (error) {
+ console.error(error);
+ throw error;
+ }
+ };
+
+ return {
+ actions: {
+ move: actions_move,
+ buildMoveCalldata: build_actions_move_calldata,
+ spawn: actions_spawn,
+ buildSpawnCalldata: build_actions_spawn_calldata,
+ },
+ };
+}
diff --git a/examples/example-vite-token-balance/src/typescript/models.gen.ts b/examples/example-vite-token-balance/src/typescript/models.gen.ts
new file mode 100644
index 00000000..2162e0cc
--- /dev/null
+++ b/examples/example-vite-token-balance/src/typescript/models.gen.ts
@@ -0,0 +1,148 @@
+import type { SchemaType as ISchemaType } from "@dojoengine/sdk";
+
+import { CairoCustomEnum, CairoOption, CairoOptionVariant, BigNumberish } from 'starknet';
+
+// Type definition for `dojo_starter::models::DirectionsAvailable` struct
+export interface DirectionsAvailable {
+ player: string;
+ directions: Array;
+}
+
+// Type definition for `dojo_starter::models::DirectionsAvailableValue` struct
+export interface DirectionsAvailableValue {
+ directions: Array;
+}
+
+// Type definition for `dojo_starter::models::Moves` struct
+export interface Moves {
+ player: string;
+ remaining: BigNumberish;
+ last_direction: CairoOption;
+ can_move: boolean;
+}
+
+// Type definition for `dojo_starter::models::MovesValue` struct
+export interface MovesValue {
+ remaining: BigNumberish;
+ last_direction: CairoOption;
+ can_move: boolean;
+}
+
+// Type definition for `dojo_starter::models::Position` struct
+export interface Position {
+ player: string;
+ vec: Vec2;
+}
+
+// Type definition for `dojo_starter::models::PositionValue` struct
+export interface PositionValue {
+ vec: Vec2;
+}
+
+// Type definition for `dojo_starter::models::Vec2` struct
+export interface Vec2 {
+ x: BigNumberish;
+ y: BigNumberish;
+}
+
+// Type definition for `dojo_starter::systems::actions::actions::Moved` struct
+export interface Moved {
+ player: string;
+ direction: DirectionEnum;
+}
+
+// Type definition for `dojo_starter::systems::actions::actions::MovedValue` struct
+export interface MovedValue {
+ direction: DirectionEnum;
+}
+
+// Type definition for `dojo_starter::models::Direction` enum
+export type Direction = {
+ Left: string;
+ Right: string;
+ Up: string;
+ Down: string;
+}
+export type DirectionEnum = CairoCustomEnum;
+
+export interface SchemaType extends ISchemaType {
+ dojo_starter: {
+ DirectionsAvailable: DirectionsAvailable,
+ DirectionsAvailableValue: DirectionsAvailableValue,
+ Moves: Moves,
+ MovesValue: MovesValue,
+ Position: Position,
+ PositionValue: PositionValue,
+ Vec2: Vec2,
+ Moved: Moved,
+ MovedValue: MovedValue,
+ },
+}
+export const schema: SchemaType = {
+ dojo_starter: {
+ DirectionsAvailable: {
+ player: "",
+ directions: [new CairoCustomEnum({
+ Left: "",
+ Right: undefined,
+ Up: undefined,
+ Down: undefined, })],
+ },
+ DirectionsAvailableValue: {
+ directions: [new CairoCustomEnum({
+ Left: "",
+ Right: undefined,
+ Up: undefined,
+ Down: undefined, })],
+ },
+ Moves: {
+ player: "",
+ remaining: 0,
+ last_direction: new CairoOption(CairoOptionVariant.None),
+ can_move: false,
+ },
+ MovesValue: {
+ remaining: 0,
+ last_direction: new CairoOption(CairoOptionVariant.None),
+ can_move: false,
+ },
+ Position: {
+ player: "",
+ vec: { x: 0, y: 0, },
+ },
+ PositionValue: {
+ vec: { x: 0, y: 0, },
+ },
+ Vec2: {
+ x: 0,
+ y: 0,
+ },
+ Moved: {
+ player: "",
+ direction: new CairoCustomEnum({
+ Left: "",
+ Right: undefined,
+ Up: undefined,
+ Down: undefined, }),
+ },
+ MovedValue: {
+ direction: new CairoCustomEnum({
+ Left: "",
+ Right: undefined,
+ Up: undefined,
+ Down: undefined, }),
+ },
+ },
+};
+export enum ModelsMapping {
+ Direction = 'dojo_starter-Direction',
+ DirectionsAvailable = 'dojo_starter-DirectionsAvailable',
+ DirectionsAvailableValue = 'dojo_starter-DirectionsAvailableValue',
+ Moves = 'dojo_starter-Moves',
+ MovesValue = 'dojo_starter-MovesValue',
+ Position = 'dojo_starter-Position',
+ PositionValue = 'dojo_starter-PositionValue',
+ Vec2 = 'dojo_starter-Vec2',
+ Moved = 'dojo_starter-Moved',
+ MovedValue = 'dojo_starter-MovedValue',
+}
\ No newline at end of file
diff --git a/examples/example-vite-token-balance/src/vite-env.d.ts b/examples/example-vite-token-balance/src/vite-env.d.ts
new file mode 100644
index 00000000..11f02fe2
--- /dev/null
+++ b/examples/example-vite-token-balance/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/example-vite-token-balance/tsconfig.app.json b/examples/example-vite-token-balance/tsconfig.app.json
new file mode 100644
index 00000000..358ca9ba
--- /dev/null
+++ b/examples/example-vite-token-balance/tsconfig.app.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/examples/example-vite-token-balance/tsconfig.json b/examples/example-vite-token-balance/tsconfig.json
new file mode 100644
index 00000000..1ffef600
--- /dev/null
+++ b/examples/example-vite-token-balance/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/examples/example-vite-token-balance/tsconfig.node.json b/examples/example-vite-token-balance/tsconfig.node.json
new file mode 100644
index 00000000..db0becc8
--- /dev/null
+++ b/examples/example-vite-token-balance/tsconfig.node.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/example-vite-token-balance/vite.config.ts b/examples/example-vite-token-balance/vite.config.ts
new file mode 100644
index 00000000..7b1e2d43
--- /dev/null
+++ b/examples/example-vite-token-balance/vite.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+import wasm from "vite-plugin-wasm";
+import topLevelAwait from "vite-plugin-top-level-await";
+import tailwindcss from "@tailwindcss/vite";
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react(), wasm(), topLevelAwait(), tailwindcss()],
+});
diff --git a/package.json b/package.json
index 046feb2d..3eb746cc 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"packageManager": "pnpm@10.5.2",
"scripts": {
"build:deps": "turbo build:deps",
+ "build:wasm": "turbo build:wasm",
"build": "turbo build",
"clean": "bash ./scripts/clean.sh",
"prettier": "pnpx prettier --write packages examples",
@@ -11,7 +12,7 @@
"format:check": "turbo format:check",
"release": "pnpm build:deps && pnpm -F './packages/**' publish -r --force --no-git-checks",
"release:dry-run": "pnpm -F './packages/**' publish -r --force --dry-run",
- "dev": "turbo watch dev --concurrency 15",
+ "dev": "turbo watch dev --concurrency 20",
"docs": "turbo run docs --ui stream"
},
"devDependencies": {
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
index 73a744a5..f6f6f707 100644
--- a/packages/sdk/package.json
+++ b/packages/sdk/package.json
@@ -74,6 +74,8 @@
"@dojoengine/core": "workspace:*",
"@dojoengine/torii-client": "workspace:*",
"@dojoengine/utils": "workspace:*",
+ "@starknet-react/chains": "catalog:",
+ "@starknet-react/core": "catalog:",
"immer": "^10.1.1",
"zustand": "^4.5.6"
},
diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts
index 9b73de79..7d052846 100644
--- a/packages/sdk/src/index.ts
+++ b/packages/sdk/src/index.ts
@@ -3,6 +3,8 @@ import type { Account, Signature, StarknetDomain, TypedData } from "starknet";
import type {
GetParams,
+ GetTokenBalanceRequest,
+ GetTokenRequest,
SchemaType,
SDK,
SDKConfig,
@@ -10,12 +12,22 @@ import type {
SubscribeResponse,
ToriiResponse,
UnionOfModelData,
+ SubscribeTokenBalanceRequest,
+ UpdateTokenBalanceSubscriptionRequest,
} from "./types";
+
import { intoEntityKeysClause } from "./convertClauseToEntityKeysClause";
import { parseEntities } from "./parseEntities";
import { parseHistoricalEvents } from "./parseHistoricalEvents";
import type { ToriiQueryBuilder } from "./toriiQueryBuilder";
import { generateTypedData } from "./generateTypedData";
+import {
+ getTokens,
+ getTokenBalances,
+ onTokenBalanceUpdated,
+ updateTokenBalanceSubscription,
+ subscribeTokenBalance,
+} from "./token";
export * from "./types";
export * from "./queryBuilder";
@@ -87,11 +99,15 @@ export async function init(
const parsedData = parseEntities({
[entityId]: entityData,
});
- callback({ data: parsedData });
+ callback({
+ data: parsedData,
+ error: undefined,
+ });
}
} catch (error) {
if (callback) {
callback({
+ data: undefined,
error:
error instanceof Error
? error
@@ -153,11 +169,13 @@ export async function init(
T,
Historical
>,
+ error: undefined,
});
}
} catch (error) {
if (callback) {
callback({
+ data: undefined,
error:
error instanceof Error
? error
@@ -169,6 +187,19 @@ export async function init(
),
];
},
+ /**
+ * Subscribes to token balance updates
+ *
+ * # Parameters
+ * @param {SubscribeTokenBalanceRequest} request
+ * @returns {Promise<[torii.TokenBalances, torii.Subscription]>}
+ */
+ subscribeTokenBalance: async (
+ request: SubscribeTokenBalanceRequest
+ ): Promise<[torii.TokenBalances, torii.Subscription]> => {
+ return await subscribeTokenBalance(client, request);
+ },
+
/**
* Fetches entities based on the provided query.
*
@@ -251,42 +282,28 @@ export async function init(
},
/**
- * @param {(string)[]} contract_addresses
- * @param {string[]} token_ids
- * @returns {Promise}
+ * @param {GetTokenRequest} request
+ * @returns {Promise}
*/
- getTokens: async (
- contract_addresses: string[],
- token_ids: string[]
- ): Promise => {
- return await client.getTokens(contract_addresses, token_ids);
+ getTokens: async (request: GetTokenRequest): Promise => {
+ return await getTokens(client, request);
},
/**
- * @param {(string)[]} contract_addresses
- * @param {(string)[]} account_addresses
- * @param {string[]} token_ids
- * @returns {Promise}
+ * @param {GetTokenBalanceRequest} request
+ * @returns {Promise}
*/
getTokenBalances: async (
- contract_addresses: string[],
- account_addresses: string[],
- token_ids: string[]
+ request: GetTokenBalanceRequest
): Promise => {
- return await client.getTokenBalances(
- contract_addresses,
- account_addresses,
- token_ids
- );
+ return await getTokenBalances(client, request);
},
/**
* 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 {SubscribeTokenBalanceRequest} request
* @param {Funtion} callback - JavaScript function to call on updates
*
* # Returns
@@ -294,44 +311,25 @@ export async function init(
* @returns torii.Subscription
*/
onTokenBalanceUpdated: (
- contract_addresses: string[],
- account_addresses: string[],
- token_ids: string[],
- callback: Function
+ request: SubscribeTokenBalanceRequest
): torii.Subscription => {
- return client.onTokenBalanceUpdated(
- contract_addresses,
- account_addresses,
- token_ids,
- callback
- );
+ return onTokenBalanceUpdated(client, request);
},
/**
* 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 (empty for all)
+ * @param {UpdateTokenBalanceSubscriptionRequest} request
*
* # Returns
* Result containing unit or error
* @returns {Promise}
*/
updateTokenBalanceSubscription: async (
- subscription: torii.Subscription,
- contract_addresses: string[],
- account_addresses: string[],
- token_ids: string[]
+ request: UpdateTokenBalanceSubscriptionRequest
): Promise => {
- return await client.updateTokenBalanceSubscription(
- subscription,
- contract_addresses,
- account_addresses,
- token_ids
- );
+ return await updateTokenBalanceSubscription(client, request);
},
/**
diff --git a/packages/sdk/src/react/hoc/with-account.tsx b/packages/sdk/src/react/hoc/with-account.tsx
new file mode 100644
index 00000000..126f1fad
--- /dev/null
+++ b/packages/sdk/src/react/hoc/with-account.tsx
@@ -0,0 +1,22 @@
+import type { AccountInterface } from "starknet";
+import { useAccount } from "@starknet-react/core";
+
+interface WithAccountProps {
+ account: AccountInterface;
+ address: `0x${string}`;
+}
+
+export function WithAccount(
+ Component: React.ComponentType
,
+ Fallback: React.ComponentType = () =>
Please connect your wallet
+): React.FC> {
+ return (props) => {
+ const { account, address } = useAccount();
+ if (!address) {
+ return Fallback ? : null;
+ }
+ const mergedProps = { ...props, account, address } as P &
+ WithAccountProps;
+ return ;
+ };
+}
diff --git a/packages/sdk/src/react/hooks.ts b/packages/sdk/src/react/hooks.ts
deleted file mode 100644
index 87e25c83..00000000
--- a/packages/sdk/src/react/hooks.ts
+++ /dev/null
@@ -1,391 +0,0 @@
-import {
- useCallback,
- useContext,
- useEffect,
- useMemo,
- useRef,
- useState,
-} from "react";
-import type { BigNumberish } from "starknet";
-import type {
- StandardizedQueryResult,
- SubscribeResponse,
- ToriiResponse,
- SchemaType,
- SubscribeParams,
-} from "../types";
-import { DojoContext, type DojoContextType } from "./provider";
-import { create, type StoreApi, type UseBoundStore } from "zustand";
-import { createDojoStoreFactory } from "../state/zustand";
-import type { GameState } from "../state";
-import type { ToriiQueryBuilder } from "../toriiQueryBuilder";
-import type { EntityKeysClause, Subscription } from "@dojoengine/torii-client";
-import { getEntityIdFromKeys } from "@dojoengine/utils";
-
-/**
- * Factory function to create a React Zustand store based on a given SchemaType.
- *
- * @template T - The schema type.
- * @returns A Zustand hook tailored to the provided schema.
- */
-export function createDojoStore() {
- // hacktually until I find a proper type input to createDojoStoreFactory
- return createDojoStoreFactory(create) as unknown as UseBoundStore<
- StoreApi>
- >;
-}
-
-/**
- * Custom hook to retrieve a specific model for a given entityId within a specified namespace.
- *
- * @param entityId - The ID of the entity.
- * @param model - The model to retrieve, specified as a string in the format "namespace-modelName".
- * @returns The model structure if found, otherwise undefined.
- */
-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>(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;
-}
-
-/**
- * Custom hook to retrieve all entities that have a specific model.
- *
- * @param model - The model to retrieve, specified as a string in the format "namespace-modelName".
- * @returns The model structure if found, otherwise undefined.
- */
-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>(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;
-}
-
-/**
- * Hook that exposes sdk features.
- *
- * @template Client Client function generated with `sozo build --typescript`
- * @template Schema Schema function generated with `sozo build --typescript`
- * @returns DojoContextType
- */
-export function useDojoSDK<
- Client extends (...args: any) => any,
- Schema extends SchemaType
->(): DojoContextType {
- return useContext>(DojoContext);
-}
-
-/**
- * If you know all distinct keys of your model, here is a way to compose it.
- *
- * @param keys Each keys corresponding to your model keys.
- * @returns Composed entityId
- */
-export function useEntityId(...keys: BigNumberish[]): BigNumberish {
- const entityId = useMemo(() => {
- if (keys.length > 0) {
- return getEntityIdFromKeys(keys.map((k) => BigInt(k)));
- }
- return BigInt(0);
- }, [keys]);
-
- return entityId;
-}
-
-/**
- * Base hook factory for creating subscription hooks with shared logic
- */
-function createSubscriptionHook<
- Schema extends SchemaType,
- Historical extends boolean = false
->(config: {
- subscribeMethod: (
- options: SubscribeParams
- ) => Promise>;
- updateSubscriptionMethod: (
- subscription: Subscription,
- clause: any,
- historical?: boolean
- ) => Promise;
- queryToHashedKeysMethod: (
- query: ToriiQueryBuilder,
- historical?: boolean
- ) => Promise<[ToriiResponse, EntityKeysClause[]]>;
- processInitialData: (data: ToriiResponse) => void;
- processUpdateData: (data: any) => void;
- getErrorPrefix: () => string;
- historical: Historical;
-}) {
- return function useSubscriptionHook(query: ToriiQueryBuilder) {
- // Subscription handle to update
- const subscriptionRef = useRef(null);
- // Handle to user input query
- const fetchingRef = useRef | null>(null);
- // Async lock to sync with event loop
- const isUpdating = useRef(false);
-
- 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]);
-
- useEffect(() => {
- if (!deepEqual(query, fetchingRef.current)) {
- fetchingRef.current = query;
-
- fetchData()
- .then((s) => {
- if (s !== null) {
- subscriptionRef.current = s;
- }
- })
- .catch((err) => {
- console.error(
- `${config.getErrorPrefix()} - error fetching data for query: `,
- JSON.stringify(query)
- );
- console.error(err);
- })
- .finally(() => {
- // Release lock
- isUpdating.current = false;
- });
- }
-
- return () => {
- if (subscriptionRef.current) {
- // subscriptionRef.current?.cancel();
- // subscriptionRef.current = null;
- }
- };
- }, [query, fetchData]);
- };
-}
-
-/**
- * Subscribe to entity changes. This hook fetches initial data from torii and subscribes to each entity change.
- * Use `useModel` to access your data.
- *
- * @param query ToriiQuery
- */
-export function useEntityQuery(
- query: ToriiQueryBuilder
-) {
- const { sdk, useDojoStore } = useDojoSDK<() => any, Schema>();
- const state = useDojoStore((s) => s);
-
- const useEntityQueryHook = createSubscriptionHook({
- subscribeMethod: (options) => sdk.subscribeEntityQuery(options),
- updateSubscriptionMethod: (subscription, clause) =>
- sdk.updateEntitySubscription(subscription, clause),
- queryToHashedKeysMethod: (query) => sdk.toriiQueryIntoHashedKeys(query),
- processInitialData: (data) => state.mergeEntities(data),
- processUpdateData: (data) => {
- const entity = data.pop();
-
- if (entity && entity.entityId !== "0x0") {
- state.updateEntity(entity);
- }
- },
- getErrorPrefix: () => "Dojo.js - useEntityQuery",
- historical: false,
- });
-
- useEntityQueryHook(query);
-}
-
-/**
- * Subscribe to event changes. This hook fetches initial events from torii and subscribes to new events.
- *
- * @param query ToriiQuery
- */
-export function useEventQuery(
- query: ToriiQueryBuilder
-) {
- const { sdk, useDojoStore } = useDojoSDK<() => any, Schema>();
- const state = useDojoStore((s) => s);
-
- const useEventQueryHook = createSubscriptionHook({
- subscribeMethod: (options) => sdk.subscribeEventQuery(options),
- updateSubscriptionMethod: (subscription, clause) =>
- sdk.updateEventMessageSubscription(subscription, clause, false),
- queryToHashedKeysMethod: (query) =>
- sdk.toriiEventMessagesQueryIntoHashedKeys(query, false),
- processInitialData: (data) => state.mergeEntities(data),
- processUpdateData: (data) => {
- const event = data.pop();
- if (event && event.entityId !== "0x0") {
- state.updateEntity(event);
- }
- },
- getErrorPrefix: () => "Dojo.js - useEventQuery",
- historical: false,
- });
-
- useEventQueryHook(query);
-}
-
-/**
- * Subscribe to historical events changes. This hook fetches initial data from torii and subscribes to entity changes.
- * You need to specify to torii which events has to be taken in account as historical events.
- *
- * @param query ToriiQuery
- */
-export function useHistoricalEventsQuery(
- query: ToriiQueryBuilder
-) {
- const { sdk } = useDojoSDK<() => any, Schema>();
- const [events, setEvents] = useState[]>([]);
-
- const useHistoricalEventsQueryHook = createSubscriptionHook({
- subscribeMethod: (options) => sdk.subscribeEventQuery(options),
- updateSubscriptionMethod: (subscription, clause) =>
- sdk.updateEventMessageSubscription(subscription, clause, true),
- queryToHashedKeysMethod: (query) =>
- sdk.toriiEventMessagesQueryIntoHashedKeys(query, true),
- processInitialData: (data) => setEvents(data),
- processUpdateData: (data) => {
- const event = data.pop();
- if (event) {
- setEvents((ev) => [event, ...ev]);
- }
- },
- getErrorPrefix: () => "Dojo.js - useHistoricalEventsQuery",
- historical: true,
- });
-
- useHistoricalEventsQueryHook(query);
-
- return events;
-}
-
-/**
- * Performs a deep comparison between two values to determine if they are equivalent.
- * @param a First value to compare
- * @param b Second value to compare
- * @returns True if the values are equivalent, false otherwise
- */
-function deepEqual(a: any, b: any): boolean {
- // If the values are strictly equal, return true
- if (a === b) return true;
-
- // If either value is null or not an object, they're not equal
- if (
- a === null ||
- b === null ||
- typeof a !== "object" ||
- typeof b !== "object"
- ) {
- return false;
- }
-
- // Handle arrays
- if (Array.isArray(a) && Array.isArray(b)) {
- 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;
- }
-
- // Handle Date objects
- if (a instanceof Date && b instanceof Date) {
- return a.getTime() === b.getTime();
- }
-
- // Handle regular expressions
- if (a instanceof RegExp && b instanceof RegExp) {
- return a.toString() === b.toString();
- }
-
- // Get all keys from both objects
- const keysA = Object.keys(a);
- const keysB = Object.keys(b);
-
- // If number of keys is different, objects are not equal
- if (keysA.length !== keysB.length) return false;
-
- // Check if every key in a exists in b and has the same value
- return keysA.every(
- (key) =>
- Object.prototype.hasOwnProperty.call(b, key) &&
- deepEqual(a[key], b[key])
- );
-}
-
-/**
- * Creates a Promise that resolves after the specified time
- * @param ms The time to sleep in milliseconds
- * @returns A Promise that resolves after the specified time
- */
-function sleep(ms: number): Promise {
- return new Promise((resolve) => setTimeout(resolve, ms));
-}
diff --git a/packages/sdk/src/react/hooks/entities.ts b/packages/sdk/src/react/hooks/entities.ts
new file mode 100644
index 00000000..2884eaa1
--- /dev/null
+++ b/packages/sdk/src/react/hooks/entities.ts
@@ -0,0 +1,35 @@
+import { useDojoSDK } from "../hooks";
+import { createSubscriptionHook } from "./hooks";
+import type { SchemaType, ToriiQueryBuilder } from "../../types";
+
+/**
+ * Subscribe to entity changes. This hook fetches initial data from torii and subscribes to each entity change.
+ * Use `useModel` to access your data.
+ *
+ * @param query ToriiQuery
+ */
+export function useEntityQuery(
+ query: ToriiQueryBuilder
+) {
+ const { sdk, useDojoStore } = useDojoSDK<() => any, Schema>();
+ const state = useDojoStore((s) => s);
+
+ const useEntityQueryHook = createSubscriptionHook({
+ subscribeMethod: (options) => sdk.subscribeEntityQuery(options),
+ updateSubscriptionMethod: (subscription, clause) =>
+ sdk.updateEntitySubscription(subscription, clause),
+ queryToHashedKeysMethod: (query) => sdk.toriiQueryIntoHashedKeys(query),
+ processInitialData: (data) => state.mergeEntities(data),
+ processUpdateData: (data) => {
+ const entity = data.pop();
+
+ if (entity && entity.entityId !== "0x0") {
+ state.updateEntity(entity);
+ }
+ },
+ getErrorPrefix: () => "Dojo.js - useEntityQuery",
+ historical: false,
+ });
+
+ useEntityQueryHook(query);
+}
diff --git a/packages/sdk/src/react/hooks/events.ts b/packages/sdk/src/react/hooks/events.ts
new file mode 100644
index 00000000..c99e33fe
--- /dev/null
+++ b/packages/sdk/src/react/hooks/events.ts
@@ -0,0 +1,70 @@
+import { useDojoSDK } from "../hooks";
+import { createSubscriptionHook } from "./hooks";
+import type { SchemaType, ToriiQueryBuilder } from "../../types";
+import { useState } from "react";
+import type { StandardizedQueryResult } from "../../types";
+
+/**
+ * Subscribe to event changes. This hook fetches initial events from torii and subscribes to new events.
+ *
+ * @param query ToriiQuery
+ */
+export function useEventQuery(
+ query: ToriiQueryBuilder
+) {
+ const { sdk, useDojoStore } = useDojoSDK<() => any, Schema>();
+ const state = useDojoStore((s) => s);
+
+ const useEventQueryHook = createSubscriptionHook({
+ subscribeMethod: (options) => sdk.subscribeEventQuery(options),
+ updateSubscriptionMethod: (subscription, clause) =>
+ sdk.updateEventMessageSubscription(subscription, clause, false),
+ queryToHashedKeysMethod: (query) =>
+ sdk.toriiEventMessagesQueryIntoHashedKeys(query, false),
+ processInitialData: (data) => state.mergeEntities(data),
+ processUpdateData: (data) => {
+ const event = data.pop();
+ if (event && event.entityId !== "0x0") {
+ state.updateEntity(event);
+ }
+ },
+ getErrorPrefix: () => "Dojo.js - useEventQuery",
+ historical: false,
+ });
+
+ useEventQueryHook(query);
+}
+
+/**
+ * Subscribe to historical events changes. This hook fetches initial data from torii and subscribes to entity changes.
+ * You need to specify to torii which events has to be taken in account as historical events.
+ *
+ * @param query ToriiQuery
+ */
+export function useHistoricalEventsQuery(
+ query: ToriiQueryBuilder
+) {
+ const { sdk } = useDojoSDK<() => any, Schema>();
+ const [events, setEvents] = useState[]>([]);
+
+ const useHistoricalEventsQueryHook = createSubscriptionHook({
+ subscribeMethod: (options) => sdk.subscribeEventQuery(options),
+ updateSubscriptionMethod: (subscription, clause) =>
+ sdk.updateEventMessageSubscription(subscription, clause, true),
+ queryToHashedKeysMethod: (query) =>
+ sdk.toriiEventMessagesQueryIntoHashedKeys(query, true),
+ processInitialData: (data) => setEvents(data),
+ processUpdateData: (data) => {
+ const event = data.pop();
+ if (event) {
+ setEvents((ev) => [event, ...ev]);
+ }
+ },
+ getErrorPrefix: () => "Dojo.js - useHistoricalEventsQuery",
+ historical: true,
+ });
+
+ useHistoricalEventsQueryHook(query);
+
+ return events;
+}
diff --git a/packages/sdk/src/react/hooks/hooks.ts b/packages/sdk/src/react/hooks/hooks.ts
new file mode 100644
index 00000000..8803a13c
--- /dev/null
+++ b/packages/sdk/src/react/hooks/hooks.ts
@@ -0,0 +1,119 @@
+import { useCallback, useEffect, useRef } from "react";
+import type {
+ SubscribeResponse,
+ ToriiResponse,
+ SchemaType,
+ SubscribeParams,
+} from "../../types";
+import type { ToriiQueryBuilder } from "../../toriiQueryBuilder";
+import type { EntityKeysClause, Subscription } from "@dojoengine/torii-client";
+import { deepEqual, sleep } from "./utils";
+
+/**
+ * Base hook factory for creating subscription hooks with shared logic
+ */
+export function createSubscriptionHook<
+ Schema extends SchemaType,
+ Historical extends boolean = false,
+>(config: {
+ subscribeMethod: (
+ options: SubscribeParams
+ ) => Promise>;
+ updateSubscriptionMethod: (
+ subscription: Subscription,
+ clause: any,
+ historical?: boolean
+ ) => Promise;
+ queryToHashedKeysMethod: (
+ query: ToriiQueryBuilder,
+ historical?: boolean
+ ) => Promise<[ToriiResponse, EntityKeysClause[]]>;
+ processInitialData: (data: ToriiResponse) => void;
+ processUpdateData: (data: any) => void;
+ getErrorPrefix: () => string;
+ historical: Historical;
+}) {
+ return function useSubscriptionHook(query: ToriiQueryBuilder) {
+ // Subscription handle to update
+ const subscriptionRef = useRef(null);
+ // Handle to user input query
+ const fetchingRef = useRef | null>(null);
+ // Async lock to sync with event loop
+ const isUpdating = useRef(false);
+
+ 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]);
+
+ useEffect(() => {
+ if (!deepEqual(query, fetchingRef.current)) {
+ fetchingRef.current = query;
+
+ fetchData()
+ .then((s) => {
+ if (s !== null) {
+ subscriptionRef.current = s;
+ }
+ })
+ .catch((err) => {
+ console.error(
+ `${config.getErrorPrefix()} - error fetching data for query: `,
+ JSON.stringify(query)
+ );
+ console.error(err);
+ })
+ .finally(() => {
+ // Release lock
+ isUpdating.current = false;
+ });
+ }
+
+ return () => {
+ if (subscriptionRef.current) {
+ // subscriptionRef.current?.cancel();
+ // subscriptionRef.current = null;
+ }
+ };
+ }, [query, fetchData]);
+ };
+}
diff --git a/packages/sdk/src/react/hooks/index.ts b/packages/sdk/src/react/hooks/index.ts
new file mode 100644
index 00000000..a512c54c
--- /dev/null
+++ b/packages/sdk/src/react/hooks/index.ts
@@ -0,0 +1,41 @@
+import { useContext, useMemo } from "react";
+import type { BigNumberish } from "starknet";
+import type { SchemaType } from "../../types";
+import { DojoContext, type DojoContextType } from "../provider";
+import { getEntityIdFromKeys } from "@dojoengine/utils";
+
+export * from "./entities";
+export * from "./events";
+export * from "./token";
+export * from "./state";
+
+/**
+ * Hook that exposes sdk features.
+ *
+ * @template Client Client function generated with `sozo build --typescript`
+ * @template Schema Schema function generated with `sozo build --typescript`
+ * @returns DojoContextType
+ */
+export function useDojoSDK<
+ Client extends (...args: any) => any,
+ Schema extends SchemaType,
+>(): DojoContextType {
+ return useContext>(DojoContext);
+}
+
+/**
+ * If you know all distinct keys of your model, here is a way to compose it.
+ *
+ * @param keys Each keys corresponding to your model keys.
+ * @returns Composed entityId
+ */
+export function useEntityId(...keys: BigNumberish[]): BigNumberish {
+ const entityId = useMemo(() => {
+ if (keys.length > 0) {
+ return getEntityIdFromKeys(keys.map((k) => BigInt(k)));
+ }
+ return BigInt(0);
+ }, [keys]);
+
+ return entityId;
+}
diff --git a/packages/sdk/src/react/hooks/state.ts b/packages/sdk/src/react/hooks/state.ts
new file mode 100644
index 00000000..752d7a1d
--- /dev/null
+++ b/packages/sdk/src/react/hooks/state.ts
@@ -0,0 +1,73 @@
+import { useContext } from "react";
+import type { BigNumberish } from "starknet";
+import type { SchemaType } from "../../types";
+import { DojoContext, type DojoContextType } from "../provider";
+import { create, type StoreApi, type UseBoundStore } from "zustand";
+import { createDojoStoreFactory } from "../../state/zustand";
+import type { GameState } from "../../state";
+
+/**
+ * Factory function to create a React Zustand store based on a given SchemaType.
+ *
+ * @template T - The schema type.
+ * @returns A Zustand hook tailored to the provided schema.
+ */
+export function createDojoStore() {
+ // hacktually until I find a proper type input to createDojoStoreFactory
+ return createDojoStoreFactory(create) as unknown as UseBoundStore<
+ StoreApi>
+ >;
+}
+
+/**
+ * Custom hook to retrieve a specific model for a given entityId within a specified namespace.
+ *
+ * @param entityId - The ID of the entity.
+ * @param model - The model to retrieve, specified as a string in the format "namespace-modelName".
+ * @returns The model structure if found, otherwise undefined.
+ */
+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>(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;
+}
+
+/**
+ * Custom hook to retrieve all entities that have a specific model.
+ *
+ * @param model - The model to retrieve, specified as a string in the format "namespace-modelName".
+ * @returns The model structure if found, otherwise undefined.
+ */
+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>(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;
+}
diff --git a/packages/sdk/src/react/hooks/token.ts b/packages/sdk/src/react/hooks/token.ts
new file mode 100644
index 00000000..47e42df4
--- /dev/null
+++ b/packages/sdk/src/react/hooks/token.ts
@@ -0,0 +1,126 @@
+import { useDojoSDK } from "../hooks";
+import { useState, useEffect, useRef, useCallback } from "react";
+import type {
+ Token,
+ Tokens,
+ TokenBalance,
+ TokenBalances,
+ Subscription,
+} from "@dojoengine/torii-client";
+import type {
+ GetTokenRequest,
+ GetTokenBalanceRequest,
+ SubscriptionCallbackArgs,
+} from "../..";
+import { deepEqual } from "./utils";
+
+export function useTokens(request: GetTokenRequest & GetTokenBalanceRequest) {
+ const { sdk } = useDojoSDK();
+ const [tokens, setTokens] = useState([]);
+ const requestRef = useRef(null);
+ const [tokenBalances, setTokenBalances] = useState([]);
+ const subscriptionRef = useRef(null);
+
+ const fetchTokens = useCallback(async () => {
+ const tokens = await sdk.getTokens({
+ contractAddresses: request.contractAddresses ?? [],
+ tokenIds: request.tokenIds ?? [],
+ });
+ console.log("tokens", tokens);
+ setTokens(tokens);
+ }, [sdk, request]);
+
+ const fetchTokenBalances = useCallback(async () => {
+ const [tokenBalances, subscription] = await sdk.subscribeTokenBalance({
+ contractAddresses: request.contractAddresses ?? [],
+ accountAddresses: request.accountAddresses ?? [],
+ tokenIds: request.tokenIds ?? [],
+ callback: ({
+ data,
+ error,
+ }: SubscriptionCallbackArgs) => {
+ if (error) {
+ console.error(error);
+ return;
+ }
+ setTokenBalances((prev) => updateTokenBalancesList(prev, data));
+ },
+ });
+ console.log("tokenBalances", tokenBalances);
+ subscriptionRef.current = subscription;
+ setTokenBalances(tokenBalances);
+ }, [sdk, request]);
+
+ useEffect(() => {
+ if (!deepEqual(request, requestRef.current)) {
+ requestRef.current = request;
+ fetchTokens();
+ fetchTokenBalances();
+ }
+ }, [request]);
+
+ function getBalance(token: Token): TokenBalance | undefined {
+ return tokenBalances.find(
+ (balance) => balance.contract_address === token.contract_address
+ );
+ }
+
+ function toDecimal(
+ token: Token,
+ balance: TokenBalance | undefined
+ ): number {
+ return (
+ Number.parseInt(balance?.balance ?? "0", 16) * 10 ** -token.decimals
+ );
+ }
+
+ return { tokens, balances: tokenBalances, getBalance, toDecimal };
+}
+
+function updateTokenBalancesList(
+ previousBalances: TokenBalance[],
+ newBalance: TokenBalance
+): TokenBalance[] {
+ const existingBalanceIndex = previousBalances.findIndex(
+ (balance) => balance.token_id === newBalance.token_id
+ );
+
+ // If balance doesn't exist, append it to the list
+ if (existingBalanceIndex === -1) {
+ return [...previousBalances, newBalance];
+ }
+
+ // If balance exists, update it while preserving order
+ return previousBalances.map((balance, index) =>
+ index === existingBalanceIndex ? newBalance : balance
+ );
+}
+
+// /**
+// * Subscribe to event changes. This hook fetches initial events from torii and subscribes to new events.
+// *
+// * @param query ToriiQuery
+// */
+// export function useTokenBalances(request: GetTokenBalanceRequest) {
+// const { sdk, useDojoStore } = useDojoSDK();
+// const state = useDojoStore((s) => s);
+
+// const useEventQueryHook = createSubscriptionHook({
+// subscribeMethod: (request) => sdk.onTokenBalanceUpdated(request),
+// updateSubscriptionMethod: (subscription, clause) =>
+// sdk.updateEventMessageSubscription(subscription, clause, false),
+// queryToHashedKeysMethod: (query) =>
+// sdk.toriiEventMessagesQueryIntoHashedKeys(query, false),
+// processInitialData: (data) => state.mergeEntities(data),
+// processUpdateData: (data) => {
+// const event = data.pop();
+// if (event && event.entityId !== "0x0") {
+// state.updateEntity(event);
+// }
+// },
+// getErrorPrefix: () => "Dojo.js - useTokenBalances",
+// historical: false,
+// });
+
+// useEventQueryHook(query);
+// }
diff --git a/packages/sdk/src/react/hooks/utils.ts b/packages/sdk/src/react/hooks/utils.ts
new file mode 100644
index 00000000..053a1bcc
--- /dev/null
+++ b/packages/sdk/src/react/hooks/utils.ts
@@ -0,0 +1,64 @@
+/**
+ * Performs a deep comparison between two values to determine if they are equivalent.
+ * @param a First value to compare
+ * @param b Second value to compare
+ * @returns True if the values are equivalent, false otherwise
+ */
+export function deepEqual(a: any, b: any): boolean {
+ // If the values are strictly equal, return true
+ if (a === b) return true;
+
+ // If either value is null or not an object, they're not equal
+ if (
+ a === null ||
+ b === null ||
+ typeof a !== "object" ||
+ typeof b !== "object"
+ ) {
+ return false;
+ }
+
+ // Handle arrays
+ if (Array.isArray(a) && Array.isArray(b)) {
+ 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;
+ }
+
+ // Handle Date objects
+ if (a instanceof Date && b instanceof Date) {
+ return a.getTime() === b.getTime();
+ }
+
+ // Handle regular expressions
+ if (a instanceof RegExp && b instanceof RegExp) {
+ return a.toString() === b.toString();
+ }
+
+ // Get all keys from both objects
+ const keysA = Object.keys(a);
+ const keysB = Object.keys(b);
+
+ // If number of keys is different, objects are not equal
+ if (keysA.length !== keysB.length) return false;
+
+ // Check if every key in a exists in b and has the same value
+ return keysA.every(
+ (key) =>
+ Object.prototype.hasOwnProperty.call(b, key) &&
+ deepEqual(a[key], b[key])
+ );
+}
+
+/**
+ * Creates a Promise that resolves after the specified time
+ * @param ms The time to sleep in milliseconds
+ * @returns A Promise that resolves after the specified time
+ */
+export function sleep(ms: number): Promise {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+}
diff --git a/packages/sdk/src/react/index.ts b/packages/sdk/src/react/index.ts
index cdd2a909..f0630210 100644
--- a/packages/sdk/src/react/index.ts
+++ b/packages/sdk/src/react/index.ts
@@ -1,2 +1,3 @@
export * from "./hooks";
export * from "./provider";
+export * from "./hoc/with-account";
diff --git a/packages/sdk/src/react/provider.tsx b/packages/sdk/src/react/provider.tsx
index af9f752f..b39885e9 100644
--- a/packages/sdk/src/react/provider.tsx
+++ b/packages/sdk/src/react/provider.tsx
@@ -1,8 +1,8 @@
-import { ReactNode, useContext, createContext } from "react";
-import { SchemaType, SDK } from "../types";
-import { DojoConfig, DojoProvider } from "@dojoengine/core";
-import { createDojoStore } from "./hooks";
-import { GameState } from "../state";
+import { type ReactNode, useContext, createContext } from "react";
+import type { SchemaType, SDK } from "../types";
+import { type DojoConfig, DojoProvider } from "@dojoengine/core";
+import { createDojoStore } from "./hooks/state";
+import type { GameState } from "../state";
// Define the hook type
export type DojoStoreHook = (
@@ -15,7 +15,7 @@ export type DojoStoreHook = (
*/
export interface DojoContextType<
Client extends (...args: any) => any,
- Schema extends SchemaType
+ Schema extends SchemaType,
> {
/** The Dojo client instance */
config: DojoConfig;
diff --git a/packages/sdk/src/token.ts b/packages/sdk/src/token.ts
new file mode 100644
index 00000000..810f313b
--- /dev/null
+++ b/packages/sdk/src/token.ts
@@ -0,0 +1,161 @@
+import type * as torii from "@dojoengine/torii-client";
+import type {
+ GetTokenBalanceRequest,
+ GetTokenRequest,
+ SubscribeTokenBalanceRequest,
+ UpdateTokenBalanceSubscriptionRequest,
+} from "./types";
+import { addAddressPadding } from "starknet";
+
+export const defaultTokenBalance: torii.TokenBalance = {
+ balance:
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
+ account_address: "0x0",
+ contract_address: "0x0",
+ token_id:
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
+};
+
+function parseTokenRequest(
+ req: T
+): T {
+ if (req.contractAddresses) {
+ req.contractAddresses = req.contractAddresses.map((r) =>
+ addAddressPadding(r)
+ );
+ }
+
+ if (req.accountAddresses) {
+ req.accountAddresses = req.accountAddresses.map((r) =>
+ addAddressPadding(r)
+ );
+ }
+
+ return req;
+}
+/**
+ * @param {GetTokenRequest} request
+ * @returns {Promise}
+ */
+export async function getTokens(
+ client: torii.ToriiClient,
+ request: GetTokenRequest
+): Promise {
+ const { contractAddresses, tokenIds } = parseTokenRequest(request);
+ return await client.getTokens(contractAddresses ?? [], tokenIds ?? []);
+}
+
+/**
+ * @param {GetTokenBalanceRequest} request
+ * @returns {Promise}
+ */
+export async function getTokenBalances(
+ client: torii.ToriiClient,
+ request: GetTokenBalanceRequest
+): Promise {
+ const { contractAddresses, accountAddresses, tokenIds } =
+ parseTokenRequest(request);
+ return await client.getTokenBalances(
+ contractAddresses ?? [],
+ accountAddresses ?? [],
+ tokenIds ?? []
+ );
+}
+
+/**
+ * Subscribes to token balance updates
+ *
+ * # Parameters
+ * @param {SubscribeTokenBalanceRequest} request
+ *
+ * # Returns
+ * Result containing subscription handle or error
+ * @returns torii.Subscription
+ */
+export function onTokenBalanceUpdated(
+ client: torii.ToriiClient,
+ request: SubscribeTokenBalanceRequest
+): torii.Subscription {
+ const { contractAddresses, accountAddresses, tokenIds, callback } =
+ parseTokenRequest(request);
+ return client.onTokenBalanceUpdated(
+ contractAddresses ?? [],
+ accountAddresses ?? [],
+ tokenIds ?? [],
+ callback
+ );
+}
+
+/**
+ * Updates an existing token balance subscription
+ *
+ * # Parameters
+ * @param {torii.Subscription} subscription - Existing subscription to update
+ * @param {UpdateTokenBalanceSubscriptionRequest} request
+ *
+ * # Returns
+ * Result containing unit or error
+ * @returns {Promise}
+ */
+export async function updateTokenBalanceSubscription(
+ client: torii.ToriiClient,
+ request: UpdateTokenBalanceSubscriptionRequest
+): Promise {
+ const { subscription, contractAddresses, accountAddresses, tokenIds } =
+ request;
+ return await client.updateTokenBalanceSubscription(
+ subscription,
+ contractAddresses ?? [],
+ accountAddresses ?? [],
+ tokenIds ?? []
+ );
+}
+/**
+ * Subscribes to token balance updates and returns initial data with subscription
+ *
+ * # Parameters
+ * @param {SubscribeTokenBalanceRequest} request - Request parameters
+ *
+ * # Returns
+ * Array containing initial token balances and subscription handle
+ * @returns {Promise<[torii.TokenBalances, torii.Subscription]>}
+ */
+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,
+ });
+ }
+ }
+ );
+
+ return [initialBalances, subscription];
+}
diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts
index c59f468d..0fc56dd2 100644
--- a/packages/sdk/src/types.ts
+++ b/packages/sdk/src/types.ts
@@ -248,16 +248,50 @@ export type UnionOfModelData = {
export type ToriiResponse<
T extends SchemaType,
- Historical extends boolean
+ Historical extends boolean,
> = Historical extends true
? StandardizedQueryResult[]
: StandardizedQueryResult;
export type SubscribeResponse<
T extends SchemaType,
- Historical extends boolean
+ Historical extends boolean,
> = [ToriiResponse, torii.Subscription];
+export interface GetTokenRequest {
+ contractAddresses?: string[];
+ tokenIds?: string[];
+}
+
+export interface GetTokenBalanceRequest extends GetTokenRequest {
+ accountAddresses?: string[];
+}
+
+type Success = {
+ data: T;
+ error: undefined;
+};
+
+type Failure = {
+ data: undefined;
+ error: E;
+};
+
+export type SubscriptionCallbackArgs = Success | Failure;
+
+// ToriiResponse
+export type SubscriptionCallback = (
+ response: SubscriptionCallbackArgs
+) => void;
+
+export type SubscribeTokenBalanceRequest = GetTokenBalanceRequest & {
+ callback: SubscriptionCallback;
+};
+
+export type UpdateTokenBalanceSubscriptionRequest = GetTokenBalanceRequest & {
+ subscription: torii.Subscription;
+};
+
/**
* SDK interface for interacting with the DojoEngine.
*
@@ -293,6 +327,17 @@ export interface SDK {
params: SubscribeParams
) => Promise>;
+ /**
+ * Subscribes to token balance updates
+ *
+ * # Parameters
+ * @param {SubscribeTokenBalanceRequest} request
+ * @returns {Promise<[torii.TokenBalances, torii.Subscription]>}
+ */
+ subscribeTokenBalance: (
+ request: SubscribeTokenBalanceRequest
+ ) => Promise<[torii.TokenBalances, torii.Subscription]>;
+
/**
* Fetches entities from the Torii client based on the provided query.
*
@@ -328,10 +373,7 @@ export interface SDK {
* @param {string[]} token_ids
* @returns {Promise}
*/
- getTokens(
- contract_addresses: string[],
- token_ids: string[]
- ): Promise;
+ getTokens(request: GetTokenRequest): Promise;
/**
* @param {string[]} account_addresses
@@ -340,9 +382,7 @@ export interface SDK {
* @returns {Promise}
*/
getTokenBalances(
- contract_addresses: string[],
- account_addresses: string[],
- token_ids: string[]
+ request: GetTokenBalanceRequest
): Promise;
/**
@@ -359,10 +399,7 @@ export interface SDK {
* @returns torii.Subscription
*/
onTokenBalanceUpdated: (
- contract_addresses: string[],
- account_addresses: string[],
- token_ids: string[],
- callback: Function
+ request: SubscribeTokenBalanceRequest
) => torii.Subscription;
/**
@@ -379,10 +416,7 @@ export interface SDK {
* @returns {Promise}
*/
updateTokenBalanceSubscription: (
- subscription: torii.Subscription,
- contract_addresses: string[],
- account_addresses: string[],
- token_ids: string[]
+ request: UpdateTokenBalanceSubscriptionRequest
) => Promise;
/**
@@ -489,25 +523,23 @@ export interface SDKFunctionOptions {
export interface SubscribeParams<
T extends SchemaType,
- Historical extends boolean = false
+ Historical extends boolean = false,
> {
// Query object used to filter entities.
query: ToriiQueryBuilder;
// The callback function to handle the response.
- callback: (response: {
- data?: ToriiResponse;
- error?: Error;
- }) => void;
+ callback: SubscriptionCallback>;
// historical events
historical?: Historical;
}
export interface GetParams<
T extends SchemaType,
- Historical extends boolean = false
+ Historical extends boolean = false,
> {
// The query object used to filter entities.
query: ToriiQueryBuilder;
// historical events
historical?: Historical;
}
+export { ToriiQueryBuilder };
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4da0e8c4..cb39db84 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -29,7 +29,7 @@ catalogs:
version: 18.3.1
starknet:
specifier: 6.23.1
- version: 6.21.0
+ version: 6.23.1
importers:
@@ -162,7 +162,7 @@ importers:
version: 3.1.0
'@starknet-react/core':
specifier: 'catalog:'
- version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.3)
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
react:
specifier: 'catalog:'
version: 18.3.1
@@ -171,7 +171,7 @@ importers:
version: 18.3.1(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
devDependencies:
'@eslint/js':
specifier: ^9.21.0
@@ -238,7 +238,7 @@ importers:
version: 3.60.0-beta.14
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
devDependencies:
typescript:
specifier: ^5.6.2
@@ -266,7 +266,7 @@ importers:
version: 11.11.1
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
devDependencies:
'@types/highlight.js':
specifier: ^10.1.0
@@ -400,7 +400,7 @@ importers:
version: 3.1.0
'@starknet-react/core':
specifier: 'catalog:'
- version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.8.2)
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.8.2)
'@t3-oss/env-core':
specifier: ^0.11.1
version: 0.11.1(typescript@5.8.2)(zod@3.24.2)
@@ -436,7 +436,7 @@ importers:
version: 7.54.2(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
tailwind-merge:
specifier: ^2.6.0
version: 2.6.0
@@ -515,7 +515,7 @@ importers:
version: 3.87.0
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
zustand:
specifier: ^4.5.5
version: 4.5.5(@types/react@19.0.10)(immer@10.1.1)(react@19.0.0)
@@ -585,7 +585,7 @@ importers:
version: 7.8.1
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
vite-plugin-wasm:
specifier: ^3.3.0
version: 3.4.1(vite@4.5.5(@types/node@20.17.10)(lightningcss@1.29.1)(terser@5.39.0))
@@ -712,7 +712,7 @@ importers:
version: 4.0.3
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
styled-components:
specifier: ^6.1.14
version: 6.1.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -833,7 +833,7 @@ importers:
version: 7.8.1
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
vite-plugin-top-level-await:
specifier: ^1.4.4
version: 1.4.4(@swc/helpers@0.5.5)(rollup@2.79.2)(vite@4.5.5(@types/node@20.17.10)(lightningcss@1.29.1)(terser@5.39.0))
@@ -918,7 +918,7 @@ importers:
version: 3.1.0
'@starknet-react/core':
specifier: 'catalog:'
- version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.3)
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
'@types/uuid':
specifier: ^10.0.0
version: 10.0.0
@@ -933,7 +933,7 @@ importers:
version: 18.3.1(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
uuid:
specifier: ^10.0.0
version: 10.0.0
@@ -1030,7 +1030,7 @@ importers:
version: 3.1.0
'@starknet-react/core':
specifier: 'catalog:'
- version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.3)
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
'@tanstack/react-query':
specifier: ^5.64.1
version: 5.64.1(react@18.3.1)
@@ -1066,7 +1066,7 @@ importers:
version: 18.3.1(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
tailwind-merge:
specifier: ^2.6.0
version: 2.6.0
@@ -1235,7 +1235,7 @@ importers:
version: 7.8.1
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
tailwind-merge:
specifier: ^2.5.2
version: 2.6.0
@@ -1350,7 +1350,7 @@ importers:
version: 2.2.14
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
vite-plugin-wasm:
specifier: ^3.3.0
version: 3.4.1(vite@5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0))
@@ -1380,6 +1380,91 @@ importers:
specifier: ^1.4.4
version: 1.4.4(@swc/helpers@0.5.5)(rollup@4.37.0)(vite@5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0))
+ examples/example-vite-token-balance:
+ dependencies:
+ '@cartridge/connector':
+ specifier: ^0.7.6
+ version: 0.7.6(@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@19.0.0)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3))(open@8.4.2)(starknet@6.23.1(encoding@0.1.13))
+ '@cartridge/controller':
+ specifier: ^0.7.6
+ version: 0.7.6(open@8.4.2)(starknet@6.23.1(encoding@0.1.13))
+ '@dojoengine/core':
+ specifier: workspace:*
+ version: link:../../packages/core
+ '@dojoengine/predeployed-connector':
+ specifier: workspace:*
+ version: link:../../packages/predeployed-connector
+ '@dojoengine/sdk':
+ specifier: workspace:*
+ version: link:../../packages/sdk
+ '@dojoengine/torii-client':
+ specifier: workspace:*
+ version: link:../../packages/torii-client
+ '@dojoengine/utils':
+ specifier: workspace:*
+ version: link:../../packages/utils
+ '@starknet-react/chains':
+ specifier: 'catalog:'
+ version: 3.1.0
+ '@starknet-react/core':
+ specifier: 'catalog:'
+ version: 3.6.2(get-starknet-core@4.0.0)(react@19.0.0)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
+ '@tailwindcss/vite':
+ specifier: ^4.0.1
+ version: 4.0.1(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0))
+ react:
+ specifier: ^19.0.0
+ version: 19.0.0
+ react-dom:
+ specifier: ^19.0.0
+ version: 19.0.0(react@19.0.0)
+ starknet:
+ specifier: 'catalog:'
+ version: 6.23.1(encoding@0.1.13)
+ tailwindcss:
+ specifier: ^4.0.14
+ version: 4.0.14
+ devDependencies:
+ '@eslint/js':
+ specifier: ^9.21.0
+ version: 9.21.0
+ '@types/react':
+ specifier: ^19.0.10
+ version: 19.0.10
+ '@types/react-dom':
+ specifier: ^19.0.4
+ version: 19.0.4(@types/react@19.0.10)
+ '@vitejs/plugin-react':
+ specifier: ^4.3.4
+ version: 4.3.4(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0))
+ eslint:
+ specifier: ^9.21.0
+ version: 9.21.0(jiti@2.4.2)
+ eslint-plugin-react-hooks:
+ specifier: ^5.1.0
+ version: 5.2.0(eslint@9.21.0(jiti@2.4.2))
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.19
+ version: 0.4.19(eslint@9.21.0(jiti@2.4.2))
+ globals:
+ specifier: ^15.15.0
+ version: 15.15.0
+ typescript:
+ specifier: ~5.7.2
+ version: 5.7.3
+ typescript-eslint:
+ specifier: ^8.24.1
+ version: 8.26.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)
+ vite:
+ specifier: ^6.2.0
+ version: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+ vite-plugin-top-level-await:
+ specifier: ^1.5.0
+ version: 1.5.0(@swc/helpers@0.5.5)(rollup@4.37.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0))
+ vite-plugin-wasm:
+ specifier: ^3.4.1
+ version: 3.4.1(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0))
+
examples/example-vue-app-recs:
dependencies:
'@dojoengine/core':
@@ -1408,7 +1493,7 @@ importers:
version: 2.2.14
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
vite-plugin-wasm:
specifier: ^3.3.0
version: 3.4.1(vite@5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0))
@@ -1439,7 +1524,7 @@ importers:
version: 2.0.13(typescript@5.7.2)(zod@3.24.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
zod:
specifier: ^3.23.8
version: 3.24.1
@@ -1473,7 +1558,7 @@ importers:
version: 1.6.0
'@starknet-react/core':
specifier: 'catalog:'
- version: 3.6.2(get-starknet-core@4.0.0)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.2)
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.2)
encoding:
specifier: ^0.1.13
version: 0.1.13
@@ -1491,7 +1576,7 @@ importers:
version: 18.3.1(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
devDependencies:
'@babel/core':
specifier: ^7.25.2
@@ -1501,10 +1586,10 @@ importers:
version: 7.26.0(@babel/core@7.26.0)
'@testing-library/react':
specifier: ^16.0.1
- version: 16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)
+ version: 16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@testing-library/react-hooks':
specifier: ^8.0.1
- version: 8.0.1(@types/react@18.3.18)
+ version: 8.0.1(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@types/js-cookie':
specifier: ^3.0.6
version: 3.0.6
@@ -1595,7 +1680,7 @@ importers:
version: 0.7.10
'@starknet-react/core':
specifier: 'catalog:'
- version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.3)
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
react:
specifier: 'catalog:'
version: 18.3.1
@@ -1604,7 +1689,7 @@ importers:
version: 18.3.1(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
devDependencies:
'@rollup/plugin-commonjs':
specifier: ^28.0.0
@@ -1674,7 +1759,7 @@ importers:
version: 7.5.5
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
type-fest:
specifier: ^2.14.0
version: 2.19.0
@@ -1721,30 +1806,36 @@ importers:
'@dojoengine/utils':
specifier: workspace:*
version: link:../utils
+ '@starknet-react/chains':
+ specifier: 'catalog:'
+ version: 3.1.0
+ '@starknet-react/core':
+ specifier: 'catalog:'
+ version: 3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
'@tanstack/react-query':
specifier: ^5.62.16
- version: 5.66.9(react@19.0.0)
+ version: 5.66.9(react@18.3.1)
'@types/react':
specifier: 'catalog:'
- version: 19.0.10
+ version: 18.3.18
'@types/react-dom':
specifier: 'catalog:'
- version: 18.3.5(@types/react@19.0.10)
+ version: 18.3.5(@types/react@18.3.18)
immer:
specifier: ^10.1.1
version: 10.1.1
react:
specifier: 'catalog:'
- version: 19.0.0
+ version: 18.3.1
react-dom:
specifier: 'catalog:'
- version: 18.3.1(react@19.0.0)
+ version: 18.3.1(react@18.3.1)
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
zustand:
specifier: ^4.5.6
- version: 4.5.6(@types/react@19.0.10)(immer@10.1.1)(react@19.0.0)
+ version: 4.5.6(@types/react@18.3.18)(immer@10.1.1)(react@18.3.1)
devDependencies:
'@rollup/plugin-commonjs':
specifier: ^28.0.2
@@ -1790,7 +1881,7 @@ importers:
version: link:../torii-client
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
vitest:
specifier: ^1.6.0
version: 1.6.0(@types/node@22.13.13)(jsdom@24.1.3)(lightningcss@1.29.1)(terser@5.39.0)
@@ -1843,7 +1934,7 @@ importers:
version: 0.2.3
starknet:
specifier: 'catalog:'
- version: 6.21.0(encoding@0.1.13)
+ version: 6.23.1(encoding@0.1.13)
devDependencies:
'@types/elliptic':
specifier: ^6.4.18
@@ -2653,6 +2744,53 @@ packages:
'@canvas/image-data@1.0.0':
resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==}
+ '@cartridge/account-wasm@0.7.6':
+ resolution: {integrity: sha512-uulPdfiPesJ5pSg7wZPOH+0ppTQ87Zv16oFipimwlQbZ+uoDX9FoAWNIHQrfCQfOnl43IHTLwYEa1Bo92p5eKQ==}
+
+ '@cartridge/connector@0.7.6':
+ resolution: {integrity: sha512-yo7JxSQUi0ukg83db3MO00WdwUaMiIQvx/mi+UK4kTgIdlNvZcqzprz9kta3h/p3dzWIMxkd9zi8P4TAGKK4Sw==}
+ peerDependencies:
+ '@starknet-react/core': ^3.7
+
+ '@cartridge/controller@0.7.6':
+ resolution: {integrity: sha512-izpepJGDlSndZmutTTulThDbT2ccpNhb7TGj7guT5XKdxQzjrwvKQNIeQqmZd7n3TTWcfp8+Z2F3fw8aRyruPw==}
+ peerDependencies:
+ open: ^10.1.0
+ starknet: ^6.21.0
+
+ '@cartridge/penpal@6.2.4':
+ resolution: {integrity: sha512-tdpOnSJJBFMlgLZ1+z9Ho5e6cG5EgMAb1Cmmh1lGT2tmplogU/XPMjLE6CwvKAPDoe6a38iMnbH+ySTAWWIOKA==}
+
+ '@cbor-extract/cbor-extract-darwin-arm64@2.2.0':
+ resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@cbor-extract/cbor-extract-darwin-x64@2.2.0':
+ resolution: {integrity: sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@cbor-extract/cbor-extract-linux-arm64@2.2.0':
+ resolution: {integrity: sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@cbor-extract/cbor-extract-linux-arm@2.2.0':
+ resolution: {integrity: sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==}
+ cpu: [arm]
+ os: [linux]
+
+ '@cbor-extract/cbor-extract-linux-x64@2.2.0':
+ resolution: {integrity: sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@cbor-extract/cbor-extract-win32-x64@2.2.0':
+ resolution: {integrity: sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==}
+ cpu: [x64]
+ os: [win32]
+
'@changesets/apply-release-plan@7.0.7':
resolution: {integrity: sha512-qnPOcmmmnD0MfMg9DjU1/onORFyRpDXkMMl2IJg9mECY6RnxL3wN0TCCc92b2sXt1jt8DgjAUUsZYGUGTdYIXA==}
@@ -7435,6 +7573,27 @@ packages:
resolution: {integrity: sha512-UsLBb+ALvxbRTYMlx3WJ36oq13Ps4n8tcN8biFrtiCbA8TiS0sgSAOr0lPQpzQqZuVSjscPjX43ciKf33hvkQw==}
engines: {node: '>=12'}
+ '@telegram-apps/bridge@1.9.2':
+ resolution: {integrity: sha512-SJLcNWLXhbbZr9MiqFH/g2ceuitSJKMxUIZysK4zUNyTUNuonrQG80Q/yrO+XiNbKUj8WdDNM86NBARhuyyinQ==}
+
+ '@telegram-apps/navigation@1.0.13':
+ resolution: {integrity: sha512-TsUueB5LQp77GQHoMa93nq26Uw7GJjrFCPbyseMVU7aBBxAc+8CV2IYytRwcVp5sv/q7ThK5X4JaKn2V1yBHDQ==}
+
+ '@telegram-apps/sdk@2.11.3':
+ resolution: {integrity: sha512-KdULzgRe1gcR8B3Z/t3hQrEaDmLGrfsL2IePtPP6ehtMn5tT0uPfnjtDLjDNQMyI7D4Tv2ZOzvDx45wOhhreXg==}
+
+ '@telegram-apps/signals@1.1.1':
+ resolution: {integrity: sha512-vz37r8lemGpPzDiBRfqpXYBynzmy3SFnY6zfHsTZABTYYt0b0WQZyU5mFDqqqugGhka78Gy11xmr9csgy4YgGA==}
+
+ '@telegram-apps/toolkit@1.1.1':
+ resolution: {integrity: sha512-+vhKx6ngfvjyTE6Xagl3z1TPVbfx5s7xAkcYzCdHYUo6T60jLIqLgyZMcI1UPoIAMuMu1pHoO+p8QNCj/+tFmw==}
+
+ '@telegram-apps/transformers@1.2.2':
+ resolution: {integrity: sha512-vvMwXckd1D7Ozc0h66PSUwF5QLrRV9HlGJFFeBuUex8QEk5mSPtsJkLiqB8aBbwuFDa91+TUSM/CxqPZO/e9YQ==}
+
+ '@telegram-apps/types@1.2.1':
+ resolution: {integrity: sha512-so4HLh7clur0YyMthi9KVIgWoGpZdXlFOuQjk3+Q5NAvJZ11nAheBSwPlGw/Ko92+zwvrSBE/lQyN2+p17RP+w==}
+
'@testing-library/dom@10.4.0':
resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==}
engines: {node: '>=18'}
@@ -7705,6 +7864,11 @@ packages:
peerDependencies:
'@types/react': ^18.0.0
+ '@types/react-dom@19.0.4':
+ resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==}
+ peerDependencies:
+ '@types/react': ^19.0.0
+
'@types/react-reconciler@0.26.7':
resolution: {integrity: sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==}
@@ -8733,6 +8897,10 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ base64url@3.0.1:
+ resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==}
+ engines: {node: '>=6.0.0'}
+
bech32@1.1.4:
resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==}
@@ -8928,6 +9096,13 @@ packages:
resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==}
hasBin: true
+ cbor-extract@2.2.0:
+ resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==}
+ hasBin: true
+
+ cbor-x@1.6.0:
+ resolution: {integrity: sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==}
+
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -11948,7 +12123,6 @@ packages:
libsql@0.4.7:
resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==}
- cpu: [x64, arm64, wasm32]
os: [darwin, linux, win32]
lie@3.3.0:
@@ -12628,6 +12802,10 @@ packages:
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ node-gyp-build-optional-packages@5.1.1:
+ resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==}
+ hasBin: true
+
node-gyp@10.3.1:
resolution: {integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==}
engines: {node: ^16.14.0 || >=18.0.0}
@@ -13464,6 +13642,11 @@ packages:
peerDependencies:
react: ^18.3.1
+ react-dom@19.0.0:
+ resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
+ peerDependencies:
+ react: ^19.0.0
+
react-element-to-jsx-string@15.0.0:
resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==}
peerDependencies:
@@ -13880,6 +14063,9 @@ packages:
scheduler@0.23.2:
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+ scheduler@0.25.0:
+ resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
+
scrypt-js@3.0.1:
resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==}
@@ -14140,8 +14326,8 @@ packages:
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
- starknet@6.21.0:
- resolution: {integrity: sha512-xUSlqyE+J/S5un3TyQY0Kehilh1u7ewPaut87eOxTDS1r90SU0QvQ3JEECp5LbW/sqsaMhfb+tGTBGrKzXg7bg==}
+ starknet@6.23.1:
+ resolution: {integrity: sha512-vQV9luXpmwZZs9RVZaRwm2iD8T0PYx1AzgZeQsCvD89tR0HwUF0paty27ZzuJrdPe0CmAs/ipAYFCE55jbj0RQ==}
stats-gl@2.4.2:
resolution: {integrity: sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==}
@@ -14408,6 +14594,9 @@ packages:
tailwindcss@4.0.1:
resolution: {integrity: sha512-UK5Biiit/e+r3i0O223bisoS5+y7ZT1PM8Ojn0MxRHzXN1VPZ2KY6Lo6fhu1dOfCfyUAlK7Lt6wSxowRabATBw==}
+ tailwindcss@4.0.14:
+ resolution: {integrity: sha512-92YT2dpt671tFiHH/e1ok9D987N9fHD5VWoly1CdPD/Cd1HMglvZwP3nx2yTj2lbXDAHt8QssZkxTLCCTNL+xw==}
+
tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
@@ -17675,6 +17864,48 @@ snapshots:
'@canvas/image-data@1.0.0': {}
+ '@cartridge/account-wasm@0.7.6': {}
+
+ '@cartridge/connector@0.7.6(@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@19.0.0)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3))(open@8.4.2)(starknet@6.23.1(encoding@0.1.13))':
+ dependencies:
+ '@cartridge/controller': 0.7.6(open@8.4.2)(starknet@6.23.1(encoding@0.1.13))
+ '@starknet-react/core': 3.6.2(get-starknet-core@4.0.0)(react@19.0.0)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)
+ transitivePeerDependencies:
+ - open
+ - starknet
+
+ '@cartridge/controller@0.7.6(open@8.4.2)(starknet@6.23.1(encoding@0.1.13))':
+ dependencies:
+ '@cartridge/account-wasm': 0.7.6
+ '@cartridge/penpal': 6.2.4
+ '@starknet-io/types-js': 0.7.10
+ '@telegram-apps/sdk': 2.11.3
+ base64url: 3.0.1
+ cbor-x: 1.6.0
+ fast-deep-equal: 3.1.3
+ open: 8.4.2
+ starknet: 6.23.1(encoding@0.1.13)
+
+ '@cartridge/penpal@6.2.4': {}
+
+ '@cbor-extract/cbor-extract-darwin-arm64@2.2.0':
+ optional: true
+
+ '@cbor-extract/cbor-extract-darwin-x64@2.2.0':
+ optional: true
+
+ '@cbor-extract/cbor-extract-linux-arm64@2.2.0':
+ optional: true
+
+ '@cbor-extract/cbor-extract-linux-arm@2.2.0':
+ optional: true
+
+ '@cbor-extract/cbor-extract-linux-x64@2.2.0':
+ optional: true
+
+ '@cbor-extract/cbor-extract-win32-x64@2.2.0':
+ optional: true
+
'@changesets/apply-release-plan@7.0.7':
dependencies:
'@changesets/config': 3.0.5
@@ -20514,7 +20745,7 @@ snapshots:
'@octokit/request-error': 3.0.3
'@octokit/types': 9.3.2
is-plain-object: 5.0.0
- node-fetch: 2.6.7(encoding@0.1.13)
+ node-fetch: 2.7.0(encoding@0.1.13)
universal-user-agent: 6.0.1
transitivePeerDependencies:
- encoding
@@ -21989,7 +22220,7 @@ snapshots:
'@scure/bip32@1.3.2':
dependencies:
'@noble/curves': 1.2.0
- '@noble/hashes': 1.3.2
+ '@noble/hashes': 1.3.3
'@scure/base': 1.1.9
'@scure/bip32@1.5.0':
@@ -22012,7 +22243,7 @@ snapshots:
'@scure/bip39@1.2.1':
dependencies:
- '@noble/hashes': 1.3.2
+ '@noble/hashes': 1.3.3
'@scure/base': 1.1.9
'@scure/bip39@1.4.0':
@@ -22028,7 +22259,7 @@ snapshots:
'@scure/starknet@1.1.0':
dependencies:
'@noble/curves': 1.7.0
- '@noble/hashes': 1.6.0
+ '@noble/hashes': 1.6.1
'@shikijs/core@1.27.0':
dependencies:
@@ -22111,7 +22342,23 @@ snapshots:
'@starknet-react/chains@3.1.0': {}
- '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.3)':
+ '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.2)':
+ dependencies:
+ '@starknet-io/types-js': 0.7.10
+ '@starknet-react/chains': 3.1.0
+ '@tanstack/react-query': 5.69.0(react@18.3.1)
+ eventemitter3: 5.0.1
+ get-starknet-core: 4.0.0
+ react: 18.3.1
+ starknet: 6.23.1(encoding@0.1.13)
+ viem: 2.23.15(typescript@5.7.2)(zod@3.24.2)
+ zod: 3.24.2
+ transitivePeerDependencies:
+ - bufferutil
+ - typescript
+ - utf-8-validate
+
+ '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)':
dependencies:
'@starknet-io/types-js': 0.7.10
'@starknet-react/chains': 3.1.0
@@ -22119,7 +22366,7 @@ snapshots:
eventemitter3: 5.0.1
get-starknet-core: 4.0.0
react: 18.3.1
- starknet: 6.21.0(encoding@0.1.13)
+ starknet: 6.23.1(encoding@0.1.13)
viem: 2.23.15(typescript@5.7.3)(zod@3.24.2)
zod: 3.24.2
transitivePeerDependencies:
@@ -22127,7 +22374,7 @@ snapshots:
- typescript
- utf-8-validate
- '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0(encoding@0.1.13))(typescript@5.8.2)':
+ '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.23.1(encoding@0.1.13))(typescript@5.8.2)':
dependencies:
'@starknet-io/types-js': 0.7.10
'@starknet-react/chains': 3.1.0
@@ -22135,7 +22382,7 @@ snapshots:
eventemitter3: 5.0.1
get-starknet-core: 4.0.0
react: 18.3.1
- starknet: 6.21.0(encoding@0.1.13)
+ starknet: 6.23.1(encoding@0.1.13)
viem: 2.23.15(typescript@5.8.2)(zod@3.24.2)
zod: 3.24.2
transitivePeerDependencies:
@@ -22143,15 +22390,16 @@ snapshots:
- typescript
- utf-8-validate
- '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(starknet@6.21.0(encoding@0.1.13))(typescript@5.7.2)':
+ '@starknet-react/core@3.6.2(get-starknet-core@4.0.0)(react@19.0.0)(starknet@6.23.1(encoding@0.1.13))(typescript@5.7.3)':
dependencies:
'@starknet-io/types-js': 0.7.10
'@starknet-react/chains': 3.1.0
- '@tanstack/react-query': 5.69.0(react@18.3.1)
+ '@tanstack/react-query': 5.69.0(react@19.0.0)
eventemitter3: 5.0.1
get-starknet-core: 4.0.0
- starknet: 6.21.0(encoding@0.1.13)
- viem: 2.23.15(typescript@5.7.2)(zod@3.24.2)
+ react: 19.0.0
+ starknet: 6.23.1(encoding@0.1.13)
+ viem: 2.23.15(typescript@5.7.3)(zod@3.24.2)
zod: 3.24.2
transitivePeerDependencies:
- bufferutil
@@ -23042,6 +23290,14 @@ snapshots:
tailwindcss: 4.0.1
vite: 6.0.11(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+ '@tailwindcss/vite@4.0.1(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0))':
+ dependencies:
+ '@tailwindcss/node': 4.0.1
+ '@tailwindcss/oxide': 4.0.1
+ lightningcss: 1.29.1
+ tailwindcss: 4.0.1
+ vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+
'@tanstack/eslint-plugin-query@5.62.16(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)':
dependencies:
'@typescript-eslint/utils': 8.20.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)
@@ -23063,16 +23319,21 @@ snapshots:
'@tanstack/query-core': 5.64.1
react: 18.3.1
- '@tanstack/react-query@5.66.9(react@19.0.0)':
+ '@tanstack/react-query@5.66.9(react@18.3.1)':
dependencies:
'@tanstack/query-core': 5.66.4
- react: 19.0.0
+ react: 18.3.1
'@tanstack/react-query@5.69.0(react@18.3.1)':
dependencies:
'@tanstack/query-core': 5.69.0
react: 18.3.1
+ '@tanstack/react-query@5.69.0(react@19.0.0)':
+ dependencies:
+ '@tanstack/query-core': 5.69.0
+ react: 19.0.0
+
'@tanstack/react-router@1.97.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/history': 1.97.0
@@ -23142,6 +23403,38 @@ snapshots:
'@tanstack/virtual-file-routes@1.97.0': {}
+ '@telegram-apps/bridge@1.9.2':
+ dependencies:
+ '@telegram-apps/signals': 1.1.1
+ '@telegram-apps/toolkit': 1.1.1
+ '@telegram-apps/transformers': 1.2.2
+ '@telegram-apps/types': 1.2.1
+
+ '@telegram-apps/navigation@1.0.13':
+ dependencies:
+ '@telegram-apps/bridge': 1.9.2
+ '@telegram-apps/signals': 1.1.1
+ '@telegram-apps/toolkit': 1.1.1
+
+ '@telegram-apps/sdk@2.11.3':
+ dependencies:
+ '@telegram-apps/bridge': 1.9.2
+ '@telegram-apps/navigation': 1.0.13
+ '@telegram-apps/signals': 1.1.1
+ '@telegram-apps/toolkit': 1.1.1
+ '@telegram-apps/transformers': 1.2.2
+
+ '@telegram-apps/signals@1.1.1': {}
+
+ '@telegram-apps/toolkit@1.1.1': {}
+
+ '@telegram-apps/transformers@1.2.2':
+ dependencies:
+ '@telegram-apps/toolkit': 1.1.1
+ '@telegram-apps/types': 1.2.1
+
+ '@telegram-apps/types@1.2.1': {}
+
'@testing-library/dom@10.4.0':
dependencies:
'@babel/code-frame': 7.26.2
@@ -23174,17 +23467,21 @@ snapshots:
lodash: 4.17.21
redent: 3.0.0
- '@testing-library/react-hooks@8.0.1(@types/react@18.3.18)':
+ '@testing-library/react-hooks@8.0.1(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
- react-error-boundary: 3.1.4
+ react: 18.3.1
+ react-error-boundary: 3.1.4(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.18
+ react-dom: 18.3.1(react@18.3.1)
- '@testing-library/react@16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)':
+ '@testing-library/react@16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@babel/runtime': 7.26.0
'@testing-library/dom': 10.4.0
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
optionalDependencies:
'@types/react': 18.3.18
'@types/react-dom': 18.3.5(@types/react@18.3.18)
@@ -23420,7 +23717,7 @@ snapshots:
dependencies:
'@types/react': 18.3.18
- '@types/react-dom@18.3.5(@types/react@19.0.10)':
+ '@types/react-dom@19.0.4(@types/react@19.0.10)':
dependencies:
'@types/react': 19.0.10
@@ -24169,6 +24466,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@vitejs/plugin-react@4.3.4(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0))':
+ dependencies:
+ '@babel/core': 7.26.10
+ '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.10)
+ '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.10)
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.14.2
+ vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+ transitivePeerDependencies:
+ - supports-color
+
'@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0))(vue@3.5.13(typescript@5.7.2))':
dependencies:
vite: 5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0)
@@ -24993,6 +25301,8 @@ snapshots:
base64-js@1.5.1: {}
+ base64url@3.0.1: {}
+
bech32@1.1.4: {}
before-after-hook@2.2.3: {}
@@ -25223,6 +25533,22 @@ snapshots:
ansicolors: 0.3.2
redeyed: 2.1.1
+ cbor-extract@2.2.0:
+ dependencies:
+ node-gyp-build-optional-packages: 5.1.1
+ optionalDependencies:
+ '@cbor-extract/cbor-extract-darwin-arm64': 2.2.0
+ '@cbor-extract/cbor-extract-darwin-x64': 2.2.0
+ '@cbor-extract/cbor-extract-linux-arm': 2.2.0
+ '@cbor-extract/cbor-extract-linux-arm64': 2.2.0
+ '@cbor-extract/cbor-extract-linux-x64': 2.2.0
+ '@cbor-extract/cbor-extract-win32-x64': 2.2.0
+ optional: true
+
+ cbor-x@1.6.0:
+ optionalDependencies:
+ cbor-extract: 2.2.0
+
ccount@2.0.1: {}
chai@4.5.0:
@@ -29286,6 +29612,11 @@ snapshots:
fetch-blob: 3.2.0
formdata-polyfill: 4.0.10
+ node-gyp-build-optional-packages@5.1.1:
+ dependencies:
+ detect-libc: 2.0.3
+ optional: true
+
node-gyp@10.3.1:
dependencies:
env-paths: 2.2.1
@@ -30253,11 +30584,10 @@ snapshots:
react: 18.3.1
scheduler: 0.23.2
- react-dom@18.3.1(react@19.0.0):
+ react-dom@19.0.0(react@19.0.0):
dependencies:
- loose-envify: 1.4.0
react: 19.0.0
- scheduler: 0.23.2
+ scheduler: 0.25.0
react-element-to-jsx-string@15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
@@ -30267,9 +30597,10 @@ snapshots:
react-dom: 18.3.1(react@18.3.1)
react-is: 18.1.0
- react-error-boundary@3.1.4:
+ react-error-boundary@3.1.4(react@18.3.1):
dependencies:
'@babel/runtime': 7.26.0
+ react: 18.3.1
react-hook-form@7.54.2(react@18.3.1):
dependencies:
@@ -30832,6 +31163,8 @@ snapshots:
dependencies:
loose-envify: 1.4.0
+ scheduler@0.25.0: {}
+
scrypt-js@3.0.1: {}
scuid@1.1.0: {}
@@ -31139,7 +31472,7 @@ snapshots:
stackback@0.0.2: {}
- starknet@6.21.0(encoding@0.1.13):
+ starknet@6.23.1(encoding@0.1.13):
dependencies:
'@noble/curves': 1.7.0
'@noble/hashes': 1.6.0
@@ -31466,6 +31799,8 @@ snapshots:
tailwindcss@4.0.1: {}
+ tailwindcss@4.0.14: {}
+
tapable@2.2.1: {}
tar-fs@2.1.1:
@@ -31851,7 +32186,7 @@ snapshots:
tunnel-rat@0.1.2(@types/react@18.3.18)(immer@10.1.1)(react@18.3.1):
dependencies:
- zustand: 4.5.5(@types/react@18.3.18)(immer@10.1.1)(react@18.3.1)
+ zustand: 4.5.6(@types/react@18.3.18)(immer@10.1.1)(react@18.3.1)
transitivePeerDependencies:
- '@types/react'
- immer
@@ -32185,10 +32520,6 @@ snapshots:
dependencies:
react: 18.3.1
- use-sync-external-store@1.4.0(react@19.0.0):
- dependencies:
- react: 19.0.0
-
util-deprecate@1.0.2: {}
util@0.10.4:
@@ -32562,6 +32893,16 @@ snapshots:
- '@swc/helpers'
- rollup
+ vite-plugin-top-level-await@1.5.0(@swc/helpers@0.5.5)(rollup@4.37.0)(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)):
+ dependencies:
+ '@rollup/plugin-virtual': 3.0.2(rollup@4.37.0)
+ '@swc/core': 1.11.13(@swc/helpers@0.5.5)
+ uuid: 10.0.0
+ vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+ transitivePeerDependencies:
+ - '@swc/helpers'
+ - rollup
+
vite-plugin-wasm@3.4.1(vite@3.2.11(@types/node@22.13.13)(terser@5.39.0)):
dependencies:
vite: 3.2.11(@types/node@22.13.13)(terser@5.39.0)
@@ -32602,6 +32943,10 @@ snapshots:
dependencies:
vite: 6.2.3(@types/node@20.17.27)(jiti@1.21.7)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+ vite-plugin-wasm@3.4.1(vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)):
+ dependencies:
+ vite: 6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)
+
vite-preset-react@2.3.0(vite@6.2.3(@types/node@20.17.27)(jiti@1.21.7)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0)):
dependencies:
'@vitejs/plugin-react': 1.3.2
@@ -32770,6 +33115,20 @@ snapshots:
tsx: 4.19.2
yaml: 2.7.0
+ vite@6.2.3(@types/node@22.13.13)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(tsx@4.19.2)(yaml@2.7.0):
+ dependencies:
+ esbuild: 0.25.1
+ postcss: 8.5.3
+ rollup: 4.37.0
+ optionalDependencies:
+ '@types/node': 22.13.13
+ fsevents: 2.3.3
+ jiti: 2.4.2
+ lightningcss: 1.29.1
+ terser: 5.39.0
+ tsx: 4.19.2
+ yaml: 2.7.0
+
vitefu@0.2.5(vite@5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0)):
optionalDependencies:
vite: 5.4.11(@types/node@22.13.13)(lightningcss@1.29.1)(terser@5.39.0)
@@ -32970,8 +33329,8 @@ snapshots:
webauthn-p256@0.0.10:
dependencies:
- '@noble/curves': 1.6.0
- '@noble/hashes': 1.5.0
+ '@noble/curves': 1.8.1
+ '@noble/hashes': 1.7.1
webgl-constants@1.1.1: {}
@@ -33366,14 +33725,6 @@ snapshots:
immer: 10.1.1
react: 18.3.1
- zustand@4.5.6(@types/react@19.0.10)(immer@10.1.1)(react@19.0.0):
- dependencies:
- use-sync-external-store: 1.4.0(react@19.0.0)
- optionalDependencies:
- '@types/react': 19.0.10
- immer: 10.1.1
- react: 19.0.0
-
zustand@5.0.3(@types/react@18.3.18)(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1)):
optionalDependencies:
'@types/react': 18.3.18