A comprehensive Gleam library for compiling Solidity contracts, inspired by deno-web3/solc.
Gleam Solc provides type-safe bindings for the Solidity compiler, enabling compilation of Solidity contracts with full support for:
- Multiple Inheritance: Interfaces, abstract contracts, and implementation chains
- Error Handling: Comprehensive compilation error detection and reporting
- Modern Solidity: Full support for Solidity 0.8+ features
- Type Safety: Leveraging Gleam's type system for safer compilation
- Cross-Platform: JavaScript runtime support
Add to your gleam.toml:
[dependencies]
gleam_solc = { git = "https://github.com/pxlvre/gleam_solc" }import gleam/dict
import gleam/option.{Some}
import solc
import solc/types
pub fn main() {
// 1. Load Solidity compiler
let assert Ok(compiler) = solc.load_solc("./cache/solc-v0.8.19.js", Some("0.8.19"))
// 2. Define your contract
let source = "
pragma solidity ^0.8.0;
contract HelloWorld {
string public message = \"Hello, World!\";
}
"
// 3. Compile
let assert Ok(output) = solc.compile_simple(compiler, "HelloWorld", source)
// 4. Access compiled contract
case output.contracts {
Some(contracts) -> {
// Use your compiled contract
io.println("Compilation successful!")
}
None -> io.println("No contracts compiled")
}
}The main entry point for the Gleam Solc library.
Downloads and loads a Solidity compiler.
Parameters:
path: Local file path to store/load the solc moduleversion: Optional specific version to download (uses latest if None)
Returns: Promise resolving to a SolcWrapper or error
Example:
import solc
import gleam/option.{Some, None}
// Load specific version
let assert Ok(solc_wrapper) = solc.load_solc("./solc-v0.8.19.js", Some("0.8.19"))
// Load latest version
let assert Ok(solc_wrapper) = solc.load_solc("./solc-latest.js", None)compile_simple(solc: SolcWrapper, contract_name: String, source_code: String) -> Result(CompilationOutput, SolcError)
Compiles a single Solidity contract with default settings.
Parameters:
solc: Loaded SolcWrapper instancecontract_name: Name identifier for the contractsource_code: Solidity source code as string
Returns: CompilationOutput or error
Example:
let source = "contract Simple { uint256 public value; }"
let assert Ok(output) = solc.compile_simple(solc_wrapper, "Simple", source)compile_multiple(solc: SolcWrapper, sources: Dict(String, String)) -> Result(CompilationOutput, SolcError)
Compiles multiple Solidity files with dependency resolution.
Parameters:
solc: Loaded SolcWrapper instancesources: Dictionary mapping filename to source code
Returns: CompilationOutput or error
Example:
import gleam/dict
let sources = dict.from_list([
#("IERC20.sol", interface_source),
#("ERC20.sol", implementation_source)
])
let assert Ok(output) = solc.compile_multiple(solc_wrapper, sources)Core type definitions for Solidity compilation.
SolcError - Comprehensive error handling
pub type SolcError {
DownloadError(String) // Network/download failures
CompilationFailed(String) // Solidity compilation errors
FFIError(String) // JavaScript FFI errors
InvalidInput(String) // Invalid compilation input
VersionNotFound(String) // Requested version unavailable
}CompilationInput - Input structure for compilation
pub type CompilationInput {
CompilationInput(
language: String, // "Solidity"
sources: Dict(String, Source), // filename -> source mapping
settings: CompilationSettings // compiler settings
)
}CompilationOutput - Results from compilation
pub type CompilationOutput {
CompilationOutput(
sources: Option(Dict(String, SourceInfo)), // Source file info
contracts: Option(Dict(String, Dict(String, Contract))), // Compiled contracts
errors: Option(List(CompilationError)) // Compilation errors
)
}Contract - Compiled contract data
pub type Contract {
Contract(
abi: List(ABIType), // Contract ABI
evm: EVM, // EVM bytecode and metadata
metadata: String // Compiler metadata
)
}Handles downloading and managing Solidity compiler versions.
Downloads a specific Solidity compiler version.
Parameters:
path: Local path to save the compilerversion: Optional version (uses latest if None)
Returns: Promise with downloaded version or error
Fetches available Solidity compiler releases from the official repository.
Returns: Promise with release information or error
Checks if a Solidity compiler file exists at the given path.
Parameters:
path: File path to check
Returns: Boolean indicating file existence
Low-level wrapper around loaded Solidity compiler modules.
Creates a wrapper around a loaded solc module.
Loads a Solidity compiler from file and creates a wrapper.
The library provides comprehensive ABI type definitions:
pub type ABIType {
ABIFunction(
name: String,
inputs: List(ABIParameter),
outputs: List(ABIParameter),
state_mutability: String
)
ABIEvent(
name: String,
inputs: List(ABIParameter),
anonymous: Bool
)
ABIConstructor(
inputs: List(ABIParameter),
state_mutability: String
)
ABIFallback(state_mutability: String)
ABIReceive(state_mutability: String)
}
pub type ABIParameter {
ABIParameter(
name: String,
type_: String,
internal_type: String,
indexed: Option(Bool)
)
}pub type EVM {
EVM(
bytecode: Bytecode,
deployed_bytecode: Option(Bytecode),
gas_estimates: Option(GasEstimates),
method_identifiers: Dict(String, String)
)
}
pub type Bytecode {
Bytecode(
object: String,
link_references: Dict(String, List(LinkReference)),
source_map: Option(String)
)
}pub type CompilationSettings {
CompilationSettings(
output_selection: OutputSelection,
optimizer: Option(OptimizerSettings),
evm_version: Option(String),
libraries: Option(Dict(String, String)),
remappings: Option(List(String))
)
}
pub type OptimizerSettings {
OptimizerSettings(
enabled: Bool,
runs: Int
)
}The library uses comprehensive error types for different failure scenarios:
import solc
case solc.compile_simple(wrapper, "Test", source) {
Ok(output) -> {
// Handle successful compilation
case output.errors {
Some(errors) -> {
// Check for warnings/errors in compilation
errors
|> list.each(fn(error) {
case error.severity {
"error" -> io.println("Error: " <> error.message)
"warning" -> io.println("Warning: " <> error.message)
_ -> Nil
}
})
}
None -> io.println("Clean compilation!")
}
}
Error(solc_error) -> {
case solc_error {
types.CompilationFailed(msg) -> io.println("Compilation failed: " <> msg)
types.InvalidInput(msg) -> io.println("Invalid input: " <> msg)
types.FFIError(msg) -> io.println("FFI error: " <> msg)
types.DownloadError(msg) -> io.println("Download error: " <> msg)
types.VersionNotFound(msg) -> io.println("Version error: " <> msg)
}
}
}import gleam/dict
import solc
pub fn compile_inheritance_example() {
let interface_source = "
pragma solidity ^0.8.0;
interface IERC20 {
function transfer(address to, uint256 amount) external returns (bool);
}
"
let abstract_source = "
pragma solidity ^0.8.0;
import \"./IERC20.sol\";
abstract contract ERC20Base is IERC20 {
mapping(address => uint256) internal _balances;
}
"
let implementation_source = "
pragma solidity ^0.8.0;
import \"./ERC20Base.sol\";
contract MyToken is ERC20Base {
function transfer(address to, uint256 amount) external override returns (bool) {
// Implementation
return true;
}
}
"
let sources = dict.from_list([
#("IERC20.sol", interface_source),
#("ERC20Base.sol", abstract_source),
#("MyToken.sol", implementation_source)
])
let assert Ok(solc_wrapper) = solc.load_solc("./solc.js", None)
let assert Ok(output) = solc.compile_multiple(solc_wrapper, sources)
// Access compiled contracts
case output.contracts {
Some(contracts) -> {
case dict.get(contracts, "MyToken.sol") {
Ok(file_contracts) -> {
case dict.get(file_contracts, "MyToken") {
Ok(contract) -> {
io.println("MyToken compiled successfully!")
io.println("ABI functions: " <> int.to_string(list.length(contract.abi)))
}
Error(_) -> io.println("MyToken not found")
}
}
Error(_) -> io.println("File not found")
}
}
None -> io.println("No contracts compiled")
}
}import solc/types
pub fn custom_compilation_example() {
let output_selection = types.OutputSelection(
selections: dict.from_list([
#("*", dict.from_list([
#("*", [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.gasEstimates",
"evm.methodIdentifiers",
"metadata",
"storageLayout"
])
]))
])
)
let settings = types.CompilationSettings(
output_selection: output_selection,
optimizer: Some(types.OptimizerSettings(enabled: True, runs: 1000)),
evm_version: Some("london"),
libraries: None,
remappings: Some([
"@openzeppelin/contracts/=./node_modules/@openzeppelin/contracts/"
])
)
let input = types.CompilationInput(
language: "Solidity",
sources: sources,
settings: settings
)
// Use custom input with wrapper
case wrapper.compile_standard(solc_module, encode_input(input)) {
Ok(output_json) -> {
// Parse output
parse_compilation_output(output_json)
}
Error(msg) -> Error(types.CompilationFailed(msg))
}
}This API documentation provides comprehensive coverage of the Gleam Solc library's functionality, types, and usage patterns.