Skip to content

SherryLabs/sherry-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Dynamic Action Example with Sherry SDK in Next.js

This project demonstrates how to implement a "Dynamic Action" (Mini App) using the Sherry SDK within a Next.js application. It shows how to expose metadata for an action and handle its execution, creating interactive blockchain applications that can be embedded in different platforms.

🌟 Features

  • Dynamic Action Metadata: Exposes a GET endpoint serving metadata required by Sherry SDK to define a dynamic action
  • Action Execution: Implements a POST endpoint that handles action execution, receiving parameters and returning serialized transactions
  • CORS Support: Complete CORS handling for cross-origin requests, including OPTIONS preflight requests
  • Blockchain Integration: Uses viem for chain details (Avalanche Fuji) and wagmi for transaction serialization
  • Parameter Validation: Robust parameter handling and validation
  • TypeScript Support: Full TypeScript implementation with proper types

πŸ“‹ Prerequisites

  • Node.js (version 18.x or higher recommended)
  • npm, yarn, or pnpm
  • Basic understanding of Next.js and blockchain concepts

πŸš€ Project Setup

1. Clone or Create Project

# Clone this repository or create a new Next.js project
npx create-next-app@latest sherry-example --typescript --eslint --tailwind --src-dir --app --import-alias "@/*"
cd sherry-example

2. Install Dependencies

npm install @sherrylinks/sdk viem wagmi
# or
yarn add @sherrylinks/sdk viem wagmi
# or
pnpm add @sherrylinks/sdk viem wagmi

3. Optional: Configure ESLint

To avoid build errors, you can disable ESLint in next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    ignoreDuringBuilds: true,
  },
}

module.exports = nextConfig

πŸƒβ€β™‚οΈ Running the Project

Start the development server:

npm run dev
# or
yarn dev
# or
pnpm dev

The application will be available at http://localhost:3000. The API endpoint will be accessible at http://localhost:3000/api/example.

πŸ“‘ API Endpoints

GET /api/example - Action Metadata

Purpose: Returns metadata for the dynamic action, used by platforms to display and interact with your mini app.

Response Example:

{
    "url": "https://sherry.social",
    "icon": "https://avatars.githubusercontent.com/u/117962315",
    "title": "Timestamped Message",
    "baseUrl": "http://localhost:3000",
    "description": "Store a message with an optimized timestamp calculated by our algorithm",
    "actions": [
        {
            "type": "dynamic",
            "label": "Store Message",
            "description": "Store your message with a custom timestamp calculated for optimal storage",
            "chains": { "source": "fuji" },
            "path": "/api/example",
            "params": [
                {
                    "name": "message",
                    "label": "Your Message Hermano!",
                    "type": "text",
                    "required": true,
                    "description": "Enter the message you want to store on the blockchain"
                }
            ]
        }
    ]
}

Important: Note that baseUrl is automatically derived from the request headers. During development, it will use http://localhost:3000, but when deployed, it will use your production domain. This happens automatically through:

const host = req.headers.get('host') || 'localhost:3000';
const protocol = req.headers.get('x-forwarded-proto') || 'http';
const serverUrl = `${protocol}://${host}`;

POST /api/example - Action Execution

Purpose: Executes the dynamic action, processes parameters, and returns a serialized transaction.

Query Parameters:

  • message (string, required): The message to process

Example Request:

POST http://localhost:3000/api/example?message=HelloSherry

Success Response:

{
    "serializedTransaction": "0x...",
    "chainId": "avalancheFuji"
}

Error Response (400 - Missing Parameter):

{
    "error": "Message parameter is required"
}

OPTIONS /api/example - CORS Preflight

Purpose: Handles CORS preflight requests for cross-origin compatibility.

Response: 204 No Content with appropriate CORS headers.

πŸ§ͺ Testing Your Mini App

You have several options to test your dynamic action:

