{"_id":"@dyadex-finance/flashtestations-sdk","name":"@dyadex-finance/flashtestations-sdk","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"@dyadex-finance/flashtestations-sdk","version":"1.1.0","author":{"name":"Melvillian"},"description":"⚒️ An SDK for working with Flashteststations","repository":{"type":"git","url":"git+https://github.com/dyadex-finance/uniswap-sdks.git"},"keywords":["flashteststations","ethereum","flashbots","unichain"],"license":"MIT","main":"./dist/cjs/src/index.js","module":"./dist/esm/src/index.js","types":"./dist/types/src/index.d.ts","bin":{"flashtestations-sdk":"dist/cjs/src/cli/index.js"},"engines":{"node":">=18"},"scripts":{"clean":"rm -rf dist","build":"bun run clean && bun run build:cjs && bun run build:esm && bun run build:types","build:cjs":"tsc -p tsconfig.cjs.json && chmod +x dist/cjs/src/cli/index.js","build:esm":"tsc -p tsconfig.esm.json && chmod +x dist/esm/src/cli/index.js","build:types":"tsc -p tsconfig.types.json","lint":"eslint src --ext .ts","test":"bun test","release":"changeset publish"},"exports":{".":{"types":"./dist/types/src/index.d.ts","import":"./dist/esm/src/index.js","require":"./dist/cjs/src/index.js"}},"publishConfig":{"access":"public","provenance":true},"sideEffects":false,"prettier":{"printWidth":80,"semi":true,"singleQuote":true,"trailingComma":"es5"},"dependencies":{"commander":"^14.0.2","viem":"^2.23.5"},"devDependencies":{"@types/node":"^18.7.16","@typescript-eslint/eslint-plugin":"^8.38.0","@typescript-eslint/parser":"^8.38.0","eslint":"^8.57.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-functional":"^3.0.2","eslint-plugin-import":"^2.22.0","prettier":"^2.4.1","ts-node":"^10.9.1","tslib":"^2.3.0","typescript":"npm:typescript@^5.6.2"},"gitHead":"06ab4ee985528ad0159a9bfb6d4356a5693d59a1","_id":"@dyadex-finance/flashtestations-sdk@1.1.0","bugs":{"url":"https://github.com/dyadex-finance/uniswap-sdks/issues"},"homepage":"https://github.com/dyadex-finance/uniswap-sdks#readme","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-MHUcYvqDmHPwEJlqhXvIXdSCcGG8kKJ2LzSJpHc71xgvzI61ea9kKPSfzAnnrg++Hnga3ddk+zfjjkte4zJSNA==","shasum":"c6dc9a8a6613ae5c2a90f5ede5700dde7be0af0f","tarball":"https://registry.npmjs.org/@dyadex-finance/flashtestations-sdk/-/flashtestations-sdk-1.1.0.tgz","fileCount":108,"unpackedSize":279773,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dyadex-finance%2fflashtestations-sdk@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBkRdYVZ0cAD2pymA7PoaCMnfTQd4+c9OWTEddqZ80dcAiBRLYAI6qBe+I6TxMmenVd2WvemOuXJ+dJsoKQIfpqm1Q=="}]},"_npmUser":{"name":"neddy34","email":"edwardlee9534@gmail.com"},"directories":{},"maintainers":[{"name":"neddy34","email":"edwardlee9534@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/flashtestations-sdk_1.1.0_1777304621670_0.7483573670688906"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-27T15:43:41.597Z","1.1.0":"2026-04-27T15:43:41.812Z","modified":"2026-04-27T15:43:42.326Z"},"maintainers":[{"name":"neddy34","email":"edwardlee9534@gmail.com"}],"description":"⚒️ An SDK for working with Flashteststations","homepage":"https://github.com/dyadex-finance/uniswap-sdks#readme","keywords":["flashteststations","ethereum","flashbots","unichain"],"repository":{"type":"git","url":"git+https://github.com/dyadex-finance/uniswap-sdks.git"},"author":{"name":"Melvillian"},"bugs":{"url":"https://github.com/dyadex-finance/uniswap-sdks/issues"},"license":"MIT","readme":"# Flashtestations SDK\n\nA Typescript SDK for interacting (programmatically as well as via CLI) with the [Flashtestations protocol](https://github.com/flashbots/flashtestations)\n\n## Overview\n\nFlashtestations are cryptographic proofs that blockchain blocks were built by Trusted Execution Environments (TEEs) running a specific version of [Flashbot's op-rbuilder](https://github.com/flashbots/op-rbuilder/tree/main), which is the TEE-based builder used to build blocks on Unichain. This SDK allows you to verify whether blocks on Unichain networks were built by the expected versions of op-rbuilder running in a TEE. Unlike on other blockchains where you have no guarantee and thus must trust the block builder to build blocks [fairly](https://www.paradigm.xyz/2024/06/priority-is-all-you-need), with flashtestations you can cryptographically verify that a Unichain block has been built with a particular version of op-rbuilder.\n\nThe TEE devices that run Unichain's builder software provide hardware-enforced isolation and attestation, enabling transparent and verifiable block building. Each TEE workload (i.e. a specific version of op-rbuilder running in a TEE) is uniquely identified by measurement registers that cryptographically commit to the exact software running inside the TEE. When op-rbuilder builds a block on Unichain, it emits a \"flashtestation\" transaction as the last transaction in the block that proves which workload built that block.\n\nThis SDK simplifies the verification process by providing a single function to check if a block contains a valid flashtestation matching your expected workload ID. For more background on flashtestations and TEE-based block building, see the [flashtestations spec](https://github.com/flashbots/rollup-boost/blob/main/specs/flashtestations.md) and the [flashtestations smart contracts](https://github.com/flashbots/flashtestations).\n\n## Getting Started\n\n### Quick Start (No Installation Needed)\n\n```bash\n# print the latest flashtestation event data on Unichain Mainnet\nnpx @uniswap/flashtestations-sdk get-event\n```\n\n### Installation\n\n```bash\nnpm install @uniswap/flashtestations-sdk\n# or\nyarn add @uniswap/flashtestations-sdk\n```\n\n### Quick Start (Importing the SDK)\n\n```typescript\nimport { verifyFlashtestationInBlock } from '@uniswap/flashtestations-sdk';\n\nasync function main() {\n  // Verify if the latest block on Unichain Mainnet was built by a specific TEE workload\n  const result = await verifyFlashtestationInBlock(\n    '0x05dcaf224f061f956e4c2df39220a3c17faba5552cf7228a0d571511c251fbfc', // An example workload ID\n    'latest', // Block to verify (can be 'latest', 'pending', 'safe', 'finalized', number, or hash)\n    { chainId: 130 } // Unichain Mainnet\n  );\n\n  if (result.isBuiltByExpectedTee) {\n    console.log('✓ Block was built by the expected TEE workload!');\n    console.log(`Workload ID: ${result.workloadMetadata.workloadId}`);\n    console.log(`Commit Hash: ${result.workloadMetadata.commitHash}`);\n    console.log(`Builder Address: ${result.workloadMetadata.builderAddress}`);\n    console.log(`Version: ${result.workloadMetadata.version}`);\n  } else {\n    console.log('\\n✗ Block was NOT built by the specified TEE workload\\n');\n\n    if (result.workloadMetadata) {\n      console.log('Block was built by a different TEE workload:');\n      console.log(`Workload ID: ${result.workloadMetadata.workloadId}`);\n      console.log(`Commit Hash: ${result.workloadMetadata.commitHash}`);\n      console.log(`Builder Address: ${result.workloadMetadata.builderAddress}`);\n      console.log(`Version: ${result.workloadMetadata.version}`);\n      console.log(\n        `Source Locators: ${\n          result.workloadMetadata.sourceLocators.length > 0\n            ? result.workloadMetadata.sourceLocators.join(', ')\n            : 'None'\n        }`\n      );\n    } else {\n      console.log('The block does not contain a flashtestation transaction');\n    }\n  }\n}\n\n// run the quick start\nmain();\n```\n\n## Supported Chains\n\n| Chain                 | Chain ID  | Status     | RPC Configuration |\n| ----------------      | --------- | ---------- | ----------------- |\n| Unichain Mainnet      | 130       | Production | Auto-configured   |\n| Unichain Sepolia      | 1301      | Testnet    | Auto-configured   |\n| Unichain Alphanet     | 22444422  | Testnet    | Manually-provided |\n| Unichain Experimental | 420120005 | Testnet    | Manually-provided |\n\n## How Do I Acquire a Particular op-rbuilder's Workload ID?\n\nThe Flashtestations protocol exists to let you cryptographically verify that a particular version of op-rbuilder is in fact building the latest block's on Unichain. To cryptographically identify these op-rbuilder versions across all of the various components (the TEE, the smart contracts, and SDK) we use a 32-byte workload ID, which is a [hash of the measurement registers of the TEE attestation](https://github.com/flashbots/flashtestations/blob/38594f37b5f6d1b1f5f6ad4203a4770c10f72a22/src/BlockBuilderPolicy.sol#L208). But this workload ID tells us nothing about what op-rbuilder source code the builder operators used to build the final Linux OS image that runs on the TEE. We need a trustless (i.e. locally verifiable) method for calculating the workload ID, given a version of op-rbuilder.\n\nThat process is what the [flashbots-images](https://github.com/flashbots/flashbots-images) repo is for. Using this repo and a simple bash command, we build a Linux OS image containing a specific version of op-rbuilder (identified by its git commit hash), and then generate TDX attestation measurement registers from that image. We can then use those measurements to calculate the workload ID. This completes the full chain of trustless verification; given a particular commit hash of flashbots-images (which has hardcoded into it a particular version of op-rbuilder), we can locally build and measure the Linux OS image, pass those measurements to the flashtestations-sdk which computes the workload ID and uses the SDK's `verifyFlashtestationInBlock` function to verify \"is Unichain building blocks with the latest version of op-rbuilder?\".\n\nPlease see the [flashbots-images](https://github.com/flashbots/flashbots-images) repo instructions on how to locally build and measure a Linux OS image running op-rbuilder.\n\n## API Reference\n\n### verifyFlashtestationInBlock\n\nVerify if a block was built by a TEE running a specific workload.\n\n```typescript\nasync function verifyFlashtestationInBlock(\n  workloadIdOrRegisters: string | WorkloadMeasurementRegisters,\n  blockParameter: BlockParameter,\n  config: ClientConfig\n): Promise<VerificationResult>;\n```\n\n**Parameters:**\n\n| Parameter             | Type                                 | Description                                                                 |\n| --------------------- | ------------------------------------ | --------------------------------------------------------------------------- |\n| workloadIdOrRegisters | `string \\| WorkloadMeasurementRegisters` | Workload ID (32-byte hex string) or measurement registers to compute the ID |\n| blockParameter        | `BlockParameter`                     | Block identifier: tag ('latest', 'earliest', etc.), number, or hash         |\n| config                | `ClientConfig`                       | Configuration object with `chainId` and optional `rpcUrl`                   |\n\n**Returns:** `Promise<VerificationResult>`\n\n| Field                | Type             | Description                                                         |\n| -------------------- | ---------------- | ------------------------------------------------------------------- |\n| isBuiltByExpectedTee | `boolean`        | Whether the block was built by the expected TEE workload            |\n| workloadId           | `string \\| null` | Workload ID that built the block (null if not TEE-built)            |\n| commitHash           | `string \\| null` | Git commit hash of the workload source code (null if not TEE-built) |\n| blockExplorerLink    | `string \\| null` | Block explorer URL (null if not available)                          |\n| builderAddress       | `string`         | Address of the block builder (optional)                             |\n| version              | `number`         | Flashtestation protocol version                                     |\n| sourceLocators       | `string[]`       | Source code locations (e.g., GitHub URLs)                           |\n\n**Throws:**\n\n- `NetworkError` - RPC connection failed or network request error\n- `BlockNotFoundError` - Block does not exist\n- `ValidationError` - Invalid measurement registers\n- `ChainNotSupportedError` - Chain ID not supported\n\n**See [Error Handling](#error-handling) for examples of handling these errors.**\n\n### Utility Functions\n\n#### computeWorkloadId\n\nCompute a workload ID from TEE measurement registers. Useful for debugging or pre-computing IDs.\n\n```typescript\nfunction computeWorkloadId(registers: WorkloadMeasurementRegisters): string;\n```\n\nReturns the workload ID as a hex string.\n\n#### getSupportedChains\n\nGet list of all supported chain IDs.\n\n```typescript\nfunction getSupportedChains(): number[];\n```\n\nReturns an array of supported chain IDs: `[130, 1301]`\n\n#### isChainSupported\n\nCheck if a chain ID is supported.\n\n```typescript\nfunction isChainSupported(chainId: number): boolean;\n```\n\nReturns `true` if the chain is supported, `false` otherwise.\n\n#### getChainConfig\n\nGet the full configuration for a chain.\n\n```typescript\nfunction getChainConfig(chainId: number): ChainConfig;\n```\n\nReturns a `ChainConfig` object with chain details (name, contract address, RPC URL, block explorer URL).\n\n**Throws:** `ChainNotSupportedError` if the chain is not supported.\n\n## Error Handling\n\nThe SDK provides custom error classes for specific failure scenarios.\n\n### NetworkError\n\nThrown when RPC connection fails or network requests error out.\n\n```typescript\nimport { verifyFlashtestationInBlock, NetworkError } from '@uniswap/flashtestations-sdk';\n\ntry {\n  const result = await verifyFlashtestationInBlock('0xabcd...', 'latest', {\n    chainId: 1301,\n    rpcUrl: 'https://invalid-rpc.example.com',\n  });\n} catch (error) {\n  if (error instanceof NetworkError) {\n    console.error('Network error:', error.message);\n    console.error('Cause:', error.cause);\n    // Retry with exponential backoff or fallback RPC\n  }\n}\n```\n\n### BlockNotFoundError\n\nThrown when the specified block does not exist on the chain.\n\n```typescript\nimport { BlockNotFoundError } from '@uniswap/flashtestations-sdk';\n\ntry {\n  const result = await verifyFlashtestationInBlock('0xabcd...', 999999999, {\n    chainId: 1301,\n  });\n} catch (error) {\n  if (error instanceof BlockNotFoundError) {\n    console.error('Block not found:', error.blockParameter);\n    // Try a different block or handle gracefully\n  }\n}\n```\n\n### ValidationError\n\nThrown when measurement registers are invalid (wrong format or length).\n\n```typescript\nimport { ValidationError } from '@uniswap/flashtestations-sdk';\n\ntry {\n  const invalidRegisters = {\n    tdattributes: '0x00', // Too short!\n    xfam: '0x0000000000000003',\n    // ... other fields\n  };\n  const result = await verifyFlashtestationInBlock(invalidRegisters, 'latest', {\n    chainId: 1301,\n  });\n} catch (error) {\n  if (error instanceof ValidationError) {\n    console.error('Validation error:', error.message);\n    console.error('Field:', error.field);\n    // Fix the invalid field\n  }\n}\n```\n\n### ChainNotSupportedError\n\nThrown when trying to use an unsupported chain ID.\n\n```typescript\nimport { ChainNotSupportedError } from '@uniswap/flashtestations-sdk';\n\ntry {\n  const result = await verifyFlashtestationInBlock('0xabcd...', 'latest', {\n    chainId: 999, // Not supported\n  });\n} catch (error) {\n  if (error instanceof ChainNotSupportedError) {\n    console.error('Chain not supported:', error.chainId);\n    console.error('Supported chains:', error.supportedChains);\n    // Use one of the supported chains\n  }\n}\n```\n\n### Error Handling Best Practices\n\n- **Retry on NetworkError**: Implement exponential backoff for transient network failures\n- **Validate inputs early**: Check chain support with `isChainSupported()` before calling verification\n- **Handle missing blocks gracefully**: `BlockNotFoundError` may indicate the block hasn't been mined yet\n- **Log error context**: All custom errors include additional context properties for debugging\n- **Use fallback RPC endpoints**: Provide alternative `rpcUrl` options for better reliability\n\n## CLI Examples\n\nThe SDK includes a CLI for quick verification from the terminal. Run commands using `npx`:\n\n```bash\nnpx . <command> [options]\n```\n\n### List Supported Chains\n\n```bash\n# View all supported chains and their configuration\nnpx . chains\n\n# Output as JSON\nnpx . chains --json\n```\n\n### Verify a Block\n\nVerify if a block was built by an expected TEE workload:\n\n```bash\n# Verify latest block on Unichain Mainnet (default) with a workload ID\nnpx . verify --workload-id 0x306ab4fe782dde50a97584b6d4cad9375f7b5d02199c4c78821ad6622670c6b7\n\n# Verify using measurement registers from a JSON file\nnpx . verify --measurements ./example-measurements.json --block latest\n\n# Use a custom RPC URL\nnpx . verify -w 0x05dcaf224f061f956e4c2df39220a3c17faba5552cf7228a0d571511c251fbfc --rpc-url https://my-rpc.example.com --chain-id 130\n\n# Output as JSON (useful for scripting)\nnpx . verify -w 0x05dcaf224f061f956e4c2df39220a3c17faba5552cf7228a0d571511c251fbfc --json\n```\n\n**Exit codes:**\n- `0` - Block was built by the expected TEE workload\n- `1` - Error occurred (network error, invalid input, etc.)\n- `2` - Block was NOT built by the expected TEE workload\n\n### Get Flashtestation Event\n\nRetrieve flashtestation transaction data from a block without verification:\n\n```bash\n# Get event from the latest block on Unichain Sepolia\nnpx . get-event\n\n# Output as JSON\nnpx . get-event --block latest --json\n```\n\n### Compute Workload ID\n\nCompute a workload ID from TEE measurement registers:\n\n```bash\n# Compute workload ID from a measurements JSON file\nnpx . compute-workload-id --measurements ./example-measurements.json\n\n# Output as JSON\nnpx . compute-workload-id -m ./measurements.json --json\n```\n\nThe measurements JSON file should contain the TDX measurement registers:\n\n```json\n{\n  \"tdattributes\": \"0x0000000000000000\",\n  \"xfam\": \"0x0000000000000003\",\n  \"mrtd\": \"0x1234567890abcdef...\",\n  \"mrconfigid\": \"0x0000000000000000...\",\n  \"rtmr0\": \"0xabcdef1234567890...\",\n  \"rtmr1\": \"0xef0123456789abcd...\",\n  \"rtmr2\": \"0x234567890abcdef1...\",\n  \"rtmr3\": \"0x67890abcdef12345...\"\n}\n```\n\n### Common Options\n\n| Option | Description |\n| ------ | ----------- |\n| `-c, --chain-id <id>` | Specify chain ID directly |\n| `--chain unichain-mainnet` | Use Unichain Mainnet (chain ID 130) [default] |\n| `--chain unichain-sepolia` | Use Unichain Sepolia (chain ID 1301) |\n| `-r, --rpc-url <url>` | Use a custom RPC URL |\n| `--json` | Output results as JSON |\n| `-V, --version` | Show CLI version |\n| `-h, --help` | Show help for a command |\n\n## Programmatic Examples\n\nSee the [examples/](./examples) directory for complete runnable examples:\n\n- `verifyBlock.ts` - Verify blocks with workload ID\n- `getFlashtestationEvent.ts` - Retrieve flashtestation transaction data\n- `computeWorkloadIdWithMeasurements.ts` - Compute a 32-byte workload ID given a TDX measurement registers in JSON format\n\n**Running examples:**\n\n```bash\n# Set your workload ID\nexport WORKLOAD_ID=0x1234567890abcdef...\n\n# Run the verification example\nbun run examples/verifyBlock.ts\n```\n\n## Development\n\n### Building the SDK\n\n```bash\nyarn build\n```\n\nThis compiles the TypeScript source to CommonJS, ESM, and TypeScript declaration files in the `dist/` directory.\n\n### Running Tests\n\n```bash\nyarn test\n```\n\n### Linting\n\n```bash\nyarn lint\n```\n","readmeFilename":"README.md","_rev":"1-bdf7f5b909e3b976796b6b03804dbc9f"}