### 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' */}
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' */}
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);
```
```