mirror of
https://github.com/stjet/banani.git
synced 2025-12-29 09:39:23 +00:00
code style, let to const
This commit is contained in:
64
util.ts
64
util.ts
@@ -35,13 +35,13 @@ export function int_to_uint8array(int: number, len: number): Uint8Array {
|
||||
let uint8array: Uint8Array = new Uint8Array(len);
|
||||
for (let i = 1; i <= len; i++) {
|
||||
if (i === 1) {
|
||||
uint8array[len - i] = int % (16 ** 2);
|
||||
uint8array[len - i] = int % 16 ** 2;
|
||||
} else {
|
||||
let subbed_int = int;
|
||||
for (let j = i - 1; j > 0; j--) {
|
||||
subbed_int -= uint8array[len - j] * (16 ** (2 * (j - 1)));
|
||||
subbed_int -= uint8array[len - j] * 16 ** (2 * (j - 1));
|
||||
}
|
||||
uint8array[len - i] = Math.floor((subbed_int) / (16 ** (2 * (i - 1))));
|
||||
uint8array[len - i] = Math.floor(subbed_int / 16 ** (2 * (i - 1)));
|
||||
}
|
||||
}
|
||||
return uint8array;
|
||||
@@ -50,22 +50,21 @@ export function int_to_uint8array(int: number, len: number): Uint8Array {
|
||||
const BASE32_CHARS = ["1", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "m", "n", "o", "p", "q", "r", "s", "t", "u", "w", "x", "y", "z"];
|
||||
//const BASE32_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567".split("");
|
||||
|
||||
//this works for normal base32 (with the exception of the second to last character) but not for nano??????
|
||||
//ok, so in addition to the different character set,** you need to pad 4 bits at the front (with 0)** so no left over bits exist. we will pad before this function is called
|
||||
//now officially a bitwise operator enthusiast
|
||||
export function uint8array_to_base32(uint8array: Uint8Array): string {
|
||||
let base32: string = "";
|
||||
for (let i = 0; i < Math.floor(uint8array.length * 8 / 5); i++) {
|
||||
let bitn = i * 5; //bit #
|
||||
let bytn = Math.floor(bitn / 8); //byte #
|
||||
let bits = bitn % 8; //bit start (in the byte)
|
||||
for (let i = 0; i < Math.floor((uint8array.length * 8) / 5); i++) {
|
||||
const bitn = i * 5; //bit #
|
||||
const bytn = Math.floor(bitn / 8); //byte #
|
||||
const bits = bitn % 8; //bit start (in the byte)
|
||||
let b32in: number; //base32 chars array index (5 bit integer)
|
||||
let r = 8 - bits;
|
||||
const r = 8 - bits;
|
||||
if (r >= 5) {
|
||||
b32in = uint8array[bytn] >> (r - 5) & 31; //rightshift to get rid of extra bits on the right, then & 31 to get it down to 5 bits
|
||||
b32in = (uint8array[bytn] >> (r - 5)) & 31; //rightshift to get rid of extra bits on the right, then & 31 to get it down to 5 bits
|
||||
} else {
|
||||
let n = 5 - r; //amount of bits to get from the next byte
|
||||
b32in = (uint8array[bytn] << n & 31) + (uint8array[bytn + 1] >> (8 - n) & (2 ** (8 - n) - 1)); //first part: left shift to get the bits from the current byte in the right position, then & 31 to get it down to 5 bits. second part: get remaining bits from front of the next byte by rightshifting (get rid of extra bits on the right) and then again doing & to get it down to the appropriate amount of bits
|
||||
const n = 5 - r; //amount of bits to get from the next byte
|
||||
b32in = ((uint8array[bytn] << n) & 31) + ((uint8array[bytn + 1] >> (8 - n)) & (2 ** (8 - n) - 1)); //first part: left shift to get the bits from the current byte in the right position, then & 31 to get it down to 5 bits. second part: get remaining bits from front of the next byte by rightshifting (get rid of extra bits on the right) and then again doing & to get it down to the appropriate amount of bits
|
||||
}
|
||||
base32 += BASE32_CHARS[b32in];
|
||||
}
|
||||
@@ -100,8 +99,11 @@ function binary_to_int(binary: string): number {
|
||||
//I don't feel like using bitwise operators for this. might need to use up to 3 bytes, too much work
|
||||
//expects length * 5 to be multiple of 8
|
||||
export function base32_to_uint8array(base32: string): Uint8Array {
|
||||
let binary = base32.split("").map((c) => int_to_binary(BASE32_CHARS.indexOf(c), 5)).join("");
|
||||
let uint8array = new Uint8Array(Math.ceil(base32.length * 5 / 8));
|
||||
const binary = base32
|
||||
.split("")
|
||||
.map((c) => int_to_binary(BASE32_CHARS.indexOf(c), 5))
|
||||
.join("");
|
||||
let uint8array = new Uint8Array(Math.ceil((base32.length * 5) / 8));
|
||||
for (let i = 0; i < uint8array.length; i++) {
|
||||
uint8array[i] = binary_to_int(binary.slice(i * 8, i * 8 + 8));
|
||||
}
|
||||
@@ -109,7 +111,7 @@ export function base32_to_uint8array(base32: string): Uint8Array {
|
||||
}
|
||||
|
||||
export function utf8_to_uint8array(utf8: string): Uint8Array {
|
||||
return (new TextEncoder()).encode(utf8);
|
||||
return new TextEncoder().encode(utf8);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -117,6 +119,8 @@ export function utf8_to_uint8array(utf8: string): Uint8Array {
|
||||
// whole and raw related
|
||||
|
||||
const BANANO_DECIMALS: number = 29;
|
||||
/** Do `rpc.DECIMALS = banani.NANO_DECIMALS` if using Nano. Putting the wrong amount of decimals in may result in LOSS OF FUNDS. */
|
||||
const NANO_DECIMALS: number = 30;
|
||||
|
||||
/** Does NOT mean whole number, can be decimal like "4.2001". Use instead of regular number since those lose precision when decimal */
|
||||
export type Whole = `${number}`; //number can include non-base-10 formats... but whatever, we can assume users will pass in only base-10 because they are normal for the most part
|
||||
@@ -125,11 +129,11 @@ export type Whole = `${number}`; //number can include non-base-10 formats... but
|
||||
export function whole_to_raw(whole: Whole, decimals = BANANO_DECIMALS): bigint {
|
||||
let raw: bigint;
|
||||
if (whole.includes(".")) {
|
||||
let parts = whole.split(".");
|
||||
if (0 > (decimals - parts[1].length)) throw Error(`Too many decimals, cannot exceed ${decimals}`)
|
||||
raw = BigInt(parts[0]) * (BigInt(10) ** BigInt(decimals)) + BigInt(parts[1]) * (BigInt(10) ** BigInt(decimals - parts[1].length));
|
||||
const parts = whole.split(".");
|
||||
if (0 > decimals - parts[1].length) throw Error(`Too many decimals, cannot exceed ${decimals}`);
|
||||
raw = BigInt(parts[0]) * BigInt(10) ** BigInt(decimals) + BigInt(parts[1]) * BigInt(10) ** BigInt(decimals - parts[1].length);
|
||||
} else {
|
||||
raw = BigInt(whole) * (BigInt(10) ** BigInt(decimals));
|
||||
raw = BigInt(whole) * BigInt(10) ** BigInt(decimals);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
@@ -141,11 +145,11 @@ export function raw_to_whole(raw: bigint, decimals = BANANO_DECIMALS): Whole {
|
||||
if (raw_string.length > decimals) {
|
||||
whole_string = raw_string.slice(0, -decimals) + "." + raw_string.slice(-decimals);
|
||||
} else {
|
||||
let r: number = decimals - raw_string.length;
|
||||
const r: number = decimals - raw_string.length;
|
||||
whole_string = "0." + "0".repeat(r > 0 ? r : 0) + raw_string;
|
||||
}
|
||||
//truncate any extra zeroes
|
||||
let cl: number = whole_string.length;
|
||||
const cl: number = whole_string.length;
|
||||
for (let c = 0; c < cl; c++) {
|
||||
if (whole_string.slice(-1) === "0" || whole_string.slice(-1) === ".") {
|
||||
whole_string = whole_string.slice(0, -1);
|
||||
@@ -167,15 +171,15 @@ export function get_public_key_from_private_key(private_key: string): string {
|
||||
|
||||
export function get_address_from_public_key(public_key: string, prefix: AddressPrefix = "ban_"): Address {
|
||||
//the previously mentioned padding the front with 4 bits
|
||||
let encoded = uint8array_to_base32(hex_to_uint8array(`0${public_key}`));
|
||||
const encoded = uint8array_to_base32(hex_to_uint8array(`0${public_key}`));
|
||||
//skip byte length assertions
|
||||
let hashed = uint8array_to_base32(blake2b(5, null, null, null, true).update(hex_to_uint8array(public_key)).digest().reverse());
|
||||
const hashed = uint8array_to_base32(blake2b(5, null, null, null, true).update(hex_to_uint8array(public_key)).digest().reverse());
|
||||
return `ban_${encoded}${hashed}`;
|
||||
}
|
||||
|
||||
export function get_public_key_from_address(address: Address): string {
|
||||
//extract just the public key portion
|
||||
let b = base32_to_uint8array(address.split("_")[1].slice(0, 52));
|
||||
const b = base32_to_uint8array(address.split("_")[1].slice(0, 52));
|
||||
b[b.length - 1] = b[b.length - 1] * 16; //this is a bug fix
|
||||
//remove padding 0 added when encoding to address, remove trailing zero added by the code
|
||||
return uint8array_to_hex(b).slice(1, -1);
|
||||
@@ -194,7 +198,8 @@ export function hash_block(block: BlockNoSignature): string {
|
||||
.update(hex_to_uint8array(get_public_key_from_address(block.representative)))
|
||||
.update(hex_to_uint8array(padded_balance))
|
||||
.update(hex_to_uint8array(block.link))
|
||||
.digest("hex").toUpperCase();
|
||||
.digest("hex")
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
export function sign_block_hash(private_key: string, block_hash: BlockHash): string {
|
||||
@@ -207,12 +212,12 @@ export function verify_block_hash(public_key: string, signature: string, block_h
|
||||
}
|
||||
|
||||
/** sign message by constructing a dummy block with the message (why not just sign the message itself instead of putting it in a dummy block? ledger support). This is already the standard across Banano services and wallets which support signing so please don't invent your own scheme
|
||||
* @return {string} The signature in hex
|
||||
*/
|
||||
export function sign_message(private_key: string, message: string, preamble=MESSAGE_PREAMBLE): string {
|
||||
* @return {string} The signature in hex
|
||||
*/
|
||||
export function sign_message(private_key: string, message: string, preamble = MESSAGE_PREAMBLE): string {
|
||||
//construct the dummy block
|
||||
const dummy32 = "0".repeat(64);
|
||||
let dummy_block: BlockNoSignature = {
|
||||
const dummy_block: BlockNoSignature = {
|
||||
type: "state",
|
||||
account: get_address_from_public_key(get_public_key_from_private_key(private_key)),
|
||||
previous: dummy32,
|
||||
@@ -225,4 +230,3 @@ export function sign_message(private_key: string, message: string, preamble=MESS
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
|
||||
Reference in New Issue
Block a user