diff --git a/.changeset/late-socks-accept.md b/.changeset/late-socks-accept.md new file mode 100644 index 00000000..313181b3 --- /dev/null +++ b/.changeset/late-socks-accept.md @@ -0,0 +1,11 @@ +--- +"@macalinao/codama-instruction-accounts-dedupe-visitor": patch +"@macalinao/codama-nodes-from-anchor-x": patch +"@macalinao/codama-renderers-markdown": patch +"@macalinao/codama-renderers-js-esm": patch +"@macalinao/codama-rename-visitor": patch +"@macalinao/clients-kamino-lending": patch +"coda-docs": patch +--- + +Update readmes diff --git a/.changeset/slow-tables-dance.md b/.changeset/slow-tables-dance.md new file mode 100644 index 00000000..7000c67b --- /dev/null +++ b/.changeset/slow-tables-dance.md @@ -0,0 +1,11 @@ +--- +"@macalinao/codama-instruction-accounts-dedupe-visitor": patch +"@macalinao/codama-nodes-from-anchor-x": patch +"@macalinao/codama-renderers-markdown": patch +"@macalinao/codama-renderers-js-esm": patch +"@macalinao/codama-rename-visitor": patch +"@macalinao/clients-kamino-lending": patch +"coda-docs": patch +--- + +Update docs and readmes diff --git a/.changeset/tasty-states-camp.md b/.changeset/tasty-states-camp.md new file mode 100644 index 00000000..a0d5be1a --- /dev/null +++ b/.changeset/tasty-states-camp.md @@ -0,0 +1,5 @@ +--- +"@macalinao/clients-kamino-lending": minor +--- + +Add an index.ts diff --git a/.changeset/tasty-taxes-fly.md b/.changeset/tasty-taxes-fly.md new file mode 100644 index 00000000..ed41ff37 --- /dev/null +++ b/.changeset/tasty-taxes-fly.md @@ -0,0 +1,12 @@ +--- +"@macalinao/codama-instruction-accounts-dedupe-visitor": patch +"@macalinao/codama-nodes-from-anchor-x": patch +"@macalinao/codama-renderers-markdown": patch +"@macalinao/codama-renderers-js-esm": patch +"@macalinao/codama-rename-visitor": patch +"@macalinao/clients-kamino-lending": patch +"@macalinao/coda": patch +"coda-docs": patch +--- + +docs diff --git a/CLAUDE.md b/CLAUDE.md index e2952160..8bcf17cd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -Coda is an automated client generation tool for Solana programs. Built on top of [Codama](https://github.com/codama-idl/codama), Coda provides a zero-config CLI that transforms Anchor IDLs into modern TypeScript clients with full type safety and ES modules support. +Coda is an automated client generation tool for Solana programs. Built on top of [Codama](https://github.com/codama-idl/codama), Coda provides a CLI that transforms Anchor IDLs into modern TypeScript clients with full type safety and ES modules support. The monorepo contains: - **Coda CLI** - The main tool for generating TypeScript clients from Anchor IDLs @@ -71,7 +71,7 @@ coda/ ## Core Packages ### 1. **@macalinao/coda** - CLI for client generation - - Zero-config by default (looks for `./idls/*.json`) + - Works out of the box (looks for `./idls/*.json` by default) - Configurable via `coda.config.mjs` - Generates TypeScript clients with full type safety - Built on Codama for extensibility diff --git a/README.md b/README.md index 9d4ae5cb..cc4154d3 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Automated client generation for Solana programs.

-Coda automatically generates type-safe TypeScript clients from your Anchor IDLs. Built on [Codama](https://github.com/codama-idl/codama), it provides a zero-config CLI that transforms Anchor IDLs into modern TypeScript clients with full type safety and ES modules support. +Coda automatically generates type-safe TypeScript clients from your Anchor IDLs. Built on [Codama](https://github.com/codama-idl/codama), it provides a CLI that transforms Anchor IDLs into modern TypeScript clients with full type safety and ES modules support. ## Documentation diff --git a/apps/docs/content/docs/configuration.mdx b/apps/docs/content/docs/configuration.mdx index dd1c15da..1d7196cb 100644 --- a/apps/docs/content/docs/configuration.mdx +++ b/apps/docs/content/docs/configuration.mdx @@ -3,7 +3,7 @@ title: Configuration description: Customize Coda generation with coda.config.mjs --- -Coda works zero-config out of the box, but you can customize its behavior with a `coda.config.mjs` file. +Coda works out of the box with sensible defaults, but you can customize its behavior with a `coda.config.mjs` file. ## Initialize Configuration diff --git a/apps/docs/content/docs/meta.json b/apps/docs/content/docs/meta.json index 81969ebe..98942d13 100644 --- a/apps/docs/content/docs/meta.json +++ b/apps/docs/content/docs/meta.json @@ -11,9 +11,8 @@ "generating-clients", "generating-docs", "examples", - "---Packages---", - "packages", "---Reference---", + "packages", "api" ] } diff --git a/apps/docs/content/docs/packages/coda.mdx b/apps/docs/content/docs/packages/coda.mdx index 62fa9f15..4a139e66 100644 --- a/apps/docs/content/docs/packages/coda.mdx +++ b/apps/docs/content/docs/packages/coda.mdx @@ -3,7 +3,7 @@ title: "@macalinao/coda" description: The main CLI tool for automated client generation from Solana IDLs --- -The core Coda package provides a zero-config CLI that transforms Anchor IDLs into modern TypeScript clients with full type safety and ES modules support. +The core Coda package provides a CLI that transforms Anchor IDLs into modern TypeScript clients with full type safety and ES modules support. ## Installation @@ -18,7 +18,7 @@ npm install -D @macalinao/coda ## Features -- 🚀 **Zero configuration** - Works out of the box with sensible defaults +- 🚀 **Minimal configuration** - Works out of the box with sensible defaults - 🔧 **Fully customizable** - Extend and transform generated code with visitors - 📦 **ES modules native** - Modern JavaScript with proper `.js` extensions - 🎯 **Type-safe** - Full TypeScript support with precise types @@ -54,7 +54,7 @@ Options: ## Configuration -### Zero-Config (Default) +### Default Configuration Coda works without any configuration by looking for IDLs in `./idls/*.json`: @@ -309,25 +309,123 @@ Use the dedupe visitor to flatten nested account structures: ```javascript import { instructionAccountsDedupeVisitor } from "@macalinao/codama-instruction-accounts-dedupe-visitor"; +export default defineConfig({ + visitors: ({ idl }) => [ + instructionAccountsDedupeVisitor(idl) + ] +}); +``` + +### Renaming Conflicts + +Resolve naming conflicts between multiple programs: + +```javascript +import { renameVisitor } from "@macalinao/codama-rename-visitor"; + export default defineConfig({ visitors: [ - instructionAccountsDedupeVisitor() + renameVisitor({ + programA: { + instructions: { + transfer: "transferProgramA" + } + }, + programB: { + instructions: { + transfer: "transferProgramB" + } + } + }) ] }); ``` -### Custom Renderers +## Documentation Generation + +Generate markdown documentation alongside your TypeScript clients: + +```bash +coda docs [options] + +Options: + -i, --idl Path to Anchor IDL file (default: "./idls/*.json") + -o, --output Output directory (default: "./docs") + -c, --config Path to config file (default: "./coda.config.mjs") +``` + +### Basic Usage + +```bash +# Generate documentation +coda docs + +# Custom output directory +coda docs -o ./api-docs +``` + +### With Configuration -Use alternative renderers for different output formats: +Add documentation generation to your config: ```javascript -import { renderJavaScriptEsmVisitor } from "@macalinao/codama-renderers-js-esm"; +import { renderMarkdownVisitor } from "@macalinao/codama-renderers-markdown"; export default defineConfig({ - visitors: ({ idl }) => { - const codama = createFromIdls([idl]); - codama.accept(renderJavaScriptEsmVisitor("./src/generated")); - return []; - } + visitors: [ + renderMarkdownVisitor("./docs") + ] }); -``` \ No newline at end of file +``` + +## Best Practices + +1. **Keep IDLs up-to-date**: Run `anchor build` before generating clients +2. **Use TypeScript**: The generated code provides full type safety +3. **Add custom PDAs**: Define program-derived addresses in your config +4. **Document your programs**: Add descriptions in your Anchor programs +5. **Version your clients**: Generate clients for each program version + +## Troubleshooting + +### IDL Not Found + +If Coda can't find your IDL: + +1. Check the default location: `./idls/*.json` +2. Specify explicit path: `coda generate -i path/to/idl.json` +3. Ensure Anchor program is built: `anchor build` + +### Import Errors + +If you see module resolution errors: + +1. Ensure `"type": "module"` is in your package.json +2. Check that tsconfig.json uses `"moduleResolution": "NodeNext"` +3. Verify all local imports use `.js` extensions + +### Type Errors + +If TypeScript shows errors: + +1. Run `bun install` to ensure dependencies are installed +2. Check that `@solana/web3.js` is installed +3. Verify tsconfig includes the generated directory + +## Examples + +### Single Program + +See the [token-metadata client](https://github.com/macalinao/coda/tree/master/clients/token-metadata) for a complete example of a single program setup. + +### Multiple Programs + +See the [Quarry client](https://github.com/macalinao/coda/tree/master/clients/quarry) for an example with multiple programs and custom visitors. + +## Related Packages + +- [@macalinao/codama-renderers-js-esm](/docs/packages/codama-renderers-js-esm) - ESM-native TypeScript renderer +- [@macalinao/codama-instruction-accounts-dedupe-visitor](/docs/packages/codama-instruction-accounts-dedupe-visitor) - Flatten nested accounts +- [@macalinao/codama-rename-visitor](/docs/packages/codama-rename-visitor) - Rename instructions and accounts +- [@macalinao/codama-renderers-markdown](/docs/packages/codama-renderers-markdown) - Generate documentation +- [@macalinao/codama-nodes-from-anchor-x](/docs/packages/codama-nodes-from-anchor-x) - Parse multiple IDLs \ No newline at end of file diff --git a/apps/docs/content/docs/packages/codama-instruction-accounts-dedupe-visitor.mdx b/apps/docs/content/docs/packages/codama-instruction-accounts-dedupe-visitor.mdx index c505defe..f0002f58 100644 --- a/apps/docs/content/docs/packages/codama-instruction-accounts-dedupe-visitor.mdx +++ b/apps/docs/content/docs/packages/codama-instruction-accounts-dedupe-visitor.mdx @@ -54,12 +54,14 @@ Use it in your `coda.config.mjs`: ```javascript import { defineConfig } from "@macalinao/coda"; import { instructionAccountsDedupeVisitor } from "@macalinao/codama-instruction-accounts-dedupe-visitor"; +import fs from "fs"; export default defineConfig({ idlPath: "./idls/my_program.json", outputDir: "./src/generated", - visitors: [ - instructionAccountsDedupeVisitor() + visitors: (idl) => [ + // Pass the IDL to the visitor + instructionAccountsDedupeVisitor(idl) ] }); ``` @@ -147,11 +149,11 @@ When flattening accounts, PDA seeds are also updated to reflect the new structur Creates a visitor that flattens nested instruction accounts: ```typescript -function instructionAccountsDedupeVisitor(idl?: Idl): Visitor; +function instructionAccountsDedupeVisitor(idl: AnchorIdl): Visitor; ``` **Parameters:** -- `idl` (optional): The Anchor IDL to use for context during transformation +- `idl`: The Anchor IDL containing the instruction definitions with potentially nested accounts **Returns:** - A Codama visitor that can be applied to transform the AST diff --git a/apps/docs/content/docs/packages/codama-nodes-from-anchor-x.mdx b/apps/docs/content/docs/packages/codama-nodes-from-anchor-x.mdx new file mode 100644 index 00000000..8b605183 --- /dev/null +++ b/apps/docs/content/docs/packages/codama-nodes-from-anchor-x.mdx @@ -0,0 +1,197 @@ +--- +title: "@macalinao/codama-nodes-from-anchor-x" +description: Create Codama root nodes from multiple Anchor IDLs with enhanced support +--- + +This package extends Codama's Anchor IDL parsing capabilities to support multiple IDLs and provides enhanced compatibility for various Anchor versions. + +## Installation + +```bash +npm install @macalinao/codama-nodes-from-anchor-x +``` + +## Features + +- **Multiple IDL Support**: Parse and combine multiple Anchor IDLs into a single Codama root node +- **Version Compatibility**: Supports both Anchor v0.0.0 and v0.1.0 IDL formats +- **Enhanced Parsing**: Flattens nested account structures for better code generation +- **Type Safety**: Full TypeScript support with proper type exports + +## Usage + +### Single IDL + +For projects with a single Anchor program: + +```typescript +import { rootNodeFromAnchor } from "@macalinao/codama-nodes-from-anchor-x"; +import { createFromRoot } from "codama"; + +// Load your IDL +const idl = JSON.parse(fs.readFileSync("./idl.json", "utf-8")); + +// Create a root node +const root = rootNodeFromAnchor(idl); + +// Use with Codama +const codama = createFromRoot(root); +``` + +### Multiple IDLs + +For projects with multiple programs (like Quarry): + +```typescript +import { rootNodeFromAnchorIdls } from "@macalinao/codama-nodes-from-anchor-x"; + +// Load multiple IDLs +const idls = [ + JSON.parse(fs.readFileSync("./idls/program1.json", "utf-8")), + JSON.parse(fs.readFileSync("./idls/program2.json", "utf-8")), + JSON.parse(fs.readFileSync("./idls/program3.json", "utf-8")), +]; + +// Create a root node containing all programs +const root = rootNodeFromAnchorIdls(idls); + +// The first IDL becomes the main program +// Additional IDLs are added as additional programs +``` + +### Program Node Only + +Get just the program node without the root wrapper: + +```typescript +import { programNodeFromAnchor } from "@macalinao/codama-nodes-from-anchor-x"; + +// Get the program node directly +const program = programNodeFromAnchor(idl); +``` + +## API Reference + +### `rootNodeFromAnchor(idl: Idl): RootNode` + +Creates a Codama root node from a single Anchor IDL. + +**Parameters:** +- `idl`: Anchor IDL object (v0.0.0 or v0.1.0) + +**Returns:** +- Codama `RootNode` containing the parsed program + +### `rootNodeFromAnchorIdls(idls: Idl[]): RootNode` + +Creates a Codama root node from multiple Anchor IDLs. + +**Parameters:** +- `idls`: Array of Anchor IDL objects + +**Returns:** +- Codama `RootNode` with the first IDL as the main program and others as additional programs + +### `programNodeFromAnchor(idl: Idl): ProgramNode` + +Creates a Codama program node from an Anchor IDL. + +**Parameters:** +- `idl`: Anchor IDL object + +**Returns:** +- Codama `ProgramNode` without the root wrapper + +## Handling Multiple Programs + +When working with multiple IDLs, be aware of potential naming conflicts: + +```typescript +import { renameVisitor } from "@macalinao/codama-rename-visitor"; + +// Rename conflicting instructions +const visitor = renameVisitor({ + programA: { + instructions: { + transfer: "transferA", + }, + }, + programB: { + instructions: { + transfer: "transferB", + }, + }, +}); + +// Apply to the root node +const updatedRoot = visit(root, visitor); +``` + +## Version Support + +This package supports multiple Anchor IDL versions: + +- **v0.0.0**: Legacy format with `metadata.address` +- **v0.1.0**: Current format with `address` field + +The package automatically detects and handles the version differences. + +## Integration with Coda + +This package is the default parser for [Coda](https://coda.ianm.com), providing the foundation for generating TypeScript clients: + +```javascript +import { defineConfig } from "@macalinao/coda"; +import { rootNodeFromAnchorIdls } from "@macalinao/codama-nodes-from-anchor-x"; + +export default defineConfig({ + idlPath: ["./idls/*.json"], + // Uses rootNodeFromAnchorIdls internally for multiple IDLs +}); +``` + +## Examples + +### Real-World Usage + +The [Quarry client](https://github.com/macalinao/coda/tree/master/clients/quarry) uses this package to parse 6 different program IDLs: + +```javascript +const idls = [ + quarryMine, + quarryMergeMine, + quarryMintWrapper, + quarryOperator, + quarryRedeemer, + quarryRegistry, +]; + +const root = rootNodeFromAnchorIdls(idls); +``` + +### Migration Support + +Support multiple versions of the same program: + +```typescript +const idls = [ + currentVersionIdl, + legacyVersionIdl, +]; + +const root = rootNodeFromAnchorIdls(idls); +// Both versions available for migration tools +``` + +## Best Practices + +1. **Order Matters**: The first IDL becomes the main program, so order them by importance +2. **Handle Conflicts**: Use `renameVisitor` to resolve naming conflicts between programs +3. **Version Check**: Ensure your IDLs are compatible versions before parsing +4. **Type Safety**: Use TypeScript for better type inference and safety + +## See Also + +- [Coda CLI Documentation](/docs/getting-started) - Automated client generation +- [codama-rename-visitor](/docs/packages/codama-rename-visitor) - Handle naming conflicts +- [codama-instruction-accounts-dedupe-visitor](/docs/packages/codama-instruction-accounts-dedupe-visitor) - Flatten nested accounts \ No newline at end of file diff --git a/apps/docs/content/docs/packages/codama-rename-visitor.mdx b/apps/docs/content/docs/packages/codama-rename-visitor.mdx index 19228e8f..de68209a 100644 --- a/apps/docs/content/docs/packages/codama-rename-visitor.mdx +++ b/apps/docs/content/docs/packages/codama-rename-visitor.mdx @@ -1,9 +1,9 @@ --- title: "@macalinao/codama-rename-visitor" -description: Codama visitor for renaming instructions, events, and types within Solana programs +description: Codama visitor for renaming accounts, instructions, and defined types within Solana programs --- -This package provides flexible visitors for renaming instructions, events, and defined types in your Codama AST. It's particularly useful when you want to change naming conventions without modifying the original IDL. +This package provides flexible visitors for renaming accounts, instructions, and defined types in your Codama AST. It's particularly useful when working with multiple programs that may have naming conflicts. ## Installation @@ -18,12 +18,12 @@ npm install -D @macalinao/codama-rename-visitor ## Why Use This Package? -When working with Solana programs, you might need to: +When working with multiple Solana programs, you might need to: - **Avoid naming conflicts** between multiple programs - **Follow consistent naming conventions** across your codebase - **Add context** to generic instruction names -- **Maintain backward compatibility** while improving naming +- **Customize generated code** without modifying the original IDL This visitor allows you to rename elements at the AST level, ensuring all references are updated correctly throughout the generated code. @@ -41,16 +41,23 @@ import { visit } from "codama"; const visitor = renameVisitor({ quarryMine: { instructions: { - claimRewards: "claimRewardsMine" + claimRewards: "claimRewardsMine", + stake: "stakeInQuarry" + }, + accounts: { + miner: "quarryMiner" + }, + definedTypes: { + StakeEvent: "QuarryStakeEvent" } }, - token: { + quarryMergeMine: { instructions: { - transfer: "transferTokens", - mint: "mintNft" + claimRewards: "claimRewardsMergeMine", + stake: "stakeInMergePool" }, - events: { - tokenMinted: "nftMinted" + accounts: { + miner: "mergeMiner" } } }); @@ -91,7 +98,7 @@ export default defineConfig({ ### Renaming Specific Element Types -For simpler use cases, you can rename just instructions or events across all programs: +For simpler use cases, you can rename specific types of elements across all programs: #### Rename Instructions Only @@ -99,49 +106,39 @@ For simpler use cases, you can rename just instructions or events across all pro import { renameInstructionsVisitor } from "@macalinao/codama-rename-visitor"; const visitor = renameInstructionsVisitor({ - oldInstructionName: "newInstructionName", transfer: "transferTokens", - mint: "mintNft" + mint: "mintNft", + burn: "burnToken" }); const updatedRoot = visit(root, visitor); ``` -#### Rename Events Only +#### Rename Accounts Only ```typescript -import { renameEventsVisitor } from "@macalinao/codama-rename-visitor"; +import { renameAccountsVisitor } from "@macalinao/codama-rename-visitor"; -const visitor = renameEventsVisitor({ - oldEventName: "newEventName", - tokenMinted: "nftMinted", - transferComplete: "transferFinished" +const visitor = renameAccountsVisitor({ + userAccount: "user", + configAccount: "config", + metadataAccount: "metadata" }); const updatedRoot = visit(root, visitor); ``` -### Legacy Single-Program Format - -For backward compatibility, you can use the legacy format for renaming in a single program: +#### Rename Defined Types Only ```typescript -import { renameVisitor } from "@macalinao/codama-rename-visitor"; +import { renameDefinedTypesVisitor } from "@macalinao/codama-rename-visitor"; -// Legacy format: applies to the current program -const visitor = renameVisitor({ - instructions: { - transfer: "transferTokens", - mint: "mintNft" - }, - events: { - tokenMinted: "nftMinted", - transferComplete: "transferFinished" - }, - definedTypes: { - TokenMetadata: "NftMetadata" - } +const visitor = renameDefinedTypesVisitor({ + TokenMetadata: "NftMetadata", + TransferEvent: "TokenTransferEvent" }); + +const updatedRoot = visit(root, visitor); ``` ## API Reference @@ -152,28 +149,19 @@ The main visitor for comprehensive renaming: ```typescript function renameVisitor( - config: RenameConfig | LegacyRenameConfig + renamesByProgram: Record ): Visitor; -// Program-specific renaming (recommended) -interface RenameConfig { - [programName: string]: ProgramRenameOptions; -} - interface ProgramRenameOptions { + accounts?: Record; instructions?: Record; - events?: Record; - definedTypes?: Record; -} - -// Legacy single-program format -interface LegacyRenameConfig { - instructions?: Record; - events?: Record; definedTypes?: Record; } ``` +**Parameters:** +- `renamesByProgram`: Object mapping program names to their rename configurations + ### renameInstructionsVisitor Visitor for renaming only instructions: @@ -187,24 +175,50 @@ function renameInstructionsVisitor( **Parameters:** - `mapping`: Object mapping old instruction names to new names -### renameEventsVisitor +### renameAccountsVisitor + +Visitor for renaming only accounts: + +```typescript +function renameAccountsVisitor( + mapping: Record +): Visitor; +``` + +**Parameters:** +- `mapping`: Object mapping old account names to new names + +### renameDefinedTypesVisitor -Visitor for renaming only events (defined types): +Visitor for renaming only defined types: ```typescript -function renameEventsVisitor( +function renameDefinedTypesVisitor( mapping: Record ): Visitor; ``` **Parameters:** -- `mapping`: Object mapping old event names to new names +- `mapping`: Object mapping old type names to new names + +### Transform Functions + +The package also exports transform functions that can be used directly: + +```typescript +// Transform individual nodes +renameInstructionTransform(node, mapping); +renameAccountTransform(node, mapping); +renameDefinedTypeTransform(node, mapping); +``` + +These are useful when building custom visitors or transforming nodes directly. ## Use Cases ### Avoiding Naming Conflicts -When working with multiple related programs: +When working with multiple related programs like Quarry: ```typescript renameVisitor({ @@ -212,14 +226,24 @@ renameVisitor({ quarryMine: { instructions: { createMiner: "createQuarryMiner", - stake: "stakeInQuarry" + stake: "stakeInQuarry", + claimRewards: "claimQuarryRewards" + }, + accounts: { + miner: "quarryMiner", + quarry: "quarryAccount" } }, // Quarry Merge Mine program quarryMergeMine: { instructions: { createMiner: "createMergeMiner", - stake: "stakeInMergePool" + stake: "stakeInMergePool", + claimRewards: "claimMergeRewards" + }, + accounts: { + miner: "mergeMiner", + pool: "mergePool" } } }) @@ -234,13 +258,23 @@ renameVisitor({ token: { instructions: { transfer: "transferToken", - burn: "burnToken" + burn: "burnToken", + mint: "mintToken" + }, + accounts: { + account: "tokenAccount", + mint: "tokenMint" } }, nft: { instructions: { transfer: "transferNft", - burn: "burnNft" + burn: "burnNft", + mint: "mintNft" + }, + accounts: { + metadata: "nftMetadata", + edition: "nftEdition" } } }) @@ -254,15 +288,45 @@ Enforce naming patterns across your codebase: renameVisitor({ myProgram: { instructions: { - // Convert to camelCase + // Convert snake_case to camelCase create_account: "createAccount", update_metadata: "updateMetadata", delete_record: "deleteRecord" }, - events: { - // Add "Event" suffix - accountCreated: "accountCreatedEvent", - metadataUpdated: "metadataUpdatedEvent" + definedTypes: { + // Add consistent suffixes + AccountCreated: "AccountCreatedEvent", + MetadataUpdated: "MetadataUpdatedEvent", + RecordDeleted: "RecordDeletedEvent" + } + } +}) +``` + +## Real-World Example + +The Quarry client uses this visitor to handle conflicts between multiple programs: + +```javascript +// From clients/quarry/coda.config.mjs +renameVisitor({ + quarryMine: { + instructions: { + claimRewards: "claimRewardsMine", + claimRewardsV2: "claimRewardsMineV2", + extractFees: "extractFeesMine", + pause: "pauseMine", + rescueTokens: "rescueTokensMine", + unpause: "unpauseMine", + // ... more renames + } + }, + quarryMergeMine: { + instructions: { + claimRewards: "claimRewardsMergeMine", + initMergeMiner: "initMergeMinerV2", + initMiner: "initMinerMergeMine", + withdrawTokens: "withdrawTokensMergeMine" } } }) @@ -274,6 +338,7 @@ renameVisitor({ 2. **Document Renames**: Comment why certain renames are necessary 3. **Be Consistent**: Apply similar naming patterns across related programs 4. **Test Generated Code**: Verify that renamed elements work correctly in your client code +5. **Order Matters**: Apply rename visitors early in your visitor chain ## Troubleshooting @@ -282,18 +347,23 @@ renameVisitor({ Ensure the visitor is added to your configuration and that names match exactly: ```javascript -// Check that program names match your IDL -console.log(idl.metadata.name); // Should match keys in renameVisitor config +// Program names must match your IDL +console.log(idl.metadata?.name || idl.name); // Should match keys in renameVisitor config ``` ### Type Errors After Renaming Make sure all references are updated. The visitor handles most cases, but verify: - Instruction builders use new names -- Event types use new names -- PDA derivations reference correct instruction names +- Account types use new names +- Defined types are correctly referenced + +### Case Sensitivity + +All names are converted to camelCase automatically. The visitor handles this conversion for you. ## Related Packages -- [@macalinao/coda](./coda) - Main CLI for client generation -- [@macalinao/codama-instruction-accounts-dedupe-visitor](./codama-instruction-accounts-dedupe-visitor) - Flatten nested accounts \ No newline at end of file +- [@macalinao/coda](/docs/packages/coda) - Main CLI for client generation +- [@macalinao/codama-instruction-accounts-dedupe-visitor](/docs/packages/codama-instruction-accounts-dedupe-visitor) - Flatten nested accounts +- [@macalinao/codama-nodes-from-anchor-x](/docs/packages/codama-nodes-from-anchor-x) - Parse multiple IDLs \ No newline at end of file diff --git a/apps/docs/content/docs/packages/codama-renderers-js-esm.mdx b/apps/docs/content/docs/packages/codama-renderers-js-esm.mdx index 7c4c5a50..ea7306cf 100644 --- a/apps/docs/content/docs/packages/codama-renderers-js-esm.mdx +++ b/apps/docs/content/docs/packages/codama-renderers-js-esm.mdx @@ -12,6 +12,7 @@ bun add -D @macalinao/codama-renderers-js-esm ``` Or with npm: + ```bash npm install -D @macalinao/codama-renderers-js-esm ``` @@ -60,7 +61,7 @@ export default defineConfig({ // Custom options if needed }); return [visitor]; - } + }, }); ``` @@ -71,6 +72,7 @@ export default defineConfig({ All relative imports automatically get `.js` extensions: #### Before (Standard Renderer) + ```typescript import { Address } from "@solana/web3.js"; import { SomeType } from "./types"; @@ -79,6 +81,7 @@ export * from "./instructions"; ``` #### After (ESM Renderer) + ```typescript import { Address } from "@solana/web3.js"; import { SomeType } from "./types/index.js"; @@ -104,10 +107,14 @@ Loose equality checks are replaced with strict checks: ```typescript // Before -if (value == null) { /* ... */ } +if (value == null) { + /* ... */ +} // After -if (value === null || value === undefined) { /* ... */ } +if (value === null || value === undefined) { + /* ... */ +} ``` ### 4. Universal JavaScript Compatibility @@ -121,14 +128,14 @@ Removes Node.js-specific code for broader runtime support: ## Comparison with Standard Renderer -| Feature | @codama/renderers-js | @macalinao/codama-renderers-js-esm | -|---------|----------------------|-------------------------------------| -| Module Format | CommonJS-compatible | Pure ESM | -| Import Extensions | No extensions | `.js` extensions | -| TypeScript Config | Standard | ESM-native | -| Runtime Checks | Node.js-specific | Universal | -| Null Checks | Loose (`==`) | Strict (`===`) | -| Tree Shaking | Good | Excellent | +| Feature | @codama/renderers-js | @macalinao/codama-renderers-js-esm | +| ----------------- | -------------------- | ---------------------------------- | +| Module Format | CommonJS-compatible | Pure ESM | +| Import Extensions | No extensions | `.js` extensions | +| TypeScript Config | Standard | ESM-native | +| Runtime Checks | Node.js-specific | Universal | +| Null Checks | Loose (`==`) | Strict (`===`) | +| Tree Shaking | Good | Excellent | ## Configuration @@ -139,12 +146,10 @@ Ensure your `tsconfig.json` is configured for ESM: ```json { "compilerOptions": { - "module": "ESNext", - "moduleResolution": "bundler", - "target": "ES2022", - "allowImportingTsExtensions": false, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ES2024", + "lib": ["ES2024"] } } ``` @@ -184,6 +189,7 @@ interface RenderOptions { ``` **Parameters:** + - `outputDir`: Directory where files will be generated - `options`: Optional configuration for the renderer @@ -236,23 +242,10 @@ If you see "Cannot find module" errors: 2. Check that `"type": "module"` is in package.json 3. Ensure TypeScript module resolution is correct -### Type Resolution Issues - -For TypeScript type resolution: - -```json -// tsconfig.json -{ - "compilerOptions": { - "moduleResolution": "bundler", - // or "node16" / "nodenext" for Node.js - } -} -``` - ### Build Tool Compatibility Works with modern build tools: + - **Vite**: Full support out of the box - **esbuild**: Works with ESM configuration - **Rollup**: Native ESM support @@ -262,4 +255,4 @@ Works with modern build tools: - [@macalinao/coda](./coda) - Main CLI using this renderer by default - [@codama/renderers-js](https://github.com/codama-idl/codama) - Original JavaScript renderer -- [@macalinao/codama-renderers-markdown](./codama-renderers-markdown) - Markdown documentation renderer \ No newline at end of file +- [@macalinao/codama-renderers-markdown](./codama-renderers-markdown) - Markdown documentation renderer diff --git a/apps/docs/content/docs/packages/codama-renderers-markdown.mdx b/apps/docs/content/docs/packages/codama-renderers-markdown.mdx index f4286526..6cd62252 100644 --- a/apps/docs/content/docs/packages/codama-renderers-markdown.mdx +++ b/apps/docs/content/docs/packages/codama-renderers-markdown.mdx @@ -5,30 +5,22 @@ description: Codama visitor that renders comprehensive markdown documentation fr This package generates beautiful, comprehensive markdown documentation from your Solana program IDLs using the Codama AST. -## Why Use This Package? - -Documentation is critical for Solana program adoption, but manually maintaining API docs is time-consuming and error-prone. This package solves these problems by: - -- **Eliminating Documentation Drift**: Your docs always match your deployed program since they're generated from the same IDL -- **Providing Complete Coverage**: Every instruction, account, type, and error is automatically documented -- **Saving Development Time**: No more manually writing and updating API documentation -- **Ensuring Consistency**: All programs in your project follow the same documentation format -- **Enabling Better Developer Experience**: Well-documented programs get more adoption - -## Live Examples +## Example Output See real documentation generated by this package: -### [Quarry Protocol Documentation](https://coda-docs.vercel.app/docs/api/clients/quarry) +### [Quarry Protocol Documentation](https://github.com/macalinao/coda/tree/master/clients/quarry/docs) -The Quarry staking protocol documentation showcases the comprehensive output: -- **[60+ Instructions](https://coda-docs.vercel.app/docs/api/clients/quarry/instructions)** - Every instruction with full parameter documentation -- **[Account Structures](https://coda-docs.vercel.app/docs/api/clients/quarry/accounts)** - All accounts with field descriptions and sizes -- **[PDA Derivations](https://coda-docs.vercel.app/docs/api/clients/quarry/pdas)** - Program-derived addresses with seed definitions -- **[Custom Types](https://coda-docs.vercel.app/docs/api/clients/quarry/types)** - All custom types and enums -- **[Error Codes](https://coda-docs.vercel.app/docs/api/clients/quarry/errors)** - Every error with code and message +The Quarry staking protocol documentation showcases the comprehensive output across 6 programs: -### [Token Metadata Documentation](https://coda-docs.vercel.app/docs/api/clients/token-metadata) +- **[Quarry Mine](https://github.com/macalinao/coda/blob/master/clients/quarry/docs/quarry-mine.md)** - Core staking program with 20+ instructions +- **[Quarry Merge Mine](https://github.com/macalinao/coda/blob/master/clients/quarry/docs/quarry-merge-mine.md)** - Pool staking across multiple quarries +- **[Quarry Mint Wrapper](https://github.com/macalinao/coda/blob/master/clients/quarry/docs/quarry-mint-wrapper.md)** - Mint wrapper for staking rewards +- **[Quarry Operator](https://github.com/macalinao/coda/blob/master/clients/quarry/docs/quarry-operator.md)** - Delegate operator management +- **[Quarry Redeemer](https://github.com/macalinao/coda/blob/master/clients/quarry/docs/quarry-redeemer.md)** - IOU token redemption +- **[Quarry Registry](https://github.com/macalinao/coda/blob/master/clients/quarry/docs/quarry-registry.md)** - Rewarder registry + +### [Token Metadata Documentation](https://github.com/macalinao/coda/blob/master/clients/token-metadata/docs/mpl-token-metadata.md) Metaplex Token Metadata program documentation demonstrating complex type handling. @@ -41,6 +33,7 @@ bun add -D @macalinao/codama-renderers-markdown ``` Or with npm: + ```bash npm install -D @macalinao/codama-renderers-markdown ``` @@ -53,10 +46,7 @@ The easiest way to use this package is through the [Coda CLI](https://coda.ianm. # Install Coda CLI bun add -D @macalinao/coda -# Generate both TypeScript client and markdown docs -coda generate --docs - -# Or just generate documentation +# Generate documentation coda docs ``` @@ -97,8 +87,8 @@ export default defineConfig({ outputDir: "./src/generated", visitors: [ // Generate both TypeScript and documentation - renderMarkdownVisitor("./docs/api") - ] + renderMarkdownVisitor("./docs/api"), + ], }); ``` @@ -109,142 +99,14 @@ Configure the output format: ```typescript const visitor = renderMarkdownVisitor("./docs", { // Format program addresses (e.g., link to explorer) - formatAddress: (address) => + formatAddress: (address) => `[${address}](https://explorer.solana.com/address/${address})`, - + // Control table of contents generation renderTableOfContents: true, }); ``` -## Generated Documentation Structure - -The renderer creates a comprehensive markdown file with the following sections: - -### 1. Program Overview - -```markdown -# Program Name - -Program description from IDL metadata - -**Program ID:** `11111111111111111111111111111111` -``` - -### 2. Table of Contents - -Automatically generated with links to all sections: - -```markdown -## Table of Contents - -- [Accounts](#accounts) - - [TokenAccount](#tokenaccount) - - [Metadata](#metadata) -- [Instructions](#instructions) - - [Transfer](#transfer) - - [Mint](#mint) -- [PDAs](#pdas) - - [Authority](#authority) -- [Types](#types) -- [Errors](#errors) -``` - -### 3. Accounts Section - -Detailed documentation for each account: - -```markdown -## Accounts - -### TokenAccount - -Token account storing balance and owner information - -| Field | Type | Description | -|-------|------|-------------| -| mint | `PublicKey` | Token mint address | -| owner | `PublicKey` | Account owner | -| amount | `u64` | Token balance | - -**Size:** 165 bytes -**Discriminator:** `[1, 2, 3, 4, 5, 6, 7, 8]` -``` - -### 4. Instructions Section - -Complete instruction documentation: - -```markdown -## Instructions - -### Transfer - -Transfer tokens between accounts - -#### Accounts - -| Name | Type | Description | -|------|------|-------------| -| source | `mut` | Source token account | -| destination | `mut` | Destination token account | -| authority | `signer` | Transfer authority | - -#### Arguments - -| Name | Type | Description | -|------|------|-------------| -| amount | `u64` | Amount to transfer | -``` - -### 5. PDAs Section - -Program-derived address documentation: - -```markdown -## PDAs - -### Authority - -Derives the program authority address - -**Seeds:** -- `"authority"` (constant) -- `user` (PublicKey) -- `mint` (PublicKey) -``` - -### 6. Types Section - -Custom type definitions: - -```markdown -## Types - -### TokenMetadata - -```typescript -type TokenMetadata = { - name: string; - symbol: string; - uri: string; - decimals: u8; -} -``` - -### 7. Errors Section - -Program error codes: - -```markdown -## Errors - -| Code | Name | Message | -|------|------|---------| -| 6000 | InvalidAmount | The provided amount is invalid | -| 6001 | Unauthorized | Unauthorized access attempt | -``` - ## API Reference ### renderMarkdownVisitor @@ -260,13 +122,14 @@ function renderMarkdownVisitor( interface MarkdownOptions { // Format addresses in the output formatAddress?: (address: string) => string; - + // Whether to render table of contents (default: true) renderTableOfContents?: boolean; } ``` **Parameters:** + - `outputDir`: Directory where markdown files will be generated - `options`: Optional configuration for formatting @@ -275,6 +138,7 @@ interface MarkdownOptions { ### Comprehensive Coverage Documents all aspects of your program: + - ✅ Accounts with all fields and metadata - ✅ Instructions with accounts and arguments - ✅ PDAs with seed definitions @@ -299,98 +163,19 @@ Types are rendered in familiar TypeScript syntax: type TransferArgs = { amount: bigint; memo?: string; -} -``` - -## Use Cases - -### Documentation Sites - -Generate API documentation for your documentation site: - -```bash -# Generate docs -coda generate-docs - -# Use with MkDocs, Docusaurus, etc. -cp ./docs/api.md ./website/docs/ -``` - -### GitHub README - -Include generated documentation in your repository: - -```javascript -// In your build script -visit(root, renderMarkdownVisitor("./")); -// Creates README.md with full API docs -``` - -### Multiple Programs - -Document multiple programs in one project: - -```javascript -// For each program -programs.forEach(program => { - const root = rootNodeFromAnchor(program.idl); - visit(root, renderMarkdownVisitor( - `./docs/${program.name}` - )); -}); -``` - -## Best Practices - -1. **Keep IDL Descriptions Updated**: Add descriptions to your Anchor program for better docs -2. **Use Semantic Names**: Clear naming improves generated documentation -3. **Version Your Docs**: Generate docs for each program version -4. **Link to Examples**: Add links to usage examples in your custom sections - -## Example Output - -Here's a snippet of generated documentation: - -```markdown -# Token Program - -A standard SPL token program implementation - -**Program ID:** `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` - -## Instructions - -### Transfer - -Transfers tokens from one account to another - -#### Accounts - -| Name | Type | Description | -|------|------|-------------| -| source | `mut` | Source token account | -| destination | `mut` | Destination token account | -| authority | `signer` | Account owner or delegate | - -#### Arguments - -| Name | Type | Description | -|------|------|-------------| -| amount | `u64` | Number of tokens to transfer | - ---- +}; ``` ## Integration with Coda -This renderer integrates seamlessly with Coda's `generate-docs` command: +This renderer integrates seamlessly with Coda's `docs` command: ```bash -# Generate both TypeScript client and markdown docs -coda generate --docs +# Generate documentation +coda docs -# Or just generate documentation -coda generate-docs +# Generate TypeScript client and documentation +coda generate && coda docs ``` ## Troubleshooting @@ -410,22 +195,8 @@ pub struct TokenAccount { } ``` -### Large Output Files - -For very large programs, consider splitting documentation: - -```typescript -// Split by component type -visit(root, renderMarkdownVisitor("./docs/accounts", { - components: ["accounts"] -})); -visit(root, renderMarkdownVisitor("./docs/instructions", { - components: ["instructions"] -})); -``` - ## Related Packages - [@macalinao/coda](./coda) - Main CLI for client generation - [@macalinao/codama-renderers-js-esm](./codama-renderers-js-esm) - TypeScript client renderer -- [@codama/nodes-from-anchor](https://github.com/codama-idl/codama) - Parse Anchor IDLs \ No newline at end of file +- [@codama/nodes-from-anchor](https://github.com/codama-idl/codama) - Parse Anchor IDLs diff --git a/apps/docs/content/docs/packages/index.mdx b/apps/docs/content/docs/packages/index.mdx index 018a0558..c5c715d2 100644 --- a/apps/docs/content/docs/packages/index.mdx +++ b/apps/docs/content/docs/packages/index.mdx @@ -5,16 +5,25 @@ description: Core packages that power Coda's client generation capabilities Coda is built as a modular system of packages that work together to generate high-quality TypeScript clients from Solana IDLs. Each package serves a specific purpose in the generation pipeline. -## Core Packages +## Core Package ### [@macalinao/coda](/docs/packages/coda) -The main CLI tool for generating TypeScript clients from Anchor IDLs. Provides zero-config defaults and extensible configuration. +The main CLI tool for generating TypeScript clients from Anchor IDLs. Works out of the box with sensible defaults and extensible configuration. + +## Parsers + +### [@macalinao/codama-nodes-from-anchor-x](/docs/packages/codama-nodes-from-anchor-x) +Creates Codama root nodes from multiple Anchor IDLs with enhanced support for various IDL versions. + +## Visitors ### [@macalinao/codama-instruction-accounts-dedupe-visitor](/docs/packages/codama-instruction-accounts-dedupe-visitor) Flattens nested account structures from Anchor IDLs while preserving relationships through naming conventions. ### [@macalinao/codama-rename-visitor](/docs/packages/codama-rename-visitor) -Provides utilities for renaming nodes in the Codama AST, useful for customizing generated code naming. +Renames accounts, instructions, and defined types in the Codama AST to avoid conflicts and customize naming. + +## Renderers ### [@macalinao/codama-renderers-js-esm](/docs/packages/codama-renderers-js-esm) ESM-native TypeScript renderer that generates modern JavaScript modules with proper `.js` extensions. @@ -39,9 +48,16 @@ Each package can be installed individually based on your needs: # Install the main CLI bun add -D @macalinao/coda -# Install specific visitors -bun add -D @macalinao/codama-instruction-accounts-dedupe-visitor -bun add -D @macalinao/codama-renderers-js-esm +# Install parsers +bun add @macalinao/codama-nodes-from-anchor-x + +# Install visitors +bun add @macalinao/codama-instruction-accounts-dedupe-visitor +bun add @macalinao/codama-rename-visitor + +# Install renderers +bun add @macalinao/codama-renderers-js-esm +bun add @macalinao/codama-renderers-markdown ``` ## Contributing diff --git a/apps/docs/content/docs/packages/meta.json b/apps/docs/content/docs/packages/meta.json index d595801b..500a40b0 100644 --- a/apps/docs/content/docs/packages/meta.json +++ b/apps/docs/content/docs/packages/meta.json @@ -4,6 +4,8 @@ "index", "---Core Package---", "coda", + "---Parsers---", + "codama-nodes-from-anchor-x", "---Visitors---", "codama-instruction-accounts-dedupe-visitor", "codama-rename-visitor", diff --git a/clients/kamino-lending/src/index.ts b/clients/kamino-lending/src/index.ts new file mode 100644 index 00000000..5a5e14ae --- /dev/null +++ b/clients/kamino-lending/src/index.ts @@ -0,0 +1 @@ +export * from "./generated/index.js"; diff --git a/packages/coda/package.json b/packages/coda/package.json index 0381e5b8..26d5bdaa 100644 --- a/packages/coda/package.json +++ b/packages/coda/package.json @@ -1,7 +1,7 @@ { "name": "@macalinao/coda", "version": "0.2.3", - "description": "Zero-config CLI for generating clients for Solana programs", + "description": "CLI for generating clients for Solana programs", "type": "module", "sideEffects": false, "author": "Ian Macalinao ", diff --git a/packages/codama-instruction-accounts-dedupe-visitor/README.md b/packages/codama-instruction-accounts-dedupe-visitor/README.md index 194d03a2..e4325c41 100644 --- a/packages/codama-instruction-accounts-dedupe-visitor/README.md +++ b/packages/codama-instruction-accounts-dedupe-visitor/README.md @@ -3,82 +3,28 @@ [![npm version](https://img.shields.io/npm/v/@macalinao/codama-instruction-accounts-dedupe-visitor.svg)](https://www.npmjs.com/package/@macalinao/codama-instruction-accounts-dedupe-visitor) [![npm downloads](https://img.shields.io/npm/dm/@macalinao/codama-instruction-accounts-dedupe-visitor.svg)](https://www.npmjs.com/package/@macalinao/codama-instruction-accounts-dedupe-visitor) -Codama visitor for deduplicating and flattening instruction accounts from Anchor IDL. This package helps handle nested account structures in Anchor programs by flattening them into a single-level structure with properly prefixed names. +Codama visitor for deduplicating and flattening instruction accounts from Anchor IDL. -## Quick Start with Coda CLI +## Documentation -This visitor is best used through the [Coda CLI](https://coda.ianm.com), which provides a complete solution for Solana client generation: +Full documentation and examples are available at [coda.ianm.com/docs/packages/codama-instruction-accounts-dedupe-visitor](https://coda.ianm.com/docs/packages/codama-instruction-accounts-dedupe-visitor). -```bash -# Install Coda CLI -bun add -D @macalinao/coda - -# Initialize configuration -coda init - -# Add this visitor to your coda.config.mjs -``` - -Learn more about Coda's zero-config approach and powerful visitor system at [coda.ianm.com](https://coda.ianm.com). - -## Installation +## Quick Start ```bash -bun add @macalinao/codama-instruction-accounts-dedupe-visitor +npm install @macalinao/codama-instruction-accounts-dedupe-visitor ``` -## Usage - ```typescript import { instructionAccountsDedupeVisitor } from "@macalinao/codama-instruction-accounts-dedupe-visitor"; -import { rootNodeFromAnchor } from "@codama/nodes-from-anchor"; -import { visit } from "codama"; - -// Your Anchor IDL -const idl = /* your anchor IDL */; - -// Create the root node from Anchor IDL -const root = rootNodeFromAnchor(idl); -// Apply the dedupe visitor +// Flatten nested account structures const visitor = instructionAccountsDedupeVisitor(idl); const deduplicatedRoot = visit(root, visitor); ``` -## How It Works - -The visitor transforms nested account structures by: - -1. **Traversing Account Groups**: Recursively processes nested account groups -2. **Prefixing Names**: Joins parent and child names with underscores -3. **Adjusting PDA Seeds**: Updates seed paths to match the flattened structure -4. **Preserving All Metadata**: Maintains all account properties and constraints - -### Example Transformation - -**Before (Nested Structure)**: - -```typescript -{ - name: "mintAccounts", - accounts: [ - { name: "mint", ... }, - { name: "metadata", ... } - ] -} -``` - -**After (Flattened Structure)**: - -```typescript -[ - { name: "mintAccounts_mint", ... }, - { name: "mintAccounts_metadata", ... } -] -``` - ## License Copyright © 2025 Ian Macalinao -Licensed under the Apache License, Version 2.0 +Licensed under the Apache License, Version 2.0 \ No newline at end of file diff --git a/packages/codama-nodes-from-anchor-x/README.md b/packages/codama-nodes-from-anchor-x/README.md index 09967026..76000cf4 100644 --- a/packages/codama-nodes-from-anchor-x/README.md +++ b/packages/codama-nodes-from-anchor-x/README.md @@ -3,203 +3,26 @@ [![npm version](https://img.shields.io/npm/v/@macalinao/codama-nodes-from-anchor-x.svg)](https://www.npmjs.com/package/@macalinao/codama-nodes-from-anchor-x) [![npm downloads](https://img.shields.io/npm/dm/@macalinao/codama-nodes-from-anchor-x.svg)](https://www.npmjs.com/package/@macalinao/codama-nodes-from-anchor-x) -An enhanced version of `@codama/nodes-from-anchor` with additional features for improved Anchor IDL parsing and transformation. This is the default parser used by the [Coda CLI](https://github.com/macalinao/coda) for generating TypeScript clients from Solana programs. +Create Codama root nodes from multiple Anchor IDLs with enhanced support. -## Features +## Documentation -This package extends `@codama/nodes-from-anchor` with: +Full documentation and examples are available at [coda.ianm.com/docs/packages/codama-nodes-from-anchor-x](https://coda.ianm.com/docs/packages/codama-nodes-from-anchor-x). -- **Multi-IDL Support**: Parse and combine multiple Anchor IDLs into a single Codama root node -- **Automatic Account Flattening**: Intelligently flattens nested account structures from Anchor IDLs for v0.1.0 format -- **Program-Level Visitors**: Apply transformations at the program level for better composability -- **Enhanced IDL Support**: Seamless handling of both v0.0.0 and v0.1.0 Anchor IDL formats - -## Quick Start with Coda CLI - -This package is used internally by the [Coda CLI](https://coda.ianm.com) for multi-program support: - -```bash -# Install Coda CLI -bun add -D @macalinao/coda - -# Generate clients from multiple IDLs -coda generate --idl "./idls/*.json" -``` - -Learn more at [coda.ianm.com](https://coda.ianm.com). - -## Installation +## Quick Start -```bash -bun add @macalinao/codama-nodes-from-anchor-x -``` - -Or with npm: ```bash npm install @macalinao/codama-nodes-from-anchor-x ``` -## Usage - -### Single IDL - -```typescript -import { rootNodeFromAnchor } from "@macalinao/codama-nodes-from-anchor-x"; -import { createFromRoot, visit } from "codama"; - -// Load your IDL -const idl = JSON.parse(fs.readFileSync("./idl.json", "utf-8")); - -// Create a root node from single IDL -const root = rootNodeFromAnchor(idl); - -// Create Codama instance and apply visitors -const codama = createFromRoot(root); -codama.accept(myVisitor); -``` - -### Multiple IDLs - ```typescript import { rootNodeFromAnchorIdls } from "@macalinao/codama-nodes-from-anchor-x"; -import { createFromRoot, visit } from "codama"; - -// Load your IDLs -const idls = [ - JSON.parse(fs.readFileSync("./idls/program1.json", "utf-8")), - JSON.parse(fs.readFileSync("./idls/program2.json", "utf-8")), - JSON.parse(fs.readFileSync("./idls/program3.json", "utf-8")), -]; - -// Create a root node containing all programs -const root = rootNodeFromAnchorIdls(idls); - -// Create Codama instance -const codama = createFromRoot(root); - -// Apply visitors -codama.accept(myVisitor); -``` - -### Program Node - -```typescript -import { programNodeFromAnchor } from "@macalinao/codama-nodes-from-anchor-x"; - -// Get just the program node (without root wrapper) -const program = programNodeFromAnchor(idl); -``` - -## API - -### rootNodeFromAnchor - -Creates a Codama root node from a single Anchor IDL. - -```typescript -function rootNodeFromAnchor(idl: AnchorIdl): RootNode; -``` - -**Parameters:** -- `idl`: An Anchor IDL object - -**Returns:** -- A Codama root node containing the program from the IDL - -### rootNodeFromAnchorIdls - -Creates a Codama root node from multiple Anchor IDLs. - -```typescript -function rootNodeFromAnchorIdls(idls: AnchorIdl[]): RootNode; -``` - -**Parameters:** -- `idls`: An array of Anchor IDL objects - -**Returns:** -- A Codama root node containing all programs from the IDLs - -**Throws:** -- Error if no IDL files are provided -- Error if no program nodes could be created - -### programNodeFromAnchor - -Creates a Codama program node from a single Anchor IDL. - -```typescript -function programNodeFromAnchor(idl: AnchorIdl): ProgramNode; -``` - -**Parameters:** -- `idl`: An Anchor IDL object - -**Returns:** -- A Codama program node (without root wrapper) - -## Key Improvements over @codama/nodes-from-anchor - -### Automatic Account Flattening - -Anchor IDL v0.1.0 often has nested account structures that need to be flattened for proper code generation. This package automatically handles this: - -```javascript -// Anchor IDL with nested accounts: -{ - "name": "mint_accounts", - "accounts": [ - { "name": "mint", "writable": true }, - { "name": "metadata", "writable": true } - ] -} - -// Automatically flattened to: -[ - { "name": "mintAccountsMint", "writable": true }, - { "name": "mintAccountsMetadata", "writable": true } -] -``` - -### Version Detection - -The package automatically detects the IDL version (v0.0.0 or v0.1.0) and applies the appropriate parsing logic, including the account flattening visitor for v0.1.0 IDLs. - -## Use Cases - -### Multiple Related Programs - -When working with a protocol that consists of multiple programs: - -```typescript -const idls = [ - mainProgramIdl, - stakingProgramIdl, - rewardsProgramIdl, -]; +// Parse multiple IDLs into a single root node +const idls = [idl1, idl2, idl3]; const root = rootNodeFromAnchorIdls(idls); -// All three programs are now in the AST ``` -### Program Versioning - -Load different versions of the same program: - -```typescript -const idls = [ - currentVersionIdl, - legacyVersionIdl, -]; - -const root = rootNodeFromAnchorIdls(idls); -// Both versions available for migration tools -``` - -## Integration with Coda - -This package is the default parser for [Coda](https://github.com/macalinao/coda), providing the foundation for generating modern, type-safe TypeScript clients for Solana programs. When you use `coda generate`, it uses this package under the hood to parse your Anchor IDLs. - ## License Copyright © 2025 Ian Macalinao diff --git a/packages/codama-rename-visitor/README.md b/packages/codama-rename-visitor/README.md index f9dd5ecd..0690c976 100644 --- a/packages/codama-rename-visitor/README.md +++ b/packages/codama-rename-visitor/README.md @@ -3,142 +3,38 @@ [![npm version](https://img.shields.io/npm/v/@macalinao/codama-rename-visitor.svg)](https://www.npmjs.com/package/@macalinao/codama-rename-visitor) [![npm downloads](https://img.shields.io/npm/dm/@macalinao/codama-rename-visitor.svg)](https://www.npmjs.com/package/@macalinao/codama-rename-visitor) -A Codama visitor for renaming instructions and events within a Solana program. +A Codama visitor for renaming accounts, instructions, and defined types within Solana programs. -## Quick Start with Coda CLI +## Documentation -This visitor works seamlessly with the [Coda CLI](https://coda.ianm.com) for automated client generation: +Full documentation and examples are available at [coda.ianm.com/docs/packages/codama-rename-visitor](https://coda.ianm.com/docs/packages/codama-rename-visitor). -```bash -# Install Coda CLI -bun add -D @macalinao/coda - -# Initialize configuration -coda init - -# Add this visitor to your coda.config.mjs -``` - -Coda provides zero-config client generation with powerful customization through visitors like this one. Learn more at [coda.ianm.com](https://coda.ianm.com). - -## Installation - -For direct usage: +## Quick Start ```bash npm install @macalinao/codama-rename-visitor ``` -## Usage - -This visitor allows you to rename instructions and events in your Codama IDL. It's particularly useful when you want to change the naming conventions of your program without modifying the original IDL. - -### Renaming Instructions - -```typescript -import { renameInstructionsVisitor } from "@macalinao/codama-rename-visitor"; -import { visit } from "codama"; - -// Rename specific instructions -const visitor = renameInstructionsVisitor({ - oldInstructionName: "newInstructionName", - transfer: "transferTokens", - mint: "mintNft" -}); - -const updatedRoot = visit(root, visitor); -``` - -### Renaming Events - -```typescript -import { renameEventsVisitor } from "@macalinao/codama-rename-visitor"; -import { visit } from "codama"; - -// Rename specific events (as defined types) -const visitor = renameEventsVisitor({ - oldEventName: "newEventName", - tokenMinted: "nftMinted", - transferComplete: "transferFinished" -}); - -const updatedRoot = visit(root, visitor); -``` - -### Program-Specific Renaming (Recommended) - -The `renameVisitor` follows the same pattern as Codama's `addPdasVisitor`, where you specify renames for specific programs: - ```typescript import { renameVisitor } from "@macalinao/codama-rename-visitor"; -import { visit } from "codama"; -// Rename elements in specific programs const visitor = renameVisitor({ - quarryMine: { - instructions: { - claimRewards: "claimRewardsMine" - } - }, - token: { + myProgram: { instructions: { - transfer: "transferTokens", - mint: "mintNft" + oldName: "newName" }, - events: { - tokenMinted: "nftMinted" + accounts: { + oldAccount: "newAccount" + }, + definedTypes: { + oldType: "newType" } } }); - -const updatedRoot = visit(root, visitor); -``` - -### Legacy Single-Program Renaming - -For backward compatibility, you can still use the legacy format for single-program renaming: - -```typescript -import { renameVisitor } from "@macalinao/codama-rename-visitor"; -import { visit } from "codama"; - -// Legacy format: rename in the current program -const visitor = renameVisitor({ - instructions: { - transfer: "transferTokens", - mint: "mintNft" - }, - events: { - tokenMinted: "nftMinted", - transferComplete: "transferFinished" - } -}); - -const updatedRoot = visit(root, visitor); ``` -## API - -### `renameVisitor(renamesByProgram: Record)` - -Creates a visitor that renames instructions, events, and defined types in specific programs. This is the recommended API. - -- `renamesByProgram`: Object mapping program names to their rename configurations - - Each program can specify: - - `instructions`: Mapping of old instruction names to new names - - `events`: Mapping of old event names to new names - - `definedTypes`: Mapping of old defined type names to new names - -### `renameInstructionsVisitor(mapping: Record)` - -Creates a visitor that renames instructions based on the provided mapping. Applies to all programs. - -### `renameEventsVisitor(mapping: Record)` - -Creates a visitor that renames events (defined types) based on the provided mapping. Applies to all programs. - ## License Copyright © 2025 Ian Macalinao -Licensed under the Apache License, Version 2.0 +Licensed under the Apache License, Version 2.0 \ No newline at end of file diff --git a/packages/codama-renderers-js-esm/README.md b/packages/codama-renderers-js-esm/README.md index 48675040..4548c5f0 100644 --- a/packages/codama-renderers-js-esm/README.md +++ b/packages/codama-renderers-js-esm/README.md @@ -3,107 +3,28 @@ [![npm version](https://img.shields.io/npm/v/@macalinao/codama-renderers-js-esm.svg)](https://www.npmjs.com/package/@macalinao/codama-renderers-js-esm) [![npm downloads](https://img.shields.io/npm/dm/@macalinao/codama-renderers-js-esm.svg)](https://www.npmjs.com/package/@macalinao/codama-renderers-js-esm) -ESM-native TypeScript renderer for [Codama](https://github.com/codama-idl/codama) JavaScript code generation. This package extends `@codama/renderers-js` to produce fully ESM-compatible TypeScript/JavaScript code. +ESM-native TypeScript renderer for Codama with proper `.js` extensions. -## Used by Coda CLI +## Documentation -This renderer is the default TypeScript renderer used by the [Coda CLI](https://coda.ianm.com): +Full documentation and examples are available at [coda.ianm.com/docs/packages/codama-renderers-js-esm](https://coda.ianm.com/docs/packages/codama-renderers-js-esm). -```bash -# Install Coda CLI - includes this ESM renderer by default -bun add -D @macalinao/coda - -# Generate ESM-native TypeScript clients with zero config -coda generate -``` - -Coda provides the easiest way to generate type-safe Solana clients from your Anchor IDLs. Learn more at [coda.ianm.com](https://coda.ianm.com). - -## Installation +## Quick Start ```bash -bun add @macalinao/codama-renderers-js-esm +npm install @macalinao/codama-renderers-js-esm ``` -## Usage - -Use this visitor in place of the standard Codama JavaScript renderer when you need ESM-compatible output: - ```typescript -import { renderESMTypeScriptVisitor } from "@macalinao/codama-renderers-js-esm"; -import { rootNode } from "codama"; - -// Your Codama root node (typically from parsing an IDL) -const root = rootNode(/* ... */); +import { renderJavaScriptVisitor } from "@macalinao/codama-renderers-js-esm"; // Generate ESM-compatible TypeScript code -const visitor = renderESMTypeScriptVisitor("./src/generated"); -visit(root, visitor); -``` - -## How It Works - -This package wraps `@codama/renderers-js`'s `getRenderMapVisitor` and applies a series of transformations to ensure ESM compatibility: - -### 1. Custom Dependency Map - -The package provides an ESM-specific dependency map that ensures all internal imports use `.js` extensions: - -```typescript -{ - errors: "../errors/index.js", - generatedAccounts: "../accounts/index.js", - generatedInstructions: "../instructions/index.js", - // ... etc -} +const visitor = renderJavaScriptVisitor("./src/generated"); +codama.accept(visitor); ``` -### 2. Import Path Transformations - -- Adds `.js` extensions to all relative imports without extensions -- Converts bare directory imports to explicit `index.js` imports -- Maintains compatibility with TypeScript's module resolution - -### 3. Code Improvements - -- Replaces loose null checks (`value == null`) with strict checks (`value === null || value === undefined`) -- Fixes type assertions for better type safety -- Removes Node.js-specific environment checks for universal JavaScript compatibility - -## Differences from @codama/renderers-js - -| Feature | @codama/renderers-js | @macalinao/codama-renderers-js-esm | -|---------|----------------------|-------------------------------------| -| Module Format | CommonJS-compatible | Pure ESM | -| Import Extensions | No extensions | `.js` extensions | -| TypeScript Config | Standard | ESM-native | -| Runtime Checks | Node.js-specific | Universal | -| Null Checks | Loose (`==`) | Strict (`===`) | - -## Example Output - -### Before (Standard Renderer) -```typescript -import { Address } from "@solana/web3.js"; -import { SomeType } from "./types"; -export * from "./accounts"; -``` - -### After (ESM Renderer) -```typescript -import { Address } from "@solana/web3.js"; -import { SomeType } from "./types/index.js"; -export * from "./accounts/index.js"; -``` - -## Requirements - -- Node.js 18+ or Bun -- TypeScript 5.0+ (for generated code) -- Package.json with `"type": "module"` - ## License Copyright © 2025 Ian Macalinao -Licensed under the Apache License, Version 2.0 +Licensed under the Apache License, Version 2.0 \ No newline at end of file diff --git a/packages/codama-renderers-markdown/README.md b/packages/codama-renderers-markdown/README.md index 179fc650..0380df55 100644 --- a/packages/codama-renderers-markdown/README.md +++ b/packages/codama-renderers-markdown/README.md @@ -5,129 +5,45 @@ A Codama visitor that renders markdown documentation from Solana program IDLs. -## Live Examples - -See the documentation this package generates in action: - -- **[Quarry Protocol Documentation](https://coda-docs.vercel.app/docs/api/clients/quarry)** - Complete documentation for the Quarry staking protocol, showcasing: - - [60+ Instructions](https://coda-docs.vercel.app/docs/api/clients/quarry/instructions) with full parameter documentation - - [Account structures](https://coda-docs.vercel.app/docs/api/clients/quarry/accounts) with field descriptions - - [PDA derivations](https://coda-docs.vercel.app/docs/api/clients/quarry/pdas) with seed definitions - - [Custom types](https://coda-docs.vercel.app/docs/api/clients/quarry/types) and enums - - [Error codes](https://coda-docs.vercel.app/docs/api/clients/quarry/errors) with messages - -- **[Token Metadata Documentation](https://coda-docs.vercel.app/docs/api/clients/token-metadata)** - Metaplex Token Metadata program documentation +## Documentation -This documentation is generated automatically from the program IDLs with zero manual editing required. +Full documentation and examples are available at [coda.ianm.com/docs/packages/codama-renderers-markdown](https://coda.ianm.com/docs/packages/codama-renderers-markdown). -## Quick Start with Coda CLI +## Quick Start -The easiest way to use this package is through the [Coda CLI](https://coda.ianm.com), which includes built-in documentation generation: +The easiest way to use this package is through the [Coda CLI](https://coda.ianm.com): ```bash -# Install Coda CLI -bun add -D @macalinao/coda +# Install Coda CLI +npm install -D @macalinao/coda -# Generate both TypeScript client and markdown docs -coda generate --docs - -# Or just generate documentation +# Generate documentation coda docs ``` -Learn more about Coda and its zero-config approach at [coda.ianm.com](https://coda.ianm.com). - -## Installation - -If you want to use this package directly: +Or use directly: ```bash npm install @macalinao/codama-renderers-markdown ``` -## Usage - ```typescript import { renderMarkdownVisitor } from "@macalinao/codama-renderers-markdown"; import { rootNodeFromAnchor } from "@codama/nodes-from-anchor"; import { visit } from "codama"; -// Load your IDL -const idl = JSON.parse(fs.readFileSync("path/to/idl.json", "utf-8")); - -// Create Codama root node +const idl = JSON.parse(fs.readFileSync("idl.json", "utf-8")); const root = rootNodeFromAnchor(idl); - -// Generate markdown documentation visit(root, renderMarkdownVisitor("./docs")); ``` -## Features - -- **Comprehensive Documentation**: Generates documentation for: - - Accounts with fields and discriminators - - Instructions with accounts and arguments - - PDAs with seed definitions - - Custom types and enums - - Program errors with codes and messages -- **Structured Output**: - - Table of contents with navigation links - - Organized sections by component type - - Cross-references between related components -- **Developer-Friendly**: - - TypeScript-style type definitions - - Formatted tables for easy scanning - - Code blocks with syntax highlighting support -- **Platform Agnostic**: - - Pure markdown output works anywhere - - Compatible with all major documentation platforms - - No vendor lock-in - -## Options - -```typescript -renderMarkdownVisitor(outputDir, { - // Format program addresses (optional) - formatAddress: (address) => address, - - // Render table of contents (default: true) - renderTableOfContents: true, -}); -``` - -## Integration Examples - -### With Documentation Platforms - -The generated markdown integrates seamlessly with popular documentation platforms: - -```bash -# Generate documentation -npx @macalinao/codama-renderers-markdown ./docs - -# Use with MkDocs -mkdocs build - -# Use with Docusaurus -npm run build - -# Use with VitePress -vitepress build docs -``` - -### CI/CD Integration - -Automatically update documentation on every deployment: +## Live Examples -```yaml -# GitHub Actions example -- name: Generate Program Documentation - run: | - npm run generate-docs - git add docs/ - git commit -m "Update program documentation" -``` +- **[Quarry Protocol](https://github.com/macalinao/coda/tree/master/clients/quarry/docs)** - Complete documentation for 6 Quarry programs +- **[Token Metadata](https://github.com/macalinao/coda/blob/master/clients/token-metadata/docs/mpl-token-metadata.md)** - Metaplex Token Metadata documentation ## License -MIT \ No newline at end of file +Copyright © 2025 Ian Macalinao + +Licensed under the Apache License, Version 2.0 \ No newline at end of file