UNPKG

@iacobus/hd

Version:

Hierarchical Deterministic Symmetric Keys.

72 lines (71 loc) 3 kB
/** * @fileoverview Provides functionality for parsing derivation paths and schemas. * @module * @author Jacob V. B. Haap <iacobus.xyz> * @license MIT */ import { getIndex } from "./utils.js"; /** defaultSchema is the default derivation path schema */ export const defaultSchema = "m / application: any / purpose: any / context: any / index: num"; /** defaultPath is the default derivation path. */ export const defaultPath = "m/42/0/1/0"; /** * newSchema parses a new derivation path schema from a given string. * @example * const str: string = "m / application: any / purpose: any / context: any / index: num"; * const schema = newSchema(str); */ export function newSchema(str) { const segments = str.split(" / "); if (segments.length > 256) { throw new RangeError(`schema cannot exceed 256 segments, got "${segments.length}"`); } if (segments[0] !== "m") { throw new SyntaxError(`schema must begin with "m", got "${segments[0]}"`); } const allowed = new Set(["str", "num", "any"]); // Allow strings, numbers, or either const result = []; // Allocate array for the parsed schema for (const segment of segments.slice(1)) { const [label, type] = segment.split(":").map(s => s.trim()); // Separate the label and the type if (!label || !type) { throw new SyntaxError(`invalid segment in schema, "${segment}"`); } if (!allowed.has(type)) { throw new TypeError(`invalid type "${type}" for label "${label} in schema"`); } result.push([label, type]); // Add the label and type to the parsed results } return result; // Return parsed schema } /** * newPath parses a new derivation path from a given hash, string, and schema. * @example * const path = newPath(h, "m/42/0/1/0", schema); */ export function newPath(h, str, schema) { const pathArray = str.split("/"); const [root, ...indices] = pathArray; if (root != "m") { throw new SyntaxError(`derivation path must begin with "m", got "${root}"`); } if (indices.length > schema.length) { throw new RangeError(`too many indices in derivation path: got "${indices.length}", expected "${schema.length}"`); } const result = []; // Allocate array for the parsed path for (let i = 0; i < indices.length; i++) { const [label, type] = schema[i]; // Get label and type for the current index from the schema let index; try { index = getIndex(h, indices[i], type); // Parse the current index, enforcing the type from the schema } catch (error) { if (error instanceof Error) { const IndexError = error.constructor; throw new IndexError(`derivation path position ${i} label "${label}", ${error.message}`); } throw error; } result.push(index); // Add the parsed index to the result } return result; // Return the parsed derivation path }