Creating Your First Trigger
Learn how to develop your mini-app with TypeScript and the Sherry SDK
Prerequisites
Before starting, ensure you have the following installed:
- Code editor such as VSCode
- Node.js (version 16 or higher)
- Basic knowledge of TypeScript and blockchain concepts
Step 1: Installation
Install the Sherry SDK using your preferred package manager:
Using npm:
npm install @sherrylinks/sdk
Using yarn:
yarn add @sherrylinks/sdk
Using pnpm:
pnpm add @sherrylinks/sdk
Step 2: Import Required Components
Import the necessary interfaces and functions from the SDK:
import { Metadata, createMetadata, ValidatedMetadata } from '@sherrylinks/sdk';
Step 3: Define Your ABI
First, create your contract ABI. This example uses an ERC-721 NFT contract:
contracts/example-abi.ts
export const exampleAbi = [
{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'owner', type: 'address' }],
outputs: [{ name: 'balance', type: 'uint256' }],
},
{
name: 'safeTransferFrom',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'tokenId', type: 'uint256' },
],
outputs: [],
},
] as const;
Step 4: Create Your Metadata
Define your trigger's metadata with proper configuration:
metadata.ts
import { Metadata } from '@sherrylinks/sdk';
import { exampleAbi } from './contracts/example-abi';
const metadata: Metadata = {
url: 'https://your-app.example.com',
icon: 'https://your-app.example.com/icon.png',
title: 'My NFT Transfer Trigger',
description: 'Transfer NFTs safely between addresses',
actions: [
{
type: 'blockchain',
label: 'Transfer NFT',
address: '0x1234567890abcdef1234567890abcdef12345678', // Replace with actual contract address
abi: exampleAbi,
functionName: 'safeTransferFrom',
chains: { source: 43114 }, // Avalanche C-Chain
params: [
{
name: 'from',
label: 'From Address',
type: 'address',
required: true,
description: 'Current owner of the NFT',
},
{
name: 'to',
label: 'To Address',
type: 'address',
required: true,
description: 'Address to receive the NFT',
},
{
name: 'tokenId',
label: 'Token ID',
type: 'number',
required: true,
description: 'Unique identifier of the NFT',
},
],
},
],
};
export default metadata;
Step 5: Validate Your Metadata
Use the createMetadata
function to validate your configuration:
import { createMetadata, ValidatedMetadata } from '@sherrylinks/sdk';
import metadata from './metadata';
async function validateMetadata() {
try {
const validatedMetadata: ValidatedMetadata = await createMetadata(metadata);
console.log('Metadata validation successful!');
return validatedMetadata;
} catch (error) {
console.error('Metadata validation failed:', error);
throw error;
}
}
// Usage
const finalMetadata = await validateMetadata();
Step 6: Understanding the Validated Output
After validation, your metadata will be processed and enhanced with additional fields:
{
"type": "action",
"url": "https://your-app.example.com",
"icon": "https://your-app.example.com/icon.png",
"title": "My NFT Transfer Trigger",
"description": "Transfer NFTs safely between addresses",
"actions": [
{
"type": "blockchain",
"label": "Transfer NFT",
"address": "0x1234567890abcdef1234567890abcdef12345678",
"abi": [...],
"functionName": "safeTransferFrom",
"chains": { "source": 43114 },
"params": [
{
"name": "from",
"label": "From Address",
"type": "address",
"required": true,
"description": "Current owner of the NFT"
},
{
"name": "to",
"label": "To Address",
"type": "address",
"required": true,
"description": "Address to receive the NFT"
},
{
"name": "tokenId",
"label": "Token ID",
"type": "number",
"required": true,
"description": "Unique identifier of the NFT"
}
],
"blockchainActionType": "nonpayable"
}
]
}
Step 7: Deploy Your Trigger
Creating an API Endpoint
Create an HTTP endpoint that serves your metadata via GET request:
Using Next.js (pages/api/metadata.ts):
import { NextApiRequest, NextApiResponse } from 'next';
import { createMetadata } from '@sherrylinks/sdk';
import metadata from '../../metadata';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') {
try {
const validatedMetadata = await createMetadata(metadata);
res.setHeader('Access-Control-Allow-Origin', '*');
res.status(200).json(validatedMetadata);
} catch (error) {
res.status(500).json({ error: 'Failed to validate metadata' });
}
} else {
res.setHeader('Allow', ['GET']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}
Using Express.js:
import express from 'express';
import cors from 'cors';
import { createMetadata } from '@sherrylinks/sdk';
import metadata from './metadata';
const app = express();
app.use(cors());
app.get('/api/metadata', async (req, res) => {
try {
const validatedMetadata = await createMetadata(metadata);
res.json(validatedMetadata);
} catch (error) {
res.status(500).json({ error: 'Failed to validate metadata' });
}
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Deployment Checklist
- Ensure your endpoint returns metadata via GET request
- Enable CORS for cross-origin requests
- Verify all contract addresses are correct for your target network
- Test your endpoint returns valid JSON
- Deploy to a publicly accessible URL
Next Steps
- Test Your Trigger: Use the Sherry Social App to test your trigger
- Add More Actions: Extend your metadata with additional blockchain actions
- Implement Dynamic Actions: Create server-side logic for complex operations
- Handle User Input: Add form validation and user-friendly interfaces
Best Practices
- Always validate user inputs before processing
- Use testnet chain IDs during development (43113 for Avalanche Fuji)
- Provide clear descriptions for all parameters
- Handle errors gracefully in your API endpoints
- Keep your ABI definitions up to date with your smart contracts
Troubleshooting
Common Issues:
- CORS errors: Ensure your server has proper CORS headers
- Invalid chain ID: Use supported chain IDs from the chains documentation
- ABI mismatch: Verify your ABI matches your deployed contract
- Network issues: Check if your contract is deployed on the specified network