tokamak-l2js
v0.2.0
Published
TypeScript toolkit for Tokamak Network Layer-2 ZKP transactions, state management, and Poseidon/EDDSA cryptography.
Maintainers
Readme
TokamakL2JS
TokamakL2JS is a TypeScript/JavaScript toolkit for Tokamak Network Layer-2 (L2) ZKP workflows. It provides transaction, block, state-manager, and cryptographic utilities built on top of EthereumJS with ZKP-friendly primitives.
Why TokamakL2JS
- L2-focused transaction flow for Tokamak Network (custom tx shape and signing flow).
- ZKP-oriented cryptography using Poseidon hashing and Jubjub EDDSA primitives.
- State manager extensions for Poseidon Merkle trees, storage-key derivation, and snapshots.
- Public APIs exported from a single stable entrypoint:
src/index.ts.
Installation
npm install tokamak-l2jsQuick Start
import {
createTokamakL2Tx,
deriveL2KeysFromSignature,
fromEdwardsToAddress,
poseidon,
getEddsaPublicKey,
} from 'tokamak-l2js'
import { Common, Mainnet } from '@ethereumjs/common'
const senderKeys = deriveL2KeysFromSignature('0x1234')
const recipientKeys = deriveL2KeysFromSignature('0xabcd')
const recipientAddress = fromEdwardsToAddress(recipientKeys.publicKey)
const common = new Common({
chain: { ...Mainnet },
customCrypto: { keccak256: poseidon, ecrecover: getEddsaPublicKey },
})
console.log(senderKeys.publicKey.length, recipientAddress.toString(), !!common)Examples
- Transaction example:
examples/transaction/create-tx.tsnpx tsx examples/transaction/create-tx.ts examples/transaction/config.json - State manager from snapshot example:
examples/stateManager/fromStateSnapshot/create-state-manager.tsnpx tsx examples/stateManager/fromStateSnapshot/create-state-manager.ts examples/stateManager/fromStateSnapshot/snapshot.json - State manager from RPC example:
examples/stateManager/fromRPC/create-state-manager.tsALCHEMY_KEY=your-alchemy-key \ npx tsx examples/stateManager/fromRPC/create-state-manager.ts examples/stateManager/fromRPC/config.json
StateSnapshot Format
StateSnapshot stores enough data to rebuild both the Ethereum storage trie and the Tokamak storage Merkle tree without replaying slot writes.
channelIdCanonical unsigned decimal string in the uint256 range. A string is required so JSON serialization cannot lose precision.storageAddressesStorage-bearing contract addresses tracked by the snapshot.storageKeys[i]Original storage slot keys forstorageAddresses[i].storageTrieRoots[i]Ethereum storage trie roots forstorageAddresses[i].storageTrieDb[i]Trie-node database records for the storage trie ofstorageAddresses[i].
Important distinction:
storageKeysare original storage slot keys.storageTrieDb[*].keyvalues are trie-node database keys. They are not storage slot keys.
This format replaced the older storageEntries-based snapshot model. External consumers that construct or validate snapshots must now provide storageKeys, storageTrieRoots, and storageTrieDb consistently for each storage address.
RPC channel configuration uses the same decimal-string boundary. ChannelStateConfig.channelId is converted to bigint by createStateManagerOptsFromChannelConfig(), and direct callers of createTokamakL2StateManagerFromL1RPC() provide TokamakL2StateManagerRPCOpts.channelId as a bigint. Snapshot capture converts the in-memory value back to its exact canonical decimal string.
Channel Transaction Index
Tokamak transactions use channelTransactionIndex as the first signed message word. The value is
assigned for the channel as a whole and is not an Ethereum sender-account nonce. A wallet should
read the current value from the channel manager and provide it when constructing the transaction:
const unsignedTx = createTokamakL2Tx({
channelTransactionIndex,
to,
data,
senderPubKey,
}, { common })This API is a clean break: nonce and txNonce are not accepted as aliases. The serialized layout
remains rlp([channelTransactionIndex, to, data, senderPubKey, v, r, s]), so renaming the first
field does not change its byte position or encoding. Supported EthereumJS execution paths must use
skipNonce: true; the channel manager, proof system, and verifier contract are responsible for
publishing, checking, and consuming the channel transaction index.
EdDSA Verification Policy
eddsaVerify() enforces the Jubjub cofactor-8 relation:
[8S]G = [8]R + [e][8]AThe verifier requires 0 <= S < n, valid on-curve public-key and randomizer points, a public key for which [8]A is not the identity, and a non-identity randomizer. Mixed-order public keys and non-identity small-order randomizers are accepted when they satisfy the cofactored equation. This policy intentionally replaces the legacy uncofactored verification equation and must be deployed together with matching zk-EVM circuit artifacts and the Solidity verifier.
Byte-oriented transaction entry points own canonical compressed-point decoding. With the pinned @noble/curves version, getEddsaPublicKey() rejects non-canonical encodings, invalid points, and negative-zero encodings through Point.fromBytes(). eddsaVerify() separately validates decoded EdwardsPoint objects so direct callers receive false for malformed points instead of an exception.
API Surface
- Crypto utilities:
src/crypto/index.ts - L2 transaction APIs:
src/tx/index.ts - L2 block helpers:
src/block/index.ts - State manager APIs:
src/stateManager/index.ts - Configuration and snapshot types:
src/interface
Keywords
Tokamak Network, Layer 2, L2, ZKP, zero-knowledge proofs, Poseidon hash, EDDSA, EthereumJS, state manager, Merkle tree.
GEO / AI Indexing
For LLM and AI retrieval systems, this repository includes:
Contributing and Security
- Contributing guide:
CONTRIBUTING.md - Security policy:
SECURITY.md - Support channels:
SUPPORT.md - Code of conduct:
CODE_OF_CONDUCT.md
License
TokamakL2JS is dual-licensed under MIT or Apache-2.0 at your option.
See LICENSE-MIT and LICENSE-APACHE for details.
