wagmi-development

0
0
Source

Creates Wagmi features across all layers - core actions, query options, framework bindings. Use when adding new actions, hooks, or working across packages/core, packages/react, packages/vue.

Install

mkdir -p .claude/skills/wagmi-development && curl -L -o skill.zip "https://mcp.directory/api/skills/download/4453" && unzip -o skill.zip -d .claude/skills/wagmi-development && rm skill.zip

Installs to .claude/skills/wagmi-development

About this skill

Wagmi Development

Full-stack patterns for adding Wagmi features. This skill covers Viem-based actions only (not Wagmi config actions).

Layer Overview

  1. Core Action (packages/core/src/actions/) - Base functionality wrapping Viem
  2. Query Options (packages/core/src/query/) - TanStack Query integration
  3. Framework Bindings - React (packages/react/src/hooks/), Vue (packages/vue/src/composables/)

1. Core Action

Structure

import {
  type MyActionErrorType as viem_MyActionErrorType,
  type MyActionParameters as viem_MyActionParameters,
  type MyActionReturnType as viem_MyActionReturnType,
  myAction as viem_myAction,
} from 'viem/actions'

import type { Config } from '../createConfig.js'
import type { ChainIdParameter, ConnectorParameter } from '../types/properties.js'
import type { Compute } from '../types/utils.js'
import { getAction } from '../utils/getAction.js'

export type MyActionParameters<config extends Config = Config> = Compute<
  ChainIdParameter<config> & viem_MyActionParameters
>

export type MyActionReturnType = viem_MyActionReturnType

export type MyActionErrorType = viem_MyActionErrorType

/** https://wagmi.sh/core/api/actions/myAction */
export async function myAction<config extends Config>(
  config: config,
  parameters: MyActionParameters<config>,
): Promise<MyActionReturnType> {
  const { chainId, ...rest } = parameters
  const client = config.getClient({ chainId })
  const action = getAction(client, viem_myAction, 'myAction')
  return action(rest)
}

Key Rules

  • Viem imports: Prefix with viem_ (e.g., viem_getBalance)
  • Client access:
    • Read-only: config.getClient({ chainId })
    • Wallet: await getConnectorClient(config, { chainId, connector, account })
    • Mixed: Use getConnectorClient for account, getClient for action (see estimateGas.ts)
  • Parameters: Add ChainIdParameter<config> always. Add ConnectorParameter for wallet actions.
  • Type params: Mirror Viem's type params for inference. Use const modifier for literal inference (abi, args).
  • Spread: Omit wagmi-specific props (chainId, connector) when calling Viem action.

Testing

Runtime tests (action.test.ts):

import { abi, address, config } from '@wagmi/test'
import { expect, test } from 'vitest'
import { myAction } from './myAction.js'

test('default', async () => {
  await expect(myAction(config, { /* required params */ })).resolves.toMatchInlineSnapshot(`...`)
})

test('parameters: chainId', async () => { /* test chainId param */ })

test('behavior: error case', async () => { /* test error handling */ })

Type tests (action.test-d.ts) - only if action has type inference:

import { config } from '@wagmi/test'
import { expectTypeOf, test } from 'vitest'
import { myAction } from './myAction.js'

test('default', async () => {
  const result = await myAction(config, { /* params */ })
  expectTypeOf(result).toEqualTypeOf<ExpectedType>()
})

Type benchmarks (action.bench-d.ts) - only if action has type inference:

import { attest } from '@ark/attest'
import { test } from 'vitest'
import type { MyActionParameters } from './myAction.js'

test('default', () => {
  type Result = MyActionParameters<typeof abi.erc20, 'balanceOf'>
  const res = {} as Result
  attest.instantiations([12345, 'instantiations'])
  attest(res.args).type.toString.snap(`readonly [account: \`0x\${string}\`]`)
})

Wallet action tests: Connect before, disconnect after:

test('default', async () => {
  await connect(config, { connector })
  await expect(myAction(config, { /* params */ })).resolves.toMatchInlineSnapshot(`...`)
  await disconnect(config, { connector })
})

2. Query Options

Query (read-only) or Mutation (wallet) options for TanStack Query.

Query Structure

import {
  type MyActionErrorType,
  type MyActionParameters,
  type MyActionReturnType,
  myAction,
} from '../actions/myAction.js'
import type { Config } from '../createConfig.js'
import type { ScopeKeyParameter } from '../types/properties.js'
import type { QueryOptions, QueryParameter } from '../types/query.js'
import type { Compute, ExactPartial } from '../types/utils.js'
import { filterQueryOptions, structuralSharing } from './utils.js'

export type MyActionOptions<
  config extends Config,
  selectData = MyActionData,
> = Compute<ExactPartial<MyActionParameters<config>> & ScopeKeyParameter> &
  QueryParameter<MyActionQueryFnData, MyActionErrorType, selectData, MyActionQueryKey<config>>

export function myActionQueryOptions<
  config extends Config,
  selectData = MyActionData,
