import { binToHex } from '@bitauth/libauth'; // TODO: Put unsorted stuff in here and then try to sort them somewhere more sensible later. export function getOutpointId(outpoint: { outpointTransactionHash: Uint8Array; outpointIndex: number; }): string { const outpointHashHex = binToHex(outpoint.outpointTransactionHash); return `${outpointHashHex}:${outpoint.outpointIndex}`; } // TODO: Jason uses form timestampMs_entityId export function generateActivityId() { return Date.now().toString(); } /** * Checks if a URL has duplicate parameters. * * @param url - The URL to check * @returns True if the URL has duplicate parameters, false otherwise */ export function hasDuplicateParams(url: string | URL): boolean { if (typeof url === 'string') { url = new URL(url); } const params = url.searchParams; const seen = new Set(); for (const [key] of params.entries()) { if (seen.has(key)) { return true; } seen.add(key); } return false; } /** * Check if the given object is a Record. * * @param object The variable to check. * @returns True if the object is a record. */ export function isRecord( value: unknown, ): value is Record { if (typeof value !== 'object' || value === null) return false; // Check if its a plain object (not a class instance, array, etc.) const prototype = Object.getPrototypeOf(value); return prototype === null || prototype === Object.prototype; } /** * Find all the ocurrences of a given key in a plain JS object. * NOTE: This function is intended to search keys in JSON objects * and it will not search the key walking through collection object structures(Set, Map, etc.) * NOTE: This function is intended to be used to traverse not too nested JSON objects. * * @param object The plain JS Object to traverse. * @param key The Key to search. * * @throws If object can't be serializated as JSON. * @throws If object is more than 100 levels nested. * @returns A list of values for the given key. */ export function findAllKeyOcurrences( object: Record, key: string, ): Array { // Check object serialization as JSON to avoid circular reference, BigInt values or other object structures(Set, Map, Date, etc..) JSON.stringify(object); // Under 100 the resource allocation is excessively fine for any JS environment or hardware. // NOTE: If for some reason this needs to be changed be sure to add proper test cases to measure performance. // Currently(11/09/2025) the JS stack size can handle roughly 10000 recursive calls on browsers and NodeJS. const allowedNestedLevels = 100; const keyValues: Array = []; function traverse( currentObj: Record, depth: number = 0, ) { // Stop if depth exceeds the amount of 'allowedNestedLevels'. if (depth > allowedNestedLevels) throw new Error( `Maximum nesting level of ${allowedNestedLevels} reached.`, ); // Stop when find a non object value. if (typeof currentObj !== 'object' || currentObj === null) return; if (Array.isArray(currentObj)) { currentObj.forEach((item) => traverse(item, depth + 1)); return; } // Check if current object has the key property we are looking if (key in currentObj) { keyValues.push(currentObj[key]); } // Recursively traverse all properties Object.values(currentObj).forEach((value) => { if (isRecord(value)) traverse(value, depth + 1); }); } traverse(object); return keyValues; }