]> git.codecow.com Git - libnemo.git/commitdiff
Replace built-in toString with faster bespoke implementation.
authorChris Duncan <chris@codecow.com>
Sat, 4 Jul 2026 06:15:21 +0000 (23:15 -0700)
committerChris Duncan <chris@codecow.com>
Sat, 4 Jul 2026 06:15:21 +0000 (23:15 -0700)
src/lib/account/index.ts
src/lib/block/index.ts
src/lib/convert/dec.ts
src/lib/tools.ts
src/lib/vault/index.ts
src/lib/vault/vault-worker.ts

index ef1230458e6357fae98531027bdaccfb1676a0f9..2247b9ac1071aad32456866b757449d6e60b4fa9 100644 (file)
@@ -4,7 +4,7 @@
 import { derive as nano25519_derive } from 'nano25519/sync'\r
 import { Block } from '../block'\r
 import { ACCOUNT_KEY_BYTE_LENGTH, ACCOUNT_KEY_HEX_LENGTH } from '../constants'\r
-import { bytes, hex } from '../convert'\r
+import { bytes, dec, hex } from '../convert'\r
 import { Rpc } from '../rpc'\r
 import { Address } from './address'\r
 import { _refresh } from './refresh'\r
@@ -133,19 +133,19 @@ export class Account {
                return {\r
                        publicKey: this.publicKey,\r
                        address: this.address,\r
-                       confirmed_balance: this.confirmed_balance?.toString(),\r
-                       confirmed_height: this.confirmed_height?.toString(),\r
+                       confirmed_balance: this.confirmed_balance == null ? null : dec.toString(this.confirmed_balance),\r
+                       confirmed_height: this.confirmed_height == null ? null : dec.toString(this.confirmed_height),\r
                        confirmed_frontier: this.confirmed_frontier,\r
-                       confirmed_receivable: this.confirmed_receivable?.toString(),\r
+                       confirmed_receivable: this.confirmed_receivable == null ? null : dec.toString(this.confirmed_receivable),\r
                        confirmed_representative: this.confirmed_representative?.address,\r
-                       balance: this.balance?.toString(),\r
+                       balance: this.balance == null ? null : dec.toString(this.balance),\r
                        block_count: this.block_count,\r
                        frontier: this.frontier,\r
                        open_block: this.open_block,\r
-                       receivable: this.receivable?.toString(),\r
+                       receivable: this.receivable == null ? null : dec.toString(this.receivable),\r
                        representative: this.representative?.address,\r
                        representative_block: this.representative_block,\r
-                       weight: this.weight?.toString(),\r
+                       weight: this.weight == null ? null : dec.toString(this.weight),\r
                }\r
        }\r
 \r
