
Research
/Security News
Fake imToken Chrome Extension Steals Seed Phrases via Phishing Redirects
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.
@fireproof/core-blockstore
Advanced tools
Multi-writer self-hosted local-first IPFS-compatible blockstore with end-to-end encryption. If you have code that expects a JavaScript blockstore, you can instantiate one of these instead and get superpowers. What kind of superpowers?
By default, encrypted blockstores are backed by the browser or the local filesystem. Each transaction is committed as a new immutable CAR file (content addressed archive), which can be replicated and hosted anywhere. The blockstore has connectors for a range of cloud storage providers, so you can easily sync your data using AWS, Netlify, Cloudflare, web3.storage, or any other cloud storage provider.
The interface will be similar to other content-addressed blockstores, like the IPFS JS blockstore
const blockstore = new EncryptedBlockstore(requiredConfig);
await blockstore.transaction(async (blocks) => {
// ... your app logic ...
await blocks.put(cid1, bytes1);
// ... your app logic ...
await blocks.put(cid2, bytes2);
// return any small data shape your code needs to read
// from the blockstore like a CID for the most recent
// user data. this is your mutable state pointer.
return { myCustomHeader: cid2 };
});
// the blockstore can be read from outside a transaction
const block = await blockstore.get(cid1);
You can see that once you are in a transaction, the blocks look just like an IPFS blockstore. In addition to put get and delete, you can also use putSync and getSync, and list blocks with entries.
This blockstore is excellent for any data structure that you want to persist locally and replicate online. It is especially useful for CRDTs and DAGs, but should work for any IPFS CID storage and retrieval.
For correctness, you'll want to have a data structure that can merge incoming data. There are very many of these. It's important because updates can come from anywhere in any order. The blockstore will make sure that all the blocks are available by CID, but it's up to your code to merge the incoming data. If your merge operation is commutative, then you can merge in any order. Warning, if you try to privilege your local data, or otherwise make a lossy merge, your app will have trouble syncing. If this sounds like something you don't want to worry about, then you should probably be using one of the libraries that depend on Encrypted Blockstore, like Fireproof which gives a MongoDB-like API and handles the merging and sync for you.
To configure the blockstore, you need to provide a callback and some implementations. The callback is called on every transaction and is where you can do things like update your UI or merge the incoming data with your data structures. The implementations are for the storage and encryption functions, which can vary by platform. The blockstore ships with basic implementations for the browser and the local filesystem, but you can also provide your own to fit your platform.
import { EncryptedBlockstore } from "@fireproof/encrypted-blockstore";
import * as crypto from "@fireproof/encrypted-blockstore/crypto-web";
import * as store from "@fireproof/encrypted-blockstore/store-web";
const blockstoreConfig = {
name: "my-app",
applyMeta: async (meta) => {
// This is called on multi-user write and local load with your custom header.
// It's where you can react to remote changes or load a new dataset.
// You can also use this to merge the incoming data with your local data.
await myDataStructure.merge(meta.myCustomHeader);
},
compact: async (compactionBlocks) => {
// Traverse your data structure with your existing code, reading from the compaction blockstore
await myDataStructure.listAll(compactionBlocks, myCustomHeader);
// return the data-structure header in the same format as a transaction call
return myCustomHeader;
},
crypto,
store,
};
const blockstore = new EncryptedBlockstore(blockstoreConfig);
The applyMeta function can call into your data structures to merge the incoming data. The encrypted blockstore takes care of making sure blocks are available by CID, so all your code needs to do is read from the blockstore. The custom header returned from your next transaction will be made available to anyone listening to the blockstore. This is how you can sync your data across multiple devices.
Without compaction, your blockstore will grow with each transaction, as each transaction is committed to a new immutable CAR file. This results in thousands of small files, many containing duplicate or out-of-date data. If you don't provide a compaction function, the blockstore can use a default compaction function that deduplicates and preserves all the CIDs in the set, into a single file (coming soon). Your data structure can do better, as it will know which blocks can be safely discarded. Implement compaction as a callback that is passed a blockstore instance which logs any blocks that it reads. Your function should traverse your entire dataset. At the end the blockstore writes out a new unified CAR file, with links to the old CAR files. This speeds up sync and read times because it results in a single CAR file that contains all the deduplicated blocks.
The compact function above is an example of this, or see the Fireproof compaction function in the CRDT library for another example.
The blockstore will take care to update the header and write out a fresh CAR file with all the blocks. This CAR file will be faster to fetch, and new operations will be performed as a diff against this CAR file.
In shared storage situations, just because compaction has removed references to old files, doesn't mean there aren't other readers that would like to read them. Instead of immediately deleting old files, it deletes the files unlinked from the previous compaction. Additionally, in many connectors, the old files are simply not deleted at all, in favor of syncing well with remote clients. Running a cloud cleanup is possible, but it's not implemented yet.
Encrypted Blockstore uses symmetric keys, and each blockstore generates its own key. This means that files are opaque to storage providers, but the key is broadcast on the metadata channel, so it's up to you how secure you want to make it. Read about the encryption model in the Fireproof docs here. The blockstore was extracted from Fireproof, so for the first releases you'll want to read the Fireproof docs for more information.
The blockstore layer includes all the Fireproof connectors, so you can leverage all the work that has been done there, and easily sync your data to any cloud storage provider. There are always more connectors, so check here for the main collection.
Read about the overall architecture in the Fireproof docs.
Please join the Fireproof discord to discuss the project and get involved.
FAQs
Live ledger for the web.
The npm package @fireproof/core-blockstore receives a total of 129 weekly downloads. As such, @fireproof/core-blockstore popularity was classified as not popular.
We found that @fireproof/core-blockstore demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.

Security News
Latio’s 2026 report recognizes Socket as a Supply Chain Innovator and highlights our work in 0-day malware detection, SCA, and auto-patching.

Company News
Join Socket for live demos, rooftop happy hours, and one-on-one meetings during BSidesSF and RSA 2026 in San Francisco.