npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@swaputer-labs/tinysol

v0.4.1

Published

Deterministic TinySol compiler, simulator, CLI and SwapVM fee estimators.

Readme

@swaputer-labs/tinysol

Compiler, assembler, simulator and offline CLI for the TinySol language. TinySol programs compile deterministically to SwapVM Mini Contract packages; the same input and compiler version always produce the same bytecode and hashes.

The package does not connect to an RPC endpoint, load a wallet, sign transactions or deploy contracts.

Version identities

TinySol publishes several independent version identifiers:

  • the npm package version identifies the JavaScript distribution and may change for packaging or tooling updates;
  • the language version identifies accepted source semantics and compatibility rules;
  • the compiler version identifies a concrete compiler implementation release;
  • the SwapVM ISA version identifies the frozen bytecode instruction set consumed by the protocol.

They must not be treated as interchangeable. The legacy-v1 compatibility profile is frozen in fixtures/legacy-compatibility-v1.json; it records the pre-extension compiler identity and asserts byte-exact program packages plus canonical ABI, event and storage artifacts without changing SwapVM ISA v2.

Installation and release status

npm install @swaputer-labs/[email protected]

The 0.4.1 release contains the language v1.1 additions below and the SwapVM input estimator. It requires Node.js 22 or newer and uses ES modules. Pin the exact version in reproducible application builds.

Compile a contract

import { compileTinySol } from "@swaputer-labs/tinysol";

const source = `
contract Counter {
  uint256 value;

  function increment(uint256 amount) returns (uint256) {
    value = value + amount;
    return value;
  }
}
`;

const result = compileTinySol(source, {
  sourceName: "Counter.tiny.sol"
});

console.log(result.codeHash);
console.log(result.packageBytes);
console.log(result.abi);

compileTinySol returns the package bytes, code hash, ABI, event descriptor, storage layout, assembly, source map and compiler identity. Compilation is atomic: invalid source throws a stable ToolchainError without returning a partial artifact set.

Check source without compiling

import {
  checkTinySol,
  formatDiagnostics,
  isToolchainError
} from "@swaputer-labs/tinysol";

try {
  const checked = checkTinySol(source, {
    sourceName: "Counter.tiny.sol"
  });
  console.log(checked.program.contract.name);
} catch (error) {
  if (!isToolchainError(error)) throw error;
  console.error(formatDiagnostics(error));
}

The public compiler pipeline also exports lexTinySol, parseTinySol, resolveTinySol, typeCheckTinySol and lowerTinySol, together with readonly syntax and artifact types.

Language v1.1 extensions

The compiler supports typed constants, enums, snapshot-value structs with declaration-order ABI flattening, fixed storage arrays, named errors, bounded indexed-collection patterns, conditional expressions, integer compound assignments, statement-form ++/--, typed delete, scalar/array/struct multi-return destructuring, local/ABI scalar, enum and non-recursive struct fixed arrays, fixed-array struct fields, array literals and every uint8...uint256 / int8...int256 width in 8-bit steps. Narrowing and signedness changes use checked explicit casts such as uint24(value); same-signed widening is implicit. Narrow integers remain one 32-byte word and do not enable storage packing. New constructs lower entirely to the existing SwapVM ISA v2. Structs can cross internal and external call boundaries, be returned directly, and be copied or updated through nested member paths without partial-value aliasing. ABI arrays and structs flatten to consecutive scalar words. Member arrays such as pool.reserves[i] and pool.positions[i].amount are bounds checked. Scalar, enum and non-recursive struct arrays support direct multidimensional syntax such as uint256[3][2] and Position[2][2], including storage, mapping values, struct fields, locals and static ABI/calls. Scalar and enum multidimensional arrays also expose fixed subarray reads, writes, returns, call arguments and delete, with each dynamic prefix index evaluated once. break and continue are supported in nested while/for loops, and fixed arrays may be declared in for initializers. Bounded vectors use T[<=N]; bounded byte and UTF-8 string values use bytes<N> and string<N>. They provide .length, .push(value), .pop(), checked reads and capacity-checked implicit expansion on indexed writes. These types work in storage, mappings, struct fields, locals and the static ABI. Array-bearing structs can be mapping values through deterministic bounded second-level storage hashing or elements of outer fixed arrays through row-major linearization with independent bounds checks. Struct fields may be fixed arrays of array-bearing structs; recursively composed static dimensions use the same lowering across storage, mappings, locals and ABI. Each dimension is limited to 256 elements and the recursively flattened shape to 65,536 words. Arrays of structs flatten field-first (all elements of the first flattened field, then all elements of the next); enum arrays retain nominal type checks and receive a range check for every element.

See docs/TINYSOL-V1.1-LANGUAGE.md for the complete syntax, lowering and security rules and docs/TINYSOL-0.4-MIGRATION.md for upgrade guidance.

Multi-file projects and libraries

import { compileTinySolProject } from "@swaputer-labs/tinysol";

const result = await compileTinySolProject({
  projectRoot: "/absolute/project/root",
  entry: "src/Token.tiny.sol"
});

