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

@spree-finance/spree-evm-sdk

v0.2.0

Published

TypeScript SDK for building unsigned transactions for Spree Finance contracts

Readme

SPREE FINANCE EVM SDK

npm version npm downloads License: MIT TypeScript

TypeScript SDK for building unsigned transactions for Spree Protocol smart contracts on Base and MOCA Devnet. Supports brand hierarchies (Spree parent, Airsp branded child) and multi-network deployments.

Features

  • Transaction Building: Build unsigned legacy transactions for offline/hardware wallet signing
  • Read Operations: Execute eth_call for view functions without building transactions
  • Type Safety: Full TypeScript support with branded Hex types
  • Gas Overrides: Customize gas parameters per transaction
  • Nonce Management: Automatic nonce handling with optional caching for batch operations
  • Error Handling: Typed errors for RPC and network failures

What's Included

The npm package includes:

  • Built Code: ESM (dist/index.js) and CommonJS (dist/index.cjs) builds
  • Type Definitions: Full TypeScript declarations (dist/index.d.ts)
  • Contract ABIs: JSON ABI files for all supported contracts (contracts/)

Package size: ~89 KB compressed, ~821 KB unpacked

Installation

npm install @spree-finance/spree-evm-sdk

Or with Yarn:

yarn add @spree-finance/spree-evm-sdk

Or with pnpm:

pnpm add @spree-finance/spree-evm-sdk

Peer Dependencies

This SDK requires ethers v6 as a peer dependency:

npm install ethers@^6.0.0

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.3 (for TypeScript projects)
  • ESM support (NodeNext module resolution)

Integrations

For end-to-end examples (backend-built unsigned tx → wallet signing → broadcasting), see:

Documentation

Breaking Changes (v0.2.0)

⚠️ Important: Version 0.2.0 includes breaking changes to PendingSPVault:

  1. createCampaign() signature changed - Now requires 3 additional parameters for supply caps:

    // New signature (v0.2.0)
    await vault.createCampaign(
      campaignId, spBudget, destinations, whitelist, metadata,
      maxTotalSupply,    // NEW: 0 = unlimited
      maxMintPerUser,    // NEW: 0 = unlimited
      dailyMintLimit     // NEW: 0 = unlimited
    );
  2. Campaign interface expanded - 10 new fields added (supply caps, fee tracking, metrics)

  3. Backward compatibility - Use createCampaignLegacy() during migration (deprecated, removed in v1.0.0)

See MIGRATION.md for detailed migration instructions.

Quick Start

Base Sepolia (Primary Testnet)

import { SpreeVault4626 } from '@spree-finance/spree-evm-sdk';

// Initialize the vault wrapper
const vault = new SpreeVault4626({
  rpcUrl: 'https://sepolia.base.org',
  chainId: 84532n,
  contractAddress: '0x...',
  from: '0x...', // Your wallet address
  defaultGasPriceWei: 1_000_000_000n, // 1 gwei
  defaultGasLimit: 500_000n,
});

// Read contract state (uses eth_call)
const balance = await vault.readBalanceOf('0x...');
const totalAssets = await vault.readTotalAssets();
const vaultHealth = await vault.readVaultHealth();

// Build unsigned transaction for signing
const unsignedTx = await vault.deposit(1_000_000n, '0x...');

// Sign with your wallet/hardware device and broadcast
const signedTx = await wallet.signTransaction(unsignedTx);
const txHash = await provider.sendTransaction(signedTx);

MOCA Devnet (Brand Deployments)

import {
  PendingSPVault,
  getContractsForBrand,
  MOCA_DEVNET_CONFIG,
} from '@spree-finance/spree-evm-sdk';

// Get brand-specific contract addresses
const spreeContracts = getContractsForBrand('spree', 5151n);
// Returns: { FACTORY, POINTS, COLLATERAL_VAULT, PENDING_SP_VAULT }

const airspContracts = getContractsForBrand('airsp', 5151n);
// Returns: { FACTORY, POINTS, COLLATERAL_VAULT, PENDING_SP_VAULT }

