@creit.tech/stellar-wallets-kit
Version:
A kit to handle all Stellar Wallets at once
199 lines (198 loc) • 7.68 kB
JavaScript
;
// Copyright 2018-2025 the Deno authors. MIT license.
Object.defineProperty(exports, "__esModule", { value: true });
exports.rAlphabet = exports.alphabet = exports.padding = void 0;
exports.calcSizeBase32 = calcSizeBase32;
exports.encode = encode;
exports.decode = decode;
exports.padding = "=".charCodeAt(0);
exports.alphabet = {
base32: new TextEncoder().encode("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"),
base32hex: new TextEncoder().encode("0123456789ABCDEFGHIJKLMNOPQRSTUV"),
base32crockford: new TextEncoder().encode("0123456789ABCDEFGHJKMNPQRSTVWXYZ"),
};
exports.rAlphabet = {
base32: new Uint8Array(128).fill(32), // alphabet.base32.length
base32hex: new Uint8Array(128).fill(32),
base32crockford: new Uint8Array(128).fill(32),
};
exports.alphabet.base32
.forEach((byte, i) => exports.rAlphabet.base32[byte] = i);
exports.alphabet.base32hex
.forEach((byte, i) => exports.rAlphabet.base32hex[byte] = i);
exports.alphabet.base32crockford
.forEach((byte, i) => exports.rAlphabet.base32crockford[byte] = i);
/**
* Calculate the output size needed to encode a given input size for
* {@linkcode encodeIntoBase32}.
*
* @param rawSize The size of the input buffer.
* @returns The size of the output buffer.
*
* @example Basic Usage
* ```ts
* import { assertEquals } from "@std/assert";
* import { calcSizeBase32 } from "@std/encoding/unstable-base32";
*
* assertEquals(calcSizeBase32(1), 8);
* ```
*/
function calcSizeBase32(rawSize) {
return ((rawSize + 4) / 5 | 0) * 8;
}
function encode(buffer, i, o, alphabet, padding) {
i += 4;
for (; i < buffer.length; i += 5) {
let x = (buffer[i - 4] << 16) | (buffer[i - 3] << 8) | buffer[i - 2];
buffer[o++] = alphabet[x >> 19];
buffer[o++] = alphabet[x >> 14 & 0x1F];
buffer[o++] = alphabet[x >> 9 & 0x1F];
buffer[o++] = alphabet[x >> 4 & 0x1F];
x = (x << 16) | (buffer[i - 1] << 8) | buffer[i];
buffer[o++] = alphabet[x >> 15 & 0x1F];
buffer[o++] = alphabet[x >> 10 & 0x1F];
buffer[o++] = alphabet[x >> 5 & 0x1F];
buffer[o++] = alphabet[x & 0x1F];
}
switch (i) {
case buffer.length + 3: {
const x = buffer[i - 4] << 16;
buffer[o++] = alphabet[x >> 19];
buffer[o++] = alphabet[x >> 14 & 0x1F];
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
break;
}
case buffer.length + 2: {
const x = (buffer[i - 4] << 16) | (buffer[i - 3] << 8);
buffer[o++] = alphabet[x >> 19];
buffer[o++] = alphabet[x >> 14 & 0x1F];
buffer[o++] = alphabet[x >> 9 & 0x1F];
buffer[o++] = alphabet[x >> 4 & 0x1F];
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
break;
}
case buffer.length + 1: {
let x = (buffer[i - 4] << 16) | (buffer[i - 3] << 8) | buffer[i - 2];
buffer[o++] = alphabet[x >> 19];
buffer[o++] = alphabet[x >> 14 & 0x1F];
buffer[o++] = alphabet[x >> 9 & 0x1F];
buffer[o++] = alphabet[x >> 4 & 0x1F];
x <<= 16;
buffer[o++] = alphabet[x >> 15 & 0x1F];
buffer[o++] = padding;
buffer[o++] = padding;
buffer[o++] = padding;
break;
}
case buffer.length: {
let x = (buffer[i - 4] << 16) | (buffer[i - 3] << 8) | buffer[i - 2];
buffer[o++] = alphabet[x >> 19];
buffer[o++] = alphabet[x >> 14 & 0x1F];
buffer[o++] = alphabet[x >> 9 & 0x1F];
buffer[o++] = alphabet[x >> 4 & 0x1F];
x = (x << 16) | (buffer[i - 1] << 8);
buffer[o++] = alphabet[x >> 15 & 0x1F];
buffer[o++] = alphabet[x >> 10 & 0x1F];
buffer[o++] = alphabet[x >> 5 & 0x1F];
buffer[o++] = padding;
break;
}
}
return o;
}
function decode(buffer, i, o, alphabet, padding) {
for (let x = buffer.length - 6; x < buffer.length; ++x) {
if (buffer[x] === padding) {
for (let y = x + 1; y < buffer.length; ++y) {
if (buffer[y] !== padding) {
throw new TypeError(`Cannot decode input as base32: Invalid character (${String.fromCharCode(buffer[y])})`);
}
}
buffer = buffer.subarray(0, x);
break;
}
}
switch ((buffer.length - o) % 8) {
case 6:
case 3:
case 1:
throw new RangeError(`Cannot decode input as base32: Length (${buffer.length - o}), excluding padding, must not have a remainder of 1, 3, or 6 when divided by 8`);
}
i += 7;
for (; i < buffer.length; i += 8) {
let x = (getByte(buffer[i - 7], alphabet) << 19) |
(getByte(buffer[i - 6], alphabet) << 14) |
(getByte(buffer[i - 5], alphabet) << 9) |
(getByte(buffer[i - 4], alphabet) << 4);
buffer[o++] = x >> 16;
buffer[o++] = x >> 8 & 0xFF;
x = (x << 16) |
(getByte(buffer[i - 3], alphabet) << 15) |
(getByte(buffer[i - 2], alphabet) << 10) |
(getByte(buffer[i - 1], alphabet) << 5) |
getByte(buffer[i], alphabet);
buffer[o++] = x >> 16 & 0xFF;
buffer[o++] = x >> 8 & 0xFF;
buffer[o++] = x & 0xFF;
}
switch (i) {
case buffer.length + 5: {
const x = (getByte(buffer[i - 7], alphabet) << 19) |
(getByte(buffer[i - 6], alphabet) << 14);
buffer[o++] = x >> 16;
break;
}
case buffer.length + 3: {
const x = (getByte(buffer[i - 7], alphabet) << 19) |
(getByte(buffer[i - 6], alphabet) << 14) |
(getByte(buffer[i - 5], alphabet) << 9) |
(getByte(buffer[i - 4], alphabet) << 4);
buffer[o++] = x >> 16;
buffer[o++] = x >> 8 & 0xFF;
break;
}
case buffer.length + 2: {
let x = (getByte(buffer[i - 7], alphabet) << 19) |
(getByte(buffer[i - 6], alphabet) << 14) |
(getByte(buffer[i - 5], alphabet) << 9) |
(getByte(buffer[i - 4], alphabet) << 4);
buffer[o++] = x >> 16;
buffer[o++] = x >> 8 & 0xFF;
x = (x << 16) |
(getByte(buffer[i - 3], alphabet) << 15);
buffer[o++] = x >> 16 & 0xFF;
break;
}
case buffer.length: {
let x = (getByte(buffer[i - 7], alphabet) << 19) |
(getByte(buffer[i - 6], alphabet) << 14) |
(getByte(buffer[i - 5], alphabet) << 9) |
(getByte(buffer[i - 4], alphabet) << 4);
buffer[o++] = x >> 16;
buffer[o++] = x >> 8 & 0xFF;
x = (x << 16) |
(getByte(buffer[i - 3], alphabet) << 15) |
(getByte(buffer[i - 2], alphabet) << 10) |
(getByte(buffer[i - 1], alphabet) << 5);
buffer[o++] = x >> 16 & 0xFF;
buffer[o++] = x >> 8 & 0xFF;
break;
}
}
return o;
}
function getByte(char, alphabet) {
const byte = alphabet[char] ?? 32;
if (byte === 32) { // alphabet.Base32.length
throw new TypeError(`Cannot decode input as base32: Invalid character (${String.fromCharCode(char)})`);
}
return byte;
}