Local relative imports inside projectRoot are resolved directly. npm-style bare imports are accepted only through an exact tinysol.lock.json entry containing a project-relative path and SHA-256 digest; the result reports the lock and per-module hashes. URL, absolute, unpinned package, symlink-escape and cyclic imports are rejected. pure library functions are statically linked; there is no dynamic loader or mutable library state. Repeated clean builds are byte-identical.

The stdlib/ seed includes checked math, ownership/roles, AccountId/address conversion, hashing, signature recovery, bounded pagination and SRC20/SRC721 interfaces.

TypeScript frontend bindings

import { generateTypeScriptBindings } from "@swaputer-labs/tinysol";

const source = generateTypeScriptBindings(result.abi, result.eventDescriptor);

Bindings contain typed calldata/result helpers, framework-neutral read/write client methods, event decoders and named-error selectors. They never hold private keys or sign without the caller's wallet. CLI compilation accepts --bindings Token.bindings.ts to write this eighth artifact.

CLI

After installing 0.4.0 in a project, run its local CLI:

npx tinysol --help

Or install the published package globally:

npm install --global @swaputer-labs/[email protected]
tinysol --help

Available commands:

tinysol check --input Contract.tiny.sol
tinysol ast --input Contract.tiny.sol --json
tinysol format --input Contract.tiny.sol --output Contract.formatted.tiny.sol
tinysol compile --input Contract.tiny.sol --output Contract.svm \
  --abi Contract.abi.json --events Contract.events.json \
  --storage-layout Contract.storage.json --manifest Contract.manifest.json \
  --assembly Contract.svasm --source-map Contract.map.json \
  --bindings Contract.bindings.ts
tinysol asm --input program.svasm --output program.svm \
  --manifest program.manifest.json
tinysol disasm --input program.svm --output program.svasm
tinysol validate --input program.svm
tinysol inspect --input program.svm --json
tinysol hash --input program.svm
tinysol simulate --input simulation.json
tinysol estimate --input estimate.json
tinysol isa check

Existing output files are never replaced unless --force is supplied. An input path cannot also be used as an output path.

Assemble a program

Assembly uses one instruction per line. Mnemonics are case-insensitive; canonical disassembly emits uppercase mnemonics and LF line endings. ;, # and // begin comments outside quoted strings.

.constructor constructor
.runtime runtime
.abi-hash 0x0123...64-hex-digits
.code

constructor:
PUSH1 0x00
STOP

runtime:
JUMPDEST
.pushlabel runtime
JUMP

Supported directives are .constructor, .runtime, .abi-hash, .abi-canonical, .code and .pushlabel. Labels mark opcode boundaries and never insert bytes. Explicit PUSH1..PUSH32 widths and leading zero bytes are preserved.

The assembler returns code, entry points, ABI and package hashes, package bytes, source map, diagnostics and a deterministic sidecar manifest.

Validate and inspect bytecode

import {
  analyzeCode,
  disassemble,
  validateCode,
  validateProgramPackage
} from "@swaputer-labs/tinysol";

validateCode(codeBytes);
validateProgramPackage(packageBytes);

const assembly = disassemble(codeBytes);
const analysis = analyzeCode(codeBytes);

validateCode checks the production bytecode boundary: non-empty code, the 16,384-byte limit, known opcodes and complete fixed-width immediates. validateProgramPackage additionally checks the package header, declared length and entry-point boundaries. analyzeCode provides advisory diagnostics that are not consensus rules.

Simulate and estimate fees

The simulator consumes an explicit state snapshot and never reads chain state.

import {
  estimateMiniVMFee,
  simulateMiniVM
} from "@swaputer-labs/tinysol";

const result = simulateMiniVM(simulationInput);
const estimate = estimateMiniVMFee(estimateInput);

Successful simulations return deterministic output, storage changes and event records. Failed executions expose a stable MiniVMErrorCode and do not return partial committed state. Fee estimates distinguish executed-byte burn from maximum exposure and are unavailable for reverted or incomplete simulations.

Estimate the native swap input

estimateSwapVMInput calculates how much native currency a swap should provide for a signed SwapVM byte limit. It uses a caller-supplied live AMM quote, verifies the final amount against a fresh quote and enforces a hard input ceiling. The package does not choose an RPC or AMM for you.

import { estimateSwapVMInput } from "@swaputer-labs/tinysol";

const estimate = await estimateSwapVMInput({
  byteGasLimit: 320,
  byteGasPrice: 1_000_000_000_000n,
  minNetTokenOut: 1n,
  maximumNativeInput: 1_000_000_000_000_000n,
  quoteGrossTokenOut: async (exactNativeInput) => {
    // Query the configured AMM and return gross sPuter output in base units.
    return quoteGrossSPuter(exactNativeInput);
  }
});

console.log(estimate.exactNativeInput);

Simulation inputs may include context.tx.router, context.tx.executor and context.tx.recipient as EVM addresses. Omitted transaction-context fields default to the zero address.

Examples

The installed package includes TinySol examples under examples/, including legacy Counter, StructuredRegistry (enum + struct + fixed array), Voting (roles + bounded pagination), and multifile-token/MultiFileToken (imports + library + named errors + committed TypeScript bindings).

License

MIT