diff --git a/examples/get-starknet/package.json b/examples/get-starknet/package.json index 069031c28..dcdd141e1 100644 --- a/examples/get-starknet/package.json +++ b/examples/get-starknet/package.json @@ -10,7 +10,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-scripts": "5.0.1", - "starknet": "^6.6.0" + "starknet": "^6.21.0" }, "devDependencies": { "@cartridge/tsconfig": "workspace:*" diff --git a/examples/next/next.config.js b/examples/next/next.config.js index c1e022054..ce18e3f5e 100644 --- a/examples/next/next.config.js +++ b/examples/next/next.config.js @@ -6,17 +6,45 @@ const nextConfig = { externalDir: true, }, webpack: (config, { isServer, dev }) => { - // Use the client static directory in the server bundle and prod mode - // Fixes `Error occurred prerendering page "/"` - config.output.webassemblyModuleFilename = - isServer && !dev - ? "../static/wasm/[modulehash].wasm" - : "static/wasm/[modulehash].wasm"; + config.output.environment = { + ...config.output.environment, + asyncFunction: true, + }; // Since Webpack 5 doesn't enable WebAssembly by default, we should do it manually - config.experiments = { ...config.experiments, asyncWebAssembly: true }; + config.experiments = { + ...config.experiments, + asyncWebAssembly: true, + topLevelAwait: true, + }; + + // https://github.com/vercel/next.js/issues/29362#issuecomment-971377869 + if (!dev && isServer) { + config.output.webassemblyModuleFilename = "chunks/[id].wasm"; + config.plugins.push(new WasmChunksFixPlugin()); + } + return config; }, }; +class WasmChunksFixPlugin { + apply(compiler) { + compiler.hooks.thisCompilation.tap("WasmChunksFixPlugin", (compilation) => { + compilation.hooks.processAssets.tap( + { name: "WasmChunksFixPlugin" }, + (assets) => + Object.entries(assets).forEach(([pathname, source]) => { + if (!pathname.match(/\.wasm$/)) return; + compilation.deleteAsset(pathname); + + const name = pathname.split("/")[1]; + const info = compilation.assetsInfo.get(pathname); + compilation.emitAsset(name, source, info); + }), + ); + }); + } +} + module.exports = nextConfig; diff --git a/examples/next/package.json b/examples/next/package.json index 22323d055..86e99e08a 100644 --- a/examples/next/package.json +++ b/examples/next/package.json @@ -16,27 +16,27 @@ "@cartridge/connector": "workspace:*", "@cartridge/controller": "workspace:*", "@cartridge/ui-next": "workspace:*", - "@starknet-react/chains": "^0.1.3", - "@starknet-react/core": "^3.0.2", - "next": "^14.2.5", + "@starknet-react/chains": "^3.1", + "@starknet-react/core": "^3.7", + "next": "^14.0.0", "next-themes": "^0.3.0", "prettier": "^2.7.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "starknet": "^6.11.0" + "starknet": "^6.21.0" }, "devDependencies": { "@cartridge/tsconfig": "workspace:*", "@playwright/test": "^1.46.0", "@types/node": "^20.6.0", - "@types/react": "^18.3.12", + "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "autoprefixer": "^10.4.18", "eslint": "^8.23.0", - "eslint-config-next": "^12.2.5", + "eslint-config-next": "^14.2.15", "postcss": "^8.4.35", "postcss-import": "^16.1.0", "tailwindcss": "^3.4.3", "typescript": "^5.4.5" } -} +} \ No newline at end of file diff --git a/examples/next/src/app/layout.tsx b/examples/next/src/app/layout.tsx index 7a7e47858..3087993e5 100644 --- a/examples/next/src/app/layout.tsx +++ b/examples/next/src/app/layout.tsx @@ -1,22 +1,20 @@ -import { Providers } from "components/providers"; +import { ReactNode } from "react"; import { Metadata } from "next"; -import { PropsWithChildren } from "react"; import "./globals.css"; +import { Providers } from "components/providers"; + +export const metadata: Metadata = { + title: "Cartridge Controller", + description: "Cartridge Controller Example", +}; -export default function RootLayout({ children }: PropsWithChildren) { +export default function RootLayout({ children }: { children: ReactNode }) { return ( - + {children} ); } - -export const metadata: Metadata = { - title: "Cartridge Controller - Example (Next.js)", - icons: { - icon: "favicon.ico", - }, -}; diff --git a/examples/next/src/app/not-found.tsx b/examples/next/src/app/not-found.tsx new file mode 100644 index 000000000..03a723868 --- /dev/null +++ b/examples/next/src/app/not-found.tsx @@ -0,0 +1,11 @@ +import { FC } from "react"; + +const NotFound: FC = () => { + return ( +
+

404 - Page Not Found

+
+ ); +}; + +export default NotFound; diff --git a/examples/next/src/app/page.tsx b/examples/next/src/app/page.tsx index adb934ec9..9e2a00b05 100644 --- a/examples/next/src/app/page.tsx +++ b/examples/next/src/app/page.tsx @@ -1,16 +1,20 @@ -import { Transfer } from "components/Transfer"; -import { ManualTransferEth } from "components/ManualTransferEth"; -import { InvalidTxn } from "components/InvalidTxn"; -import { SignMessage } from "components/SignMessage"; -import { DelegateAccount } from "components/DelegateAccount"; +"use client"; + +import { FC } from "react"; + import { ColorModeToggle } from "components/ColorModeToggle"; -import { Profile } from "components/Profile"; -import { LookupControllers } from "components/LookupControllers"; import Header from "components/Header"; +import { DelegateAccount } from "components/DelegateAccount"; +import { InvalidTxn } from "components/InvalidTxn"; +import { LookupControllers } from "components/LookupControllers"; +import { ManualTransferEth } from "components/ManualTransferEth"; +import { Profile } from "components/Profile"; +import { SignMessage } from "components/SignMessage"; +import { Transfer } from "components/Transfer"; -export default function Home() { +const Home: FC = () => { return ( -
+

Controller Example (Next.js) @@ -25,6 +29,8 @@ export default function Home() { -

+
); -} +}; + +export default Home; diff --git a/examples/next/src/app/token/page.tsx b/examples/next/src/app/token/page.tsx deleted file mode 100644 index 6a44ba98a..000000000 --- a/examples/next/src/app/token/page.tsx +++ /dev/null @@ -1,140 +0,0 @@ -"use client"; - -import { - useAccount, - useReadContract, - useSendTransaction, -} from "@starknet-react/core"; -import { useCallback, useMemo, useState } from "react"; -import { cairo, Call, CallData, uint256 } from "starknet"; -import { ConnectWallet } from "components/ConnectWallet"; -import { useTokenContract } from "hooks/token"; -import { Abi } from "starknet"; -import Erc20Abi from "abi/erc20.json"; -import { Button, Input } from "@cartridge/ui-next"; - -function UserBalance() { - const { account } = useAccount(); - - const { data, isLoading, error } = useReadContract({ - abi: Erc20Abi as Abi, - address: - "0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10", - functionName: "balanceOf", - args: account ? [account] : undefined, - }); - - const content = useMemo(() => { - if (isLoading || !(data as [])?.length) { - return
Loading balance
; - } - - if (error) { - console.error(error); - return
Error!
; - } - - const balance = uint256.uint256ToBN(cairo.uint256(data[0])); - return
{balance.toString(10)}
; - }, [data, isLoading, error]); - - return ( -
-

User balance

- {content} -
- ); -} - -function MintToken() { - const { account, address } = useAccount(); - const [amount, setAmount] = useState(""); - const [amountError, setAmountError] = useState(); - - const { contract } = useTokenContract(); - - const calls: Call[] = useMemo(() => { - if (!address || !contract) return []; - - const amountBn = cairo.uint256(amount); - return [ - { - contractAddress: contract.address, - entrypoint: "mint", - calldata: CallData.compile([address, amountBn]), - }, - ]; - }, [address, contract, amount]); - - const { sendAsync, isPending, error, reset } = useSendTransaction({ - calls: calls, - }); - - const updateAmount = useCallback( - (newAmount: string) => { - // soft-validate amount - setAmount(newAmount); - try { - BigInt(newAmount); - setAmountError(undefined); - } catch (err) { - console.error(err); - setAmountError("Please input a valid number"); - } - }, - [setAmount], - ); - - const onMint = useCallback(() => { - reset(); - if (account && !amountError) { - sendAsync(); - } - }, [account, amountError, reset, sendAsync]); - - const mintButtonDisabled = useMemo(() => { - if (isPending) return true; - return !account || !!amountError; - }, [isPending, account, amountError]); - - return ( -
-

Mint token

-

- Amount: - updateAmount(evt.target.value)} - /> -

- - {error && ( -

- <>Error: {error} -

- )} -
- ); -} - -export default function TokenPage() { - const { address } = useAccount(); - - if (!address) { - return ( -
-

Connect Wallet

- -
- ); - } - return ( -
-

Connected: {address}

- - -
- ); -} diff --git a/examples/next/src/components/ConnectWallet.tsx b/examples/next/src/components/ConnectWallet.tsx deleted file mode 100644 index b81c2ab8e..000000000 --- a/examples/next/src/components/ConnectWallet.tsx +++ /dev/null @@ -1,121 +0,0 @@ -"use client"; - -import { useAccount, useConnect, useDisconnect } from "@starknet-react/core"; -import ControllerConnector from "@cartridge/connector/controller"; -import React, { useEffect, useState, useRef } from "react"; -import { Button } from "@cartridge/ui-next"; - -export function ConnectWallet() { - const { connect, connectors } = useConnect(); - const { disconnect } = useDisconnect(); - const { address } = useAccount(); - - const controller = connectors[0] as ControllerConnector; - const [isDragging, setIsDragging] = useState(false); - const [position, setPosition] = useState({ x: -1000, y: -1000 }); - const dragRef = useRef<{ startX: number; startY: number }>(); - - useEffect(() => { - setPosition({ - x: window.innerWidth - 220, - y: window.innerHeight - 220, - }); - }, []); - - const [username, setUsername] = useState(); - useEffect(() => { - if (!address) return; - controller.username()?.then((n) => setUsername(n)); - }, [address, controller]); - - const handleMouseDown = (e: React.MouseEvent) => { - setIsDragging(true); - dragRef.current = { - startX: e.pageX - position.x, - startY: e.pageY - position.y, - }; - }; - - const handleMouseMove = (e: React.MouseEvent) => { - if (!isDragging || !dragRef.current) return; - - setPosition({ - x: e.pageX - dragRef.current.startX, - y: e.pageY - dragRef.current.startY, - }); - }; - - const handleMouseUp = () => { - setIsDragging(false); - dragRef.current = undefined; - }; - - const registerSessionUrl = - "http://localhost:3001/session?public_key=0x2cb057c18198ae4555a144bfdace051433b9a545dc88224de58fa04e323f269&redirect_uri=http://localhost:3002&policies=%5B%7B%22target%22:%220x03661Ea5946211b312e8eC71B94550928e8Fd3D3806e43c6d60F41a6c5203645%22,%22method%22:%22attack%22,%22description%22:%22Attack%20the%20beast%22%7D,%7B%22target%22:%220x03661Ea5946211b312e8eC71B94550928e8Fd3D3806e43c6d60F41a6c5203645%22,%22method%22:%22claim%22,%22description%22:%22Claim%20your%20tokens%22%7D%5D&rpc_url=http://localhost:8001/x/starknet/sepolia"; - - const openRegisterSessionUrl = () => { - window.open(registerSessionUrl, "_blank", "noopener,noreferrer"); - }; - - return ( -
- {address && ( - <> -

Account: {address}

- {username &&

Username: {username}

} - - )} - {address ? ( - - ) : ( -
- - {/* */} - -
- )} - - {/* Draggable test overlay */} -
-
- Drag me around -
- (Clickjacking Test) -
-
-
- ); -} diff --git a/examples/next/src/components/Header.tsx b/examples/next/src/components/Header.tsx index b0f4353a9..bd3610fb2 100644 --- a/examples/next/src/components/Header.tsx +++ b/examples/next/src/components/Header.tsx @@ -9,16 +9,16 @@ import { useNetwork, useSwitchChain, } from "@starknet-react/core"; -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect, useRef, useMemo } from "react"; import { constants, num } from "starknet"; import { Chain } from "@starknet-react/chains"; +import SessionConnector from "@cartridge/connector/session"; const Header = () => { const { connect, connectors } = useConnect(); const { disconnect } = useDisconnect(); const { chain, chains } = useNetwork(); - const { address, connector, status } = useAccount(); - const controllerConnector = connector as never as ControllerConnector; + const { address, status } = useAccount(); const [networkOpen, setNetworkOpen] = useState(false); const [profileOpen, setProfileOpen] = useState(false); const { switchChain } = useSwitchChain({ @@ -28,6 +28,18 @@ const Header = () => { }); const networkRef = useRef(null); const profileRef = useRef(null); + const controllerConnector = useMemo( + () => ControllerConnector.fromConnectors(connectors), + [connectors], + ); + + const sessionConnector = useMemo(() => { + try { + return SessionConnector.fromConnectors(connectors); + } catch (error) { + return undefined; + } + }, [connectors]); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { @@ -132,13 +144,20 @@ const Header = () => { )}
) : ( - +
+ + {sessionConnector && ( + + )} +
)} ); diff --git a/examples/next/src/components/providers/StarknetProvider.tsx b/examples/next/src/components/providers/StarknetProvider.tsx index 249774b48..166897aad 100644 --- a/examples/next/src/components/providers/StarknetProvider.tsx +++ b/examples/next/src/components/providers/StarknetProvider.tsx @@ -10,6 +10,7 @@ import { PropsWithChildren } from "react"; import ControllerConnector from "@cartridge/connector/controller"; import { SessionPolicies } from "@cartridge/controller"; import { constants } from "starknet"; +import SessionConnector from "@cartridge/connector/session"; export const ETH_CONTRACT_ADDRESS = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; @@ -98,25 +99,19 @@ const provider = jsonRpcProvider({ }, }); -export function StarknetProvider({ children }: PropsWithChildren) { - return ( - - {children} - - ); -} - const controller = new ControllerConnector({ policies, chains: [ - { rpcUrl: process.env.NEXT_PUBLIC_RPC_SEPOLIA! }, - { rpcUrl: process.env.NEXT_PUBLIC_RPC_MAINNET! }, + { + rpcUrl: + process.env.NEXT_PUBLIC_RPC_SEPOLIA ?? + "https://api.cartridge.gg/x/starknet/sepolia", + }, + { + rpcUrl: + process.env.NEXT_PUBLIC_RPC_MAINNET ?? + "https://api.cartridge.gg/x/starknet/mainnet", + }, ], defaultChainId: constants.StarknetChainId.SN_SEPOLIA, url: @@ -138,10 +133,31 @@ const controller = new ControllerConnector({ // namespace: "darkshuffle_s0", tokens: { erc20: [ - // $LORDS "0x0124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49", - // $FLIP - // "0x01bfe97d729138fc7c2d93c77d6d1d8a24708d5060608017d9b384adf38f04c7", ], }, }); + +const session = new SessionConnector({ + policies, + rpc: + process.env.NEXT_PUBLIC_RPC_SEPOLIA ?? + "https://api.cartridge.gg/x/starknet/sepolia", + chainId: constants.StarknetChainId.SN_SEPOLIA, + redirectUrl: typeof window !== "undefined" ? window.location.origin : "", + keychainUrl: "http://localhost:3001", +}); + +export function StarknetProvider({ children }: PropsWithChildren) { + return ( + + {children} + + ); +} diff --git a/examples/next/src/components/providers/index.tsx b/examples/next/src/components/providers/index.tsx index 67fe12ca9..da1fbe404 100644 --- a/examples/next/src/components/providers/index.tsx +++ b/examples/next/src/components/providers/index.tsx @@ -1,6 +1,13 @@ +"use client"; + import { PropsWithChildren } from "react"; import { ThemeProvider } from "./ThemeProvider"; -import { StarknetProvider } from "./StarknetProvider"; +import dynamic from "next/dynamic"; + +const StarknetProviderClient = dynamic( + () => import("./StarknetProvider").then((mod) => mod.StarknetProvider), + { ssr: false }, +); export function Providers({ children }: PropsWithChildren) { return ( @@ -10,7 +17,7 @@ export function Providers({ children }: PropsWithChildren) { enableSystem disableTransitionOnChange > - {children} + {children} ); } diff --git a/examples/next/tsconfig.json b/examples/next/tsconfig.json index 30b7f0c24..2e7861632 100644 --- a/examples/next/tsconfig.json +++ b/examples/next/tsconfig.json @@ -2,8 +2,17 @@ "$schema": "https://json.schemastore.org/tsconfig", "extends": "@cartridge/tsconfig/react.json", "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + }, + "target": "ES2020", + "module": "ESNext", + "lib": ["ES2020", "DOM"], "baseUrl": "./src", + "allowJs": true, + "strict": true, "noEmit": true, + "types": ["node"], "plugins": [ { "name": "next" @@ -15,10 +24,8 @@ "next-env.d.ts", "**/*.ts", "**/*.tsx", - ".next/types/**/*.ts" + ".next/types/**/*.ts", + "**/*.wasm" ], - "exclude": [ - "node_modules", - "tests" - ] + "exclude": ["node_modules", "tests"] } diff --git a/examples/svelte/package.json b/examples/svelte/package.json index 60a2f2836..1b4d4f26b 100644 --- a/examples/svelte/package.json +++ b/examples/svelte/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@cartridge/controller": "workspace:*", - "starknet": "^6.11.0" + "starknet": "^6.21.0" }, "devDependencies": { "@cartridge/tsconfig": "workspace:*", diff --git a/package.json b/package.json index 9e5c727ba..4a56b4218 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "tsup": "^8.0.1", "turbo": "^2.0.12", "vercel": "^37.4.2", - "@types/react": "^18.3.12" + "@types/react": "^18.3.12", + "typescript": "^5.4.5" } } \ No newline at end of file diff --git a/packages/account_sdk/src/signers/mod.rs b/packages/account_sdk/src/signers/mod.rs index 65f2a0a14..80d044bc6 100644 --- a/packages/account_sdk/src/signers/mod.rs +++ b/packages/account_sdk/src/signers/mod.rs @@ -137,7 +137,7 @@ pub enum SignError { #[error("No allowed session methods error")] NoAllowedSessionMethods, - #[error("Session policy not allowed error{0}")] + #[error("Session policy not allowed error: {0}")] SessionPolicyNotAllowed(SessionPolicyError), #[error("Invalid message provided: {0}")] diff --git a/packages/connector/package.json b/packages/connector/package.json index e9294100c..eb2557e3e 100644 --- a/packages/connector/package.json +++ b/packages/connector/package.json @@ -34,6 +34,7 @@ "tsup": { "entry": [ "src/controller.ts", + "src/session.ts", "src/index.ts" ], "format": [ @@ -44,13 +45,14 @@ "clean": true, "dts": "resolve" }, + "peerDependencies": { + "@starknet-react/core": "^3.7" + }, "dependencies": { - "@cartridge/controller": "workspace:*", - "@starknet-react/core": "^3.0.2", - "starknet": "^6.11.0" + "@cartridge/controller": "workspace:*" }, "devDependencies": { "@cartridge/tsconfig": "workspace:*", "typescript": "^5.4.5" } -} +} \ No newline at end of file diff --git a/packages/connector/src/controller.ts b/packages/connector/src/controller.ts index 97248850d..703dbfc1a 100644 --- a/packages/connector/src/controller.ts +++ b/packages/connector/src/controller.ts @@ -1,5 +1,5 @@ import ControllerProvider, { ControllerOptions } from "@cartridge/controller"; -import { InjectedConnector } from "@starknet-react/core"; +import { Connector, InjectedConnector } from "@starknet-react/core"; export default class ControllerConnector extends InjectedConnector { public controller: ControllerProvider; @@ -28,4 +28,12 @@ export default class ControllerConnector extends InjectedConnector { async delegateAccount() { return await this.controller.delegateAccount(); } + + static fromConnectors(connectors: Connector[]): ControllerConnector { + const connector = connectors.find((c) => c.id === "controller"); + if (!connector) { + throw new Error("Controller connector not found"); + } + return connector as ControllerConnector; + } } diff --git a/packages/connector/src/index.ts b/packages/connector/src/index.ts index 06bb33d9c..841327fe0 100644 --- a/packages/connector/src/index.ts +++ b/packages/connector/src/index.ts @@ -1,3 +1 @@ export { default as ControllerConnector } from "./controller"; -// export { default as SessionConnector } from "./session"; -// export { default as TelegramConnector } from "./telegram"; diff --git a/packages/connector/src/session.ts b/packages/connector/src/session.ts index e3e7e8faf..552283498 100644 --- a/packages/connector/src/session.ts +++ b/packages/connector/src/session.ts @@ -1,7 +1,7 @@ import SessionProvider, { SessionOptions } from "@cartridge/controller/session"; -import { InjectedConnector } from "@starknet-react/core"; +import { Connector, InjectedConnector } from "@starknet-react/core"; -export default class ControllerConnector extends InjectedConnector { +export default class SessionConnector extends InjectedConnector { public controller: SessionProvider; constructor(options: SessionOptions) { @@ -16,4 +16,12 @@ export default class ControllerConnector extends InjectedConnector { this.controller = controller; } + + static fromConnectors(connectors: Connector[]): SessionConnector { + const connector = connectors.find((c) => c.id === "controller_session"); + if (!connector) { + throw new Error("Session connector not found"); + } + return connector as SessionConnector; + } } diff --git a/packages/connector/tsconfig.json b/packages/connector/tsconfig.json index cd3387c49..8de246138 100644 --- a/packages/connector/tsconfig.json +++ b/packages/connector/tsconfig.json @@ -6,8 +6,7 @@ "rootDir": "./src", "outDir": "./dist", "composite": false, - "incremental": false, - "moduleResolution": "node" + "incremental": false }, "include": ["src/**/*"] } diff --git a/packages/controller/package.json b/packages/controller/package.json index 3a93e1859..3b0c0f689 100644 --- a/packages/controller/package.json +++ b/packages/controller/package.json @@ -14,10 +14,22 @@ "version": "pnpm pkg get version" }, "exports": { - ".": "./dist/index.js", - "./session": "./dist/session/index.js", - "./provider": "./dist/provider/index.js", - "./types": "./dist/types/index.js" + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./session": { + "types": "./dist/session/index.d.ts", + "default": "./dist/session/index.js" + }, + "./provider": { + "types": "./dist/provider/index.d.ts", + "default": "./dist/provider/index.js" + }, + "./types": { + "types": "./dist/types/index.d.ts", + "default": "./dist/types/index.js" + } }, "tsup": { "entry": [ @@ -30,6 +42,9 @@ "sourcemap": true, "clean": true }, + "peerDependencies": { + "starknet": "^6.21.0" + }, "dependencies": { "@cartridge/account-wasm": "workspace:*", "@cartridge/penpal": "^6.2.3", @@ -38,8 +53,7 @@ "base64url": "^3.0.1", "cbor-x": "^1.5.0", "fast-deep-equal": "^3.1.3", - "query-string": "^7.1.1", - "starknet": "^6.11.0" + "query-string": "^7.1.1" }, "devDependencies": { "@cartridge/tsconfig": "workspace:*", @@ -49,4 +63,4 @@ "ts-jest": "^29.2.5", "typescript": "^5.4.5" } -} +} \ No newline at end of file diff --git a/packages/controller/src/controller.ts b/packages/controller/src/controller.ts index 6cec5638e..f5e19353e 100644 --- a/packages/controller/src/controller.ts +++ b/packages/controller/src/controller.ts @@ -347,6 +347,7 @@ export default class ControllerProvider extends BaseProvider { reject(new Error("Timeout waiting for keychain")); return; } + if (!this.keychain) return; clearInterval(id); diff --git a/packages/controller/src/mutex.ts b/packages/controller/src/mutex.ts new file mode 100644 index 000000000..558482122 --- /dev/null +++ b/packages/controller/src/mutex.ts @@ -0,0 +1,22 @@ +function releaseStub() {} + +/** + * A simple mutual exclusion lock. It allows you to obtain and release a lock, + * ensuring that only one task can access a critical section at a time. + */ +export class Mutex { + private m_lastPromise: Promise = Promise.resolve(); + + /** + * Acquire lock + * @param [bypass=false] option to skip lock acquisition + */ + public async obtain(bypass = false): Promise<() => void> { + let release = releaseStub; + if (bypass) return release; + const lastPromise = this.m_lastPromise; + this.m_lastPromise = new Promise((resolve) => (release = resolve)); + await lastPromise; + return release; + } +} diff --git a/packages/controller/src/policies.ts b/packages/controller/src/policies.ts new file mode 100644 index 000000000..c70f41116 --- /dev/null +++ b/packages/controller/src/policies.ts @@ -0,0 +1,49 @@ +import { + ContractPolicy, + Method, + SessionPolicies, + SignMessagePolicy, +} from "@cartridge/presets"; + +export type ParsedSessionPolicies = { + verified: boolean; + contracts?: SessionContracts; + messages?: SessionMessages; +}; + +export type SessionContracts = Record< + string, + Omit & { + methods: (Method & { authorized?: boolean })[]; + } +>; + +export type SessionMessages = (SignMessagePolicy & { + authorized?: boolean; +})[]; + +export function parsePolicies( + policies: SessionPolicies, +): ParsedSessionPolicies { + return { + verified: false, + contracts: policies.contracts + ? Object.fromEntries( + Object.entries(policies.contracts).map(([address, contract]) => [ + address, + { + ...contract, + methods: contract.methods.map((method) => ({ + ...method, + authorized: true, + })), + }, + ]), + ) + : undefined, + messages: policies.messages?.map((message) => ({ + ...message, + authorized: true, + })), + }; +} diff --git a/packages/controller/src/provider.ts b/packages/controller/src/provider.ts index a7d0be55f..5cb86bf71 100644 --- a/packages/controller/src/provider.ts +++ b/packages/controller/src/provider.ts @@ -16,6 +16,9 @@ import { import manifest from "../package.json"; import { icon } from "./icon"; +import { Mutex } from "./mutex"; + +const mutex = new Mutex(); export default abstract class BaseProvider implements StarknetWindowObject { public id = "controller"; @@ -26,10 +29,37 @@ export default abstract class BaseProvider implements StarknetWindowObject { public account?: WalletAccount; public subscriptions: WalletEvents[] = []; + private _probePromise: Promise | null = null; + + protected async safeProbe(): Promise { + // If we already have an account, return it + if (this.account) { + return this.account; + } + + // If we're already probing, wait for the existing probe + if (this._probePromise) { + return this._probePromise; + } + + const release = await mutex.obtain(); + return await new Promise(async (resolve) => { + try { + this._probePromise = this.probe(); + const result = await this._probePromise; + resolve(result); + } finally { + this._probePromise = null; + } + }).finally(() => { + release(); + }); + } + request: RequestFn = async (call) => { switch (call.type) { case "wallet_getPermissions": - await this.probe(); + await this.safeProbe(); if (this.account) { return [Permission.ACCOUNTS]; @@ -45,7 +75,8 @@ export default abstract class BaseProvider implements StarknetWindowObject { const silentMode = call.params && (call.params as RequestAccountsParameters).silent_mode; - this.account = await this.probe(); + this.account = await this.safeProbe(); + if (!this.account && !silentMode) { this.account = await this.connect(); } diff --git a/packages/controller/src/session/account.ts b/packages/controller/src/session/account.ts index 239f3f879..092ca60a3 100644 --- a/packages/controller/src/session/account.ts +++ b/packages/controller/src/session/account.ts @@ -33,6 +33,7 @@ export default class SessionAccount extends WalletAccount { ) { super({ nodeUrl: rpcUrl }, provider); + this.address = address; this.controller = CartridgeSessionAccount.new_as_registered( rpcUrl, privateKey, diff --git a/packages/controller/src/session/provider.ts b/packages/controller/src/session/provider.ts index 443798bc3..702f9d4e2 100644 --- a/packages/controller/src/session/provider.ts +++ b/packages/controller/src/session/provider.ts @@ -6,6 +6,7 @@ import BaseProvider from "../provider"; import { toWasmPolicies } from "../utils"; import { SessionPolicies } from "@cartridge/presets"; import { AddStarknetChainParameters } from "@starknet-io/types-js"; +import { ParsedSessionPolicies } from "../policies"; interface SessionRegistration { username: string; @@ -20,6 +21,7 @@ export type SessionOptions = { chainId: string; policies: SessionPolicies; redirectUrl: string; + keychainUrl?: string; }; export default class SessionProvider extends BaseProvider { @@ -30,39 +32,110 @@ export default class SessionProvider extends BaseProvider { protected _rpcUrl: string; protected _username?: string; protected _redirectUrl: string; - protected _policies: SessionPolicies; + protected _policies: ParsedSessionPolicies; + protected _keychainUrl: string; - constructor({ rpc, chainId, policies, redirectUrl }: SessionOptions) { + constructor({ + rpc, + chainId, + policies, + redirectUrl, + keychainUrl, + }: SessionOptions) { super(); + this._policies = { + verified: false, + contracts: policies.contracts + ? Object.fromEntries( + Object.entries(policies.contracts).map(([address, contract]) => [ + address, + { + ...contract, + methods: contract.methods.map((method) => ({ + ...method, + authorized: true, + })), + }, + ]), + ) + : undefined, + messages: policies.messages?.map((message) => ({ + ...message, + authorized: true, + })), + }; + this._rpcUrl = rpc; this._chainId = chainId; this._redirectUrl = redirectUrl; - this._policies = policies; + this._keychainUrl = keychainUrl || KEYCHAIN_URL; if (typeof window !== "undefined") { (window as any).starknet_controller_session = this; } } + private validatePoliciesSubset( + newPolicies: ParsedSessionPolicies, + existingPolicies: ParsedSessionPolicies, + ): boolean { + if (newPolicies.contracts) { + if (!existingPolicies.contracts) return false; + + for (const [address, contract] of Object.entries(newPolicies.contracts)) { + const existingContract = existingPolicies.contracts[address]; + if (!existingContract) return false; + + for (const method of contract.methods) { + const existingMethod = existingContract.methods.find( + (m) => m.entrypoint === method.entrypoint, + ); + if (!existingMethod || !existingMethod.authorized) return false; + } + } + } + + if (newPolicies.messages) { + if (!existingPolicies.messages) return false; + + for (const message of newPolicies.messages) { + const existingMessage = existingPolicies.messages.find( + (m) => + JSON.stringify(m.domain) === JSON.stringify(message.domain) && + JSON.stringify(m.types) === JSON.stringify(message.types), + ); + if (!existingMessage || !existingMessage.authorized) return false; + } + } + + return true; + } + async username() { await this.tryRetrieveFromQueryOrStorage(); return this._username; } async probe(): Promise { - await this.tryRetrieveFromQueryOrStorage(); - return; + if (this.account) { + return this.account; + } + + this.account = await this.tryRetrieveFromQueryOrStorage(); + return this.account; } async connect(): Promise { - await this.tryRetrieveFromQueryOrStorage(); + if (this.account) { + return this.account; + } + this.account = await this.tryRetrieveFromQueryOrStorage(); if (this.account) { - return; + return this.account; } - // Generate a random local key pair const pk = stark.randomAddress(); const publicKey = ec.starkCurve.getStarkKey(pk); @@ -74,7 +147,11 @@ export default class SessionProvider extends BaseProvider { }), ); - const url = `${KEYCHAIN_URL}/session?public_key=${publicKey}&redirect_uri=${ + localStorage.setItem("sessionPolicies", JSON.stringify(this._policies)); + + const url = `${ + this._keychainUrl + }/session?public_key=${publicKey}&redirect_uri=${ this._redirectUrl }&redirect_query_name=startapp&policies=${JSON.stringify( this._policies, @@ -83,7 +160,7 @@ export default class SessionProvider extends BaseProvider { localStorage.setItem("lastUsedConnector", this.id); window.open(url, "_blank"); - return; + return this.account; } switchStarknetChain(_chainId: string): Promise { @@ -97,12 +174,17 @@ export default class SessionProvider extends BaseProvider { disconnect(): Promise { localStorage.removeItem("sessionSigner"); localStorage.removeItem("session"); + localStorage.removeItem("sessionPolicies"); this.account = undefined; this._username = undefined; return Promise.resolve(); } async tryRetrieveFromQueryOrStorage() { + if (this.account) { + return this.account; + } + const signerString = localStorage.getItem("sessionSigner"); const signer = signerString ? JSON.parse(signerString) : null; let sessionRegistration: SessionRegistration | null = null; @@ -135,6 +217,47 @@ export default class SessionProvider extends BaseProvider { return; } + // Check expiration + const expirationTime = parseInt(sessionRegistration.expiresAt) * 1000; + console.log("Session expiration check:", { + expirationTime, + currentTime: Date.now(), + expired: Date.now() >= expirationTime, + }); + if (Date.now() >= expirationTime) { + console.log("Session expired, clearing stored session"); + this.clearStoredSession(); + return; + } + + // Check stored policies + const storedPoliciesStr = localStorage.getItem("sessionPolicies"); + console.log("Checking stored policies:", { + storedPoliciesStr, + currentPolicies: this._policies, + }); + if (storedPoliciesStr) { + const storedPolicies = JSON.parse( + storedPoliciesStr, + ) as ParsedSessionPolicies; + + const isValid = this.validatePoliciesSubset( + this._policies, + storedPolicies, + ); + console.log("Policy validation result:", { + isValid, + storedPolicies, + requestedPolicies: this._policies, + }); + + if (!isValid) { + console.log("Policy validation failed, clearing stored session"); + this.clearStoredSession(); + return; + } + } + this._username = sessionRegistration.username; this.account = new SessionAccount(this, { rpcUrl: this._rpcUrl, @@ -148,4 +271,10 @@ export default class SessionProvider extends BaseProvider { return this.account; } + + private clearStoredSession(): void { + localStorage.removeItem("sessionSigner"); + localStorage.removeItem("session"); + localStorage.removeItem("sessionPolicies"); + } } diff --git a/packages/controller/src/telegram/provider.ts b/packages/controller/src/telegram/provider.ts index 89d33b417..5d751a168 100644 --- a/packages/controller/src/telegram/provider.ts +++ b/packages/controller/src/telegram/provider.ts @@ -12,6 +12,7 @@ import BaseProvider from "../provider"; import { toWasmPolicies } from "../utils"; import { SessionPolicies } from "@cartridge/presets"; import { AddStarknetChainParameters } from "@starknet-io/types-js"; +import { ParsedSessionPolicies, parsePolicies } from "../policies"; interface SessionRegistration { username: string; @@ -25,7 +26,7 @@ export default class TelegramProvider extends BaseProvider { private _tmaUrl: string; protected _chainId: string; protected _username?: string; - protected _policies: SessionPolicies; + protected _policies: ParsedSessionPolicies; private _rpcUrl: string; constructor({ @@ -44,7 +45,7 @@ export default class TelegramProvider extends BaseProvider { this._rpcUrl = rpc; this._tmaUrl = tmaUrl; this._chainId = chainId; - this._policies = policies; + this._policies = parsePolicies(policies); if (typeof window !== "undefined") { (window as any).starknet_controller = this; diff --git a/packages/controller/src/utils.ts b/packages/controller/src/utils.ts index d50b4b19e..1ca4f9b98 100644 --- a/packages/controller/src/utils.ts +++ b/packages/controller/src/utils.ts @@ -12,6 +12,7 @@ import { import wasm from "@cartridge/account-wasm/controller"; import { Policies, SessionPolicies } from "@cartridge/presets"; import { ChainId } from "@starknet-io/types-js"; +import { ParsedSessionPolicies } from "./policies"; // Whitelist of allowed property names to prevent prototype pollution const ALLOWED_PROPERTIES = new Set([ @@ -88,13 +89,14 @@ export function toSessionPolicies(policies: Policies): SessionPolicies { : policies; } -export function toWasmPolicies(policies: SessionPolicies): wasm.Policy[] { +export function toWasmPolicies(policies: ParsedSessionPolicies): wasm.Policy[] { return [ ...Object.entries(policies.contracts ?? {}).flatMap( ([target, { methods }]) => toArray(methods).map((m) => ({ target, method: m.entrypoint, + authorized: m.authorized, })), ), ...(policies.messages ?? []).map((p) => { @@ -112,6 +114,7 @@ export function toWasmPolicies(policies: SessionPolicies): wasm.Policy[] { return { scope_hash: hash.computePoseidonHash(domainHash, typeHash), + authorized: p.authorized, }; }), ]; diff --git a/packages/controller/tsconfig.json b/packages/controller/tsconfig.json index 3a795d5a3..38471eb8a 100644 --- a/packages/controller/tsconfig.json +++ b/packages/controller/tsconfig.json @@ -5,8 +5,7 @@ "rootDir": ".", "outDir": "./dist", "composite": false, - "incremental": false, - "moduleResolution": "node" + "incremental": false }, "include": ["src/**/*", "package.json"] } diff --git a/packages/keychain/package.json b/packages/keychain/package.json index 373c537fe..7b1fe212c 100644 --- a/packages/keychain/package.json +++ b/packages/keychain/package.json @@ -94,8 +94,8 @@ "vitest": "^2.1.8" }, "peerDependencies": { - "@starknet-react/chains": "^3.0.0", - "@starknet-react/core": "^3.0.2", - "starknet": "^6.11.0" + "@starknet-react/chains": "^3.1", + "@starknet-react/core": "3.7", + "starknet": "^6.21.0" } } diff --git a/packages/keychain/src/components/connect/CreateSession.tsx b/packages/keychain/src/components/connect/CreateSession.tsx index c8af9c6ce..a4ec3175c 100644 --- a/packages/keychain/src/components/connect/CreateSession.tsx +++ b/packages/keychain/src/components/connect/CreateSession.tsx @@ -57,6 +57,7 @@ export function CreateSession({ try { setError(undefined); setIsConnecting(true); + // Set all contract policies to authorized if (policies.contracts) { Object.keys(policies.contracts).forEach((address) => { diff --git a/packages/keychain/src/components/connect/RegisterSession.tsx b/packages/keychain/src/components/connect/RegisterSession.tsx index 34943441b..ccb57026e 100644 --- a/packages/keychain/src/components/connect/RegisterSession.tsx +++ b/packages/keychain/src/components/connect/RegisterSession.tsx @@ -56,6 +56,24 @@ export function RegisterSession({ return; } + // Set all contract policies to authorized + if (policies.contracts) { + Object.keys(policies.contracts).forEach((address) => { + if (policies.contracts![address]) { + policies.contracts![address].methods.forEach((method) => { + method.authorized = true; + }); + } + }); + } + + // Set all message policies to authorized + if (policies.messages) { + policies.messages.forEach((message) => { + message.authorized = true; + }); + } + const { transaction_hash } = await controller.registerSession( expiresAt, policies, diff --git a/packages/keychain/src/components/session/MessageCard.tsx b/packages/keychain/src/components/session/MessageCard.tsx index 253f89fba..87fcb491b 100644 --- a/packages/keychain/src/components/session/MessageCard.tsx +++ b/packages/keychain/src/components/session/MessageCard.tsx @@ -46,7 +46,7 @@ export function MessageContent({ <> {messages.map((m, i) => (
{m.name ?? `Message ${i + 1}`}
@@ -69,9 +69,9 @@ export function MessageContent({ {Object.entries(m.types).map(([name, types]) => ( - {types.map((t) => ( + {types.map((t, typeIndex) => ( = 16'} - '@noble/hashes@1.3.3': - resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} - engines: {node: '>= 16'} - '@noble/hashes@1.4.0': resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} @@ -2540,6 +2533,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + '@peculiar/asn1-schema@2.3.15': resolution: {integrity: sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==} @@ -3302,9 +3299,6 @@ packages: '@scure/bip39@1.5.0': resolution: {integrity: sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==} - '@scure/starknet@1.0.0': - resolution: {integrity: sha512-o5J57zY0f+2IL/mq8+AYJJ4Xpc1fOtDhr+mFQKbHnYFmm3WQrC+8zj2HEgxak1a+x86mhmBC1Kq305KUpVf0wg==} - '@scure/starknet@1.1.0': resolution: {integrity: sha512-83g3M6Ix2qRsPN4wqLDqiRZ2GBNbjVWfboJE/9UjfG+MHr6oDSu/CWgy8hsBSJejr09DkkL+l0Ze4KVrlCIdtQ==} @@ -3389,9 +3383,6 @@ packages: '@starknet-io/types-js@0.7.7': resolution: {integrity: sha512-WLrpK7LIaIb8Ymxu6KF/6JkGW1sso988DweWu7p5QY/3y7waBIiPvzh27D9bX5KIJNRDyOoOVoHVEKYUYWZ/RQ==} - '@starknet-react/chains@0.1.7': - resolution: {integrity: sha512-UNh97I1SvuJKaAhKOmpEk8JcWuZWMlPG/ba2HcvFYL9x/47BKndJ+Da9V+iJFtkHUjreVnajT1snsaz1XMG+UQ==} - '@starknet-react/chains@3.1.2': resolution: {integrity: sha512-/Oldb4AVYdvHXzlBRxu01s0WwdOjqL2Q47BAmiv07/aBRU7mSZl6r/6l+bYKNrChSZl7WVnlpb+ojfwhRpbGcw==} @@ -3957,16 +3948,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@5.62.0': - resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/parser@7.18.0': resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -5507,6 +5488,10 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.18.0: + resolution: {integrity: sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==} + engines: {node: '>=10.13.0'} + enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} @@ -5734,8 +5719,8 @@ packages: peerDependencies: eslint: '>=6.0.0' - eslint-config-next@12.3.4: - resolution: {integrity: sha512-WuT3gvgi7Bwz00AOmKGhOeqnyA5P29Cdyr0iVjLyfDbk+FANQKcOjFUTZIdyYfe5Tq1x4TGcmoe4CwctGvFjHQ==} + eslint-config-next@14.2.23: + resolution: {integrity: sha512-qtWJzOsDZxnLtXLNtnVjbutHmnEp6QTTSZBTlTCge/Wy0AsUaq8nwR91dBcZZvFg3eY3zKFPBhUkLMHu3Qpauw==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -5752,12 +5737,18 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-import-resolver-typescript@2.7.1: - resolution: {integrity: sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==} - engines: {node: '>=4'} + eslint-import-resolver-typescript@3.7.0: + resolution: {integrity: sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==} + engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '*' eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true eslint-module-utils@2.12.0: resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} @@ -6050,9 +6041,6 @@ packages: fetch-cookie@3.0.1: resolution: {integrity: sha512-ZGXe8Y5Z/1FWqQ9q/CrJhkUD73DyBU9VF0hBQmEO/wPHe4A9PKTjplFDLeFX8aOsYypZUcX5Ji/eByn3VCVO3Q==} - fetch-cookie@3.1.0: - resolution: {integrity: sha512-s/XhhreJpqH0ftkGVcQt8JE9bqk+zRn4jF5mPJXWZeQMCI5odV9K+wEWYbnzFPHgQZlvPSMjS4n4yawWE8RINw==} - fflate@0.4.8: resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} @@ -6288,14 +6276,15 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - glob@7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} - deprecated: Glob versions prior to v9 are no longer supported - glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -6633,6 +6622,9 @@ packages: resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} engines: {node: '>= 0.4'} + is-bun-module@1.3.0: + resolution: {integrity: sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -6866,6 +6858,10 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -8748,6 +8744,9 @@ packages: ssim.js@3.5.0: resolution: {integrity: sha512-Aj6Jl2z6oDmgYFFbQqK7fght19bXdOxY7Tj03nF+03M9gCBAjeIiO8/PlEGMfKDwYpw4q6iBqVq2YuREorGg/g==} + stable-hash@0.0.4: + resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -8755,9 +8754,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - starknet@6.11.0: - resolution: {integrity: sha512-u50KrGDi9fbu1Ogu7ynwF/tSeFlp3mzOg1/Y5x50tYFICImo3OfY4lOz9OtYDk404HK4eUujKkhov9tG7GAKlg==} - starknet@6.21.0: resolution: {integrity: sha512-xUSlqyE+J/S5un3TyQY0Kehilh1u7ewPaut87eOxTDS1r90SU0QvQ3JEECp5LbW/sqsaMhfb+tGTBGrKzXg7bg==} @@ -8990,6 +8986,10 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + tar@4.4.18: resolution: {integrity: sha512-ZuOtqqmkV9RE1+4odd+MhBpibmCxNP6PJhH/h2OqNuotTX7/XHPZQJv2pKvWMplFH9SIZZhitehh6vBH6LO8Pg==} engines: {node: '>=4.5'} @@ -12075,9 +12075,9 @@ snapshots: '@next/env@14.2.23': {} - '@next/eslint-plugin-next@12.3.4': + '@next/eslint-plugin-next@14.2.23': dependencies: - glob: 7.1.7 + glob: 10.3.10 '@next/swc-darwin-arm64@14.2.23': optional: true @@ -12110,10 +12110,6 @@ snapshots: dependencies: '@noble/hashes': 1.3.2 - '@noble/curves@1.3.0': - dependencies: - '@noble/hashes': 1.3.3 - '@noble/curves@1.4.2': dependencies: '@noble/hashes': 1.4.0 @@ -12124,8 +12120,6 @@ snapshots: '@noble/hashes@1.3.2': {} - '@noble/hashes@1.3.3': {} - '@noble/hashes@1.4.0': {} '@noble/hashes@1.6.0': {} @@ -12146,6 +12140,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.18.0 + '@nolyfill/is-core-module@1.0.39': {} + '@peculiar/asn1-schema@2.3.15': dependencies: asn1js: 3.0.5 @@ -12928,11 +12924,6 @@ snapshots: '@noble/hashes': 1.6.1 '@scure/base': 1.2.1 - '@scure/starknet@1.0.0': - dependencies: - '@noble/curves': 1.3.0 - '@noble/hashes': 1.3.3 - '@scure/starknet@1.1.0': dependencies: '@noble/curves': 1.7.0 @@ -13042,11 +13033,9 @@ snapshots: '@starknet-io/types-js@0.7.7': {} - '@starknet-react/chains@0.1.7': {} - '@starknet-react/chains@3.1.2': {} - '@starknet-react/core@3.7.1(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.11.0)(typescript@5.7.3)': + '@starknet-react/core@3.7.1(get-starknet-core@4.0.0)(react@18.3.1)(starknet@6.21.0)(typescript@5.7.3)': dependencies: '@starknet-io/types-js': 0.7.10 '@starknet-react/chains': 3.1.2 @@ -13055,7 +13044,7 @@ snapshots: eventemitter3: 5.0.1 get-starknet-core: 4.0.0 react: 18.3.1 - starknet: 6.11.0 + starknet: 6.21.0 viem: 2.22.9(typescript@5.7.3)(zod@3.24.1) zod: 3.24.1 transitivePeerDependencies: @@ -13957,6 +13946,24 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.3(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -13992,11 +13999,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.3)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3)': dependencies: - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.7.3) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 7.18.0 debug: 4.4.0 eslint: 8.57.1 optionalDependencies: @@ -14044,6 +14052,18 @@ snapshots: '@typescript-eslint/types': 8.20.0 '@typescript-eslint/visitor-keys': 8.20.0 + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.3) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.7.3) + debug: 4.4.0 + eslint: 8.57.1 + ts-api-utils: 1.4.3(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/type-utils@7.18.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.3) @@ -14131,6 +14151,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.3) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@7.18.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.18.0(jiti@1.21.7)) @@ -15547,7 +15578,7 @@ snapshots: camel-case@4.1.2: dependencies: pascal-case: 3.1.2 - tslib: 2.4.1 + tslib: 2.8.1 camelcase-css@2.0.1: {} @@ -15560,7 +15591,7 @@ snapshots: capital-case@1.0.4: dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 upper-case-first: 2.0.2 cardinal@2.1.1: @@ -15820,7 +15851,7 @@ snapshots: constant-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 upper-case: 2.0.2 constants-browserify@1.0.0: {} @@ -16158,7 +16189,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 dotenv@16.4.7: {} @@ -16234,6 +16265,11 @@ snapshots: dependencies: once: 1.4.0 + enhanced-resolve@5.18.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 @@ -16549,15 +16585,16 @@ snapshots: eslint: 9.18.0(jiti@1.21.7) semver: 7.6.3 - eslint-config-next@12.3.4(eslint@8.57.1)(typescript@5.7.3): + eslint-config-next@14.2.23(eslint@8.57.1)(typescript@5.7.3): dependencies: - '@next/eslint-plugin-next': 12.3.4 + '@next/eslint-plugin-next': 14.2.23 '@rushstack/eslint-patch': 1.10.5 - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.4(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -16565,6 +16602,7 @@ snapshots: typescript: 5.7.3 transitivePeerDependencies: - eslint-import-resolver-webpack + - eslint-plugin-import-x - supports-color eslint-config-prettier@9.1.0(eslint@9.18.0(jiti@1.21.7)): @@ -16579,30 +16617,34 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1): + eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1): dependencies: + '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 + enhanced-resolve: 5.18.0 eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) - glob: 7.2.3 + fast-glob: 3.3.3 + get-tsconfig: 4.8.1 + is-bun-module: 1.3.0 is-glob: 4.0.3 - resolve: 1.22.10 - tsconfig-paths: 3.15.0 + stable-hash: 0.0.4 + optionalDependencies: + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -16613,7 +16655,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -16625,7 +16667,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -17034,11 +17076,6 @@ snapshots: set-cookie-parser: 2.7.1 tough-cookie: 4.1.4 - fetch-cookie@3.1.0: - dependencies: - set-cookie-parser: 2.7.1 - tough-cookie: 5.1.0 - fflate@0.4.8: {} figures@3.2.0: @@ -17294,6 +17331,14 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.3.10: + dependencies: + foreground-child: 3.3.0 + jackspeak: 2.3.6 + minimatch: 9.0.5 + minipass: 7.1.2 + path-scurry: 1.11.1 + glob@10.4.5: dependencies: foreground-child: 3.3.0 @@ -17303,15 +17348,6 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@7.1.7: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -17477,7 +17513,7 @@ snapshots: header-case@2.0.4: dependencies: capital-case: 1.0.4 - tslib: 2.4.1 + tslib: 2.8.1 hey-listen@1.0.8: {} @@ -17716,6 +17752,10 @@ snapshots: call-bound: 1.0.3 has-tostringtag: 1.0.2 + is-bun-module@1.3.0: + dependencies: + semver: 7.6.3 + is-callable@1.2.7: {} is-core-module@2.16.1: @@ -17973,6 +18013,12 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 + jackspeak@2.3.6: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -18845,7 +18891,7 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.4.1 + tslib: 2.8.1 node-addon-api@2.0.2: {} @@ -19154,7 +19200,7 @@ snapshots: param-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 parent-module@1.0.1: dependencies: @@ -19193,14 +19239,14 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 path-browserify@1.0.1: {} path-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 path-exists@4.0.0: {} @@ -19947,7 +19993,7 @@ snapshots: sentence-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 upper-case-first: 2.0.2 set-blocking@2.0.0: {} @@ -20058,7 +20104,7 @@ snapshots: snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 sonic-boom@2.8.0: dependencies: @@ -20125,30 +20171,14 @@ snapshots: ssim.js@3.5.0: {} + stable-hash@0.0.4: {} + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 stackback@0.0.2: {} - starknet@6.11.0: - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.7.0 - '@scure/base': 1.1.9 - '@scure/starknet': 1.0.0 - abi-wan-kanabi: 2.2.4 - fetch-cookie: 3.1.0 - get-starknet-core: 4.0.0 - isomorphic-fetch: 3.0.0 - lossless-json: 4.0.2 - pako: 2.1.0 - starknet-types-07: '@starknet-io/types-js@0.7.10' - ts-mixer: 6.0.4 - url-join: 4.0.1 - transitivePeerDependencies: - - encoding - starknet@6.21.0: dependencies: '@noble/curves': 1.7.0 @@ -20473,6 +20503,8 @@ snapshots: transitivePeerDependencies: - ts-node + tapable@2.2.1: {} + tar@4.4.18: dependencies: chownr: 1.1.4 @@ -20712,34 +20744,6 @@ snapshots: tslib@2.8.1: {} - tsup@8.3.5(@swc/core@1.10.7(@swc/helpers@0.5.5))(jiti@1.21.7)(postcss@8.5.1)(tsx@4.19.2)(typescript@4.9.5)(yaml@2.7.0): - dependencies: - bundle-require: 5.1.0(esbuild@0.24.2) - cac: 6.7.14 - chokidar: 4.0.3 - consola: 3.4.0 - debug: 4.4.0 - esbuild: 0.24.2 - joycon: 3.1.1 - picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.1)(tsx@4.19.2)(yaml@2.7.0) - resolve-from: 5.0.0 - rollup: 4.30.1 - source-map: 0.8.0-beta.0 - sucrase: 3.35.0 - tinyexec: 0.3.2 - tinyglobby: 0.2.10 - tree-kill: 1.2.2 - optionalDependencies: - '@swc/core': 1.10.7(@swc/helpers@0.5.5) - postcss: 8.5.1 - typescript: 4.9.5 - transitivePeerDependencies: - - jiti - - supports-color - - tsx - - yaml - tsup@8.3.5(@swc/core@1.10.7(@swc/helpers@0.5.5))(jiti@1.21.7)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0): dependencies: bundle-require: 5.1.0(esbuild@0.24.2)