>(
  config: config,
  options: MyActionOptions<config, selectData> = {},
): MyActionQueryOptions<config, selectData> {
  return {
    ...options.query,
    enabled: Boolean(options.requiredParam && (options.query?.enabled ?? true)),
    queryFn: async (context) => {
      const [, { scopeKey: _, ...parameters }] = context.queryKey
      if (!parameters.requiredParam) throw new Error('requiredParam is required')
      const result = await myAction(config, {
        ...(parameters as MyActionParameters),
        requiredParam: parameters.requiredParam,
      })
      return result ?? null
    },
    queryKey: myActionQueryKey(options),
    structuralSharing, // include when returning complex objects/arrays
  }
}

export type MyActionQueryFnData = Compute<MyActionReturnType>
export type MyActionData = MyActionQueryFnData

export function myActionQueryKey<config extends Config>(
  options: Compute<ExactPartial<MyActionParameters<config>> & ScopeKeyParameter> = {},
) {
  return ['myAction', filterQueryOptions(options)] as const
}

export type MyActionQueryKey<config extends Config> = ReturnType<typeof myActionQueryKey<config>>

export type MyActionQueryOptions<
  config extends Config,
  selectData = MyActionData,
> = QueryOptions<MyActionQueryFnData, MyActionErrorType, selectData, MyActionQueryKey<config>>

Mutation Structure

import type { MutationOptions, MutationParameter } from '../types/query.js'

export type MyActionOptions<config extends Config, context = unknown> = MutationParameter<
  MyActionData,
  MyActionErrorType,
  MyActionVariables<config>,
  context
>

export function myActionMutationOptions<config extends Config, context>(
  config: config,
  options: MyActionOptions<config, context> = {},
): MyActionMutationOptions<config> {
  return {
    ...options.mutation,
    mutationFn: async (variables) => {
      return myAction(config, variables)
    },
    mutationKey: ['myAction'],
  }
}

export type MyActionMutationOptions<config extends Config> = MutationOptions<
  MyActionData,
  MyActionErrorType,
  MyActionVariables<config>
>

Key Rules

  • ExactPartial vs UnionExactPartial: Use ExactPartial for simple types, UnionExactPartial for complex unions (contract actions)
  • enabled: Based on required params being truthy
  • structuralSharing: Include when action returns objects/arrays
  • filterQueryOptions: Filters common non-serializable props. Skip props like onReplaced manually in query key.
  • Query key: Always ['actionName', filterQueryOptions(options)]

Testing

import { config } from '@wagmi/test'
import { expect, test } from 'vitest'
import { myActionQueryOptions } from './myAction.js'

test('default', () => {
  expect(myActionQueryOptions(config, {})).toMatchInlineSnapshot(`
    {
      "enabled": false,
      "queryFn": [Function],
      "queryKey": ["myAction", {}],
    }
  `)
})

test('enabled', () => {
  expect(myActionQueryOptions(config, { requiredParam: 'value' }).enabled).toBe(true)
})

test('queryFn: calls query fn', async () => {
  const options = myActionQueryOptions(config, { requiredParam: 'value' })
  const result = await options.queryFn({ queryKey: options.queryKey } as any)
  expect(result).toMatchInlineSnapshot(`...`)
})

3. Framework Bindings

React Query Hook

'use client'
import type { Config, MyActionErrorType, ResolvedRegister } from '@wagmi/core'
import type { Compute } from '@wagmi/core/internal'
import {
  type MyActionData,
  type MyActionOptions,
  myActionQueryOptions,
} from '@wagmi/core/query'
import type { ConfigParameter } from '../types/properties.js'
import { type UseQueryReturnType, useQuery } from '../utils/query.js'
import { useChainId } from './useChainId.js'
import { useConfig } from './useConfig.js'

export type UseMyActionParameters<
  config extends Config = Config,
  selectData = MyActionData,
> = Compute<MyActionOptions<config, selectData> & ConfigParameter<config>>

export type UseMyActionReturnType<selectData = MyActionData> =
  UseQueryReturnType<selectData, MyActionErrorType>

/** https://wagmi.sh/react/api/hooks/useMyAction */
export function useMyAction<
  config extends Config = ResolvedRegister['config'],
  selectData = MyActionData,
>(
  parameters: UseMyActionParameters<config, selectData> = {},
): UseMyActionReturnType<selectData> {
  const config = useConfig(parameters)
  const chainId = useChainId({ config })
  const options = myActionQueryOptions(config, {
    ...parameters,
    chainId: parameters.chainId ?? chainId,
    query: parameters.query,
  })
  return useQuery(options)
}

React Mutation Hook

'use client'
import { useMutation } from '@tanstack/react-query'
import type { Config, ResolvedRegister, MyActionErrorType } from '@wagmi/core'
import {
  type MyActionData,
  type MyActionMutate,
  type MyActionMutateAsync,
  type MyActionOptions,
  type MyActionVariables,
  myActionMutationOptions,
} from '@wagmi/core/query'
import type { ConfigParameter } from '../types/properties.js'
import type { UseMutationReturnType } from '../utils/query.js'
import { useConfig } from './useConfig.js'

export type UseMyActionParameters<config extends Config = Config, context = unknown> =
  MyActionOptions<config, context> & ConfigParameter<config>

export type UseMyActionReturnType<config extends Con

---

*Content truncated.*

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

643969

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

591705

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

318398

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

339397

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

451339

fastapi-templates

wshobson

Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.

304231

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.