agentsclimarketplace

Alchemy webhooks events

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/alchemy-pack/skills/alchemy-webhooks-events

'Implement Alchemy Notify webhooks for real-time blockchain event notifications.From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill alchemy-webhooks-events

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.2 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it

Alchemy Webhooks & Events (Notify API)

Overview

Alchemy Notify provides real-time push notifications for on-chain events. Instead of polling, receive webhook callbacks for wallet activity, mined transactions, dropped transactions, and smart contract events.

Webhook Types

TypeTriggerUse Case
Address ActivityETH/token transfer to/from addressWallet notifications
Mined TransactionTransaction confirmed on-chainPayment confirmation
Dropped TransactionTransaction removed from mempoolFailed tx alerting
NFT ActivityNFT transfer eventsMarketplace notifications
Custom WebhookGraphQL-defined filterComplex event tracking

Instructions

Step 1: Create Webhook via Dashboard or API

# Create Address Activity webhook via Alchemy API
curl -X POST "https://dashboard.alchemy.com/api/create-webhook" \
  -H "X-Alchemy-Token: ${ALCHEMY_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "network": "ETH_MAINNET",
    "webhook_type": "ADDRESS_ACTIVITY",
    "webhook_url": "https://your-app.com/webhooks/alchemy",
    "addresses": [
      "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
    ]
  }'

Step 2: Webhook Handler with Signature Verification

// src/webhooks/alchemy-handler.ts
import express from 'express';
import crypto from 'crypto';

const router = express.Router();

router.post('/webhooks/alchemy',
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    // Verify webhook signature
    const signature = req.headers['x-alchemy-signature'] as string;
    if (!verifySignature(req.body.toString(), signature)) {
      return res.status(401).json({ error: 'Invalid signature' });
    }

    const event = JSON.parse(req.body.toString());
    await processAlchemyEvent(event);
    res.status(200).json({ ok: true });
  }
);

function verifySignature(body: string, signature: string): boolean {
  const signingKey = process.env.ALCHEMY_WEBHOOK_SIGNING_KEY!;
  const hmac = crypto.createHmac('sha256', signingKey);
  hmac.update(body, 'utf8');
  const digest = hmac.digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}

Step 3: Event Router

// src/webhooks/event-router.ts
interface AlchemyWebhookEvent {
  webhookId: string;
  id: string;
  createdAt: string;
  type: 'ADDRESS_ACTIVITY' | 'MINED_TRANSACTION' | 'DROPPED_TRANSACTION' | 'NFT_ACTIVITY';
  event: {
    network: string;
    activity: Array<{
      fromAddress: string;
      toAddress: string;
      value: number;
      asset: string;
      category: 'external' | 'internal' | 'erc20' | 'erc721' | 'erc1155';
      hash: string;
      blockNum: string;
    }>;
  };
}

async function processAlchemyEvent(event: AlchemyWebhookEvent): Promise<void> {
  switch (event.type) {
    case 'ADDRESS_ACTIVITY':
      for (const activity of event.event.activity) {
        console.log(`${activity.category} transfer: ${activity.value} ${activity.asset}`);
        console.log(`  From: ${activity.fromAddress}`);
        console.log(`  To: ${activity.toAddress}`);
        console.log(`  Tx: ${activity.hash}`);
        // Trigger application logic (e.g., update balance, send notification)
      }
      break;

    case 'MINED_TRANSACTION':
      console.log('Transaction mined:', event.event);
      break;

    case 'DROPPED_TRANSACTION':
      console.log('Transaction dropped:', event.event);
      // Alert user their transaction was dropped
      break;

    case 'NFT_ACTIVITY':
      for (const activity of event.event.activity) {
        console.log(`NFT transfer: ${activity.asset} #${activity.value}`);
      }
      break;
  }
}

Step 4: Programmatic Webhook Management

// src/webhooks/manage-webhooks.ts
import { Alchemy, Network, WebhookType } from 'alchemy-sdk';

const alchemy = new Alchemy({
  apiKey: process.env.ALCHEMY_API_KEY,
  network: Network.ETH_MAINNET,
  authToken: process.env.ALCHEMY_AUTH_TOKEN, // Required for Notify API
});

async function setupAddressWebhook(addresses: string[], webhookUrl: string) {
  const webhook = await alchemy.notify.createWebhook(
    webhookUrl,
    WebhookType.ADDRESS_ACTIVITY,
    { addresses, network: Network.ETH_MAINNET }
  );
  console.log(`Webhook created: ${webhook.id}`);
  return webhook;
}

async function listWebhooks() {
  const webhooks = await alchemy.notify.getAllWebhooks();
  for (const wh of webhooks.webhooks) {
    console.log(`${wh.id}: ${wh.webhookType} → ${wh.webhookUrl} (${wh.isActive ? 'active' : 'inactive'})`);
  }
}

async function addAddressToWebhook(webhookId: string, newAddresses: string[]) {
  await alchemy.notify.updateWebhook(webhookId, {
    addAddresses: newAddresses,
  });
}

Output

  • Address Activity webhook for wallet monitoring
  • HMAC signature verification for webhook security
  • Event router handling all Alchemy webhook types
  • Programmatic webhook management via Notify API

Error Handling

IssueCauseSolution
Invalid signatureWrong signing keyCopy from Alchemy webhook details page
Missing eventsWebhook URL not reachableEnsure HTTPS endpoint is publicly accessible
Duplicate eventsNo idempotencyTrack webhook event IDs

Resources

Next Steps

For performance optimization, see alchemy-performance-tuning.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.