import { Tools } from './lib/tools'
import { Wallet } from './lib/wallet'
+declare global {
+ type Bytes = Uint8Array<ArrayBuffer>
+}
+
export {
Account,
Blake2b,
* @param {Uint8Array} publicKey - Public key bytes as Uint8Array
* @returns Nano address string using `nano_` prefix
*/
- static fromPublicKey (publicKey: ArrayBuffer | Uint8Array<ArrayBuffer>): string {
+ static fromPublicKey (publicKey: ArrayBuffer | Bytes): string {
const checksum = new Blake2b(5).update(publicKey).digest().reverse()
const encodedPublicKey = bytes.toBase32(publicKey)
const encodedChecksum = bytes.toBase32(checksum)
}
constructor (address: string)
- constructor (publicKey: string | ArrayBuffer | Uint8Array<ArrayBuffer>)
+ constructor (publicKey: string | ArrayBuffer | Bytes)
constructor (value: unknown) {
if (typeof value !== 'string' && !(value instanceof ArrayBuffer) && !(value instanceof Uint8Array)) {
throw new TypeError('Invalid address input', { cause: value })
*
* @returns Public key bytes as ArrayBuffer
*/
- toPublicKey (): Uint8Array<ArrayBuffer> {
+ toPublicKey (): Bytes {
const publicKey = base32.toBytes(this.#address.slice(-60, -8))
const checksum = base32.toBytes(this.#address.slice(-8))
const rechecksum = new Blake2b(5).update(publicKey).digest().reverse()
/** @returns {'Account'} */\r
static get DB_NAME (): 'Account' { return 'Account' }\r
\r
- #publicKey: Uint8Array<ArrayBuffer> = new Uint8Array(32)\r
+ #publicKey: Bytes = new Uint8Array(32)\r
#address?: Address\r
\r
#confirmed_balance?: bigint\r
constructor (address: string)\r
/**\r
* Instantiates an Account object from its public key.\r
- * @param {(string | Uint8Array<ArrayBuffer>)} publicKey - Public key of the account\r
+ * @param {(string | Bytes)} publicKey - Public key of the account\r
* @returns {Account} A new Account object\r
*/\r
- constructor (publicKey: string | ArrayBuffer | Uint8Array<ArrayBuffer>)\r
+ constructor (publicKey: string | ArrayBuffer | Bytes)\r
/**\r
* Instantiates an Account object from its public or private key.\r
*\r
* If the key is indicated as private, then it is copied locally, used to\r
* derive the corresponding public key, and finally zeroed out; the user is\r
* responsible for securely handling the original input.\r
- * @param {(string | Uint8Array<ArrayBuffer>)} key - Public or private key of the account\r
+ * @param {(string | Bytes)} key - Public or private key of the account\r
* @param {string} type - Indicates which type the key is\r
* @returns {Account} A new Account object\r
*/\r
- constructor (key: string | ArrayBuffer | Uint8Array<ArrayBuffer>, type: 'public' | 'private')\r
+ constructor (key: string | ArrayBuffer | Bytes, type: 'public' | 'private')\r
constructor (input: unknown, type: unknown = 'public') {\r
if (type === 'private') {\r
try {\r
* Represents a block as defined by the Nano cryptocurrency protocol.
*/
export class Block {
- [key: string]: bigint | string | Account | Function | Uint8Array<ArrayBuffer> | 'send' | 'receive' | 'change' | undefined
+ [key: string]: bigint | string | Account | Function | Bytes | 'send' | 'receive' | 'change' | undefined
/**
* Validates the format of Block properties.
subtype?: 'send' | 'receive' | 'change'
account: Account
balance: bigint
- previous: Uint8Array<ArrayBuffer>
+ previous: Bytes
representative?: Account
- link?: Uint8Array<ArrayBuffer>
+ link?: Bytes
signature?: string
work?: string
* @param {string} base32 - String to convert
* @returns {Uint8Array} Byte array representation of the input string
*/
- toBytes (base32: string): Uint8Array<ArrayBuffer> {
+ toBytes (base32: string): Bytes {
const leftover = (base32.length * 5) % 8
const offset = leftover === 0
? 0
*
* @param bytes - Buffer or bytes to erase
*/
- erase (bytes?: ArrayBuffer | Uint8Array<ArrayBuffer> | null): void {
+ erase (bytes?: ArrayBuffer | Bytes | null): void {
if (bytes == null) return
if (bytes instanceof ArrayBuffer && bytes.byteLength === 0) return
if (bytes instanceof Uint8Array && bytes.buffer.byteLength === 0) return
* @param {Uint8Array} bytes - Byte array to convert
* @returns {string} UTF-8 encoded text string
*/
- toUtf8 (bytes: Uint8Array<ArrayBuffer>): string {
+ toUtf8 (bytes: Bytes): string {
return decoder.decode(bytes)
},
})
* @param {number} [padding=1] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes
* @returns {Uint8Array} Byte array representation of the input decimal
*/
- toBytes (decimal: bigint | number | string, padding: number = 1): Uint8Array<ArrayBuffer> {
+ toBytes (decimal: bigint | number | string, padding: number = 1): Bytes {
if (decimal == null) {
throw new TypeError(`Failed to convert '${decimal}' from decimal to bytes`)
}
* @param {number} [padding=1] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes
* @returns {Uint8Array} Byte array representation of the input value
*/
- toBytes (hex: string, padding: number = 1): Uint8Array<ArrayBuffer> {
+ toBytes (hex: string, padding: number = 1): Bytes {
if (typeof hex !== 'string' || !/^[0-9a-f]+$/i.test(hex)) {
throw new TypeError('Invalid string when converting hex to bytes', { cause: hex })
}
* @param {string} utf8 - String to convert
* @returns {Uint8Array} Byte array representation of the input string
*/
- toBytes (utf8: string): Uint8Array<ArrayBuffer> {
+ toBytes (utf8: string): Bytes {
return encoder.encode(utf8)
},
* SHA-256 hash of entropy that is appended to the entropy and subsequently\r
* used to generate the mnemonic phrase.\r
*\r
- * @param {Uint8Array<ArrayBuffer>} entropy - Cryptographically strong pseudorandom data of length N bits\r
+ * @param {Bytes} entropy - Cryptographically strong pseudorandom data of length N bits\r
* @returns {Promise<bigint>} First N/32 bits of the hash as a bigint\r
*/\r
- static checksum (entropy: Uint8Array<ArrayBuffer>): Promise<bigint> {\r
+ static checksum (entropy: Bytes): Promise<bigint> {\r
const checksumBitLength = (entropy.byteLength / 4) | 0\r
return crypto.subtle.digest('SHA-256', entropy)\r
.then(hash => {\r
* the limit of 128-256 bits defined in BIP-39. Typically, wallets use the\r
* maximum entropy allowed.\r
*\r
- * @param {(ArrayBuffer|Uint8Array<ArrayBuffer>)} entropy - Cryptographically secure random value\r
+ * @param {(ArrayBuffer|Bytes)} entropy - Cryptographically secure random value\r
* @returns {Promise<Bip39>} Mnemonic phrase created using the BIP-39 wordlist\r
*/\r
- static fromEntropy (entropy: ArrayBuffer | Uint8Array<ArrayBuffer>): Promise<Bip39> {\r
+ static fromEntropy (entropy: ArrayBuffer | Bytes): Promise<Bip39> {\r
if (entropy instanceof ArrayBuffer) {\r
entropy = new Uint8Array(entropy)\r
}\r
\r
private constructor () { }\r
\r
- #bip39Seed?: Uint8Array<ArrayBuffer>\r
- #blake2bSeed?: Uint8Array<ArrayBuffer>\r
+ #bip39Seed?: Bytes\r
+ #blake2bSeed?: Bytes\r
#phrase?: string[]\r
\r
/**\r
* or not a string, the empty string ("") is used instead.\r
*\r
* @param {string} [passphrase=''] - Used as the PBKDF2 salt. Default: ""\r
- * @returns {Promise<Uint8Array<ArrayBuffer>>} Promise for seed as bytes\r
+ * @returns {Promise<Bytes>} Promise for seed as bytes\r
*/\r
- toBip39Seed (passphrase: string): Promise<Uint8Array<ArrayBuffer>>\r
+ toBip39Seed (passphrase: string): Promise<Bytes>\r
/**\r
* Converts the mnemonic phrase to a BIP-39 seed.\r
*\r
* @returns {Promise<string>} Promise for seed as hexadecimal string\r
*/\r
toBip39Seed (passphrase: string, format: 'hex'): Promise<string>\r
- toBip39Seed (passphrase: unknown, format?: 'hex'): Promise<string | Uint8Array<ArrayBuffer>> {\r
+ toBip39Seed (passphrase: unknown, format?: 'hex'): Promise<string | Bytes> {\r
if (this.phrase == null) {\r
throw new Error('BIP-39 mnemonic phrase not found')\r
}\r
/**\r
* Converts the mnemonic phrase to a BLAKE2b seed.\r
*\r
- * @returns {Uint8Array<ArrayBuffer>} Seed as bytes\r
+ * @returns {Bytes} Seed as bytes\r
*/\r
- toBlake2bSeed (): Uint8Array<ArrayBuffer>\r
+ toBlake2bSeed (): Bytes\r
/**\r
* Converts the mnemonic phrase to a BLAKE2b seed.\r
*\r
* @returns {string} Seed as hexadecimal string\r
*/\r
toBlake2bSeed (format: 'hex'): string\r
- toBlake2bSeed (format?: 'hex'): string | Uint8Array<ArrayBuffer> {\r
+ toBlake2bSeed (format?: 'hex'): string | Bytes {\r
if (this.#phrase?.length !== 24) {\r
throw new Error('BIP-39 mnemonic phrase must be 24 words to convert to BLAKE2b seed')\r
}\r
import { Point, getPublicKey as secp256k1_getPublicKey } from '@noble/secp256k1'
-type Bytes = Uint8Array<ArrayBuffer>
type Curve = 'Bitcoin seed' | 'ed25519 seed'
type ExtendedKey = {
privateKey: ArrayBuffer
*
* @param {Uint8Array} out - Buffer to store the final output
*/
- #blake2bFinal (out: Uint8Array<ArrayBuffer>): void {
+ #blake2bFinal (out: Bytes): void {
this.#t += BigInt(this.#c) // add final message block size to total bytes
this.#b.fill(0, this.#c) // pad final block with zeros
this.#blake2bCompress(true) // set final block flag and compress
* Creates a BLAKE2b hashing context.
*
* @param {number} length - Output length between 1-64 bytes
- * @param {Uint8Array} [key] - (_optional_) Used for keyed hashing (MAC and PRF)
- * @param {Uint8Array} [salt] - (_optional_) Used to simplify randomized hashing for digital signatures
- * @param {Uint8Array} [personal] - (_optional_) Arbitrary user-specified value
+ * @param {Bytes} [key] - (_optional_) Used for keyed hashing (MAC and PRF)
+ * @param {Bytes} [salt] - (_optional_) Used to simplify randomized hashing for digital signatures
+ * @param {Bytes} [personal] - (_optional_) Arbitrary user-specified value
*/
- constructor (length: number, key?: Uint8Array<ArrayBuffer>, salt?: Uint8Array<ArrayBuffer>, personal?: Uint8Array<ArrayBuffer>)
+ constructor (length: number, key?: Bytes, salt?: Bytes, personal?: Bytes)
constructor (length: unknown, key?: unknown, salt?: unknown, personal?: unknown) {
const B = this.constructor as typeof Blake2b
if (length == null) {
* Finalizes the streaming hash with one last compression and truncates the
* output to the requested byte length.
*
- * @returns {Uint8Array<ArrayBuffer>}
+ * @returns {Bytes}
*/
- digest (): Uint8Array<ArrayBuffer> {
+ digest (): Bytes {
const buf = new Uint8Array(this.#outlen)
this.#blake2bFinal(buf)
return buf
//! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { APDU_CODES, DERIVATION_PATH, LedgerTransport, LISTEN_TIMEOUT, OPEN_TIMEOUT, STATUS_CODES } from '.'
+import { APDU_CODES, DERIVATION_PATH, LISTEN_TIMEOUT, LedgerTransport, OPEN_TIMEOUT, STATUS_CODES } from '.'
import { Account } from '../account'
import { Block } from '../block'
import { HARDENED_OFFSET } from '../constants'
return res.signature
}
-async function signNonce (transport: LedgerTransport, index: number, nonce: Uint8Array<ArrayBuffer>): Promise<string> {
+async function signNonce (transport: LedgerTransport, index: number, nonce: Bytes): Promise<string> {
if (nonce.byteLength !== 16) {
throw new RangeError('Nonce must be 16-byte string')
}
}
export class Tools {
- static #normalize (input: string | ArrayBuffer | Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer> {
+ static #normalize (input: string | ArrayBuffer | Bytes): Bytes {
return (typeof input === 'string')
? hex.toBytes(input)
: input instanceof ArrayBuffer
* Signs an arbitrary string with a secret key using nano25519. The input data
* is encoded as UTF-8 and can be up to 32 KiB in total.
*
- * @param {(string | ArrayBuffer | Uint8Array<ArrayBuffer>)} secretKey - 64-byte secret key
+ * @param {(string | ArrayBuffer | Bytes)} secretKey - 64-byte secret key
* @param {string} input - Data to be signed
* @returns {string} 64-byte hexadecimal signature
*/
- static sign (secretKey: string | ArrayBuffer | Uint8Array<ArrayBuffer>, input: string): string {
+ static sign (secretKey: string | ArrayBuffer | Bytes, input: string): string {
if (navigator.userActivation?.isActive === false) {
throw new DOMException(
'Signing request was blocked due to lack of user activation',
/**
* Verifies the signature of an arbitrary string using a public key.
*
- * @param {(string | ArrayBuffer | Uint8Array<ArrayBuffer>)} publicKey - 32-byte hexadecimal public key
- * @param {(string | ArrayBuffer | Uint8Array<ArrayBuffer>)} signature - 128-character hexadcimal signature
+ * @param {(string | ArrayBuffer | Bytes)} publicKey - 32-byte hexadecimal public key
+ * @param {(string | ArrayBuffer | Bytes)} signature - 128-character hexadcimal signature
* @param {string} input - Data to be verified
* @returns {boolean} True if the data was signed by the public key's matching private key
*/
- static verify (publicKey: string | ArrayBuffer | Uint8Array<ArrayBuffer>, signature: string | ArrayBuffer | Uint8Array<ArrayBuffer>, input: string): boolean {
+ static verify (publicKey: string | ArrayBuffer | Bytes, signature: string | ArrayBuffer | Bytes, input: string): boolean {
const k = this.#normalize(publicKey)
const s = this.#normalize(signature)
try {
import { VaultTimer } from './vault-timer'
const encoder = new TextEncoder()
-const encode = (input?: string): Uint8Array<ArrayBuffer> => encoder.encode(input)
+const encode = (input?: string): Bytes => encoder.encode(input)
let _locked: boolean = true
let _timeout: number = 120_000
let _timer: VaultTimer = new VaultTimer(() => { }, 0)