skills/tempo-codegen/tempo-codegen/SKILL.md
Skill for generating Tempo code.
npx skillsauth add aiagentskills/skills tempo-codegenInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When generating actions (in src/tempo/actions/), follow these guidelines.
An example of a generated action set can be found in src/tempo/actions/token.ts.
test/tempo/docs/specs/.test/tempo/docs/specs) and the precompiles (test/tempo/crates/contracts/src/precompiles). Always prefer the precompile interfaces over the specs.All actions must include comprehensive JSDoc with:
@example block - Complete working example showing:
createClient, http, action imports)@param tags - For each parameter (client, parameters)@returns tag - Description of the return valueExample:
/**
* Gets the pool ID for a token pair.
*
* @example
* ```ts
* import { createClient, http } from 'viem'
* import { tempo } from 'tempo.ts/chains'
* import { Actions } from 'tempo.ts/viem'
*
* const client = createClient({
* chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' })
* transport: http(),
* })
*
* const poolId = await Actions.amm.getPoolId(client, {
* userToken: '0x...',
* validatorToken: '0x...',
* })
* ```
*
* @param client - Client.
* @param parameters - Parameters.
* @returns The pool ID.
*/
For view/pure functions that only read state:
readContract from viem/actionsReadContractReturnTypeReadParametersFor state-changing functions, both variants must be implemented:
1. Standard Async Variant
writeContract from viem/actionsexport async function myAction<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: myAction.Parameters<chain, account>,
): Promise<myAction.ReturnValue> {
return myAction.inner(writeContract, client, parameters)
}
2. Sync Variant (*Sync)
Sync suffix (e.g., mintSync, burnSync, rebalanceSwapSync)writeContractSync from viem/actionsextractEvent to get return values (not simulateContract)export async function myActionSync<
chain extends Chain | undefined,
account extends Account | undefined,
>(
client: Client<Transport, chain, account>,
parameters: myActionSync.Parameters<chain, account>,
): Promise<myActionSync.ReturnValue> {
const { throwOnReceiptRevert = true, ...rest } = parameters
const receipt = await myAction.inner(writeContractSync, client, {
...rest,
throwOnReceiptRevert,
} as never)
const { args } = myAction.extractEvent(receipt.logs)
return {
...args,
receipt,
} as never
}
All actions must include the following components within their namespace:
Parameters Type// Read actions
export type Parameters = ReadParameters & Args
// Write actions
export type Parameters<
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = WriteParameters<chain, account> & Args
Args TypeArguments must be documented with JSDoc.
export type Args = {
/** JSDoc for each argument */
argName: Type
}
ReturnValue Type// Read actions
export type ReturnValue = ReadContractReturnType<typeof Abis.myAbi, 'functionName', never>
// Write actions
export type ReturnValue = WriteContractReturnType
ErrorType Type (for write actions)Write actions must include an ErrorType export. Use BaseErrorType from viem as a placeholder with a TODO comment for future exhaustive error typing:
// TODO: exhaustive error type
export type ErrorType = BaseErrorType
call FunctionRequired for all actions - enables composition with other viem actions:
/**
* Defines a call to the `functionName` function.
*
* Can be passed as a parameter to:
* - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call
* - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call
* - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls
*
* @example
* ```ts
* import { createClient, http, walletActions } from 'viem'
* import { tempo } from 'tempo.ts/chains'
* import { Actions } from 'tempo.ts/viem'
*
* const client = createClient({
* chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' })
* transport: http(),
* }).extend(walletActions)
*
* const hash = await client.sendTransaction({
* calls: [actions.amm.myAction.call({ arg1, arg2 })],
* })
* ```
*
* @param args - Arguments.
* @returns The call.
*/
export function call(args: Args) {
return defineCall({
address: Addresses.contractName,
abi: Abis.contractName,
args: [/* transformed args */],
functionName: 'functionName',
})
}
The call function enables these use cases:
sendCalls - Batch multiple calls in one transactionsendTransaction with calls - Send transaction with multiple operationsmulticall - Execute multiple calls in parallelestimateContractGas - Estimate gas costssimulateContract - Simulate executionextractEvent Function (for mutate-based actions)Required for all actions that emit events:
/**
* Extracts the `EventName` event from logs.
*
* @param logs - The logs.
* @returns The `EventName` event.
*/
export function extractEvent(logs: Log[]) {
const [log] = parseEventLogs({
abi: Abis.contractName,
logs,
eventName: 'EventName',
strict: true,
})
if (!log) throw new Error('`EventName` event not found.')
return log
}
inner Function (for write actions)/** @internal */
export async function inner<
action extends typeof writeContract | typeof writeContractSync,
chain extends Chain | undefined,
account extends Account | undefined,
>(
action: action,
client: Client<Transport, chain, account>,
parameters: Parameters<chain, account>,
): Promise<ReturnType<action>> {
const { arg1, arg2, ...rest } = parameters
const call = myAction.call({ arg1, arg2 })
return (await action(client, {
...rest,
...call,
} as never)) as never
}
Organize actions using namespace pattern:
export async function myAction(...) { ... }
export namespace myAction {
export type Parameters = ...
export type Args = ...
export type ReturnValue = ...
export async function inner(...) { ... } // for write actions
export function call(args: Args) { ... }
export function extractEvent(logs: Log[]) { ... } // for mutate actions
}
When encountering situations that require judgment:
Sync suffix (e.g., myActionSync)extractEvent should match contract event names exactlyTests should be co-located with actions in *action-name*.test.ts files. Reference contract tests in test/tempo/crates/precompiles/ for expected behavior.
See src/tempo/actions/token.test.ts for a comprehensive example of test patterns and structure.
Organize tests by action name with a default test case and behavior-specific tests:
describe('actionName', () => {
test('default', async () => {
// Test the primary/happy path scenario
const { receipt, ...result } = await Actions.namespace.actionSync(client, {
param1: value1,
param2: value2,
})
expect(receipt).toBeDefined()
expect(result).toMatchInlineSnapshot(`...`)
})
test('behavior: specific edge case', async () => {
// Test specific behaviors, edge cases, or variations
})
test('behavior: error conditions', async () => {
// Test error handling
await expect(
actions.namespace.actionSync(client, { ... })
).rejects.toThrow()
})
})
describe.todo('unimplementedAction')
documentation
Guides using bun.sys for system calls and file I/O in Zig. Use when implementing file operations instead of std.fs or std.posix.
development
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
development
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
development
Guides writing HMR/Dev Server tests in test/bake/. Use when creating or modifying dev server, hot reloading, or bundling tests.