// Initialize with brand-specific address
const pendingSP = new PendingSPVault({
  rpcUrl: MOCA_DEVNET_CONFIG.rpcUrl,
  chainId: MOCA_DEVNET_CONFIG.chainId,
  contractAddress: spreeContracts!.PENDING_SP_VAULT,
  from: userAddress,
  defaultGasPriceWei: 1_000_000_000n,
  defaultGasLimit: 500_000n,
});

// Create campaign on MOCA Devnet
const campaignTx = await pendingSP.createCampaign(
  campaignId,
  spBudget,
  [settlementDestination],
  [transferWhitelist],
  metadata,
  0n, // maxTotalSupply (0 = unlimited)
  0n, // maxMintPerUser (0 = unlimited)
  0n  // dailyMintLimit (0 = unlimited)
);

MOCA Testnet (Spree Deployments)

import {
  PendingSPVault,
  getContractsForBrand,
  MOCA_TESTNET_CONFIG,
} from '@spree-finance/spree-evm-sdk';

// Get Spree contract addresses on MOCA Testnet
const spreeContracts = getContractsForBrand('spree', 222888n);
// Returns: { FACTORY, POINTS, COLLATERAL_VAULT, PENDING_SP_VAULT }

// Initialize with testnet configuration
const pendingSP = new PendingSPVault({
  rpcUrl: MOCA_TESTNET_CONFIG.rpcUrl,
  chainId: MOCA_TESTNET_CONFIG.chainId,
  contractAddress: spreeContracts!.PENDING_SP_VAULT,
  from: userAddress,
  defaultGasPriceWei: 1_000_000_000n,
  defaultGasLimit: 500_000n,
});

// Create campaign on MOCA Testnet
const campaignTx = await pendingSP.createCampaign(
  campaignId,
  spBudget,
  [settlementDestination],
  [transferWhitelist],
  metadata,
  0n, // maxTotalSupply (0 = unlimited)
  0n, // maxMintPerUser (0 = unlimited)
  0n  // dailyMintLimit (0 = unlimited)
);

Examples

The examples/ directory contains 20+ runnable examples demonstrating best practices for using the SDK. These examples show how to build unsigned transactions and perform read-only operations.

Setup

cd examples
npm install

# Configure environment
cp .env.example .env
# Edit .env with your values (RPC URL, private key, contract addresses)

Getting Started

1. Read Contract State (Query without transactions)

Query vault metrics using eth_call - no transaction needed:

import { SpreeVault4626 } from '@spree-finance/spree-evm-sdk';

const vault = new SpreeVault4626({
    rpcUrl: 'https://sepolia.base.org',
    chainId: 84532n,
    contractAddress: '0x...',
    from: '0x...',
    defaultGasPriceWei: 1_000_000_000n,
    defaultGasLimit: 500_000n,
});

// Query vault health metrics
const health = await vault.readVaultHealth();
console.log(`Total Assets: ${health.totalAssets}`);
console.log(`Utilization: ${health.utilization}%`);
console.log(`Is Balanced: ${health.isBalanced}`);

// Run: npm run read:vault-health

