### Install @cherrydotfun/miniapp-sdk Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Install the core SDK package using npm. ```bash npm install @cherrydotfun/miniapp-sdk ``` -------------------------------- ### Install Cherry Miniapp SDK and Dependencies Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Install the core SDK and any required peer dependencies based on your app's needs, such as Solana wallet adapter or React. ```bash npm install @cherrydotfun/miniapp-sdk # For @solana/web3.js + wallet-adapter: npm install @solana/wallet-adapter-base @solana/web3.js # For @solana/kit: npm install @solana/signers # For React hooks: npm install react ``` -------------------------------- ### Install Cherry Mini-App SDK Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Install the SDK using npm. Peer dependencies depend on your chosen Solana SDK. ```bash npm install @cherrydotfun/miniapp-sdk ``` ```bash # For @solana/web3.js projects npm install @solana/wallet-adapter-base @solana/web3.js # For @solana/kit projects — no additional deps needed ``` -------------------------------- ### Install Peer Dependencies for @solana/web3.js Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Install necessary peer dependencies if using the @solana/web3.js (legacy wallet-adapter) integration. ```bash # For @solana/web3.js (legacy wallet-adapter) npm install @solana/wallet-adapter-base @solana/web3.js ``` -------------------------------- ### Install Peer Dependencies for React Hooks Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Install React if you plan to use the React hooks provided by the SDK. ```bash # For React hooks npm install react ``` -------------------------------- ### Install Peer Dependencies for @solana/kit Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Install necessary peer dependencies if using the @solana/kit (modern) integration. ```bash # For @solana/kit (modern) npm install @solana/signers ``` -------------------------------- ### Quick Start: @solana/kit Integration Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Initialize the CherryMiniApp and create a TransactionSigner for @solana/kit. Use this signer for signing transactions and messages. ```tsx import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; const cherry = new CherryMiniApp(); await cherry.init(); // TransactionSigner — use with @solana/kit transaction builders const signer = createCherrySigner(cherry); // Sign transactions const [signed] = await signer.signTransactions([{ messageBytes, signatures: {} }]); // Sign messages const [signature] = await signer.signMessages([messageBytes]); ``` -------------------------------- ### Privy Integration with Cherry Launch Token Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Example of dual-mode login for Privy, using Cherry's launch token for transparent login when embedded. Requires setup in the Privy dashboard. ```tsx import { CherryMiniAppProvider, useCherryApp, useCherryEnvironment } from '@cherrydotfun/miniapp-sdk/react'; import { usePrivy } from '@privy-io/react-auth'; function AuthGate({ children }) { const { isEmbedded } = useCherryEnvironment(); const cherry = useCherryApp(); const { loginWithCustomAccessToken, authenticated, ready } = usePrivy(); useEffect(() => { if (!ready || authenticated) return; if (isEmbedded && cherry?.launchToken) { loginWithCustomAccessToken(cherry.launchToken); // transparent login } }, [ready, authenticated, isEmbedded, cherry]); if (!authenticated && !isEmbedded) return ; return <>{children}; } ``` -------------------------------- ### Quick Start: @solana/web3.js Integration Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Integrate the Cherry MiniApp SDK with @solana/web3.js using React hooks for wallet and app context. Requires CherryWalletAdapter and @solana/wallet-adapter-react. ```tsx import { CherryMiniAppProvider, useCherryMiniApp, useCherryWallet } from '@cherrydotfun/miniapp-sdk/react'; import { CherryWalletAdapter } from '@cherrydotfun/miniapp-sdk/solana'; // Drop-in for @solana/wallet-adapter-react const wallets = [new CherryWalletAdapter()]; function MyGame() { const { user, room, launchToken, isReady } = useCherryMiniApp(); const { publicKey, signTransaction, signAllTransactions, signMessage } = useCherryWallet(); if (!isReady) return
Loading...
; return (

Welcome, {user.displayName}!

Room: {room.title} ({room.memberCount} members)

); } ``` -------------------------------- ### Cherry MiniApp Provider Setup Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Wrap your embedded application with CherryMiniAppProvider to access user and room context. Standalone mode does not require this provider. ```typescript import { CherryMiniAppProvider } from '@cherrydotfun/miniapp-sdk/react'; function Root() { const embedded = isInsideCherry(); if (embedded) { return ( ); } return ; // standalone mode } ``` -------------------------------- ### Quick Start: React + @solana/kit Integration Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Use the useCherryApp hook within a CherryMiniAppProvider to access the CherryMiniApp instance and create a signer for transaction signing. ```tsx import { CherryMiniAppProvider, useCherryApp } from '@cherrydotfun/miniapp-sdk/react'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; function MyGame() { const app = useCherryApp(); // CherryMiniApp instance const handleSign = async () => { const signer = createCherrySigner(app); const [signed] = await signer.signTransactions([{ messageBytes, signatures: {} }]); }; } ``` -------------------------------- ### Privy Integration Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Instructions and code examples for integrating Cherry MiniApp SDK with Privy for seamless authentication, utilizing Cherry's launch token as a custom auth provider. ```APIDOC ## Privy Integration This section details how to integrate your Cherry MiniApp with [Privy](https://privy.io) for authentication, enabling zero-click login for users within Cherry. ### Setup 1. **Privy Dashboard Configuration**: * Navigate to **Settings** → **Custom Auth** in your Privy dashboard. * Click **Add Provider**. * **JWKS URL**: `https://chat.cherry.fun/.well-known/jwks.json` * **Issuer**: `https://chat.cherry.fun` * **User ID field**: `sub` 2. **Code Implementation**: Use the `CherryMiniAppProvider`, `useCherryApp`, and `useCherryEnvironment` hooks from the SDK along with Privy's `usePrivy` hook to handle dual-mode login (Cherry embedded and standalone). ```tsx import { CherryMiniAppProvider, useCherryApp, useCherryEnvironment } from '@cherrydotfun/miniapp-sdk/react'; import { usePrivy } from '@privy-io/react-auth'; import React, { useEffect } from 'react'; function AuthGate({ children }) { const { isEmbedded } = useCherryEnvironment(); const cherry = useCherryApp(); const { loginWithCustomAccessToken, authenticated, ready } = usePrivy(); useEffect(() => { if (!ready || authenticated) return; if (isEmbedded && cherry?.launchToken) { loginWithCustomAccessToken(cherry.launchToken); // transparent login } }, [ready, authenticated, isEmbedded, cherry]); // Replace PrivyLoginButton with your actual login button component // if (!authenticated && !isEmbedded) return ; return <>{children}; } ``` 3. **Helper Function**: Retrieve authentication configuration programmatically using `getCherryCustomAuthConfig`. ```ts import { getCherryCustomAuthConfig } from '@cherrydotfun/miniapp-sdk'; // Assuming 'cherry' is an instance of CherryMiniApp const { token, jwksUrl, issuer } = getCherryCustomAuthConfig(cherry); ``` ### Login Methods | Environment | Login Method | User Action | |-----------------|----------------------------------|----------------------| | Inside Cherry | `loginWithCustomAccessToken(launchToken)` | None — automatic | | Standalone | Standard Privy UI (email, social, wallet) | User clicks login | Refer to the [integration skill](./skills/cherry-miniapp-integration/SKILL.md) for a comprehensive step-by-step guide. ``` -------------------------------- ### Copy Cherry Mini-App Integration Skill to Codex Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/README.md Use this command to copy the skill to the Codex skills directory. Verify the destination path matches your Codex setup. ```bash cp -r skills/cherry-miniapp-integration ~/.agents/skills/ ``` -------------------------------- ### Add Cherry Mini-App Integration Skill to CLAUDE.md Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/README.md Include this markdown snippet in your project's CLAUDE.md file to reference the Cherry Mini-App Integration skill. This guides the AI on where to find the skill's documentation. ```markdown ## Cherry Mini-App Integration When integrating Cherry Mini-App SDK, follow the skill at: `node_modules/@cherrydotfun/miniapp-sdk/skills/cherry-miniapp-integration/SKILL.md` ``` -------------------------------- ### Configure Solana Wallets with Cherry Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Conditionally include CherryWalletAdapter when inside Cherry, otherwise use standard adapters. This setup is for projects using @solana/wallet-adapter-react. ```typescript import { CherryWalletAdapter } from '@cherrydotfun/miniapp-sdk/solana'; import { isInsideCherry } from '@cherrydotfun/miniapp-sdk'; function getWallets() { if (isInsideCherry()) { return [new CherryWalletAdapter()]; } return [new PhantomWalletAdapter(), new SolflareWalletAdapter()]; } const wallets = useMemo(() => getWallets(), []); const embedded = isInsideCherry(); {embedded ? {children} : children} ``` ```typescript function AutoSelectCherry({ children }: { children: ReactNode }) { const { select, wallets } = useWallet(); useEffect(() => { const cherry = wallets.find(w => w.adapter.name === 'Cherry'); if (cherry) select(cherry.adapter.name); }, [wallets, select]); return <>{children}; } ``` -------------------------------- ### Privy and Cherry MiniApp Provider Setup Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Configures PrivyProvider and CherryMiniAppProvider for dual-mode operation. It conditionally hides the Privy wallet UI when embedded within Cherry and sets up Privy for embedded wallets. ```tsx import { PrivyProvider } from '@privy-io/react-auth'; import { CherryMiniAppProvider } from '@cherrydotfun/miniapp-sdk/react'; import { isInsideCherry } from '@cherrydotfun/miniapp-sdk'; const embedded = isInsideCherry(); function App() { return ( {embedded ? ( ) : ( )} ); } ``` -------------------------------- ### Initialize and Use CherryMiniApp Client Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Instantiate the `CherryMiniApp` client, call `init()` to handshake with the host, and then access user/room context, perform wallet operations, and use navigation APIs. Remember to call `destroy()` for cleanup. ```typescript import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; const cherry = new CherryMiniApp({ initTimeout: 10_000, // ms to wait for cherry:init handshake (default: 10000) strict: false, // use strict environment detection }); await cherry.init(); // waits for host handshake, rejects on timeout // User and room context (available after init) console.log(cherry.user.publicKey); // Solana wallet address (base58) console.log(cherry.user.displayName); // 'Alice' console.log(cherry.user.avatarUrl); // 'https://...' console.log(cherry.room.id); // room identifier console.log(cherry.room.title); // 'Solana Miners' console.log(cherry.room.memberCount); // 42 console.log(cherry.launchToken); // JWT string for backend verification // Wallet operations const msg = new TextEncoder().encode('hello cherry'); const signature = await cherry.wallet.signMessage(msg); // Uint8Array const signedTx = await cherry.wallet.signTransaction(myTransaction); // Uint8Array const signedAll = await cherry.wallet.signAllTransactions([tx1, tx2, tx3]); // Uint8Array[] const txSig = await cherry.wallet.signAndSendTransaction(myTransaction); // signature string // Navigation await cherry.navigate.userProfile('alice.sol'); // by .sol domain await cherry.navigate.userProfile('@alice'); // by @handle await cherry.navigate.userProfile('7xKXtg...'); // by wallet address await cherry.navigate.openRoom('@solminer'); // by room handle await cherry.navigate.openRoom('roomId123'); // by room ID // Lifecycle events cherry.on('suspended', () => { /* user left chat — pause game */ }); cherry.on('resumed', () => { /* user returned — resume */ }); cherry.on('walletDisconnected', () => { /* handle wallet disconnect */ }); cherry.off('suspended', handler); // remove a specific listener // Cleanup cherry.destroy(); // removes all listeners, destroys bridge ``` -------------------------------- ### useCherryMiniApp() Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Returns the user profile, room context, launch token, ready state, and any initialization error. Must be called inside . ```APIDOC ## `useCherryMiniApp()` — User, Room, and Launch Token Hook Returns the user profile, room context, launch token, ready state, and any initialization error. Must be called inside ``. ```tsx import { useCherryMiniApp } from '@cherrydotfun/miniapp-sdk/react'; function GameUI() { const { user, room, launchToken, isReady, error } = useCherryMiniApp(); if (error) return
Error: {error.message}
; if (!isReady) return
Connecting to Cherry...
; return (

Welcome, {user.displayName}!

{/* 'Alice' */} avatar

Wallet: {user.publicKey}

{/* 'A1b2C3...' */}

Room: {room.title} ({room.memberCount} members)

Token: {launchToken.slice(0, 20)}...

); } ``` ``` -------------------------------- ### Initialize Cherry Mini App SDK and Access Properties (Vanilla JS) Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Initialize the `CherryMiniApp` class for use in vanilla JavaScript applications. Access wallet address, room title, and launch token directly from the instance. ```typescript import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; const cherry = new CherryMiniApp(); await cherry.init(); cherry.user.publicKey; // wallet address cherry.room.title; // room name cherry.launchToken; // JWT for backend const sig = await cherry.wallet.signMessage(new TextEncoder().encode('hello')); const signed = await cherry.wallet.signAllTransactions([tx1, tx2, tx3]); // batch sign await cherry.navigate.userProfile('alice.sol'); cherry.on('suspended', () => console.log('App suspended')); cherry.on('resumed', () => console.log('App resumed')); ``` -------------------------------- ### Vanilla JS Initialization and Usage Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Initialize and use the Cherry MiniApp SDK with vanilla JavaScript for direct access to core functionalities like wallet interactions and navigation. ```APIDOC ## Vanilla JS (No React) ```ts import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; const cherry = new CherryMiniApp(); await cherry.init(); cherry.user.publicKey; // wallet address cherry.room.title; // room name cherry.launchToken; // JWT for backend const sig = await cherry.wallet.signMessage(new TextEncoder().encode('hello')); const signed = await cherry.wallet.signAllTransactions([tx1, tx2, tx3]); // batch sign await cherry.navigate.userProfile('alice.sol'); cherry.on('suspended', () => console.log('App suspended')); cherry.on('resumed', () => console.log('App resumed')); ``` ``` -------------------------------- ### Get Cherry Custom Auth Config Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Helper function to programmatically retrieve authentication configuration for Privy integration, including token, JWKS URL, and issuer. ```ts import { getCherryCustomAuthConfig } from '@cherrydotfun/miniapp-sdk'; const { token, jwksUrl, issuer } = getCherryCustomAuthConfig(cherry); ``` -------------------------------- ### Navigate User Profiles and Rooms with `useCherryNavigate` Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Use this hook inside `` to open Cherry host screens like user profiles or rooms. It supports navigation by wallet address, .sol domain, @handle, or room ID. ```tsx import { useCherryNavigate, useCherryEnvironment } from '@cherrydotfun/miniapp-sdk/react'; function UserCard({ address, handle }: { address: string; handle: string }) { const navigate = useCherryNavigate(); const { isEmbedded } = useCherryEnvironment(); const openProfile = async () => { if (isEmbedded) { // Opens the Cherry profile screen for this user await navigate.userProfile(address); // by wallet address // or: await navigate.userProfile('alice.sol'); // by .sol domain // or: await navigate.userProfile('@alice'); // by @handle } else { window.location.href = `/profile/${address}`; } }; const openRoom = async () => { await navigate.openRoom('@solminer'); // by handle // or: await navigate.openRoom('roomId123'); // by ID }; return (
); } ``` -------------------------------- ### CherryMiniAppProvider Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Wraps the mini-app's React tree, creates a CherryMiniApp instance, calls init(), and makes all context available via hooks. Should be conditionally rendered only when isInsideCherry() is true. ```APIDOC ## `CherryMiniAppProvider` — React Provider Wraps the mini-app's React tree, creates a `CherryMiniApp` instance, calls `init()`, and makes all context available via hooks. Should be conditionally rendered only when `isInsideCherry()` is true. ```tsx import { CherryMiniAppProvider } from '@cherrydotfun/miniapp-sdk/react'; import { isInsideCherry } from '@cherrydotfun/miniapp-sdk'; const embedded = isInsideCherry(); function Root() { if (embedded) { return ( // initTimeout and strict are forwarded to the internal CherryMiniApp instance ); } // Standalone: render app with standard wallet providers return ; } ``` ``` -------------------------------- ### Detect Cherry Environment Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Use these functions to detect if your app is running inside Cherry and get environment details. Strict mode can be enabled to prevent false positives. ```typescript import { isInsideCherry, getCherryEnvironment } from '@cherrydotfun/miniapp-sdk'; const embedded = isInsideCherry(); const { platform } = getCherryEnvironment(); // platform: 'webview' (mobile) | 'iframe' (web) | 'standalone' ``` ```typescript import { useCherryEnvironment } from '@cherrydotfun/miniapp-sdk/react'; function App() { const { isEmbedded, platform } = useCherryEnvironment(); } ``` ```typescript // All detection APIs accept { strict: true } isInsideCherry({ strict: true }); const { isEmbedded } = useCherryEnvironment({ strict: true }); ...; new CherryMiniApp({ strict: true }); ``` -------------------------------- ### Navigation Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Use the `useCherryNavigate` hook to open user profiles or rooms from your mini-app. ```APIDOC ## Navigation Open Cherry screens from your mini-app: ```tsx import { useCherryNavigate } from '@cherrydotfun/miniapp-sdk/react'; function MyComponent() { const navigate = useCherryNavigate(); // Open user profile — accepts wallet address, domain, or @handle await navigate.userProfile('alice.sol'); await navigate.userProfile('@alice'); // Open room — accepts roomId or @handle await navigate.openRoom('@solminer'); await navigate.openRoom('roomId123'); } ``` ``` -------------------------------- ### CherryMiniApp Core Methods Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Core functionalities for interacting with the Cherry MiniApp environment, including initialization, accessing data, and managing the application lifecycle. ```APIDOC ## CherryMiniApp (Core) ### Constructor - **`new CherryMiniApp(opts?)`**: Initializes the Cherry MiniApp SDK. - `opts.initTimeout` (number): Timeout in milliseconds for initialization (default: 10000). - `opts.strict` (boolean): Disables fallback detection if set to true. ### Initialization - **`init()`**: Initiates the handshake with the Cherry host. This method should be called to ensure the mini-app is ready to communicate with the host. ### Data Access - **`user`**: Object containing user information. - `publicKey` (string): The public key of the user. - `displayName` (string): The display name of the user. - `avatarUrl` (string): The URL of the user's avatar. - **`room`**: Object containing room information. - `id` (string): The unique identifier of the room. - `title` (string): The title of the room. - `memberCount` (number): The number of members in the room. - **`launchToken`**: JWT string used for backend verification. ### Wallet Operations - **`wallet.signTransaction(tx)`**: Signs a single transaction. - Returns: `Uint8Array` - The signed transaction. - **`wallet.signAllTransactions(txs)`**: Signs multiple transactions in a batch. - Returns: `Uint8Array[]` - An array of signed transactions. - **`wallet.signMessage(msg)`**: Signs an arbitrary message. - **`wallet.signAndSendTransaction(tx)`**: Signs and submits a transaction. ### Navigation - **`navigate.userProfile(id)`**: Opens a user profile. - `id` (string): User identifier (wallet/domain/@handle). - **`navigate.openRoom(id)`**: Opens a room. - `id` (string): Room identifier (roomId/@handle). ### Event Handling - **`on(event, handler)`**: Listens for specific events. - `event` (string): The event name. Supported events: `suspended`, `resumed`, `walletDisconnected`. - `handler` (function): The callback function to execute when the event occurs. ### Cleanup - **`destroy()`**: Cleans up event listeners and resources. ``` -------------------------------- ### useCherryApp() Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Returns the underlying CherryMiniApp instance. Needed for use with createCherrySigner from the @solana/kit entry point, or for advanced usage that goes beyond what the other hooks expose. ```APIDOC ## `useCherryApp()` — Raw CherryMiniApp Instance Hook Returns the underlying `CherryMiniApp` instance. Needed for use with `createCherrySigner` from the `@solana/kit` entry point, or for advanced usage that goes beyond what the other hooks expose. ```tsx import { useCherryApp } from '@cherrydotfun/miniapp-sdk/react'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; function SignButton() { const app = useCherryApp(); // CherryMiniApp | null const handleSign = async () => { if (!app) return; const signer = createCherrySigner(app); const [signed] = await signer.signTransactions([{ messageBytes, signatures: {}, }]); console.log(signed.signatures[signer.address]); // Uint8Array (64 bytes) }; return ; } ``` ``` -------------------------------- ### CherryMiniApp - Core Client Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt The main client class for interacting with the Cherry host environment, handling handshakes, user/room context, wallet operations, and navigation. ```APIDOC ## CherryMiniApp ### Description The main client class that handles the handshake with the Cherry host, exposes user/room context, and provides wallet signing and navigation APIs. Must call `init()` before accessing any state. Emits lifecycle events (`suspended`, `resumed`, `walletDisconnected`). ### Initialization ```ts import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; const cherry = new CherryMiniApp({ initTimeout: 10_000, // ms to wait for cherry:init handshake (default: 10000) strict: false, // use strict environment detection }); await cherry.init(); // waits for host handshake, rejects on timeout ``` ### User and Room Context ```ts // Available after init console.log(cherry.user.publicKey); // Solana wallet address (base58) console.log(cherry.user.displayName); // 'Alice' console.log(cherry.user.avatarUrl); // 'https://...' console.log(cherry.room.id); // room identifier console.log(cherry.room.title); // 'Solana Miners' console.log(cherry.room.memberCount); // 42 console.log(cherry.launchToken); // JWT string for backend verification ``` ### Wallet Operations ```ts // Sign a message const msg = new TextEncoder().encode('hello cherry'); const signature = await cherry.wallet.signMessage(msg); // Uint8Array // Sign a transaction const signedTx = await cherry.wallet.signTransaction(myTransaction); // Uint8Array // Sign multiple transactions const signedAll = await cherry.wallet.signAllTransactions([tx1, tx2, tx3]); // Uint8Array[] // Sign and send a transaction const txSig = await cherry.wallet.signAndSendTransaction(myTransaction); // signature string ``` ### Navigation ```ts // Navigate to user profile await cherry.navigate.userProfile('alice.sol'); // by .sol domain await cherry.navigate.userProfile('@alice'); // by @handle await cherry.navigate.userProfile('7xKXtg...'); // by wallet address // Open a room await cherry.navigate.openRoom('@solminer'); // by room handle await cherry.navigate.openRoom('roomId123'); // by room ID ``` ### Lifecycle Events ```ts cherry.on('suspended', () => { /* user left chat — pause game */ }); cherry.on('resumed', () => { /* user returned — resume */ }); cherry.on('walletDisconnected', () => { /* handle wallet disconnect */ }); cherry.off('suspended', handler); // remove a specific listener ``` ### Cleanup ```ts cherry.destroy(); // removes all listeners, destroys bridge ``` ``` -------------------------------- ### useCherryNavigate() — Navigation Hook Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt This hook allows mini-apps to open native Cherry host screens such as user profiles and rooms. It must be used within a `` context. ```APIDOC ## `useCherryNavigate()` — Navigation Hook Opens Cherry host screens (user profiles, rooms) from within the mini-app. Must be inside ``. ```tsx import { useCherryNavigate, useCherryEnvironment } from '@cherrydotfun/miniapp-sdk/react'; function UserCard({ address, handle }: { address: string; handle: string }) { const navigate = useCherryNavigate(); const { isEmbedded } = useCherryEnvironment(); const openProfile = async () => { if (isEmbedded) { // Opens the Cherry profile screen for this user await navigate.userProfile(address); // by wallet address // or: await navigate.userProfile('alice.sol'); // by .sol domain // or: await navigate.userProfile('@alice'); // by @handle } else { window.location.href = `/profile/${address}`; } }; const openRoom = async () => { await navigate.openRoom('@solminer'); // by handle // or: await navigate.openRoom('roomId123'); // by ID }; return (
); } ``` ``` -------------------------------- ### Copy Cherry Mini-App Integration Skill Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/README.md Use this command to copy the skill to your Claude Code skills directory. Ensure the path is correct for your system. ```bash cp -r skills/cherry-miniapp-integration ~/.claude/skills/ ``` -------------------------------- ### useCherryEnvironment(options?) — Environment Hook Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt This hook synchronously detects the current platform (webview, iframe, standalone). It does not require `` and is safe to call early in the component tree. Strict mode can be enabled with `{ strict: true }`. ```APIDOC ## `useCherryEnvironment(options?)` — Environment Hook Detects the current platform synchronously. Does **not** require `` — safe to call at any level of the component tree before the provider is mounted. Accepts `{ strict: true }` to use strict mode. ```tsx import { useCherryEnvironment, CherryMiniAppProvider } from '@cherrydotfun/miniapp-sdk/react'; function App() { const { isEmbedded, platform } = useCherryEnvironment({ strict: true }); // platform: 'webview' | 'iframe' | 'standalone' // Conditionally hide elements not needed inside Cherry return ( <> {!isEmbedded &&
} {!isEmbedded && } {isEmbedded ? ( ) : ( )} {platform === 'webview' && } ); } ``` ``` -------------------------------- ### Verify JWT Launch Token on Backend Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Verify the JWT launch token signed by Cherry's server on your backend using the `verifyLaunchToken` function. Ensure `expectedAppId` is provided. ```typescript import { verifyLaunchToken } from '@cherrydotfun/miniapp-sdk'; const payload = await verifyLaunchToken(token, { expectedAppId: 'your-app-id', // jwksUrl defaults to https://chat.cherry.fun/.well-known/jwks.json }); // payload.sub — wallet address // payload.room_id — room where app was opened // payload.user — { display_name, avatar_url } // payload.room — { title, member_count } ``` -------------------------------- ### CherryWalletAdapter for Solana Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Drop-in adapter for @solana/wallet-adapter-react. Handles connect, signTransaction, signAllTransactions, signMessage, and sendTransaction. ```ts import { CherryWalletAdapter } from '@cherrydotfun/miniapp-sdk/solana'; ``` -------------------------------- ### CherryWalletAdapter Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md A drop-in wallet adapter for `@solana/wallet-adapter-react`, providing seamless integration with Cherry's wallet functionalities. ```APIDOC ## CherryWalletAdapter (solana/) ```ts import { CherryWalletAdapter } from '@cherrydotfun/miniapp-sdk/solana'; ``` This adapter is a drop-in replacement for `BaseWalletAdapter` from `@solana/wallet-adapter-react`. It handles the connection, signing of transactions (single and batch), signing messages, and sending transactions within the Cherry MiniApp environment. ``` -------------------------------- ### useCherryMiniApp Hook for User Data Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Accesses user profile, room context, launch token, and ready state within a Cherry MiniApp. Must be called inside CherryMiniAppProvider. ```tsx import { useCherryMiniApp } from '@cherrydotfun/miniapp-sdk/react'; function GameUI() { const { user, room, launchToken, isReady, error } = useCherryMiniApp(); if (error) return
Error: {error.message}
; if (!isReady) return
Connecting to Cherry...
; return (

Welcome, {user.displayName}!

{/* 'Alice' */} avatar

Wallet: {user.publicKey}

{/* 'A1b2C3...' */}

Room: {room.title} ({room.memberCount} members)

Token: {launchToken.slice(0, 20)}...

); } ``` -------------------------------- ### `verifyLaunchToken(token, options)` — Backend Token Verification Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Server-side function to verify the JWT launch token issued by Cherry. It validates the signature, expiry, and `app_id` claim. ```APIDOC ## `verifyLaunchToken(token, options)` — Backend Token Verification ### Description Server-side function to verify the JWT launch token issued by Cherry. Fetches the JWKS from Cherry's well-known endpoint and validates the signature, expiry, and `app_id` claim. Returns the decoded `LaunchTokenPayload` on success. ### Usage ```ts import { verifyLaunchToken } from '@cherrydotfun/miniapp-sdk'; // Express/Node.js endpoint example app.post('/api/verify', async (req, res) => { const { token } = req.body; try { const payload = await verifyLaunchToken(token, { expectedAppId: 'your-registered-app-id', // jwksUrl defaults to https://chat.cherry.fun/.well-known/jwks.json // expectedOrigin: 'https://yourgame.example', // optional origin check }); // payload.sub — verified Solana wallet address (base58) // payload.app_id — your app's registered ID // payload.room_id — room where the mini-app was opened // payload.origin — origin of the mini-app // payload.user — { display_name, avatar_url } // payload.room — { title, member_count } // payload.iat / .exp — issued-at / expiry (unix timestamp) // payload.jti — unique token ID res.json({ verified: true, payload }); } catch (err) { res.status(401).json({ verified: false, error: err.message }); // Possible errors: // - JWT signature invalid // - Token expired (TTL is 5 minutes) // - app_id mismatch // - origin mismatch (if expectedOrigin provided) } }); ``` ``` -------------------------------- ### Create Cherry Transaction Signer with @solana/kit Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Use `createCherrySigner` to create a `TransactionSigner` for Cherry. It handles batch signing, multi-signer transactions, and preserves pre-existing signatures. Ensure CherryMiniApp is initialized before creating the signer. ```typescript import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; import { address, createNoopSigner, createTransactionMessage, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstruction, compileTransaction, pipe, lamports, } from '@solana/kit'; import { getTransferSolInstruction } from '@solana-program/system'; const cherry = new CherryMiniApp(); await cherry.init(); const signer = createCherrySigner(cherry); // signer.address — the user's Solana wallet address // Build a kit transaction message const userAddress = address(cherry.user.publicKey); const feePayer = createNoopSigner(userAddress); const message = pipe( createTransactionMessage({ version: 0 }), m => setTransactionMessageFeePayerSigner(feePayer, m), m => setTransactionMessageLifetimeUsingBlockhash( { blockhash: await getLatestBlockhash(), lastValidBlockHeight: 0n }, m ), m => appendTransactionMessageInstruction( getTransferSolInstruction({ source: feePayer, destination: userAddress, amount: lamports(1000n) }), m ), ); const { messageBytes } = compileTransaction(message); // Single transaction const [signed] = await signer.signTransactions([{ messageBytes, signatures: {} }]); const mySig = signed.signatures[signer.address]; // Uint8Array (64 bytes) // Batch — all presented to user in a single wallet confirmation const batchSigned = await signer.signTransactions([ { messageBytes: tx1Bytes, signatures: {} }, { messageBytes: tx2Bytes, signatures: {} }, { messageBytes: tx3Bytes, signatures: { [otherSigner]: preExistingSig } }, // multisig ]); // Sign messages const [sig] = await signer.signMessages([new TextEncoder().encode('hello')]); ``` -------------------------------- ### Navigate to User Profile and Open Room using React Hook Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Use the `useCherryNavigate` hook in React to open user profiles by wallet address, domain, or @handle, and to open rooms by roomId or @handle. ```typescript import { useCherryNavigate } from '@cherrydotfun/miniapp-sdk/react'; function MyComponent() { const navigate = useCherryNavigate(); // Open user profile — accepts wallet address, domain, or @handle await navigate.userProfile('alice.sol'); await navigate.userProfile('@alice'); // Open room — accepts roomId or @handle await navigate.openRoom('@solminer'); await navigate.openRoom('roomId123'); } ``` -------------------------------- ### React Hooks Reference Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Reference for available React hooks to interact with the Cherry MiniApp SDK within a React environment. ```APIDOC ## API Reference ### React Hooks | Hook | Description | |------|-------------| | `useCherryMiniApp()` | `{ user, room, launchToken, isReady, error }` | | `useCherryApp()` | `CherryMiniApp` instance (for kit signer etc.) | | `useCherryWallet()` | `{ publicKey, connected, signTransaction, signAllTransactions, signMessage, signAndSendTransaction }` | | `useCherryNavigate()` | `{ userProfile(id), openRoom(id) }` | | `useCherryEnvironment(opts?)` | `{ isEmbedded, platform }` — no provider needed; pass `{ strict: true }` to disable fallbacks | ``` -------------------------------- ### Symlink Cherry Mini-App Integration Skill Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/README.md Use this command to create a symbolic link for the skill in your Claude Code skills directory. This is useful for development to avoid re-copying. ```bash ln -s $(pwd)/skills/cherry-miniapp-integration ~/.claude/skills/cherry-miniapp-integration ``` -------------------------------- ### Cherry Signer for @solana/kit Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Integrate Cherry MiniApp and create a transaction signer for use with @solana/kit. Supports signing transactions and messages. ```typescript import { CherryMiniApp } from '@cherrydotfun/miniapp-sdk'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; const cherry = new CherryMiniApp(); await cherry.init(); // TransactionSigner — use with @solana/kit transaction builders const signer = createCherrySigner(cherry); // Sign transactions const [signed] = await signer.signTransactions([{ messageBytes, signatures: {} }]); // Sign messages const [signature] = await signer.signMessages([messageBytes]); ``` ```typescript import { CherryMiniAppProvider, useCherryApp } from '@cherrydotfun/miniapp-sdk/react'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; function MyComponent() { const app = useCherryApp(); const handleSign = async () => { const signer = createCherrySigner(app); const [signed] = await signer.signTransactions([{ messageBytes, signatures: {} }]); }; } ``` -------------------------------- ### Configure X-Frame-Options for Iframe Embedding (Legacy) Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Use the X-Frame-Options header to allow Cherry's origin for iframe embedding. Note that this is a legacy option and less flexible than CSP. ```http X-Frame-Options: ALLOW-FROM https://chat.cherry.fun ``` -------------------------------- ### Handle Cherry Mini App Lifecycle Events Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/skills/cherry-miniapp-integration/SKILL.md Listen for lifecycle events such as 'suspended', 'resumed', and 'walletDisconnected' to manage your mini app's state gracefully. Ensure proper handling when the user leaves or returns to the chat, or when the wallet connection is lost. ```typescript cherry.on('suspended', () => { /* user left chat — pause game */ }); cherry.on('resumed', () => { /* user came back — resume */ }); cherry.on('walletDisconnected', () => { /* handle gracefully */ }); ``` -------------------------------- ### React Hooks for Cherry Mini App SDK Source: https://github.com/cherrydotfun/miniapp-sdk/blob/main/README.md Overview of available React hooks for interacting with the Cherry Mini App SDK, including hooks for app state, wallet, navigation, and environment. ```typescript /// React Hooks // `useCherryMiniApp()` // `{ user, room, launchToken, isReady, error }` // `useCherryApp()` // `CherryMiniApp` instance (for kit signer etc.) // `useCherryWallet()` // `{ publicKey, connected, signTransaction, signAllTransactions, signMessage, signAndSendTransaction }` // `useCherryNavigate()` // `{ userProfile(id), openRoom(id) }` // `useCherryEnvironment(opts?)` // `{ isEmbedded, platform }` — no provider needed; pass `{ strict: true }` to disable fallbacks ``` -------------------------------- ### useCherryApp Hook for Raw Instance Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Retrieves the raw CherryMiniApp instance for advanced usage, such as creating signers with @solana/kit. Returns null if not available. ```tsx import { useCherryApp } from '@cherrydotfun/miniapp-sdk/react'; import { createCherrySigner } from '@cherrydotfun/miniapp-sdk/kit'; function SignButton() { const app = useCherryApp(); // CherryMiniApp | null const handleSign = async () => { if (!app) return; const signer = createCherrySigner(app); const [signed] = await signer.signTransactions([ { messageBytes, signatures: {}, }, ]); console.log(signed.signatures[signer.address]); // Uint8Array (64 bytes) }; return ; } ``` -------------------------------- ### Integrate Cherry Wallet with Solana Adapter Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Provides `CherryWalletAdapter` for `@solana/wallet-adapter-react`, allowing seamless integration of the Cherry wallet. It supports legacy and versioned transactions, message signing, and transaction sending. The `getWallets` function conditionally exposes the Cherry wallet when inside Cherry, otherwise defaults to Phantom. ```tsx import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'; import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui'; import { PhantomWalletAdapter } from '@solana/wallet-adapter-wallets'; import { CherryWalletAdapter } from '@cherrydotfun/miniapp-sdk/solana'; import { isInsideCherry } from '@cherrydotfun/miniapp-sdk'; import { useEffect, useMemo } from 'react'; import { useWallet } from '@solana/wallet-adapter-react'; function getWallets() { // Inside Cherry: only expose the Cherry wallet if (isInsideCherry()) return [new CherryWalletAdapter()]; // Standalone: standard wallet list return [new PhantomWalletAdapter()]; } // Auto-select Cherry wallet when embedded function AutoSelectCherry({ children }: { children: React.ReactNode }) { const { select, wallets } = useWallet(); useEffect(() => { const cherry = wallets.find(w => w.adapter.name === 'Cherry'); if (cherry) select(cherry.adapter.name); }, [wallets, select]); return <>{children}; } const embedded = isInsideCherry(); function Providers({ children }: { children: React.ReactNode }) { const wallets = useMemo(() => getWallets(), []); return ( {embedded ? {children} : children } ); } ``` -------------------------------- ### getCherryCustomAuthConfig Source: https://context7.com/cherrydotfun/miniapp-sdk/llms.txt Extracts the launch token and JWKS/issuer config needed to use Cherry as a custom auth provider in Privy, enabling zero-click transparent login inside Cherry with standard Privy login as a fallback in standalone mode. ```APIDOC ## `getCherryCustomAuthConfig(cherry)` — Privy Custom Auth Integration Extracts the launch token and JWKS/issuer config needed to use Cherry as a custom auth provider in [Privy](https://privy.io), enabling zero-click transparent login inside Cherry with standard Privy login as a fallback in standalone mode. ```tsx import { getCherryCustomAuthConfig } from '@cherrydotfun/miniapp-sdk'; // Assuming 'cherry' is an object with a 'launchToken' property const { token } = getCherryCustomAuthConfig(cherry); ``` ```