@hisoka-io/nox-client
v0.1.5
Published
TypeScript client SDK for the NOX mixnet — anonymous DeFi transactions and HTTP proxying
Readme
@hisoka-io/nox-client
TypeScript client SDK for the NOX mixnet. Route Ethereum transactions, JSON RPC calls, and HTTP requests through a 3 hop Sphinx mix network for network layer privacy.
Install
npm install @hisoka-io/nox-clientThe WASM dependency (@hisoka-io/nox-wasm) is installed automatically.
Usage
Connect to the mixnet
import { NoxClient } from "@hisoka-io/nox-client";
const client = await NoxClient.connect({
seeds: ["https://seed.hisoka.io"],
powDifficulty: 0,
timeoutMs: 30000,
});The client resolves a seed node, fetches the network topology, selects a 3 hop route (entry, mix, exit), loads the WASM Sphinx crypto module, and starts background polling for responses.
Submit a transaction
const response = await client.submitTransaction(
"0xContractAddress",
calldata, // Uint8Array
);The transaction is wrapped in a Sphinx packet, routed through 3 relay nodes, and executed by the exit node. The response comes back through Single Use Reply Blocks (SURBs) so the exit node never learns who sent the request.
JSON RPC calls
const blockNumber = await client.rpcCall("eth_blockNumber", []);
const balance = await client.rpcCall("eth_getBalance", [address, "latest"]);
const logs = await client.rpcCall("eth_getLogs", [{ address, fromBlock: "0x0", toBlock: "latest" }]);All RPC calls are routed through the mixnet. The exit node forwards them to its configured Ethereum RPC endpoint.
HTTP requests
const body = await client.httpRequest(
"GET",
"https://api.example.com/data",
{ "Accept": "application/json" },
new Uint8Array(0),
);Cover traffic
To hide when you are actually using the network, enable cover traffic. This sends dummy Sphinx packets at a configurable rate.
import { createCoverController } from "@hisoka-io/nox-client";
const cover = createCoverController(client);
cover.start({ lambdaP: 1.0 }); // 1 packet per second average (Poisson)
cover.stop();Disconnect
client.disconnect();Configuration
const client = await NoxClient.connect({
seeds: ["https://node1.example.com", "https://node2.example.com"],
ethRpcUrl: "https://eth.llamarpc.com", // on chain topology verification
registryAddress: "0xNoxRegistryAddress", // NoxRegistry contract
powDifficulty: 0, // proof of work difficulty
timeoutMs: 30000, // per request timeout
surbsPerRequest: 10, // SURBs sent with each request
topologyRefreshMs: 60000, // topology refresh interval
dangerouslySkipFingerprintCheck: false, // skip on chain verification
});If ethRpcUrl and registryAddress are provided, the client verifies the topology fingerprint against the on chain NoxRegistry contract. This prevents a malicious seed node from serving a fake topology.
How it works
- Client fetches the network topology from a seed node (list of relay nodes with their Sphinx public keys)
- Client selects a 3 hop route: entry node, mix node, exit node
- For each request, the client builds a Sphinx packet with layered encryption. Each relay node can only decrypt its own layer and learn the next hop.
- The packet is sent to the entry node via HTTP POST
- Each relay node peels one encryption layer and forwards to the next hop via libp2p
- The exit node decrypts the final layer, executes the request (RPC call, transaction, HTTP fetch), and sends the response back through SURBs
- SURBs are pre built anonymous return paths. The exit node packs the response into SURB packets without knowing the destination.
- The client polls the entry node for responses and decrypts them using the SURB recovery keys
Large responses are automatically fragmented and reassembled with Reed Solomon forward error correction.
Requirements
Node.js 18 or later. Works in browsers with WASM support.
License
BUSL-1.1
