import baseX from "base-x"; const alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; const base58 = baseX(alphabet); const SEPARATOR = "_"; /** * Version 1 keys are constructed of 3 parts * 1. 1 byte for the version * 2. 1 byte to let us know the byteLength of the random part * 3. LEN bytes of random data * [VERSION, LEN, X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X] */ export class KeyV1 { public readonly version = 1; public readonly prefix?: string; public readonly random: Uint8Array; constructor(s: string); constructor(opts: { byteLength: number; prefix?: string }); constructor(arg: string | { byteLength: number; prefix?: string }) { if (typeof arg === "string") { let s = arg; const parts = arg.split(SEPARATOR); if (parts.length === 2) { this.prefix = parts[0]; s = parts[1]; } const buf = base58.decode(s); if (buf[0] !== 1) { throw new Error("Only version 1 keys are supported"); } const len = buf[1]; this.random = buf.slice(2, 2 + len); return; } if (arg.byteLength < 8 || arg.byteLength > 255) { throw new Error("v1 keys must be between 8 and 255 bytes long"); } this.prefix = arg.prefix; this.random = crypto.getRandomValues(new Uint8Array(arg.byteLength)); } static fromString(s: string): KeyV1 { return new KeyV1(s); } public toString(): string { const buf = new Uint8Array(2 + this.random.length); buf[0] = this.version; buf[1] = this.random.length; buf.set(this.random, 2); const enc = base58.encode(buf); if (this.prefix) { return [this.prefix, enc].join(SEPARATOR); } return enc; } }