2. Build Unsigned Transaction (SDK's core purpose)

Build an unsigned deposit transaction for later signing:

import { SpreeVault4626 } from '@spree-finance/spree-evm-sdk';

const vault = new SpreeVault4626(config);

// Build unsigned transaction (no signing, no broadcasting)
const unsignedTx = await vault.deposit(1_000_000n, receiverAddress);

// unsignedTx is a hex string ready for:
// - Hardware wallet signing
// - Software wallet signing
// - Storage for later signing
// - Audit before execution

// Run: npm run tx:build-deposit

3. Complete Transaction Flow (Build → Sign → Broadcast)

Using ethers v6 to sign and broadcast SDK-built transactions:

import { SpreeVault4626 } from '@spree-finance/spree-evm-sdk';
import { Wallet, JsonRpcProvider } from 'ethers';

const vault = new SpreeVault4626(config);
const provider = new JsonRpcProvider(process.env.RPC_URL);
const wallet = new Wallet(process.env.PRIVATE_KEY, provider);

// Step 1: SDK builds unsigned transaction
const unsignedTx = await vault.deposit(1_000_000n, receiverAddress);

// Step 2: Sign with ethers
const signedTx = await wallet.signTransaction(unsignedTx);

// Step 3: Broadcast to network
const txResponse = await provider.broadcastTransaction(signedTx);
console.log(`Transaction hash: ${txResponse.hash}`);

// Run: npm run tx:sign-broadcast

4. Advanced Multi-Step Workflow (Campaign creation)

Create a Pending SP campaign with token approvals and boost configuration:

import { PendingSPVault, BoostEngine, ERC20 } from '@spree-finance/spree-evm-sdk';

const spToken = new ERC20(config);
const pendingSP = new PendingSPVault(config);
const boostEngine = new BoostEngine(config);

// Step 1: Approve SP tokens for campaign
const approveTx = await spToken.approve(vaultAddress, budget);
const signedApprove = await signTransaction(approveTx);
await broadcastTransaction(signedApprove);

// Step 2: Create campaign
const createTx = await pendingSP.createCampaign(
    campaignId,
    spBudget,
    [settlementDestination],
    [transferWhitelist],
    metadata
);

// Step 3: Configure boost multipliers
const boostTx = await boostEngine.setNamespaceMultipliers(
    namespace,
    [100n, 125n, 150n, 200n, 250n] // Tier 0-4 multipliers
);

// Step 4: Activate campaign
const activateTx = await pendingSP.setCampaignActive(campaignId, true);

// Run: npm run pending-sp:create-campaign

All Examples

| Category | Command | Description | |----------|---------|-------------| | Read Operations | | | | | npm run read:vault-health | Query vault metrics (total assets, utilization, health) | | | npm run read:balances | Check USDC, SP token, and vault share balances | | | npm run read:campaign-info | View Pending SP campaign details and budget | | | npm run read:user-status | Query user tier, status, and boost multiplier | | | npm run read:boost-multiplier | Check boost multipliers for reward calculation | | Transactions | | | | | npm run tx:build-deposit | Build unsigned deposit transaction | | | npm run tx:sign-broadcast | Complete flow: build, sign, and broadcast | | | npm run tx:batch-nonce | Batch multiple transactions with nonce caching | | Pending SP Vault | | | | | npm run pending-sp:create-campaign | Create campaign with boost integration | | | npm run pending-sp:create-basic | Simple campaign creation | | | npm run pending-sp:create-and-mint | Create campaign and mint tokens | | | npm run pending-sp:mint | Mint pSP tokens to users | | | npm run pending-sp:mint-boosted | Mint with automatic boost calculation | | | npm run pending-sp:expire | Expire campaign tokens | | | npm run pending-sp:fund-campaign | Fund campaign with SP tokens | | | npm run pending-sp:user-story | Complete user workflow demonstration | | Factory | | | | | npm run factory:mint | Mint SP tokens through factory | | Rewards | | | | | npm run rewards:claim | Claim all available rewards in batch |

See examples/README.md for detailed documentation on each example.

Contract Wrappers

SpreeVault4626

ERC-4626 compliant yield vault with harvest/rebalance functionality.

import { SpreeVault4626 } from '@spree-finance/spree-evm-sdk';

const vault = new SpreeVault4626(config);

// ERC-4626 Core Operations
await vault.deposit(assets, receiver);
await vault.mint(shares, receiver);
await vault.withdraw(assets, receiver, owner);
await vault.redeem(shares, receiver, owner);

// Read Functions
const shares = await vault.readConvertToShares(assets);
const assets = await vault.readConvertToAssets(shares);
const health = await vault.readVaultHealth();

// Strategy Operations
await vault.harvest();
await vault.rebalance();
await vault.emergencyWithdrawAll();

// Admin Functions
await vault.setFees(mintFeeBps, redeemFeeBps, feeReceiver);
await vault.setAdapter(adapterAddress);
await vault.updateParameters(minIdleBufferBps, maxUtilizationBps);

BonusRewardsVault

Epoch-based bonus reward distribution vault.

import { BonusRewardsVault } from '@spree-finance/spree-evm-sdk';

const rewards = new BonusRewardsVault(config);

// Claim Rewards
await rewards.claimBonus(epochId);
await rewards.claimBonusBatch([1n, 2n, 3n]);

// Read Functions
const currentEpoch = await rewards.readGetCurrentEpochId();
const claimable = await rewards.readGetClaimableEpochs(user, 10n);
const estimate = await rewards.readBonusEstimateForEpoch(user, epochId);

// TVL Snapshots
await rewards.takeTVLSnapshot();
const history = await rewards.readGetTVLHistory();

// Partner Management
await rewards.registerPartner(partnerAddress);
const revenue = await rewards.readGetPartnerRevenue(partner);

Factory

Vault creation and mint/redeem operations.

import { Factory } from '@spree-finance/spree-evm-sdk';

const factory = new Factory(config);

// Vault Management
await factory.createVault(asset, assetToSharesRate);
await factory.pauseVault(asset);
await factory.unpauseVault(asset);

// Mint/Redeem
await factory.mint(asset, amount, receiver, expectBasketMode);
await factory.requestToRedeem(asset, pointsAmount, receiver, expectBasketMode);
await factory.finalizeRedeem(account);

// Configuration
await factory.setMintRate(asset, rate);
await factory.setRedeemRate(asset, rate);
await factory.setGlobalCap(limit);

Points

ERC-20 points token with TWAB tracking.

import { Points } from '@spree-finance/spree-evm-sdk';

const points = new Points(config);

// ERC-20 Operations
await points.transfer(to, amount);
await points.approve(spender, amount);
const balance = await points.readBalanceOf(owner);

// Admin Functions
await points.mint(to, amount);
await points.burn(from, amount);
await points.addToTransferWhitelist(account);

PythPriceOracle

Pyth Network price oracle integration.

import { PythPriceOracle } from '@spree-finance/spree-evm-sdk';

const oracle = new PythPriceOracle(config);

// Read Prices
const price = await oracle.readGetPrice(asset);
const priceWithAge = await oracle.readGetPriceNoOlderThan(asset, maxAge);

// Configuration
await oracle.setPriceFeed(asset, pythFeedId);
await oracle.setPythSource(pythOracleAddress);

PendingSPVault

Conditional reward token system with campaign-scoped budgets and programmable settlement.

import { PendingSPVault } from '@spree-finance/spree-evm-sdk';

const pendingSP = new PendingSPVault(config);

// Campaign Management
await pendingSP.createCampaign(
  campaignId,
  spBudget,
  settlementDestinations,
  transferWhitelist,
  metadata
);
await pendingSP.fundCampaign(campaignId, amount);
await pendingSP.setCampaignActive(campaignId, true);

// Token Operations
await pendingSP.mint(campaignId, to, amount, metadata);
await pendingSP.settle(from, to, amount, campaignId, metadata);
await pendingSP.expire(from, amount, campaignId, metadata);
await pendingSP.transferWithCampaign(to, amount, campaignId);

// Read Functions
const campaign = await pendingSP.readGetCampaign(campaignId);
const balance = await pendingSP.readBalanceOfCampaign(user, campaignId);
const availableBudget = await pendingSP.readGetCampaignAvailableBudget(campaignId);
const userCampaigns = await pendingSP.readGetUserCampaigns(user);

Mint with Boost

Use mintBoosted() for automatic tier-based boost calculation and application:

import { PendingSPVault } from '@spree-finance/spree-evm-sdk';

const pendingSP = new PendingSPVault(config);

// Standard mint (no boost)
await pendingSP.mint(campaignId, to, amount, metadata);

// Mint with automatic boost calculation
// Contract calculates boost based on user's tier and mints base + boost amount
await pendingSP.mintBoosted(campaignId, to, amount, metadata);

The mintBoosted() function:

  • Calculates boost amount using the configured BoostEngine
  • Mints baseAmount + boostAmount in a single transaction
  • Emits both PspMinted and BoostedMint events
  • Respects campaign budget with the total (base + boost) amount

Complete Campaign Workflow

Full campaign lifecycle with nonce management for batch operations:

import { PendingSPVault, ERC20 } from '@spree-finance/spree-evm-sdk';

const spToken = new ERC20(erc20Config);
const pendingSP = new PendingSPVault(config);

// Enable nonce caching for sequential transactions
pendingSP.enableNonceCache();
spToken.enableNonceCache();

// Step 1: Approve SP tokens
const approveTx = await spToken.approve(vaultAddress, budget);
const signedApprove = await signTransaction(approveTx);
await broadcastTransaction(signedApprove);

// Step 2: Create campaign
const createTx = await pendingSP.createCampaign(
  campaignId,
  spBudget,
  [settlementDestination],
  [transferWhitelist],
  metadata
);

// Step 3: Fund campaign
const fundTx = await pendingSP.fundCampaign(campaignId, spBudget);

// Step 4: Set campaign admin and minter
await pendingSP.setCampaignAdmin(campaignId, adminAddress, true);
await pendingSP.setMinter(campaignId, minterAddress, mintAllowance, true);

// Step 5: Activate campaign
const activateTx = await pendingSP.setCampaignActive(campaignId, true);

// Disable nonce caching when done
pendingSP.disableNonceCache();
spToken.disableNonceCache();

See the examples/pending-sp/ directory for complete implementations including:

  • create-campaign.ts - Full campaign creation with boost integration
  • create-and-mint.ts - Create, fund, mint, and settle workflow
  • mint-boosted.ts - Mint with automatic boost calculation
  • user-story.ts - Complete user journey demonstration
  • expire.ts - Token expiration handling

Brand Configuration

The SDK supports multiple brands with parent-child relationships:

Available Brands

  • spree: Root/parent brand
  • airsp: Branded child of Spree

Supported Networks

  • Base Sepolia (chainId: 84532) - Ethereum testnet
  • MOCA Devnet (chainId: 5151) - Spree/Airsp deployments (active)
  • MOCA Testnet (chainId: 222888) - Spree deployments (active)

Using Brand Configuration

import {
  getBrandConfig,
  getContractsForBrand,
  getChildBrands,
  ContractRegistry,
} from '@spree-finance/spree-evm-sdk';

// Get brand configuration
const spreeConfig = getBrandConfig('spree');
const airspConfig = getBrandConfig('airsp');

// Get contracts for brand on specific chain
const spreeContracts = getContractsForBrand('spree', 5151n);
// Returns: { FACTORY, POINTS, COLLATERAL_VAULT, PENDING_SP_VAULT }

// Get child brands
const spreeChildren = getChildBrands('spree'); // [airspConfig]

// Use ContractRegistry for brand hierarchy
const registry = new ContractRegistry({ apiBaseUrl: '...' });
const hierarchy = registry.getContractsForBrandHierarchy('spree', 5151);
// Returns: { parent: {...}, children: [{...}] }

// Get specific vault addresses
const pendingSPAddress = registry.getPendingSPVaultAddress('airsp', 5151);
const collateralVaultAddress = registry.getCollateralVaultAddress('spree', 5151);

SpreeStatusRegistry

User tier and status management system with TWAB integration.

import { SpreeStatusRegistry } from '@spree-finance/spree-evm-sdk';

const statusRegistry = new SpreeStatusRegistry(config);

// Read User Status
const tier = await statusRegistry.readGetTier(user, namespace);
const status = await statusRegistry.readGetStatus(user, namespace);
const multiplier = await statusRegistry.readGetBoostMultiplier(user, namespace);

// Tier Configuration (admin)
await statusRegistry.createNamespace(namespace, admin);
await statusRegistry.setTierConfig(namespace, tierLevel, {
  spThreshold: 1000_000_000_000n,
  holdingPeriod: 2592000n,
  boostMultiplier: 125n,
});
await statusRegistry.setMaxTier(namespace, 5);

// Tier Updates
await statusRegistry.updateTier(user, namespace);
await statusRegistry.batchUpdateTiers([user1, user2], namespace);

// Oracle/Operator Functions
await statusRegistry.setUserTier(user, namespace, 3, 100n);
await statusRegistry.setTierByOracle(user, namespace, 2, 50n);

BoostEngine

Tier-based reward boosting system with campaign-specific configurations.

import { BoostEngine } from '@spree-finance/spree-evm-sdk';

const boostEngine = new BoostEngine(config);

// Read Boost Information
const multiplier = await boostEngine.readGetMultiplier(user, namespace);
const tierMultiplier = await boostEngine.readGetTierMultiplier(namespace, tier);
const boostedAmount = await boostEngine.readCalculateBoostedReward(
  user,
  namespace,
  baseAmount
);

// Configure Namespace Multipliers (admin)
await boostEngine.setNamespaceMultipliers(namespace, [
  100n, // Tier 0
  125n, // Tier 1
  150n, // Tier 2
  200n, // Tier 3
  250n, // Tier 4
]);

// Configure Campaign Boosts (configurator)
await boostEngine.setCampaignBoost(campaignId, {
  baseMultiplier: 100n,
  earlyBirdBonus: 10n,
  earlyBirdCount: 100n,
  loyaltyBonus: 5n,
  referralBonus: 5n,
  maxPerUser: 10_000_000_000n,
  cooldownSeconds: 86400n,
});

// Record Boost Application (recorder)
await boostEngine.recordBoostApplication(user, namespace, campaignId);

Advanced Usage

Gas Overrides

Customize gas parameters per transaction:

const tx = await vault.deposit(1_000_000n, receiver, {
  gasLimit: 300_000n,
  gasPriceWei: 2_000_000_000n,
  valueWei: 0n, // For payable functions
});

Nonce Caching

For batch transaction building:

// Enable caching to avoid RPC calls per transaction
vault.enableNonceCache();

const tx1 = await vault.deposit(1_000_000n, receiver);
const tx2 = await vault.withdraw(500_000n, receiver, owner);
const tx3 = await vault.harvest();

// All transactions have sequential nonces without extra RPC calls

vault.disableNonceCache();

Manual Nonce Control

vault.setNonce(42n); // Start from specific nonce

const tx = await vault.deposit(1_000_000n, receiver);
// Transaction will have nonce 42

vault.resetNonceCache(); // Clear and fetch fresh on next call

Calldata Encoding

Encode function calls without building full transactions:

const calldata = vault.encodeCall('deposit', [1_000_000n, receiver]);
// Use for multicall or direct contract interaction

Error Handling

import { RpcError, NetworkError } from '@spree-finance/spree-evm-sdk';

try {
  const tx = await vault.deposit(1_000_000n, receiver);
} catch (error) {
  if (error instanceof NetworkError) {
    console.error('Network issue:', error.message);
  } else if (error instanceof RpcError) {
    console.error('RPC error:', error.code, error.message);
  }
}

API Reference

Configuration

All contract wrappers accept a BaseContractConfig:

interface BaseContractConfig {
  rpcUrl: string;          // JSON-RPC endpoint URL
  chainId: bigint;         // Chain ID (e.g., 84532n for Base Sepolia)
  contractAddress: Hex;    // Contract address
  from: Hex;               // Sender address for nonce lookup
  defaultGasPriceWei: bigint;  // Default gas price
  defaultGasLimit: bigint;     // Default gas limit
}

Types

type Hex = `0x${string}`;  // Branded hex string

interface TxOverrides {
  gasPriceWei?: bigint;
  gasLimit?: bigint;
  valueWei?: bigint;
}

Development

# Install dependencies
npm install

# Build
npm run build

# Run SDK tests
npm test
npm run test:coverage

# Run example tests
cd examples
npm install
npm test
npm run test:coverage

Pre-publish Checklist

Before publishing to npm, run the full validation:

npm run prepublishOnly

This runs: lint → test → build

See AGENTS.md for detailed development guidelines and CLAUDE.md for Claude Code specific instructions.

Changelog

See CHANGELOG.md for version history and release notes.

License

MIT