blocklock-js
v1.0.2
Published
A library for encrypting and decrypting data for the future
Readme
blocklock-js
blocklock-js is a TypeScript library that simplifies generating encrypted data off-chain for use with the dcrypt network. It allows developers to securely encrypt data tied to a user-defined condition, e.g., a future block height. This encrypted payload can then be referenced in on-chain timelock encryption requests via smart contracts. Once the specified block is mined, the decryption key is automatically delivered to the smart contract via a callback, enabling conditional data access on-chain.
The library also enables developers to track the status of a conditional encryption request.
On-Chain Integration
Solidity interfaces and associated documentation can be found in the blocklock-solidity repository.
Smart Contract Addresses
BlocklockSender Proxy
A lightweight proxy contract that enables upgradeability for the BlocklockSender implementation. It delegates all calls to the underlying implementation and serves as the primary interface for user interaction.
| Network | Address | |----------------------------|-----------------------------------------------------------------------------------------------------------------------------| | Filecoin Mainnet | 0x34092470CC59A097d770523931E3bC179370B44b | | Filecoin Calibration Testnet | 0xF00aB3B64c81b6Ce51f8220EB2bFaa2D469cf702 | | Base Sepolia | 0x82Fed730CbdeC5A2D8724F2e3b316a70A565e27e | | Polygon PoS | 0x82Fed730CbdeC5A2D8724F2e3b316a70A565e27e | | Optimism Sepolia | 0xd22302849a87d5B00f13e504581BC086300DA080 | | Arbitrum Sepolia | 0xd22302849a87d5B00f13e504581BC086300DA080 | | Avalanche (C-Chain) Testnet | 0xd22302849a87d5B00f13e504581BC086300DA080 | | Sei Testnet | 0xd22302849a87d5B00f13e504581BC086300DA080 |
Other contract addresses
You should only need the BlocklockSender proxy above, but a full list of contract addresses can be found in the solidity repo's README.
Installation
To install the library, install the latest version using:
npm install blocklock-jsUsage Example
Prerequisites
- ethers for wallet setup and message encoding.
- Node.js v22+
Setup
- Create a
.envfile or set the following environment variables, e.g., for Filecoin mainnet:
RPC_URL=https://your-rpc-url
PRIVATE_KEY=your_private_key- Install dependencies:
npm installUsage example
This example demonstrates encrypting a uint256 value and using the Ciphertext and condition bytes in a user smart contract that implements the createTimelockRequestWithDirectFunding function to create a timelock encryption request on-chain. An example use case is a sealed-bid auction where bid amounts are encrypted and only decrypted at the auction ending block number.
The example user smart contract source code can be found here.
This script shows how to encrypt data with a future block as a condition
import { createProvider, Blocklock, encodeCiphertextToSolidity, encodeCondition } from "blocklock-js"
import { Wallet, Provider, NonceManager, ethers, getBytes } from "ethers"
import { MockBlocklockReceiver__factory } from "../types"; // Users' solidity contract TypeScript binding
async function main() {
const rpc = createProvider(process.env.RPC_URL || "")
const wallet = new NonceManager(new Wallet(process.env.PRIVATE_KEY || "", rpc))
// Create a Blocklock instance for the Filecoin mainnet
const blocklock = Blocklock.createFilecoinMainnet(wallet)
// Value to encrypt (4 ETH as uint256)
const msg = ethers.utils.parseEther("4");
const plaintext = Buffer.from(msg)
const currentBlock = await rpc.getBlockNumber()
const targetBlock = BigInt(currentBlock + 5)
console.log(`Encrypting for block ${targetBlock} (current: ${currentBlock})`)
const ciphertext = await blocklock.encrypt(plaintext, targetBlock)
// User contract
const mockBlocklockReceiver = MockBlocklockReceiver__factory.connect("user blocklcok receiver contract address", wallet);
// Generate the timelock encryption condition bytes string
const conditionBytes = encodeCondition(targetBlock);
// Amount of gas users callback function is expected to consume, i.e., the function that will be called with the decryption key
const callbackGasLimit = 500_000;
// Compute the request price to pay for the direct funding request
const requestPrice = await blocklock.calculateRequestPriceNative(callbackGasLimit);
// Call `createTimelockRequestWithDirectFunding` on the user's contract
// for a direct or ad hoc funding request with the following parameters:
// uint32 callbackGasLimit,
// bytes calldata condition and,
// TypesLib.Ciphertext calldata encryptedData
const tx = await mockBlocklockReceiver
.connect(wallet)
.createTimelockRequestWithDirectFunding(callbackGasLimit, conditionBytes, encodeCiphertextToSolidity(ciphertext),
{value: requestPrice});
// Note: for subscription-based funding,
// use createTimelockRequestWithSubscription instead.
const receipt = await tx.wait(1);
if (!receipt) {
throw new Error("Transaction has not been mined");
}
console.log("Timelock request created!");
}
main().catch((error) => {
console.error("Error:", error);
});How It Works
- Encoding and Encryption:
Use blocklock-js to:
Create a provider and signer using Wallet and NonceManager.
Initialize a Blocklock instance for your target network (e.g., Filecoin mainnet).
Prepare the message to encrypt (e.g., 4 ETH encoded as a uint256).
Select a future block height as the decryption condition.
const msg = ethers.utils.parseEther("4"); const plaintext = Buffer.from(msg); const currentBlock = await rpc.getBlockNumber(); const targetBlock = BigInt(currentBlock + 5); const ciphertext = await blocklock.encrypt(plaintext, targetBlock); const conditionBytes = encodeCondition(targetBlock);
On-Chain Interaction:
Use your own smart contract (e.g.,
MockBlocklockReceiver) to create a timelock encryption request.Call
createTimelockRequestWithDirectFunding, which:Stores the encrypted data (Ciphertext) and decryption condition on-chain via the
BlocklockSendercontract.Funds the request by paying the
requestPricevia the transaction.Generates a unique request ID.Call the appropriate function in the user contract with the encrypted data and the chain height used during off-chain encryption.
const callbackGasLimit = 500_000; const requestPrice = await blocklock.calculateRequestPriceNative(callbackGasLimit); await mockBlocklockReceiver.createTimelockRequestWithDirectFunding( callbackGasLimit, conditionBytes, encodeCiphertextToSolidity(ciphertext), {value: requestPrice} );
Automatic Decryption and Callback:
Once the specified condition is met (e.g., target block is mined):
The
BlocklockSendercontract receives the decryption key from the dcipher Threshold Network.It automatically triggers a callback to the users contract with the key.
The users contract can optionally call decrypt to recover the original message on-chain.
Common Errors
Webpack Configuration
When using the library in web applications, there might be webpack errors such as the one displayed below:

To resolve this error, one solution is to update your next.config.ts configuration file if you use one with similar configurations for webpack below.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
webpack: (config) => {
config.externals.push({
'node:crypto': 'crypto',
});
return config;
},
};
export default nextConfig;In the library's Webpack configuration, the following setting is used:
externals: {
'node:crypto': 'commonjs crypto',
}This configuration tells the bundler not to include the crypto module in the final bundle. Instead, it treats 'node:crypto' as an external dependency and expects it to be available in the runtime environment. 'commonjs crypto' ensures that the module is required using the CommonJS format, making it compatible with Node.js. This ensures compatibility with environments where the crypto module is natively available.
Licensing
This library is licensed under the MIT License which can be accessed here.
Contributing
Contributions are welcome! If you find a bug, have a feature request, or want to improve the code, feel free to open an issue or submit a pull request.
Acknowledgements
Special thanks to the Filecoin Foundation for supporting the development of this library.
