From e291d3252ba1652987f4cf35f1e7106298a0d60d Mon Sep 17 00:00:00 2001 From: romt-safe Date: Wed, 15 Jan 2025 00:41:55 +0100 Subject: [PATCH 1/2] better react.md --- src/pages/controller/examples/react.md | 386 ++++++++++++++----------- 1 file changed, 220 insertions(+), 166 deletions(-) diff --git a/src/pages/controller/examples/react.md b/src/pages/controller/examples/react.md index 5425556..ab0aa29 100644 --- a/src/pages/controller/examples/react.md +++ b/src/pages/controller/examples/react.md @@ -7,28 +7,64 @@ description: Learn how to integrate the Cartridge Controller into your React app This guide demonstrates how to integrate the Cartridge Controller with a React application. +## Creating a New Project + +To start, create a new Next.js application. Choose one of the following commands based on your package manager: + +:::code-group + +```bash [pnpm] +pnpm create next-app@latest my-project +``` + +```bash [npm] +npx create-next-app@latest my-project +``` + +```bash [yarn] +yarn create next-app my-project +``` + +```bash [bun] +bun create next my-project +``` + +::: + +When prompted, select the following options: + +- **TypeScript**: Yes (recommended) +- **ESLint**: No +- **Tailwind CSS**: Yes +- **src/ Directory**: Yes +- **Import Alias**: Yes + +After the project is created, navigate to your project directory: + +```bash +cd my-project +``` + ## Installation +Next, install the necessary dependencies: + :::code-group ```bash [npm] -npm install @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet -npm install -D tailwindcss vite-plugin-mkcert +npm install @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet @chakra-ui/react ``` ```bash [pnpm] -pnpm add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet -pnpm add -D tailwindcss vite-plugin-mkcert +pnpm add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet @chakra-ui/react ``` ```bash [yarn] -yarn add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet -yarn add -D tailwindcss vite-plugin-mkcert +yarn add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet @chakra-ui/react ``` ```bash [bun] -bun add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet -bun add -D tailwindcss vite-plugin-mkcert +bun add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet @chakra-ui/react ``` ::: @@ -37,220 +73,238 @@ bun add -D tailwindcss vite-plugin-mkcert ### 1. Configure the Starknet Provider -First, set up the Starknet provider with the Cartridge Controller connector: - -You can customize the `ControllerConnector` by providing configuration options -during instantiation. The `ControllerConnector` accepts an options object that -allows you to configure various settings such as policies, RPC URLs, theme, and -more. +Begin by setting up the Starknet provider with the Cartridge Controller connector. This allows your React app to interact with the Starknet blockchain via the Cartridge Controller. -> ⚠️ **Important**: The `ControllerConnector` instance must be created outside of any React components. Creating it inside a component will cause the connector to be recreated on every render, which can lead to connection issues. +Make sure that the `ControllerConnector` is instantiated outside of any React components. Instantiating it inside a component can lead to issues because it will be recreated on every render. ```typescript -import { sepolia, mainnet } from "@starknet-react/chains"; +import { sepolia, mainnet, Chain } from "@starknet-react/chains"; import { - StarknetConfig, - jsonRpcProvider, - starkscan, + StarknetConfig, + jsonRpcProvider, + starkscan, } from "@starknet-react/core"; import ControllerConnector from "@cartridge/connector/controller"; import { SessionPolicies } from "@cartridge/controller"; // Define your contract addresses const ETH_TOKEN_ADDRESS = - '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7' + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; // Define session policies const policies: SessionPolicies = { - contracts: { - [ETH_TOKEN_ADDRESS]: { - methods: [ - { - name: "approve", - entrypoint: "approve", - description: "Approve spending of tokens", + contracts: { + [ETH_TOKEN_ADDRESS]: { + methods: [ + { + name: "approve", + entrypoint: "approve", + description: "Approve spending of tokens", + }, + { name: "transfer", entrypoint: "transfer" }, + ], }, - { name: "transfer", entrypoint: "transfer" }, - ], }, - }, -} +}; // Initialize the connector const connector = new ControllerConnector({ - policies, - rpc: 'https://api.cartridge.gg/x/starknet/sepolia', -}) + policies, + rpc: "https://api.cartridge.gg/x/starknet/sepolia", +}); // Configure RPC provider const provider = jsonRpcProvider({ - rpc: (chain: Chain) => { - switch (chain) { - case mainnet: - return { nodeUrl: 'https://api.cartridge.gg/x/starknet/mainnet' } - case sepolia: - default: - return { nodeUrl: 'https://api.cartridge.gg/x/starknet/sepolia' } - } - }, -}) + rpc: (chain: Chain) => { + switch (chain) { + case mainnet: + return { + nodeUrl: "https://api.cartridge.gg/x/starknet/mainnet", + }; + case sepolia: + default: + return { + nodeUrl: "https://api.cartridge.gg/x/starknet/sepolia", + }; + } + }, +}); export function StarknetProvider({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ) + return ( + + {children} + + ); } ``` ### 2. Create a Wallet Connection Component -Use the `useConnect`, `useDisconnect`, and `useAccount` hooks to manage wallet -connections: +Use the `useConnect`, `useDisconnect`, and `useAccount` hooks from `@starknet-react/core` to manage wallet connections. The following component allows users to connect their wallet and view their username once connected. ```typescript -import { useAccount, useConnect, useDisconnect } from '@starknet-react/core' -import { useEffect, useState } from 'react' -import ControllerConnector from '@cartridge/connector/controller' -import { Button } from '@cartridge/ui-next' +import { useAccount, useConnect, useDisconnect } from "@starknet-react/core"; +import { useEffect, useState } from "react"; +import ControllerConnector from "@cartridge/connector/controller"; +import { Button } from "@chakra-ui/react"; export function ConnectWallet() { - const { connect, connectors } = useConnect() - const { disconnect } = useDisconnect() - const { address } = useAccount() - const controller = connectors[0] as ControllerConnector - const [username, setUsername] = useState() - - useEffect(() => { - if (!address) return - controller.username()?.then((n) => setUsername(n)) - }, [address, controller]) - - return ( -
- {address && ( - <> -

Account: {address}

- {username &&

Username: {username}

} - - )} - {address ? ( - - ) : ( - - )} -
- ) + const { connect, connectors } = useConnect(); + const { disconnect } = useDisconnect(); + const { address } = useAccount(); + const controller = connectors[0] as ControllerConnector; + const [username, setUsername] = useState(); + + useEffect(() => { + if (!address) return; + controller.username()?.then((n) => setUsername(n)); + }, [address, controller]); + + return ( +
+ {address && ( + <> +

Account: {address}

+ {username &&

Username: {username}

} + + )} + {address ? ( + + ) : ( + + )} +
+ ); } ``` ### 3. Performing Transactions -Execute transactions using the `account` object from `useAccount` hook: +Execute transactions using the `account` object from the `useAccount` hook. Below is an example of transferring ETH through a smart contract: ```typescript -import { useAccount, useExplorer } from '@starknet-react/core' -import { useCallback, useState } from 'react' +import { useAccount, useExplorer } from "@starknet-react/core"; +import { useCallback, useState } from "react"; +import { Button } from "@chakra-ui/react"; const ETH_CONTRACT = - '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7' + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; export const TransferEth = () => { - const [submitted, setSubmitted] = useState(false) - const { account } = useAccount() - const explorer = useExplorer() - const [txnHash, setTxnHash] = useState() - - const execute = useCallback( - async (amount: string) => { - if (!account) return - setSubmitted(true) - setTxnHash(undefined) - try { - const result = await account.execute([ - { - contractAddress: ETH_CONTRACT, - entrypoint: 'approve', - calldata: [account?.address, amount, '0x0'], - }, - { - contractAddress: ETH_CONTRACT, - entrypoint: 'transfer', - calldata: [account?.address, amount, '0x0'], - }, - ]) - setTxnHash(result.transaction_hash) - } catch (e) { - console.error(e) - } finally { - setSubmitted(false) - } - }, - [account], - ) - - if (!account) return null - - return ( -
-

Transfer ETH

- - {txnHash && ( -

- Transaction hash:{' '} - - {txnHash} - -

- )} -
- ) -} + const [submitted, setSubmitted] = useState(false); + const { account } = useAccount(); + const explorer = useExplorer(); + const [txnHash, setTxnHash] = useState(); + + const execute = useCallback( + async (amount: string) => { + if (!account) return; + setSubmitted(true); + setTxnHash(undefined); + try { + const result = await account.execute([ + { + contractAddress: ETH_CONTRACT, + entrypoint: "approve", + calldata: [account?.address, amount, "0x0"], + }, + { + contractAddress: ETH_CONTRACT, + entrypoint: "transfer", + calldata: [account?.address, amount, "0x0"], + }, + ]); + setTxnHash(result.transaction_hash); + } catch (e) { + console.error(e); + } finally { + setSubmitted(false); + } + }, + [account] + ); + + if (!account) return null; + + return ( +
+

Transfer ETH

+ + {txnHash && ( +

+ Transaction hash:{" "} + + {txnHash} + +

+ )} +
+ ); +}; ``` ### 4. Add Components to Your App +Finally, integrate the components into your main application: + ```typescript -import { StarknetProvider } from './context/StarknetProvider' -import { ConnectWallet } from './components/ConnectWallet' -import { TransferEth } from './components/TransferEth' +import { StarknetProvider } from "./context/StarknetProvider"; +import { ConnectWallet } from "./components/ConnectWallet"; +import { TransferEth } from "./components/TransferEth"; function App() { - return ( - - - - - ) + return ( + + + + + + + ); } -export default App +export default App; ``` ## Important Notes -Make sure to use HTTPS in development by configuring Vite: +To enable HTTPS in development, you need to modify your `package.json` file and add the following `dev` script: + +```json +{ + "scripts": { + "dev": "next dev --experimental-https" + } +} +``` + +Additionally, make sure to configure `next.config.ts` for HTTPS: ```typescript -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' -import mkcert from 'vite-plugin-mkcert' +import type { NextConfig } from "next"; + +import mkcert from "vite-plugin-mkcert"; + +const nextConfig: NextConfig = { + plugins: [mkcert()], +}; -export default defineConfig({ - plugins: [react(), mkcert()], -}) +export default nextConfig; ``` From 61d2045f48342351f8db6057be1d7a6a124647f7 Mon Sep 17 00:00:00 2001 From: RomThpt Date: Mon, 20 Jan 2025 22:13:34 +0100 Subject: [PATCH 2/2] review: Update documentation for React integration and enhance .gitignore - Added support for Vite in the React integration guide. - Updated the button components to use standard HTML buttons instead of Chakra UI's Button. - Included instructions for enabling HTTPS in development for both Next.js and Vite. - Added new entries to .gitignore for cursor-related files. --- .gitignore | 3 ++ src/pages/controller/examples/react.md | 53 +++++++++++++++++++++----- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 4c28c06..f825215 100644 --- a/.gitignore +++ b/.gitignore @@ -187,3 +187,6 @@ lcov.info account.json keystore.json + +.cursorignore +.cursorrules \ No newline at end of file diff --git a/src/pages/controller/examples/react.md b/src/pages/controller/examples/react.md index ab0aa29..f832a96 100644 --- a/src/pages/controller/examples/react.md +++ b/src/pages/controller/examples/react.md @@ -9,8 +9,9 @@ This guide demonstrates how to integrate the Cartridge Controller with a React a ## Creating a New Project -To start, create a new Next.js application. Choose one of the following commands based on your package manager: +To start, create a new Next.js or Vite application. Choose one of the following commands based on your package manager: +### Next.js :::code-group ```bash [pnpm] @@ -31,6 +32,28 @@ bun create next my-project ::: +### Vite + +:::code-group + +```bash [pnpm] +pnpm create vite +``` + +```bash [npm] +npm create vite@latest +``` + +```bash [yarn] +yarn create vite +``` + +```bash [bun] +bun create vite +``` + +::: + When prompted, select the following options: - **TypeScript**: Yes (recommended) @@ -153,7 +176,6 @@ Use the `useConnect`, `useDisconnect`, and `useAccount` hooks from `@starknet-re import { useAccount, useConnect, useDisconnect } from "@starknet-react/core"; import { useEffect, useState } from "react"; import ControllerConnector from "@cartridge/connector/controller"; -import { Button } from "@chakra-ui/react"; export function ConnectWallet() { const { connect, connectors } = useConnect(); @@ -176,11 +198,11 @@ export function ConnectWallet() { )} {address ? ( - + ) : ( - + )} ); @@ -194,7 +216,6 @@ Execute transactions using the `account` object from the `useAccount` hook. Belo ```typescript import { useAccount, useExplorer } from "@starknet-react/core"; import { useCallback, useState } from "react"; -import { Button } from "@chakra-ui/react"; const ETH_CONTRACT = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; @@ -238,12 +259,12 @@ export const TransferEth = () => { return (

Transfer ETH

- + {txnHash && (

Transaction hash:{" "} @@ -284,7 +305,7 @@ export default App; ``` ## Important Notes - +### Next.js HTTPS Setup To enable HTTPS in development, you need to modify your `package.json` file and add the following `dev` script: ```json @@ -308,3 +329,17 @@ const nextConfig: NextConfig = { export default nextConfig; ``` + +### Vite HTTPS Setup + +To enable HTTPS in development with Vite, modify your `vite.config.ts` file: + +```typescript +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import mkcert from 'vite-plugin-mkcert' + +export default defineConfig({ + plugins: [react(), mkcert()], +}) +```