Option 1: Sherry Social Platform

  1. Visit https://app.sherry.social/home
  2. Enter your endpoint URL:
    • During development: http://localhost:3000/api/example (only works if your local server is publicly accessible)
    • After deployment: Use your actual deployed URL (e.g., https://your-app-name.vercel.app/api/example)
  3. The platform will automatically render your mini app

Important: The localhost URL is only provided as a reference. For actual integration with the Sherry platform, you must deploy your application and use the public URL. The Sherry platform cannot access your localhost unless you're using a tunneling service.

Option 2: Sherry Debugger (Recommended for Development)

  1. Go to https://app.sherry.social/debugger
  2. Test using one of three methods:
    • URL: Paste your GET endpoint URL (localhost during development, deployed URL in production)
    • JSON: Copy and paste the metadata JSON
    • TypeScript: Paste your TypeScript code directly

Note: The debugger is in active development and may contain bugs. You can report issues directly from the debugger interface.

Testing Steps:

  1. Start Development Server:

    npm run dev
  2. Verify GET Endpoint:

    • Navigate to http://localhost:3000/api/example locally
    • After deployment, use your deployed URL (e.g., https://your-app-name.vercel.app/api/example)
    • Confirm you see the metadata JSON response
  3. Test in Debugger:

    • Use appropriate URL based on environment (local or deployed)
    • Verify input fields render correctly
    • Test form completion and submission
  4. Verify Execution:

    • Fill in required parameters
    • Click the action button
    • Confirm you receive a serialized transaction

πŸ—οΈ Project Structure

β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   └── example/
β”‚   β”‚       └── route.ts          # Main API endpoint
β”‚   β”œβ”€β”€ globals.css               # Global styles
β”‚   β”œβ”€β”€ layout.tsx               # Root layout
β”‚   └── page.tsx                 # Home page
β”œβ”€β”€ README.md                    # This file
└── package.json                 # Dependencies

πŸ”§ Key Components

Sherry SDK Integration

  • createMetadata: Validates and structures metadata objects
  • Metadata, ValidatedMetadata, ExecutionResponse: TypeScript types for proper data handling
    • ExecutionResponse is specifically used to type the transaction response, ensuring the proper format:
      const resp: ExecutionResponse = {
          serializedTransaction: serialized,
          chainId: avalancheFuji.name,
      }
  • Parameter validation and processing

Blockchain Integration

  • viem: Provides chain configurations (Avalanche Fuji)
  • wagmi: Handles transaction serialization
    • The serialize function from wagmi is used to convert a transaction object into a serialized format:
      import { serialize } from 'wagmi'
      
      const tx = {
          to: '0x5ee75a1B1648C023e885E58bD3735Ae273f2cc52',
          value: BigInt(1000000),
          chainId: avalancheFuji.id,
      }
      
      const serialized = serialize(tx)
  • Support for multiple blockchain networks

CORS Implementation

Complete CORS setup allowing cross-origin requests from any domain, essential for platform integration.

πŸ› οΈ Customization

Adding New Parameters

To add new input fields, extend the params array in your metadata:

params: [
    // ... existing params
    {
        name: "newParam",
        label: "New Parameter",
        type: "number",
        required: false,
        description: "Description of the new parameter"
    }
]

Changing Target Blockchain

Update the chain configuration:

import { mainnet } from "viem/chains"; // or any other chain

const tx = {
    to: '0x...',
    value: BigInt(1000000),
    chainId: mainnet.id, // Update chain ID
}

const response: ExecutionResponse = {
    serializedTransaction: serialized,
    chainId: mainnet.name, // Update chain name
}

Adding Business Logic

Extend the POST handler with your custom logic:

export async function POST(req: NextRequest) {
    try {
        const { searchParams } = new URL(req.url);
        const message = searchParams.get("message");
        
        // Add your custom business logic here
        const processedData = await processMessage(message);
        
        // Create transaction based on processed data
        const tx = createCustomTransaction(processedData);
        
        // ... rest of the handler
    } catch (error) {
        // Handle errors
    }
}

πŸ› Troubleshooting

Common Issues

CORS Errors:

  • Ensure all endpoints include proper CORS headers
  • Verify OPTIONS method is implemented

Metadata Validation Failures:

  • Check all required fields are present
  • Verify data types match expected formats
  • Use createMetadata() for validation

Parameter Issues:

  • Confirm parameter names match between metadata and POST handler
  • Verify required parameters are marked correctly

Transaction Serialization:

  • Ensure values are in correct format (BigInt for wei amounts)
  • Verify chainId is valid for target network
  • Check destination address format

Debug Tips

  1. Check Browser Console: Look for JavaScript errors when testing
  2. Verify JSON Response: Ensure GET endpoint returns valid JSON
  3. Test Parameters: Use browser developer tools to inspect network requests
  4. Console Logging: Add console.log statements to trace execution flow

πŸ“š Additional Resources

🀝 Contributing

Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.

πŸ“„ License

This project is open source and available under the MIT License.

About

Example of Dynamic Action

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published