Skip to content

Conversation

@donjne
Copy link

@donjne donjne commented Jul 11, 2025

Add Configuration System with sbpf.toml

The Problem I Discovered

While using sbpf, I noticed some patterns that made development slower and more error-prone:

  1. Developers working on Solana programs end up typing the same command-line flags over and over again. For example, someone working on a DeFi protocol might type sbpf deploy my-program localhost dozens of times per day. When they forget and accidentally deploy the code to mainnet... well, that's a very expensive mistake.

  2. I've seen teams where each developer had their own way of building the same project. Dean uses release builds and deploys to devnet, Joe uses debug builds on localhost, Toly has custom linker flags. When Dean tells Joe "just run sbpf build," they get different results because there's no shared understanding of how the project should be built.

  3. Developers working on multiple Solana projects simultaneously have to mentally remember completely different command sequences for each project. Project A needs optimization flags, Project B needs custom linker scripts, Project C deploys to testnet. This is exhausting and mistakes are inevitable.

Why I Almost Didn't Fix It

Honestly, I debated whether this was worth the effort:

  • Why build a configuration system just to save developers some typing?
  • At least when you see sbpf build --optimization release you know exactly what's happening
  • There are existing workarounds
  • Configuration files adds complexity

Why I Went Ahead Anyway

But then I realized this isn't just about saving keystrokes, it's about developer experience and team collaboration:

  1. Time is money

  2. Most wonderful development tools use configuration files

  3. Configuration prevents the mistakes highlighted above

  4. I believe there are big plans for sbpf so configuration would be necessary for some of these plans to actually be possible

What I added

I added a TOML-based configuration system that transforms sbpf into a project-aware development environment:

New Features Added

1. sbpf.toml Configuration Files

[project]
name = "my-solana-program"
version = "0.1.0"

[build]
optimization = "debug"
target = "sbf"
flags = ["--strip"]

[deploy]
cluster = "localhost"
program_id = "SBPFxKXt..."

[test]
framework = "mollusk"
validator_args = ["--reset"]

2. Configuration Management Commands

  • sbpf config init - Create configuration file
  • sbpf config show - View current settings
  • sbpf config set key value - Modify settings

3. Project Initialization

  • sbpf init now automatically creates sbpf.toml files
  • Pre-configured based on test framework choice (Mollusk/TypeScript)

4. Configuration-Aware Commands

  • All existing commands (build, deploy, test) now respect configuration
  • Command-line arguments still work and override config when specified
  • Projects without config work exactly as before, so it is 100% backward compatible

How to Try It

Create a new project with configuration:

sbpf init my-program
cd my-test-program
cat sbpf.toml  # See the generated config

Add configuration to existing project:

sbpf config init
sbpf config show

Customize or modify your project configuration:

sbpf config set build.optimization debug
sbpf config set deploy.cluster localhost
sbpf config set test.framework mollusk

Build with project awareness:

sbpf build   # Uses optimization = "debug" from config
sbpf deploy  # Uses cluster = "localhost" from config
sbpf test    # Uses framework = "mollusk" from config

What I Tested

I tested this to ensure I got the exact result I envisioned:

  1. Existing projects without configuration files work exactly as before. No breaking changes.

  2. You can create a project with configuration, commit it to git, and verify that anyone cloning the repo gets identical build behavior without setup.

  3. Tested malformed TOML files, missing configuration, invalid values and they all produce helpful error messages that guide users to solutions.

  4. Verified that command-line arguments still override configuration when specified, maintaining user control.

The Results

The transformation is immediate and noticeable:

Before:

# Every single time, manually specify everything
sbpf build --optimization release --target sbf-custom
sbpf deploy my-program testnet --program-id SBPFxKXt...
sbpf test --framework mollusk --validator-args --reset

After:

# Project knows what it needs
sbpf build
sbpf deploy  
sbpf test

@deanmlittle
Copy link
Collaborator

This is awesome. Let me collate some additional feedback and make sure we have covered everything. It looks very complete though. Great work!

@deanmlittle
Copy link
Collaborator

My preliminary thoughts: Overall very good. I have a few critiques:

  1. I'm not sure that we need build settings. We would always want to strip everything that isn't absolutely necessary and we would not be optimizing anything as assembly should maintain a 1:1 relationship with bytecode. If versioned bytecode ever goes live and we subsequently decided to support it, it might make more sense.

  2. What if we simply allow the user to define a test command which would default to cargo test-sbf and could be changed to yarn test if they chose typescript tests at init time. This would mean people can write tests in any language or framework they like, such as litesvm, bankrun, solana-test-validator, python, golang, etc. There are also many awesome devs who would love to score an easy PR by providing boilerplate for each of these out of the box to make it easy for anyone to get started.

  3. For deploy, could we perhaps do something similar to what anchor does where they allow you to define multiple deploy environments, and define the keypair directory instead of the address?

