export type MezoId = `${string}.mezo` // NOTE: This was copied from mezo-portal and is based on the validation from // workers/passport-auth/src/utils/mezo-id.ts. // Most of these are restrictions for an DNS hostname label (i.e., the part // before/after `.` in a full hostname) as outlined in RFC1034 // (https://www.rfc-editor.org/rfc/rfc1034). // // A few addenda are made to ensure that nothing can sneak through that could // look like an Ethereum or Bitcoin address. export const DISALLOWED_MEZO_ID_PATTERNS: { pattern: RegExp; error: string }[] = [ // RFC1034. { pattern: /^$/, error: "Must not be empty." }, { pattern: /^.{16,}$/, error: "Must have 15 characters or fewer." }, { pattern: /^[^A-Za-z]/, error: "Must start with one of the letters A-Z or a-z.", }, { pattern: /[^A-Za-z0-9-]/, error: "Must only use letters or numbers (A-Z, a-z, or 0-9), or hyphen (-).", }, { pattern: /-$/, error: "Must not end in a hyphen (-)." }, // On-chain shenanigan avoidance. { pattern: /0x/i, error: "Must not contain 0x." }, { pattern: /^(?:bc1|tb1|[a-z]pub|[a-z]priv)/i, error: "Must not start with a Bitcoin magic string.", }, { pattern: /^m[0-9]+$/i, error: 'No "m" + "numeric string" prefixes.', }, ] export function validateMezoId(mezoId: string): string[] { if (!/\.mezo$/.test(mezoId)) { return ["Must end with '.mezo'."] } const mezoIdWithoutSuffix = mezoId.replace(/\.mezo$/, "") const errors = DISALLOWED_MEZO_ID_PATTERNS.flatMap(({ pattern, error }) => pattern.test(mezoIdWithoutSuffix) ? [error] : [], ) return errors }