solana-program-metadata
v1.2.1
Published
Save Solana program metadata and IDLs on chain
Downloads
1,511
Maintainers
Readme
Solana Program Metadata CLI
Table of Contents
Quick Start
# Install and upload IDL in one command
npx solana-program-metadata idl upload ./my-idl.json <program-id>
Description
A Solana program for storing and retrieving program metadata on-chain. It enables:
- Storage of IDL files
- Program metadata (name, logo, contact info, etc.)
- Verifiable program information through upgrade authority validation
- Optional URL-based storage for reduced on-chain footprint
The trick is that only the program upgrade authority can create the associated PDA. This makes the metadata very easy to find by just using the seeds "idl", "metadata" or anything else you want.
At the moment the IDL and Metadata are not yet merged into Solana explorer but here is a preview build that can show you how it looks like: https://explorer-dun.vercel.app/address/6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A/program-metadata?cluster=devnet https://explorer-dun.vercel.app/address/6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A/idl?cluster=devnet
CLI Usage
Installation
There is no need to install the CLI you can just run it with npx:
npx solana-program-metadata
Commands
IDL Commands
Upload IDL from a JSON file. This will write the IDL compressed to the metadata account:
npx solana-program-metadata idl upload <file> <program-id> \
[-k <keypair-path>] \
[-u <rpc-url>] \
[-p <priority-fees>]
Upload IDL from URL. This will write a URL to a json file to the metadata account:
npx solana-program-metadata idl upload-url <url> <program-id> \
[-k <keypair-path>] \
[-u <rpc-url>] \
[-p <priority-fees>]
Download IDL to file:
npx solana-program-metadata idl download <program-id> [output-file] \
[-u <rpc-url>]
Metadata Commands
You can also upload metadata for you program. This is the recommended format of the metadata json file. Similar to security.txt.
Create a template metadata.json file:
npx solana-program-metadata metadata init
{
"name": "MyProgramName",
"logo": "https://upload.wikimedia.org/wikipedia/en/b/b9/Solana_logo.png",
"description": "Example program for meta data",
"notification": "On the first of january we will release a new version! Please update your SDKS!!!!",
"sdk": "https://github.com/solana-developers/js_sdk",
"project_url": "https://github.com/solana-developers/",
"contacts": [
"email:[email protected]",
"discord:MyProgram#1234",
"twitter:@MyProgram"
],
"policy": "https://example.com/security-policy",
"preferred_languages": ["en", "de"],
"encryption": "https://example.com/pgp-key",
"source_code": "https://github.com/solana-developers/",
"source_release": "v0.1.0",
"source_revision": "abc123def456",
"auditors": ["Audit Firm A", "Security Researcher B"],
"acknowledgements": "https://example.com/security-acknowledgements",
"expiry": "2024-12-31",
"version": "0.1.0"
}
Upload metadata from JSON file:
npx solana-program-metadata metadata upload <file> <program-id> \
[-k <keypair-path>] \
[-u <rpc-url>] \
[-p <priority-fees>]
Upload metadata from URL:
npx solana-program-metadata metadata upload-url <url> <program-id> \
[-k <keypair-path>] \
[-u <rpc-url>] \
[-p <priority-fees>]
Download metadata to file:
npx solana-program-metadata metadata download <program-id> [output-file] \
[-u <rpc-url>]
Options
-k, --keypair <path>
: Path to keypair file (optional, defaults to local Solana config)
-u, --url <string>
: Custom RPC URL (optional)-ul, --url-local
: Use localhost RPC (default)-ud, --url-devnet
: Use Devnet RPC-um, --url-mainnet
: Use Mainnet RPC
-p, --priority-fees <number>
: Priority fees per compute unit (optional, defaults to 100000)-a, --add-signer-seed
: Add signer's public key as additional seed. This will create not associated metadata which needs this seed to be found instead of just using the seeds "idl", "metadata" and the program id. (optional, defaults to false)
Examples
# Upload IDL using default keypair that is the program authority
npx solana-program-metadata idl upload ./target/idl/my_program.json 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A
# Upload metadata with custom keypair to devnet
npx solana-program-metadata metadata upload ./metadata.json 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A \
-k ./my-keypair.json \
-ud
# Upload metadata with non-associated PDA (using signer's pubkey as additional seed creating a non associated metadata account)
npx solana-program-metadata metadata upload-url https://example.com/metadata.json 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A \
--add-signer-seed
# Download associated metadata (default)
npx solana-program-metadata metadata download 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A ./my-metadata.json
# Download non-associated metadata (requires signer's pubkey)
npx solana-program-metadata metadata download 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A ./my-metadata.json \
-s tes5FTVnmJAeq2Nb1Uv15pqiRuPdCHmCSThVbUNfe37
npx solana-program-metadata idl upload tests/testidl.json 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A \
-k tests/wallet2.json -ud
npx solana-program-metadata metadata upload tests/metadata.json 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A \
-k tests/wallet2.json -ud
npx solana-program-metadata metadata upload-url https://raw.githubusercontent.com/solana-developers/idl-program/refs/heads/main/tests/metadata.json 6XzaKuAwqP7Nn37vwRdUqpuzNX6K8s1ADE6tHXSZG17A \
-k tests/wallet2.json -ud
JavaScript Usage
await uploadIdlUrl(url, programId, keypair, rpcUrl, priorityFees);
or
await uploadIdlByJsonPath(
pathToJsonFile,
programId,
keypair,
rpcUrl,
priorityFees
);
Then you can retrieve the IDL or URL using:
await fetchIDL(programId, rpcUrl);
and the metadata using:
await fetchProgramMetadata(programId, rpcUrl);
Non-Associated PDAs
When using the -a, --add-signer-seed
option, the program will add the signer's public key as an additional seed when deriving the PDA. This creates a non-associated PDA that is unique to that signer, allowing multiple metadata entries for the same program. Note that these can not easily be found anymore by just using the seeds "idl", "metadata" and the program id.
This can be useful though if there is some entity that wants to upload metadata for a program but does not have the authority to do so.
Changelog
1.2.0 (2024-12-21)
- Added extra fields to metadata account
- format
- encoding
- compression
- data_source
- Use account coder to decode metadata accounts
- Change data type to always be the same as seed
- Moved pubkeys together in metadata account
- Added option to upload metadata as an account, with offset and length
1.1.0 (2024-12-20)
Added
- New CLI Commands
list-pdas
: View all metadata PDAs controlled by your authoritylist-buffers
: View all buffer accounts controlled by your authorityclose-buffer
: Recover rent from buffer accountsclose-pda
: Close metadata PDA accounts and recover rent
- Multisig Support
- Added
--export-transaction
flag for Squads integration - Returns base58 and base64 encoded transactions for multisig execution
- Added
Improved
- Account Structure
- Separated
MetadataBuffer
fromMetadataAccount2
for better type safety - Added program ID to buffer accounts for better tracking
- Separated
- CLI Output
- Enhanced listing displays with program ID, data length, and data type
- Better formatted console output
- Error Handling
- More descriptive error messages
- Better validation of inputs
Technical
- Refactored account listing logic into reusable functions
- Improved TypeScript type definitions
- Better code organization and maintainability
1.0.0
added automatic rpc url and local keypair loading
added close metadata account instruction
added data type field to metadata account
Breaking: Changed metadata account structure. Users must:
- Close existing metadata accounts using
close1
instruction - Create new metadata accounts with updated structure
- Seed derivation changed to have the dynamic seed at the end for security reasons
- Close existing metadata accounts using