A Solana SPL token program for creating and managing NYU tokens with admin-only controls.
- Admin-only access controls
- Program Derived Address (PDA) for mint authority
- Input validation and error handling
- Event emission for operations
- Token burning functionality
- Metadata management
- Governance system with proposals and voting
- Multi-signature admin support
- Token creation with controlled access
- Token minting with proper authorization
- PDA-based mint authority
- Event system for operation transparency
- Admin-only operations
- Supply limits (1 billion tokens max)
- PDA-secured mint authority
- Input validation
This project uses environment variables to secure sensitive information like program IDs, wallet addresses, and API keys. No hardcoded values are stored in the source code.
All sensitive configuration is managed through environment variables:
PROGRAM_ID
- Your deployed program IDADMIN_WALLET
- Admin wallet public keyTOKEN_IMAGE_URL
- Token image URLANCHOR_PROVIDER_URL
- Solana RPC endpointANCHOR_WALLET
- Path to wallet keypair
- Never commit
.env
files to version control - Always use environment variables for sensitive data
- Use placeholder values in source code that get replaced during deployment
- Run the cleanup script before committing code changes
- Node.js (v16 or higher)
- Rust (latest stable)
- Solana CLI
- Anchor Framework
-
Clone the repository
git clone <your-repository-url> cd nyu-coin
-
Install dependencies
npm install # or yarn install
-
Configure environment variables
cp env.example .env # Edit .env with your actual values
-
Configure Solana
solana config set --url devnet solana-keygen new # Create a new keypair if needed solana airdrop 2 # Get some devnet SOL
-
Deploy the program
npm run deploy:devnet
Run the test suite:
# Run all tests with environment configuration
npm run test
# Build and test
npm run build
npm run test
The test suite covers:
- Program deployment and loading
- Token creation with valid parameters
- Event emission validation
- Authorization checks
- Input validation
- PDA derivation and validation
- Additional token minting
- Security edge cases
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { NyuCoin } from "./target/types/nyu_coin";
import { getConfig } from "./src/config";
// Setup with environment configuration
const config = getConfig();
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.NyuCoin as Program<NyuCoin>;
// Generate new mint
const mintKeypair = Keypair.generate();
const amount = new anchor.BN(1_000_000_000_000); // 1000 tokens
// Create token
const tx = await program.methods
.createNyuToken(amount)
.accounts({
payer: provider.wallet.publicKey,
mint: mintKeypair.publicKey,
// ... other accounts
})
.signers([mintKeypair])
.rpc();
// Mint additional tokens to existing token account
const additionalAmount = new anchor.BN(500_000_000_000); // 500 tokens
const tx = await program.methods
.mintAdditionalTokens(additionalAmount)
.accounts({
authority: provider.wallet.publicKey,
mint: mintPublicKey,
destination: tokenAccountPublicKey,
// ... other accounts
})
.rpc();
- Program ID: Set via
PROGRAM_ID
environment variable - Admin Wallet: Set via
ADMIN_WALLET
environment variable - Token Decimals: 9
- Max Supply: 1,000,000,000,000,000,000 (1 billion tokens with 9 decimals)
Copy the example environment file and configure:
cp env.example .env
Edit .env
with your values:
# Program Configuration
PROGRAM_ID=your-deployed-program-id
ADMIN_WALLET=your-admin-wallet-address
# Solana Configuration
ANCHOR_PROVIDER_URL=https://api.devnet.solana.com
ANCHOR_WALLET=~/.config/solana/id.json
# Token Configuration
TOKEN_NAME=NYU
TOKEN_SYMBOL=NYU
TOKEN_DECIMALS=9
MAX_TOKEN_SUPPLY=1000000000000000000
# Metadata Configuration
TOKEN_DESCRIPTION=The official meme coin - NYU!
TOKEN_IMAGE_URL=your-token-image-url-here
# Network Configuration
SOLANA_NETWORK=devnet
RPC_ENDPOINT=https://api.devnet.solana.com
# Development Configuration
NODE_ENV=development
LOG_LEVEL=info
nyu-coin/
├── programs/
│ └── nyu-coin/
│ ├── src/
│ │ └── lib.rs # Main program logic
│ └── Cargo.toml # Rust dependencies
├── tests/
│ └── nyu-coin.ts # Comprehensive test suite
├── scripts/
│ ├── deploy.sh # Secure deployment script
│ ├── test.sh # Test script with env config
│ └── clean.sh # Reset to placeholder values
├── migrations/
│ └── deploy.ts # Deployment script
├── src/
│ └── config.ts # Environment configuration
├── target/ # Build artifacts
├── Anchor.toml # Anchor configuration
├── Cargo.toml # Workspace configuration
├── package.json # Node.js dependencies
├── env.example # Environment template
└── README.md # This file
# Deploy to devnet
npm run deploy:devnet
# Deploy to mainnet
npm run deploy:mainnet
# Custom deployment
npm run deploy
# Run tests with environment config
npm run test
# Build program
npm run build
# Reset config to placeholder values
chmod +x scripts/clean.sh && ./scripts/clean.sh
# Lint and format code
npm run lint
npm run lint:fix
- Only the designated admin wallet can create tokens
- Admin wallet is configured via environment variables
- No ability to change admin after deployment
- Maximum supply limit prevents excessive token creation
- All minting operations are logged via events
- PDA-based mint authority prevents unauthorized minting
- Comprehensive input validation on all parameters
- Account validation ensures proper account types
- Error handling with descriptive error messages
- No hardcoded IDs or keys in source code
- All sensitive data in environment variables
- Placeholder values in source code
- Secure deployment scripts
# Set cluster to devnet
solana config set --url devnet
# Deploy using secure script
npm run deploy:devnet
# Verify deployment
solana program show $PROGRAM_ID
Important: Test thoroughly on devnet before mainnet deployment
# Set cluster to mainnet
solana config set --url mainnet-beta
# Deploy using secure script
npm run deploy:mainnet
# Verify deployment
solana program show $PROGRAM_ID
- Name: Set via
TOKEN_NAME
environment variable - Symbol: Set via
TOKEN_SYMBOL
environment variable - Description: Set via
TOKEN_DESCRIPTION
environment variable - Decimals: 9
- Image: Set via
TOKEN_IMAGE_URL
environment variable
Creates a new NYU token mint and mints initial supply.
Parameters:
amount: u64
- Amount of tokens to mint (with 9 decimals)
Accounts:
payer
- Admin wallet (signer, mutable)mint
- New mint account (signer, mutable)payer_token_account
- Token account for admin (mutable)mint_authority
- PDA mint authority- System programs
Mints additional tokens to an existing token account.
Parameters:
amount: u64
- Amount of tokens to mint
Accounts:
authority
- Admin wallet (signer, mutable)mint
- Existing mint account (mutable)destination
- Destination token account (mutable)mint_authority
- PDA mint authority- Token program
Burns tokens from a token account (admin only).
Parameters:
amount: u64
- Amount of tokens to burn
Accounts:
authority
- Admin wallet (signer, mutable)mint
- Mint account (mutable)from
- Token account to burn from (mutable)- Token program
Updates token metadata (admin only).
Parameters:
name: String
- New token name (max 32 chars)symbol: String
- New token symbol (max 10 chars)uri: String
- New metadata URI (max 200 chars)
Accounts:
authority
- Admin wallet (signer, mutable)mint
- Mint accountmetadata
- Metadata PDA account- System program
Creates a governance proposal (admin only).
Parameters:
title: String
- Proposal title (max 64 chars)description: String
- Proposal description (max 500 chars)proposal_type: ProposalType
- Type of proposal
Accounts:
authority
- Admin wallet (signer, mutable)proposal
- New proposal account- System program
Vote on a governance proposal.
Parameters:
vote: bool
- True for yes, false for no
Accounts:
voter
- Voter wallet (signer, mutable)proposal
- Proposal account (mutable)voter_record
- Voter record PDA- System program
Execute a governance proposal (admin only).
Accounts:
authority
- Admin wallet (signer, mutable)proposal
- Proposal account (mutable)
Initialize multi-signature admin functionality.
Parameters:
required_signatures: u8
- Number of signatures requiredadmins: Vec<Pubkey>
- List of admin public keys
Accounts:
initializer
- Current admin (signer, mutable)multisig
- New multisig account- System program
Create a multisig transaction proposal.
Parameters:
instruction_data: Vec<u8>
- Instruction data to execute
Accounts:
proposer
- Admin proposer (signer, mutable)multisig
- Multisig accounttransaction
- New transaction account- System program
Sign a multisig transaction.
Accounts:
signer
- Admin signer (signer, mutable)multisig
- Multisig accounttransaction
- Transaction account (mutable)
Execute a multisig transaction.
Accounts:
executor
- Executor (signer, mutable)multisig
- Multisig accounttransaction
- Transaction account (mutable)
Emitted when a new token is created.
pub struct TokenCreated {
pub mint: Pubkey, // Mint account
pub authority: Pubkey, // Mint authority (PDA)
pub recipient: Pubkey, // Initial recipient
pub amount: u64, // Initial amount minted
pub decimals: u8, // Token decimals
pub timestamp: i64, // Creation timestamp
}
Emitted when additional tokens are minted.
pub struct TokensMinted {
pub mint: Pubkey, // Mint account
pub recipient: Pubkey, // Recipient account
pub amount: u64, // Amount minted
pub timestamp: i64, // Mint timestamp
}
Emitted when tokens are burned.
pub struct TokensBurned {
pub mint: Pubkey, // Mint account
pub from: Pubkey, // Account burned from
pub amount: u64, // Amount burned
pub timestamp: i64, // Burn timestamp
}
Emitted when metadata is updated.
pub struct MetadataUpdated {
pub mint: Pubkey, // Mint account
pub name: String, // New token name
pub symbol: String, // New token symbol
pub uri: String, // New metadata URI
pub timestamp: i64, // Update timestamp
}
Emitted when a governance proposal is created.
pub struct ProposalCreated {
pub proposal_id: Pubkey, // Proposal ID
pub title: String, // Proposal title
pub description: String, // Proposal description
pub proposal_type: ProposalType, // Proposal type
pub proposer: Pubkey, // Proposer address
pub voting_ends_at: i64, // Voting end timestamp
}
Emitted when a vote is cast.
pub struct VoteCast {
pub proposal_id: Pubkey, // Proposal ID
pub voter: Pubkey, // Voter address
pub vote: bool, // Vote (true = yes)
pub timestamp: i64, // Vote timestamp
}
Emitted when a proposal is executed.
pub struct ProposalExecuted {
pub proposal_id: Pubkey, // Proposal ID
pub executed_by: Pubkey, // Executor address
pub timestamp: i64, // Execution timestamp
}
Emitted when multisig is initialized.
pub struct MultisigInitialized {
pub multisig: Pubkey, // Multisig account
pub required_signatures: u8, // Required signatures
pub admins: Vec<Pubkey>, // Admin addresses
pub timestamp: i64, // Initialization timestamp
}
Emitted when a multisig transaction is created.
pub struct MultisigTransactionCreated {
pub transaction: Pubkey, // Transaction account
pub multisig: Pubkey, // Multisig account
pub proposer: Pubkey, // Proposer
pub timestamp: i64, // Creation timestamp
}
Emitted when a multisig transaction is signed.
pub struct MultisigTransactionSigned {
pub transaction: Pubkey, // Transaction account
pub signer: Pubkey, // Signer
pub signatures_count: u8, // Current signature count
pub timestamp: i64, // Sign timestamp
}
Emitted when a multisig transaction is executed.
pub struct MultisigTransactionExecuted {
pub transaction: Pubkey, // Transaction account
pub executor: Pubkey, // Executor
pub timestamp: i64, // Execution timestamp
}
Code | Description |
---|---|
Unauthorized |
Only admin can perform this action |
InvalidMintAuthority |
PDA derivation failed |
InvalidAmount |
Amount must be greater than zero |
ExcessiveTokenSupply |
Amount exceeds maximum allowed |
InvalidDecimals |
Invalid token decimals |
MintNotFound |
Token mint not found |
InsufficientPermissions |
Insufficient permissions |
InvalidMetadata |
Name, symbol, or URI too long |
InvalidProposal |
Title or description too long |
ProposalNotActive |
Proposal is not active |
VotingPeriodEnded |
Voting period has ended |
VotingPeriodNotEnded |
Voting period has not ended yet |
AlreadyVoted |
Already voted on this proposal |
ProposalFailed |
Proposal failed to pass |
InvalidMultisigConfig |
Invalid multisig configuration |
TooManyAdmins |
Too many admins (max 10) |
NotAnAdmin |
Not an admin |
TransactionAlreadyExecuted |
Transaction already executed |
AlreadySigned |
Already signed this transaction |
InsufficientSignatures |
Insufficient signatures |
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Run cleanup script before committing (
./scripts/clean.sh
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter any issues or have questions:
- Check the test suite for usage examples
- Review the program code for implementation details
- Open an issue on GitHub with detailed information
- Core token creation functionality
- Admin-only access controls
- Test suite
- Documentation
- Token governance features
- Multi-signature admin support
- Token burn functionality
- Metadata management
- Security features
- Event emission system
- Error handling
- Environment variable security
- Secure deployment scripts