index 9f348a2e2cbc72affc3f6b37a37dc4367b7fc968..c76dc8693cdc2592fff096705ef151ba3e512c12 100644 (file)
@@ -133,7 +133,7 @@ export class Block {
                                "account": this.account.address,
                                "previous": bytes.toHex(this.previous),
                                "representative": this.representative.address ?? '',
-                               "balance": this.balance.toString(),
+                               "balance": dec.toString(this.balance),
                                "link": bytes.toHex(this.link),
                                "signature": this.signature ?? '',
                                "work": this.work ?? ''
index 712449832de22b721f44f310c8625bc122d03783..32e3ce17530f83823fc724a61a8eacf9fbda1c41 100644 (file)
@@ -44,21 +44,50 @@ export const dec = Object.freeze({
                if (decimal == null) {
                        throw new TypeError(`Failed to convert '${decimal}' from decimal to hex`)
                }
-               if (typeof padding !== 'number' || padding < 1 || padding > 0x1fffffffe) {
+               if (typeof padding !== 'number' || padding < 1 || padding > 0xffffffff) {
                        throw new TypeError('Invalid padding')
                }
                let int = BigInt(decimal)
                if (int < 0n) {
                        throw new TypeError('Decimal must be non-negative')
                }
-               let hex: string = ''
+               let str: string = ''
                while (int > 0n) {
-                       hex = HEXCHAR[Number(int & 15n)] + hex
+                       str = HEXCHAR[Number(int & 15n)] + str
                        int >>= 4n
                }
-               while (hex.length < padding) {
-                       hex = '0' + hex
+               while (str.length < padding) {
+                       str = '0' + str
+               }
+               return str
+       },
+
+       /**
+        * Convert a non-negative decimal integer to a decimal string.
+        *
+        * @param {(bigint|number)} decimal - Integer to convert
+        * @param {number} [padding=1] - Minimum length of the resulting string padded as necessary with starting zeroes
+        * @returns {string} Hexadecimal string representation of the input decimal
+        */
+       toString (decimal: bigint | number | null, padding: number = 1): string {
+               if (decimal == undefined) {
+                       throw new TypeError(`Failed to convert '${decimal}' from decimal to string`)
+               }
+               if (typeof padding !== 'number' || padding < 1 || padding > 0xffffffff) {
+                       throw new TypeError('Invalid padding')
+               }
+               let int = BigInt(decimal)
+               if (int < 0n) {
+                       throw new TypeError('Decimal must be non-negative')
+               }
+               let str: string = ''
+               while (int > 0n) {
+                       str = HEXCHAR[Number(int % 10n)] + str
+                       int /= 10n
+               }
+               while (str.length < padding) {
+                       str = '0' + str
                }
-               return hex
+               return str
        },
 })
index 0f4f90b5f2a1705f192fa7c0cfd134f73acfcb90..b15143cdf909ab28d247d53a8fc2cd731ae85941 100644 (file)
@@ -5,7 +5,7 @@ import { sign as nano25519_sign, verify as nano25519_verify } from 'nano25519/sy
 import { Account } from './account'
 import { Block } from './block'
 import { MAX_SUPPLY, UNITS } from './constants'
-import { bytes, hex, utf8 } from './convert'
+import { bytes, dec, hex, utf8 } from './convert'
 import { Rpc } from './rpc'
 import { Wallet } from './wallet'
 
@@ -62,7 +62,7 @@ export class Tools {
 
                let [i, f] = typeof amount === 'string'
                        ? amount.split('.')
-                       : amount.toString().split('.')
+                       : dec.toString(amount).split('.')
                i = i.replace(/^0*/g, '')
                f = f?.replace(/0*$/g, '')
 
@@ -89,8 +89,7 @@ export class Tools {
 
                // convert to desired denomination
                const outUnit = UNITS[outputUnit]
-               i = int.toString()
-               while (i.length < 40) i = '0' + i
+               i = dec.toString(int, 40)
                f = i.slice(40 - outUnit).replace(/0*$/g, '')
                i = i.slice(0, 40 - outUnit).replace(/^0*/g, '')
                const output = `${i === '' ? '0' : i}${f === '' ? '' : '.'}${f}`
index a57c7091b8d0acf6a1607ec997f93ebed5aee268..ece62954a23103fe7f640644365e88ff319d7bca 100644 (file)
@@ -2,6 +2,7 @@
 //! SPDX-License-Identifier: GPL-3.0-or-later
 
 import { Worker as NodeWorker } from 'node:worker_threads'
+import { dec } from '../convert'
 import { Data } from '../database'
 
 type TaskData = {
@@ -52,7 +53,7 @@ export class Vault {
                                stderr: false,
                                stdout: false
                        })
-                       this.#url = this.#worker.threadId.toString()
+                       this.#url = dec.toString(this.#worker.threadId)
                        this.#worker.on('message', listener)
                }
        }
index 1d111f79767f413506c5ea70a211739e51acd530..6c242c4c78f5835c682d05a550cb82fcb1c5c2ac 100644 (file)
@@ -4,6 +4,7 @@
 import { derive as nano25519_derive, sign as nano25519_sign } from 'nano25519/sync'
 import { parentPort, threadId } from 'node:worker_threads'
 import { BIP44_COIN_NANO } from '../constants'
+import { dec } from '../convert'
 import { Bip39, Bip44, Blake2b, WalletAesGcm } from '../crypto'
 import { WalletType } from '../wallet'
 import { parseAction, parseData, parseIv, parseKeySalt, parseType } from './parsers'
@@ -31,7 +32,7 @@ const listener = (event: MessageEvent<any>): void => {
        const { url, id } = data
        if (typeof id !== 'string') return
        BROWSER: if (url !== location.href) return
-       NODE: if (url !== threadId.toString()) return
+       NODE: if (url !== dec.toString(threadId)) return
        NODE: if (parentPort == null) setTimeout(() => listener(event), 0)
        const action = parseAction(data)
        const keySalt = parseKeySalt(action, data)
@@ -383,7 +384,7 @@ async function _autolock (): Promise<void> {
        const { isLocked } = await lock()
        const id = 'autolock'
        BROWSER: self.postMessage({ url: location.href, id, isLocked })
-       NODE: parentPort?.postMessage({ data: { url: threadId.toString(), id, isLocked } })
+       NODE: parentPort?.postMessage({ data: { url: dec.toString(threadId), id, isLocked } })
 }
 
 const _index = new DataView(new ArrayBuffer(4))