Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.skale.space/llms.txt

Use this file to discover all available pages before exploring further.

TypeScript transpiles to JavaScript, so the SDK works in both TypeScript and JavaScript across Node.js, Bun, and browser environments. If you run into an issue, reach out in Discord or open an issue on GitHub.
The BITE TypeScript SDK (@skalenetwork/bite) lets applications and wallets encrypt EVM transactions using threshold encryption. It works with any SKALE chain that has Programmable Privacy enabled.

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 SKALE chain with Programmable Privacy. Currently, it 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);

// Encrypt a transaction
const tx = {
  to: '0x1234567890abcdef1234567890abcdef12345678',
  data: '0x1234abcd',
};
const encryptedTx = await bite.encryptTransaction(tx);

// Send via your wallet/provider
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 BITE instance configured with a JSON-RPC endpoint. Parameters:
  • endpoint: string — JSON-RPC endpoint
Example:
const bite = new BITE('https://your-skale-chain.skale.network');

bite.encryptTransaction(tx)

Encrypts a transaction using BLS threshold encryption. The encrypted transaction will have its to field set to the magic address. Parameters:
  • tx: { to: string; data: string; gasLimit?: number } — Standard hex strings
Returns: Promise<Transaction> — Encrypted transaction safe to submit to eth_sendTransaction Encryption Process:
  1. RLP encodes original data and to fields
  2. Encrypts encoded data using AES with randomly generated key
  3. Encrypts AES key using BLS threshold encryption
  4. Creates final payload: [EPOCH_ID, ENCRYPTED_BITE_DATA]
Committee Behavior:
  • Single Committee: AES key encrypted with current BLS public key
  • Dual Committee: During rotation, AES key encrypted twice (current + next committee keys)
Set gasLimit manually. estimateGas does not return a reliable value for encrypted transactions. If gasLimit is omitted, defaults to 300000.

BITE.encryptTransactionWithCommitteeInfo(tx, committees)

Static method that encrypts using provided committee info, avoiding internal RPC call. Parameters:
  • tx: object — Transaction with data and to fields
  • committees: Array — Committee info objects (from getCommitteesInfo)
Returns:
  • Promise<Transaction> — Encrypted transaction
Use Case: Offline/cached encryption when committee info is already known.

bite.encryptMessage(message)

Encrypts a raw hex-encoded message using BLS threshold encryption. Parameters:
  • message: string — Hex string to encrypt (with or without 0x prefix)
Returns: Promise<string> — Encrypted hex string in RLP format with epoch and encryption data Example:
const encryptedMessage = await bite.encryptMessage('0x48656c6c6f20576f726c64'); // "Hello World"

bite.getDecryptedTransactionData(transactionHash)

Retrieves decrypted transaction data after consensus finality using bite_getDecryptedTransactionData JSON-RPC method. Parameters:
  • transactionHash: string — The transaction hash
Returns: Promise<object> — JSON with data and to keys containing 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 works only for encrypted transactions that have already been processed and decrypted by the network. If the transaction does not exist, or if decrypted data is unavailable, the call throws an error.

bite.getCommitteesInfo()

Fetches committee information using bite_getCommitteesInfo JSON-RPC method. Returns: Promise<Array> — Array of 1-2 committee objects:
  • commonBLSPublicKey: 256-char hex (128-byte BLS public key)
  • epochId: Integer epoch identifier
Array Contents:
  • 1 element: Normal operation (single active committee)
  • 2 elements: Committee rotation period (scheduled for next 3 minutes)
Example:
const committeesInfo = await bite.getCommitteesInfo();
console.log('Current BLS Public Key:', committeesInfo[0].commonBLSPublicKey);

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

Transaction Structure

Encrypted Transaction Format

interface BiteTransaction {
  to: string;      // Always set to the magic address
  data: string;    // Encrypted payload containing [EPOCH_ID, ENCRYPTED_DATA]
  from: string;    // Sender address (unchanged)
  value: string;   // ETH value (unchanged)
  gas: string;     // Gas limit (must be set manually)
  gasPrice: string; // Gas price (unchanged)
  nonce: number;   // Nonce (unchanged)
}

Encryption Payload Structure

The encrypted data field contains RLP-encoded array:
[EPOCH_ID, ENCRYPTED_BITE_DATA]
  • EPOCH_ID — Current committee epoch
  • ENCRYPTED_BITE_DATA — AES-encrypted payload with BLS-encrypted AES key

Best Practices

Gas Limit Management

Always set an explicit gas limit for encrypted transactions. Do not rely on estimateGas().
// Always set an appropriate gas limit
const tx = {
    to: '0x...',
    data: '0x...',
    gasLimit: 200000,
};
const encryptedTx = await bite.encryptTransaction(tx);

Browser Polyfills

When using the SDK in the browser, you may need to polyfill Buffer:
npm install buffer
Vite — add to vite.config.ts:
import { defineConfig } from 'vite'
export default defineConfig({
  resolve: { alias: { buffer: 'buffer' } },
})
Webpack 5 — add to webpack.config.js:
module.exports = {
  resolve: { fallback: { buffer: require.resolve('buffer/') } },
}

Committee Rotation Monitoring

const INTERVAL_MS = 30000;

async function monitorCommitteeRotation() {
    const committees = await bite.getCommitteesInfo();
    if (committees.length === 2) {
        console.warn('Committee rotation in progress');
    }
    setTimeout(monitorCommitteeRotation, INTERVAL_MS);
}

Common Use Cases

Private Token Transfers

const transferData = iface.encodeFunctionData('transfer', [recipient, amount]);
const tx = { to: tokenAddress, data: transferData, gasLimit: 200000 };
const encryptedTx = await bite.encryptTransaction(tx);

Confidential Contract Interactions

const callData = iface.encodeFunctionData('confidentialFunction', [secretParam]);
const tx = { to: contractAddress, data: callData, gasLimit: 300000 };
const encryptedTx = await bite.encryptTransaction(tx);

Cached Committee Encryption

const committees = await bite.getCommitteesInfo();
const tx1 = await BITE.encryptTransactionWithCommitteeInfo(transaction1, committees);
const tx2 = await BITE.encryptTransactionWithCommitteeInfo(transaction2, committees);

Resources