A functional programming interface for merkletreejs that provides an intuitive, viem-inspired API for working with Merkle trees. This wrapper makes it easy to create, manipulate, and verify Merkle trees with a clean, functional interface.
- Functional API: Intuitive, functional interface inspired by viem
- Type Safety: Full TypeScript support with proper type definitions
- Flexible Input: Accepts strings, buffers, objects, and numbers as leaves
- Multiple Hash Functions: Built-in support for SHA256 (default), keccak256, and custom hash functions
- Proof Generation: Easy proof creation and verification
- Tree Manipulation: Add, remove, and update leaves
- Serialization: Marshal/unmarshal trees and proofs to JSON
- Advanced Options: Support for Bitcoin-style trees, sorted trees, and complete trees
npm install merkletreejsimport { createMerkleTree, getHexRoot, getProof, verifyProof } from 'merkletreejs'
// Create a simple Merkle tree
const leaves = ['a', 'b', 'c', 'd']
const tree = createMerkleTree(leaves)
const root = getHexRoot(tree)
// Generate and verify a proof
const proof = getProof(tree, 'b')
const isValid = verifyProof(proof, 'b', root)
console.log('Proof valid:', isValid) // trueYou can also import the original MerkleTree class if needed:
import { MerkleTree, createMerkleTree } from 'merkletreejs'
// Using the functional API
const functionalTree = createMerkleTree(['a', 'b', 'c'])
// Using the original class API
const classTree = new MerkleTree(['a', 'b', 'c'])Creates a Merkle tree from an array of leaves. Uses SHA256 as the default hash function.
const tree = createMerkleTree(['a', 'b', 'c'])
// Using custom hash function
const customHashFn = (data) => {
const crypto = require('crypto')
return crypto.createHash('sha256').update(data).digest()
}
const treeWithOptions = createMerkleTree(leaves, customHashFn, { sort: true })Gets the root hash as a hex string.
const root = getHexRoot(tree)Gets the root hash as a Buffer.
const rootBuffer = getRoot(tree)Adds a single leaf to the tree.
const updatedTree = addLeaf(tree, 'newLeaf')
const updatedTreeWithHash = addLeaf(tree, 'newLeaf', { shouldHash: true })Adds multiple leaves to the tree.
const updatedTree = addLeaves(tree, ['leaf1', 'leaf2'])
const updatedTreeWithHash = addLeaves(tree, ['leaf1', 'leaf2'], { shouldHash: true })Removes a leaf by index.
const removedLeaf = removeLeaf(tree, 0)Updates a leaf at a specific index.
updateLeaf(tree, 0, 'newValue')
updateLeaf(tree, 0, 'newValue', { shouldHash: true })Gets a proof for a specific leaf.
const proof = getProof(tree, 'targetLeaf')Gets a proof as hex strings.
const hexProof = getHexProof(tree, 'targetLeaf')Verifies a proof against a root and target leaf.
const isValid = verifyProof(proof, 'targetLeaf', root)Gets a multiproof for multiple indices.
const multiProof = getMultiProof(tree, [0, 2, 4])Verifies a multiproof.
const isValid = verifyMultiProof(root, [0, 2], [leaf0, leaf2], 5, proof)Gets all leaves as Buffers.
const leaves = getLeaves(tree)Gets all leaves as hex strings.
const hexLeaves = getHexLeaves(tree)Gets the number of leaves.
const count = getLeafCount(tree)Gets a specific leaf by index.
const leaf = getLeaf(tree, 0)Gets a specific leaf by index as a hex string.
const hexLeaf = getHexLeaf(tree, 0)Gets the index of a specific leaf.
const index = getLeafIndex(tree, 'targetLeaf')Converts a tree to JSON string.
const json = marshalTree(tree)Creates a tree from JSON string.
const tree = unmarshalTree(jsonStr)Converts a proof to JSON string.
const proofJson = marshalProof(proof)Creates a proof from JSON string.
const proof = unmarshalProof(proofJson)The functional API uses SHA256 as the default hash function. You can specify a custom hash function as the second parameter:
import { createMerkleTree } from 'merkletreejs'
// Default SHA256
const tree = createMerkleTree(['a', 'b', 'c'])
// Custom keccak256
const keccakTree = createMerkleTree(['a', 'b', 'c'], (data) => {
const keccak256 = require('keccak256')
return keccak256(Buffer.from(String(data)))
})
// Custom SHA1
const sha1Tree = createMerkleTree(['a', 'b', 'c'], (data) => {
const crypto = require('crypto')
return crypto.createHash('sha1').update(data).digest()
})The wrapper supports all options from the original MerkleTree class:
const options = {
duplicateOdd: false, // Duplicate odd nodes
hashLeaves: false, // Hash leaves before adding (default: false)
isBitcoinTree: false, // Use Bitcoin-style tree
sortLeaves: false, // Sort leaves
sortPairs: false, // Sort pairs
sort: false, // Sort leaves and pairs
fillDefaultHash: null, // Fill default hash function
complete: false, // Create complete tree (recommended for multiproofs)
concatenator: Buffer.concat // Concatenation function
}import { createMerkleTree, getHexRoot, getProof, verifyProof } from 'merkletreejs'
// Create tree
const leaves = ['a', 'b', 'c', 'd']
const tree = createMerkleTree(leaves)
const root = getHexRoot(tree)
// Generate proof
const proof = getProof(tree, 'b')
// Verify proof
const isValid = verifyProof(proof, 'b', root)
console.log('Valid:', isValid) // trueimport { createMerkleTree, getHexRoot, getProof } from 'merkletreejs'
const data = [
{ owner: "0x123...", handle: "alice" },
{ owner: "0x456...", handle: "bob" }
]
// Hash the objects first, then create tree
const hashedData = data.map(item => Buffer.from(JSON.stringify(item)))
const tree = createMerkleTree(hashedData)
const root = getHexRoot(tree)
// Get proof for bob's data (need to hash it first)
const bobHash = Buffer.from(JSON.stringify(data[1]))
const bobProof = getProof(tree, bobHash)import { createMerkleTree } from 'merkletreejs'
// Bitcoin-style tree with SHA256 (default hash function)
const bitcoinTree = createMerkleTree(leaves, undefined, {
isBitcoinTree: true
})
// Using keccak256 hash function
const keccakTree = createMerkleTree(leaves, (data) => {
const keccak256 = require('keccak256')
return keccak256(Buffer.from(String(data)))
})
// Sorted tree (recommended for multiproofs)
const sortedTree = createMerkleTree(leaves, undefined, {
sort: true
})
// Complete tree (recommended for multiproofs)
const completeTree = createMerkleTree(leaves, undefined, {
complete: true
})import { createMerkleTree, addLeaf, addLeaves, removeLeaf, updateLeaf } from 'merkletreejs'
let tree = createMerkleTree(['a', 'b'])
// Add single leaf
tree = addLeaf(tree, 'c')
// Add multiple leaves
tree = addLeaves(tree, ['d', 'e'])
// Add leaves with hashing
tree = addLeaf(tree, 'f', { shouldHash: true })
tree = addLeaves(tree, ['g', 'h'], { shouldHash: true })
// Update leaf
updateLeaf(tree, 0, 'newValue')
// Remove leaf
const removed = removeLeaf(tree, 0)const tree = new MerkleTree(leaves, hashFn, options)
const root = tree.getHexRoot()
const proof = tree.getProof(leaf)
const isValid = tree.verify(proof, leaf, root)const tree = createMerkleTree(leaves, hashFn, options)
const root = getHexRoot(tree)
const proof = getProof(tree, leaf)
const isValid = verifyProof(proof, leaf, root)- Intuitive API: Functional approach inspired by viem
- Type Safety: Full TypeScript support
- Flexible Input: Accepts various data types
- Easy Integration: Drop-in replacement for existing code
- Comprehensive: All original features available
- Well Documented: Clear examples and documentation
This functional API is designed to be a thin layer over the original MerkleTreeJS library. All the original functionality is preserved while providing a more intuitive API. Feel free to contribute improvements or additional features!