datahaven/test/launcher/utils/crypto.ts
Facundo Farall 9b311e00ef
test: 🏗️ Setup e2e testing framework (#104)
## Implement E2E Testing Framework with Isolated Networks

### Summary
Refactors the existing E2E testing infrastructure to provide isolated
test environments with parallel execution support. Each test suite now
runs in its own network namespace, preventing resource conflicts.

### Key Changes
- **New Testing Framework** (`test/framework/`): Base classes for test
lifecycle management with automatic setup/teardown
- **Launcher Module** (`test/launcher/`): Extracted network
orchestration logic from CLI handlers for reusability
- **Parallel Execution**: Added `test-parallel.ts` script with
concurrency limits to prevent resource exhaustion
- **Test Isolation**: Each suite gets unique network IDs (format:
`suiteName-timestamp`) and Docker networks
- **Improved Test Organization**: Migrated tests to new framework,
deprecated old test structure

### Test Improvements
- Added 4 new test suites demonstrating framework usage. :
  - `contracts.test.ts` - Smart contract deployment/interaction
  - `datahaven-substrate.test.ts` - Substrate API operations  
  - `cross-chain.test.ts` - Snowbridge cross-chain messaging
  - `ethereum-basic.test.ts` - Ethereum network operations

> [!WARNING]
The test suites themselves are bad and shouldn't be consider examples of
good tests. They were AI generated just to test the concurrency of test
runners

### Documentation
- Added comprehensive framework overview (`E2E_FRAMEWORK_OVERVIEW.md`)
- Updated README with parallel testing commands
- Added test patterns and best practices

### Breaking Changes
- Old test suites moved to `e2e - DEPRECATED/` directory
- Test execution now requires extending `BaseTestSuite` class

### Testing
Run tests with: `bun test:e2e` or `bun test:e2e:parallel` (with
concurrency limits)

### TODO
- [ ] Implement good test examples.
- [ ] Implement useful test utils (like waiting for an event to show up
in DataHaven or Ethereum).
- [ ] Enforce tests with CI (currently cannot be done due to
intermittent error when sending a transaction with PAPI).

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: undercover-cactus <lola@moonsonglabs.com>
2025-07-16 18:51:07 +02:00

42 lines
1.5 KiB
TypeScript

import { secp256k1 } from "@noble/curves/secp256k1";
import { keccak_256 } from "@noble/hashes/sha3";
import type { Hex } from "viem";
/**
* Converts a compressed ECDSA public key to an Ethereum address.
* Used for converting BEEFY authorities public keys to Ethereum addresses.
*
* @param compressedPubKey - The compressed public key (33 bytes)
* @returns The Ethereum address derived from the public key
*/
export const compressedPubKeyToEthereumAddress = (compressedPubKey: Hex): Hex => {
// Remove 0x prefix if present
const pubKeyBytes = compressedPubKey.startsWith("0x")
? compressedPubKey.slice(2)
: compressedPubKey;
// Convert hex string to Uint8Array
const matches = pubKeyBytes.match(/.{1,2}/g);
if (!matches) {
throw new Error("Invalid hex string format");
}
const compressedBytes = new Uint8Array(matches.map((byte) => Number.parseInt(byte, 16)));
// Get the uncompressed point
const point = secp256k1.ProjectivePoint.fromHex(compressedBytes);
const uncompressedBytes = point.toRawBytes(false); // false = uncompressed
// Remove the first byte (0x04) which indicates uncompressed format
const publicKeyBytes = uncompressedBytes.slice(1);
// Keccak256 hash of the public key
const hash = keccak_256(publicKeyBytes);
// Take the last 20 bytes as the Ethereum address
const address = hash.slice(-20);
// Convert to hex string with 0x prefix
return `0x${Array.from(address)
.map((b) => b.toString(16).padStart(2, "0"))
.join("")}` as Hex;
};