Let me know what you think :)

@Adrena-Corto
Copy link

Adrena-Corto commented Jul 14, 2025

Developers working on multiple Solana projects simultaneously have to mentally remember completely different command sequences for each project

Work 2 weeks on a side geyser client, come back to main project and forget how to build (real)

Also interested by Dean suggestion for the tests in any languages/framework

@donjne
Copy link
Author

donjne commented Jul 14, 2025

Thanks for the feedback! I think these suggestions make the system much more flexible:

  1. The build settings removal makes sense because assembly should maintain that 1:1 relationship with bytecode. Removing optimization flags keeps it original.

  2. I love the flexible test commands approach. Instead of hardcoding frameworks, we could have:

[test]
language = "typescript"        # Defaults to "yarn test"
# command = "pnpm test"  # Override when needed
  1. The deploy environments could work like this:
[deploy]
default = "devnet"  # default environment
localhost = { keypair_dir = "./deploy", url = "http://localhost:8899" }
devnet = { keypair_dir = "./keys/devnet", url = "https://api.devnet.solana.com" }
mainnet = { keypair_dir = "./keys/mainnet", url = "https://api.mainnet-beta.solana.com" }

The command sbpf deploy uses the default while sbpf deploy --env mainnet overrides it. All deploy commands would use the right keypair directory and URL. The same format should also work for custom rpc endpoints and they can add an rpc endpoint like this:

custom_rpc_endpoint = { keypair_dir = "./keys/custom_rpc", url = "https://custom-rpc.example.com" } #custom rpc endpoint

and then deploy using the command:

sbpf deploy --env custom_rpc_endpoint

@deanmlittle
Copy link
Collaborator

I think the way I'd rather go about it is to do something more like this:

[project]
name = "my-solana-program"
version = "0.1.0"

[scripts]
test = "cargo test"

[deploy]
cluster = "http://localhost:8899"
wallet = "~/.config/solana/id.json"

That way, the test script is totally customizable and interoperable with any Anchor test script, and we can make it easy for the user to set up multiple other scripts, and for deploy, they can just maintain multiple versions and comment out the ones the don't want to public.

The only downside I can see here is that it would be rather easy to accidentally dox your deployment RPC.

@donjne donjne force-pushed the feature/configuration-system branch from 127eaf0 to 8128d19 Compare August 6, 2025 19:50
@donjne
Copy link
Author

donjne commented Aug 6, 2025

I'm done working on it @deanmlittle. Check it out. I also made some improvements to the CLI. In details:

Environment Variables

  • Added support for environment variables in configuration values using ${VAR:-default} syntax
  • Enables secure handling of sensitive data like RPC endpoints and API keys
  • Automatic resolution during config loading with helpful user feedback

Scripts

  • Implemented scripts allowing custom commands in sbpf.toml
  • Added sbpf script <name> command to run user-defined scripts
  • Built-in command overrides (test, build, deploy) via scripts configuration
  • Intelligent defaults: Rust projects get "cargo test", TypeScript projects get "yarn test"

Security Warnings

  • Security validation that warns about potentially sensitive configurations
  • Mainnet RPC detection with recommendations for environment variables
  • Custom RPC endpoint warnings to prevent accidental exposure of private info
  • Non-blocking warnings that inform without restricting user choice

CLI Override

  • Command-line arguments now take precedence over configuration file settings
  • Added --mode, --optimization flags for build command
  • Added --cluster and --program flag for deploy command
  • Added --command flag for test command
  • Clear feedback showing when CLI overrides are active

Build

  • Added build.mode configuration for switching between "full" (Solana toolchain) and "light" (sbpf-assembler) builds
  • Enhanced light build integration with project configuration
  • Better validation and error messages for build configurations

Cluster

  • Automatic mapping of cluster names to RPC URLs (localhosthttp://localhost:8899)
  • Support for both short names (devnet) and full URLs (https://custom-rpc.com)
  • Flexible deployment targeting for any Solana-compatible network

@donjne donjne force-pushed the feature/configuration-system branch 2 times, most recently from bf08557 to 28d0321 Compare August 12, 2025 09:38
@donjne donjne force-pushed the feature/configuration-system branch from 28d0321 to 1e0be17 Compare August 12, 2025 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants