src/account/address.ts
v0.3.0 · 1 KB
import { HlAccountError } from './errors.js';
/** A full 20-byte EVM address in lowercase. */
export type Address = `0x${string}`;
const ADDRESS_ANY_CASE = /^0x[0-9a-fA-F]{40}$/;
/** True for a full `0x` + 40 hex address in any letter case. Shortened forms are never valid. */
export function isAddress(value: unknown): value is string {
return typeof value === 'string' && ADDRESS_ANY_CASE.test(value);
}
/**
* Validates and lowercases an address.
*
* Why lowercase on input: HL accepts any case, but may echo addresses back in checksum or lower
* case, and viem returns checksum form. Mixed case silently breaks cache keys, dedup and the
* comparison with `extraAgents` (one account ends up as two records).
*
* @throws {HlAccountError} `INVALID_ARGUMENT` when the value is not a full address.
*/
export function normalizeAddress(value: unknown, what = 'address'): Address {
if (!isAddress(value)) {
throw new HlAccountError('INVALID_ARGUMENT', `${what} must be a full 0x-prefixed 40-hex address`);
}
return value.toLowerCase() as Address;
}