Skip to main content
Typescript transpiles to JavaScript. The SDK is compatible with both JavaScript and Typescript in both Node.js, Bun, and browser environments. If you have any issues, please join us in Discord to report the problem or open an issue on GitHub.

Using the SDK

The BITE JavaScript SDK enables application and wallet developers to encrypt EVM transactions. BITE extends SKALE’s provably secure consensus protocol with threshold encryption, allowing developers to build private and confidential applications on SKALE.

Installation

# npm
npm i @skalenetwork/bite

# yarn
yarn add @skalenetwork/bite

# pnpm
pnpm add @skalenetwork/bite

# Bun
bun add @skalenetwork/bite
The SDK works with any BITE-enabled SKALE chain. Currently, BITE is available on SKALE Base Mainnet and Testnet ONLY.

Quick Start

import { BITE } from '@skalenetwork/bite';

const providerUrl = 'https://your-fair-rpc';
const bite = new BITE(providerUrl);

// Minimal tx object: encrypts `to` and `data` and rewrites `to` to BITE magic address
const tx = {
  to: '0x1234567890abcdef1234567890abcdef12345678',
  data: '0x1234abcd',
};

const encryptedTx = await bite.encryptTransaction(tx);
// send via your wallet / provider, e.g. 
window.ethereum.request({ method: 'eth_sendTransaction', params: [encryptedTx] })

// Later, fetch revealed original fields after block finality
const result = await bite.getDecryptedTransactionData('<txHash>');
// result => { to: '0x...', data: '0x...' }

API Reference

new BITE(endpoint)

Creates a new BITE instance configured to use a specific BITE JSON-RPC endpoint. Parameters:
  • endpoint: string – BITE URL provider (JSON-RPC endpoint)
Example:
const bite = new BITE('https://your-skale-chain.skale.network');

bite.encryptTransaction(tx)

Encrypts a transaction object using the BLS threshold encryption public key(s) from the configured BITE provider. The encrypted transaction will have its to field set to the BITE magic address. Parameters:
  • tx: { to: string; data: string; /* optional gas and other fields */ } – Standard hex strings
Returns: Promise<Transaction> – Encrypted params safe to submit to eth_sendTransaction
When passing a transaction to bite.ts, it is necessary to set the gasLimit field manually. This is because estimateGas does not return a proper value for encrypted transactions. If gasLimit is omitted, bite.ts will automatically set it to 300000.
Encryption Process:
  1. RLP encodes the original data and to fields
  2. Encrypts the encoded data using AES with a randomly generated key
  3. Encrypts the AES key using BLS threshold encryption
  4. Creates the final payload in RLP format: [EPOCH_ID, ENCRYPTED_BITE_DATA]

bite.encryptMessage(message)

Encrypts a raw hex-encoded message using the BLS threshold encryption from the configured BITE provider. Parameters:
  • message: string – A hex string to encrypt (with or without 0x prefix)
Returns: Promise<string> – An encrypted hex string in RLP format with epoch and encryption data Example:
const encryptedMessage = await bite.encryptMessage('0x48656c6c6f20576f726c64'); // "Hello World"
console.log('Encrypted:', encryptedMessage);

bite.getDecryptedTransactionData(transactionHash)

Retrieves decrypted transaction data from the configured BITE provider using the bite_getDecryptedTransactionData JSON-RPC method. Parameters:
  • transactionHash: string – The transaction hash to decrypt
Returns: Promise<object> – JSON object with data and to keys containing the original decrypted fields Example:
const decryptedData = await bite.getDecryptedTransactionData('0x1234...abcd');
console.log('Original to:', decryptedData.to);
console.log('Original data:', decryptedData.data);
This method only works for BITE transactions that have been processed and decrypted by the consensus. If the transaction doesn’t exist or has no decrypted data, an error is thrown.

bite.getCommitteesInfo()

Fetches committee information from the configured BITE provider using the bite_getCommitteesInfo JSON-RPC method. Returns: Promise<Array> – An array of 1-2 JSON objects, each containing:
  • commonBLSPublicKey: A 256-character hex string (128-byte BLS public key)
  • epochId: An integer representing the epoch identifier
Array Contents:
  • 1 element: During normal operation (single active committee)
  • 2 elements: During committee rotation periods (scheduled for next 3 minutes)
Example:
const committeesInfo = await bite.getCommitteesInfo();
console.log('Current BLS Public Key:', committeesInfo[0].commonBLSPublicKey);
console.log('Current Epoch ID:', committeesInfo[0].epochId);

if (committeesInfo.length === 2) {
    console.log('Rotation in progress - dual encryption active');
}

Integration Examples

MetaMask
import { BITE } from '@skalenetwork/bite';

const bite = new BITE('https://your-skale-chain.skale.network');

async function sendEncryptedTransaction(to, data) {
    const tx = { to, data };
    const encryptedTx = await bite.encryptTransaction(tx);
    
    const txHash = await window.ethereum.request({
        method: 'eth_sendTransaction',
        params: [encryptedTx],
    });
    
    return txHash;
}
Ethers.js
import { BITE } from '@skalenetwork/bite';
import { ethers } from 'ethers';

const bite = new BITE('https://your-skale-chain.skale.network');
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

async function sendEncryptedERC20Transfer(tokenAddress, to, amount) {
    const iface = new ethers.Interface([
        'function transfer(address to, uint256 amount)'
    ]);
    const data = iface.encodeFunctionData('transfer', [to, amount]);
    
    const tx = { to: tokenAddress, data };
    const encryptedTx = await bite.encryptTransaction(tx);
    
    const txResponse = await signer.sendTransaction(encryptedTx);
    return txResponse.hash;
}

Best Practices

Gas Limit Management

Always set a proper gas limit for encrypted transactions. Do not rely on estimateGas() as it doesn’t work correctly with encrypted payloads.
// Bad - will use default 300000 gas
const encryptedTx = await bite.encryptTransaction(tx);

// Good - set appropriate gas limit
const tx = {
    to: '0x...',
    data: '0x...',
    gasLimit: 200000, // Set appropriate limit for your transaction
};
const encryptedTx = await bite.encryptTransaction(tx);

Monitoring Committee Changes


const INTERVAL_MS = 30000; // 30 seconds

// Check for upcoming committee rotations
async function monitorCommitteeRotation() {
    const committees = await bite.getCommitteesInfo();
    
    if (committees.length === 2) {
        console.warn('Committee rotation in progress - dual encryption active');
        // Implement rotation-specific logic if needed
    }
    
    // Schedule periodic checks
    setTimeout(monitorCommitteeRotation, INTERVAL_MS);
}
This is not a requirement for single use encrypted transactions. If you are building with Conditional Transactions, you can optionally monitor committee changes to handle expiration of a conditional transaction which can occur during

Resources