Sol.College

Full lesson

FairLane-Router

What it does

From the project README:

What it really costs to land a transaction on Solana through each delivery service — Jito, Nozomi, bloXroute, plain RPC — measured on-chain, normalised against the same slot, and put side by side on a public dashboard.
Original
FairLaneRouter/FairLane-Router
SuperStack fork
Blockchains/FairLane-Router @ 91e21f7
Stars
0
Last push (original)
2026-10-25
Languages
TypeScript, HTML, CSS
Detected stack
not detected
Categories
Other
Licence
MIT
Homepage
https://fairlanerouter.github.io/FairLane-Router/

Architecture

109 source files. By extension: .ts ×100, .tsx ×9.

Top-level directorySource files
apps64
packages42
scripts3

Dapp: devnet deploy pending

⏳ Devnet deploy pending — goes live when the devnet wallet is topped up. This fork's own dapp is not deployed yet, so there is no program address or transaction to show. It is queued in dapp-queue.txt; once devnet SOL is available it is deployed, exercised with real devnet transactions, and this section switches to the live dapp at /dapps/fairlane-router/. Until then, the lesson and step-by-step guide below are complete, and you can run it locally with the commands below.

Key code, explained

Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.

FairLaneRouter/FairLane-Router · packages/shared/src/rpc.ts L349–372 @ 91e21f7 · MIT · original
    async sendTransaction(wire) {      const result = await call('sendTransaction', [        // `btoa`, not `Buffer`: this module is in the web bundle too. A wire        // transaction is at most 1232 bytes, well within one spread.        btoa(String.fromCharCode(...wire)),        { encoding: 'base64', skipPreflight: true },      ])      const parsed = z.string().min(1).safeParse(result)      if (!parsed.success) throw new RpcError('sendTransaction: the result is not a signature')      return parsed.data    },     // `confirmed`, not the default `finalized`: a finalized blockhash is ~32    // slots old already, and that is time cut off the window both legs share.    async getLatestBlockhash() {      const result = await call('getLatestBlockhash', [{ commitment: 'confirmed' }])      const parsed = latestBlockhashSchema.safeParse(result)      if (!parsed.success) throw new RpcError('getLatestBlockhash: the result is not a blockhash')      return { ...parsed.data.value, slot: parsed.data.context.slot }    },     async getBlockHeight() {      const result = await call('getBlockHeight', [{ commitment: 'confirmed' }])      const parsed = slotSchema.safeParse(result)
  1. Line 349 async sendTransaction(wire) {: Submits the signed transaction to the cluster.
  2. Line 363 async getLatestBlockhash() {: Fetches a recent blockhash. Transactions expire if it gets too old.

How to run, build and test

These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.

DirectoryCommandRuns
.npm run buildpnpm -r run build
.npm run testpnpm -r run test
.npm run lintbiome lint .
apps/webnpm run devvite
apps/webnpm run buildtsc -p tsconfig.json --noEmit && vite build
apps/webnpm run testvitest run --passWithNoTests
apps/apinpm run startnode --env-file-if-exists=../../.env src/index.ts
apps/apinpm run buildtsc -p tsconfig.json
apps/apinpm run testvitest run --passWithNoTests
apps/indexernpm run startnode --env-file-if-exists=../../.env src/index.ts
apps/indexernpm run buildtsc -p tsconfig.json
apps/indexernpm run testvitest run --passWithNoTests
packages/sharednpm run buildtsc -p tsconfig.json
packages/sharednpm run testvitest run --passWithNoTests
packages/sdknpm run buildtsc -p tsconfig.build.json
packages/sdknpm run testvitest run --passWithNoTests

What you could build from it

Used in lessons