@macalinao/codama-rename-visitor
Codama visitor for renaming accounts, instructions, and defined types within Solana programs
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
bun add -D @macalinao/codama-rename-visitor
Or with npm:
npm install -D @macalinao/codama-rename-visitor
Why Use This Package?
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
- 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.
Usage
Program-Specific Renaming (Recommended)
The most powerful way to use this visitor is to specify renames for specific programs:
import { renameVisitor } from "@macalinao/codama-rename-visitor";
import { visit } from "codama";
// Rename elements in specific programs
const visitor = renameVisitor({
quarryMine: {
instructions: {
claimRewards: "claimRewardsMine",
stake: "stakeInQuarry"
},
accounts: {
miner: "quarryMiner"
},
definedTypes: {
StakeEvent: "QuarryStakeEvent"
}
},
quarryMergeMine: {
instructions: {
claimRewards: "claimRewardsMergeMine",
stake: "stakeInMergePool"
},
accounts: {
miner: "mergeMiner"
}
}
});
const updatedRoot = visit(root, visitor);
With Coda Configuration
Use it in your coda.config.mjs
:
import { defineConfig } from "@macalinao/coda";
import { renameVisitor } from "@macalinao/codama-rename-visitor";
export default defineConfig({
idlPath: "./idls/*.json",
outputDir: "./src/generated",
visitors: [
renameVisitor({
quarryMine: {
instructions: {
// Avoid conflicts with quarryMergeMine
claimRewards: "claimRewardsMine",
claimRewardsV2: "claimRewardsMineV2"
}
},
quarryMergeMine: {
instructions: {
// Give these distinct names
claimRewards: "claimRewardsMergeMine"
}
}
})
]
});
Renaming Specific Element Types
For simpler use cases, you can rename specific types of elements across all programs:
Rename Instructions Only
import { renameInstructionsVisitor } from "@macalinao/codama-rename-visitor";
const visitor = renameInstructionsVisitor({
transfer: "transferTokens",
mint: "mintNft",
burn: "burnToken"
});
const updatedRoot = visit(root, visitor);
Rename Accounts Only
import { renameAccountsVisitor } from "@macalinao/codama-rename-visitor";
const visitor = renameAccountsVisitor({
userAccount: "user",
configAccount: "config",
metadataAccount: "metadata"
});
const updatedRoot = visit(root, visitor);
Rename Defined Types Only
import { renameDefinedTypesVisitor } from "@macalinao/codama-rename-visitor";
const visitor = renameDefinedTypesVisitor({
TokenMetadata: "NftMetadata",
TransferEvent: "TokenTransferEvent"
});
const updatedRoot = visit(root, visitor);
API Reference
renameVisitor
The main visitor for comprehensive renaming:
function renameVisitor(
renamesByProgram: Record<string, ProgramRenameOptions>
): Visitor;
interface ProgramRenameOptions {
accounts?: Record<string, string>;
instructions?: Record<string, string>;
definedTypes?: Record<string, string>;
}
Parameters:
renamesByProgram
: Object mapping program names to their rename configurations
renameInstructionsVisitor
Visitor for renaming only instructions:
function renameInstructionsVisitor(
mapping: Record<string, string>
): Visitor;
Parameters:
mapping
: Object mapping old instruction names to new names
renameAccountsVisitor
Visitor for renaming only accounts:
function renameAccountsVisitor(
mapping: Record<string, string>
): Visitor;
Parameters:
mapping
: Object mapping old account names to new names
renameDefinedTypesVisitor
Visitor for renaming only defined types:
function renameDefinedTypesVisitor(
mapping: Record<string, string>
): Visitor;
Parameters:
mapping
: Object mapping old type names to new names
Transform Functions
The package also exports transform functions that can be used directly:
// 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 like Quarry:
renameVisitor({
// Quarry Mine program
quarryMine: {
instructions: {
createMiner: "createQuarryMiner",
stake: "stakeInQuarry",
claimRewards: "claimQuarryRewards"
},
accounts: {
miner: "quarryMiner",
quarry: "quarryAccount"
}
},
// Quarry Merge Mine program
quarryMergeMine: {
instructions: {
createMiner: "createMergeMiner",
stake: "stakeInMergePool",
claimRewards: "claimMergeRewards"
},
accounts: {
miner: "mergeMiner",
pool: "mergePool"
}
}
})
Adding Context
Make generic names more specific:
renameVisitor({
token: {
instructions: {
transfer: "transferToken",
burn: "burnToken",
mint: "mintToken"
},
accounts: {
account: "tokenAccount",
mint: "tokenMint"
}
},
nft: {
instructions: {
transfer: "transferNft",
burn: "burnNft",
mint: "mintNft"
},
accounts: {
metadata: "nftMetadata",
edition: "nftEdition"
}
}
})
Consistent Naming Conventions
Enforce naming patterns across your codebase:
renameVisitor({
myProgram: {
instructions: {
// Convert snake_case to camelCase
create_account: "createAccount",
update_metadata: "updateMetadata",
delete_record: "deleteRecord"
},
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:
// 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"
}
}
})
Best Practices
- Use Program-Specific Renaming: Always prefer the program-specific format to avoid unintended renames
- Document Renames: Comment why certain renames are necessary
- Be Consistent: Apply similar naming patterns across related programs
- Test Generated Code: Verify that renamed elements work correctly in your client code
- Order Matters: Apply rename visitors early in your visitor chain
Troubleshooting
Renames Not Applied
Ensure the visitor is added to your configuration and that names match exactly:
// 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
- 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 - Main CLI for client generation
- @macalinao/codama-instruction-accounts-dedupe-visitor - Flatten nested accounts
- @macalinao/codama-nodes-from-anchor-x - Parse multiple IDLs