import type { SqlExecutor } from "./storage.ts";
import type { AddressRow, OwnerRef } from "./types.ts";
const ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789";
const LOCAL_PART_LENGTH = 10;
const MAX_CREATE_ATTEMPTS = 5;
// Addresses must not be predictable: users can mint addresses and see the
// results, and Math.random()'s PRNG state is recoverable from observed
// output, which would let one user guess another's addresses. Uses rejection
// sampling: bytes at or above the largest multiple of the alphabet length
// are discarded rather than folded in with %, which would bias the low
// characters of the alphabet.
const REJECTION_LIMIT = 256 - (256 % ALPHABET.length);
// Exported since other receivers (mail.tm) need their own random strings
// (a local part, an account password) with the same guarantee.
export function randomAlphanumeric(length: number): string {
let out = "";
while (out.length < length) {
const bytes = new Uint8Array(length);
crypto.getRandomValues(bytes);
for (const byte of bytes) {
if (byte >= REJECTION_LIMIT) {
continue;
}
out += ALPHABET[byte % ALPHABET.length];
if (out.length === length) {
break;
}
}
}
return out;
}
export async function createAddress(
db: SqlExecutor,
owner: OwnerRef,
domain: string,
ttlSeconds: number,