Files
AtreidesAssetsFree/server/ai/aliases.js
T

88 lines
2.9 KiB
JavaScript
Raw Normal View History

2026-10-29 11:57:29 +01:00
// Generated, do not edit. sha256:09721f6e6374d0297156a1b8af0d4578d0bbb9c98d4ea7c96458dafbb2d56dcc
import { createHmac } from 'node:crypto';
const HANDLE_TEKENS = 6;
const BECH32 = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
const BASE58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
const HEX = '0123456789abcdef';
const SOORTEN = Object.freeze({
address: Object.freeze({ prefix: 'bc1q', lengte: 42, alfabet: BECH32, onmogelijk: 'o' }),
xpub: Object.freeze({ prefix: 'xpub', lengte: 111, alfabet: BASE58, onmogelijk: '0' }),
txid: Object.freeze({ prefix: '', lengte: 64, alfabet: HEX, onmogelijk: 'z' }),
});
export const ALIAS_SOORTEN = Object.freeze(Object.keys(SOORTEN));
function vul(alfabet, lengte, zaad) {
let s = '';
for (let i = 0; i < lengte; i++) {
const paar = parseInt(zaad.slice((i * 2) % zaad.length, (i * 2) % zaad.length + 2) || '0', 16);
s += alfabet[(paar + i) % alfabet.length];
}
return s;
}
export function schijnwaarde(soort, zaad) {
const s = SOORTEN[soort];
if (!s) throw new Error(`unknown alias kind: ${soort}`);
const romp = vul(s.alfabet, s.lengte - s.prefix.length, String(zaad));
const met = `${romp.slice(0, 2)}${s.onmogelijk}${romp.slice(3)}`;
return `${s.prefix}${met}`;
}
export function isSchijnwaarde(tekst) {
if (typeof tekst !== 'string') return false;
for (const [, s] of Object.entries(SOORTEN)) {
if (s.prefix && !tekst.startsWith(s.prefix)) continue;
if (tekst.length !== s.lengte) continue;
const data = tekst.slice(s.prefix.length);
if (data.includes(s.onmogelijk)) return true;
}
return false;
}
export function createAliasRegistry({ secret } = {}) {
if (typeof secret !== 'string' || secret.length < 32) {
throw new Error('An alias registry without a secret is not allowed.');
}
const heen = new Map();
const terug = new Map();
const afgeleid = (soort, waarde) =>
createHmac('sha256', secret).update(`${soort}\0${waarde}`).digest('hex');
function onthoud(sleutel, uit, soort, waarde) {
const bestaand = terug.get(uit);
if (bestaand && bestaand.waarde !== waarde) {
throw new Error(`Handle collision on '${uit}': two different values yield the same handle.`);
}
heen.set(sleutel, uit);
terug.set(uit, { soort, waarde });
return uit;
}
return {
alias(soort, waarde) {
const sleutel = `${soort} ${waarde}`;
if (heen.has(sleutel)) return heen.get(sleutel);
return onthoud(sleutel, schijnwaarde(soort, afgeleid(soort, waarde)), soort, waarde);
},
handle(soort, waarde) {
const sleutel = `${soort} ${waarde}`;
if (heen.has(sleutel)) return heen.get(sleutel);
return onthoud(sleutel, `${soort}:${afgeleid(soort, waarde).slice(0, HANDLE_TEKENS)}`, soort, waarde);
},
resolve(uit) {
const r = terug.get(uit);
return r ? r.waarde : null;
},
uitgegeven() {
return [...terug.entries()].map(([uit, r]) => ({ uit, soort: r.soort }));
},
};
}