Amend Primitives/Tooling

This commit is contained in:
Jim Hamill
2025-01-13 09:43:11 +00:00
parent 06c9d52b56
commit f53fc4b456
29 changed files with 817 additions and 463 deletions
+65 -15
View File
@@ -18,13 +18,20 @@ import type { KnownAddressTypeContents } from '@bitauth/libauth';
export type AddressType = 'P2PK' | 'P2PKH' | 'P2SH20' | 'P2SH32';
export const DEFAULT_ADDRESS_PREFIXES = [
'',
'bitcoincash',
'bchtest',
'bchreg',
];
/**
* Address Entity.
*/
export class Address {
public readonly addressContents: KnownAddressTypeContents;
constructor(addressContents: KnownAddressTypeContents) {
protected constructor(addressContents: KnownAddressTypeContents) {
this.addressContents = addressContents;
}
@@ -37,13 +44,16 @@ export class Address {
*
* @returns {Address} Instance of Address.
*/
public static from(address: string): Address {
public static from(
address: string,
tryPrefixes = DEFAULT_ADDRESS_PREFIXES,
): Address {
// Attempt to decode as a Cash Address.
try {
return Address.fromCashAddr(address);
return this.fromCashAddr(address, tryPrefixes);
} catch (_error) {
// And if that fails, attempt to decode as a Base58 Address.
return Address.fromLegacy(address);
return this.fromLegacy(address);
}
}
@@ -61,7 +71,7 @@ export class Address {
*/
public static fromCashAddr(
cashAddr: string,
tryPrefixes: Array<string> = ['', 'bitcoincash', 'bchtest', 'bchreg'],
tryPrefixes: Array<string> = DEFAULT_ADDRESS_PREFIXES,
): Address {
// Try all prefixes (including empty string) until we find a valid decode
const decodeResult = tryPrefixes
@@ -158,7 +168,7 @@ export class Address {
}
// Return a new instance of address.
return new Address({ payload, type });
return this.fromRaw({ payload, type });
}
/**
@@ -181,7 +191,7 @@ export class Address {
const contractBytecode = hexToBin(hex);
// Return a new instance of address.
return Address.fromRedeemScript(contractBytecode, type);
return this.fromRedeemScript(contractBytecode, type);
}
/**
@@ -201,7 +211,7 @@ export class Address {
throw new Error(`Invalid type (${addressContents.type})`);
}
return new Address(addressContents);
return this.fromRaw(addressContents);
}
/**
@@ -220,7 +230,7 @@ export class Address {
const lockScriptBytes = hexToBin(hex);
return Address.fromLockscriptBytes(lockScriptBytes);
return this.fromLockscriptBytes(lockScriptBytes);
}
/**
@@ -244,7 +254,7 @@ export class Address {
);
}
return new Address({ payload: hash160, type });
return this.fromRaw({ payload: hash160, type });
}
/**
@@ -267,16 +277,34 @@ export class Address {
const hash160Bytes = hexToBin(hash160Hex);
return Address.fromHash160(hash160Bytes, type);
return this.fromHash160(hash160Bytes, type);
}
/**
* Creates an Address instance from a raw object representation (LibAuth's KnownAddressTypeContents).
*
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param obj - LibAuth Object of type KnownAddressTypeContents
* @returns A new Address instance
*/
public static fromRaw(addressContents: KnownAddressTypeContents) {
return new this(addressContents);
}
public static isValid(address: string): boolean {
/**
* Checks whether the given address is a valid Legacy or CashAddr.
*
* @param address The address.
*
* @returns boolean indicating whether the address is a valid Legacy Address or CashAddr.
*/
public static isValid(
address: string,
tryPrefixes = DEFAULT_ADDRESS_PREFIXES,
): boolean {
try {
Address.from(address);
Address.from(address, tryPrefixes);
} catch (_error) {
return false;
}
@@ -284,6 +312,13 @@ export class Address {
return true;
}
/**
* Checks whether the given address is a valid Legacy Address.
*
* @param address The address.
*
* @returns boolean indicating whether the address is a valid Legacy Address.
*/
public static isValidLegacy(address: string): boolean {
try {
Address.fromLegacy(address);
@@ -294,9 +329,19 @@ export class Address {
return true;
}
public static isValidCashAddr(address: string): boolean {
/**
* Checks whether the given address is a valid CashAddr.
*
* @param address The address.
*
* @returns boolean indicating whether the address is a valid CashAddr.
*/
public static isValidCashAddr(
address: string,
tryPrefixes = DEFAULT_ADDRESS_PREFIXES,
): boolean {
try {
Address.fromCashAddr(address);
Address.fromCashAddr(address, tryPrefixes);
} catch (_error) {
return false;
}
@@ -467,6 +512,11 @@ export class Address {
return lockscriptAsm;
}
/**
* Converts the address to its raw LibAuth representation (KnownAddressTypeContents).
*
* @returns A LibAuth KnownAddressTypeContents object.
*/
public toRaw() {
return { ...this.addressContents };
}
+50 -10
View File
@@ -24,7 +24,7 @@ export class BlockHeader {
* @param bits - Compact representation of the target threshold
* @param nonce - Value modified during mining to make the block hash valid
*/
constructor(
protected constructor(
private readonly version: number,
private readonly previousBlockHash: Uint8Array,
private readonly merkleRoot: Uint8Array,
@@ -33,6 +33,24 @@ export class BlockHeader {
private readonly nonce: number,
) {}
/**
* Instantiates a blockheader from either:
*
* 1. Transaction bytecode
* 2. Transaction bytecode (in hexadecimal format)
*
* @param blockHeader The block header in one of the above formats.
*
* @throws {Error} If the block header cannot be decoded.
*
* @returns The created BlockHeader Primitive.
*/
public static from(blockHeader: Uint8Array | string) {
return blockHeader instanceof Uint8Array
? BlockHeader.fromBytes(blockHeader)
: BlockHeader.fromHex(blockHeader);
}
/**
* Creates a BlockHeader instance from a byte array.
* @param bytes - 80-byte array containing the serialized block header
@@ -72,6 +90,9 @@ export class BlockHeader {
/**
* Creates a BlockHeader instance from a raw object representation.
*
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param obj - Object containing the block header fields
* @returns A new BlockHeader instance
*/
@@ -86,6 +107,23 @@ export class BlockHeader {
);
}
/**
* Checks whether the given BlochHeader is of a valid structure.
*
* @param blockHeader The blockheader as hex or a Uint8Array.
*
* @returns boolean indicating whether the blockheader is of a valid structure.
*/
public static isValid(blockHeader: Uint8Array | string): boolean {
try {
BlockHeader.from(blockHeader);
} catch (_error) {
return false;
}
return true;
}
/**
* Serializes the block header to a byte array.
* @returns 80-byte array containing the serialized block header
@@ -106,7 +144,17 @@ export class BlockHeader {
}
/**
* Converts the block header to a raw object representation.
* Converts the block header to a hex string.
*
* @returns 160-character hex string representing the block header
*/
toHex(): string {
return binToHex(this.toBytes());
}
/**
* Converts the block header to a serializable raw object representation.
*
* @returns Object containing the block header fields
*/
toRaw(): BlockHeaderRaw {
@@ -120,14 +168,6 @@ export class BlockHeader {
};
}
/**
* Converts the block header to a hex string.
* @returns 160-character hex string representing the block header
*/
toHex(): string {
return binToHex(this.toBytes());
}
// Getters
getVersion(): number {
return this.version;
+1 -1
View File
@@ -23,7 +23,7 @@ export class Bytes {
*
* @param bytes {Uint8Array} The bytes to use.
*/
constructor(bytes: Uint8Array) {
protected constructor(bytes: Uint8Array) {
this.bytes = bytes;
}
+5 -3
View File
@@ -1,6 +1,8 @@
// TODO: These are intended as temporary stand-ins until this functionality has been implemented directly in LibAuth.
// We are doing this so that we may better standardize with the rest of the BCH eco-system in future.
// See: https://github.com/bitauth/libauth/pull/108
/**
* TODO: These are intended as temporary stand-ins until this functionality has been implemented directly in LibAuth.
* We are doing this so that we may better standardize with the rest of the BCH eco-system in future.
* See: https://github.com/bitauth/libauth/pull/108
*/
import { binToHex, hexToBin } from '@bitauth/libauth';
-137
View File
@@ -1,137 +0,0 @@
import {
isHex,
isBase64,
binToHex,
base64ToBin,
hexToBin,
utf8ToBin,
ripemd160,
sha256,
} from '@bitauth/libauth';
/**
* Represents a hash primitive that provides various cryptographic hashing capabilities.
* This class handles conversions between different formats (bytes, hex, UTF-8) and
* supports multiple hashing algorithms (SHA256, RIPEMD160, Hash160, Hash256).
*/
export class Hasher {
/**
* Creates a new Hash instance.
* @param bytes - The byte array representation of the data to be hashed
*/
constructor(public bytes: Uint8Array) {}
/**
* Creates a Hash instance from a byte array.
* @param bytes - The byte array to create the hash from
* @returns A new Hash instance containing the provided bytes
*/
public static fromBytes(bytes: Uint8Array) {
return new this(bytes);
}
/**
* Creates a Hash instance from a Base64 string.
* @param base64 - The Base64 string to create the hash from
* @returns A new Hash instance containing the bytes converted from the Base64 string
* @throws {Error} If the provided string is not valid Base64
*/
public static fromBase64(base64: string) {
// Ensure that the given string is base64.
if (!isBase64(base64)) {
throw new Error('The given string is not valid Base64.');
}
return new this(base64ToBin(base64));
}
/**
* Creates a Hash instance from a hexadecimal string.
* @param hex - The hexadecimal string to create the hash from
* @returns A new Hash instance containing the bytes converted from the hex string
* @throws {Error} If the provided string is not valid hexadecimal
*/
public static fromHex(hex: string) {
// Ensure that the given string is hex.
if (!isHex(hex)) {
throw new Error('The given string is not valid hexadecimal.');
}
return new this(hexToBin(hex));
}
/**
* Creates a Hash instance from a UTF-8 string.
* @param utf8 - The UTF-8 string to create the hash from
* @returns A new Hash instance containing the bytes converted from the UTF-8 string
*/
public static fromUTF8(utf8: string) {
return new this(utf8ToBin(utf8));
}
/**
* Computes the SHA256 hash of the stored bytes.
* @returns A Uint8Array containing the SHA256 hash
*/
public toSHA256Bytes(): Uint8Array {
return sha256.hash(this.bytes);
}
/**
* Computes the SHA256 hash of the stored bytes and returns it as a hexadecimal string.
* @returns The SHA256 hash as a hexadecimal string
*/
public toSHA256Hex(): string {
return binToHex(this.toSHA256Bytes());
}
/**
* Computes the RIPEMD160 hash of the stored bytes.
* @returns A Uint8Array containing the RIPEMD160 hash
*/
public toRIPEMD160Bytes(): Uint8Array {
return ripemd160.hash(this.bytes);
}
/**
* Computes the RIPEMD160 hash of the stored bytes and returns it as a hexadecimal string.
* @returns The RIPEMD160 hash as a hexadecimal string
*/
public toRIPEMD160Hex(): string {
return binToHex(this.toRIPEMD160Bytes());
}
/**
* Computes the Hash160 (RIPEMD160(SHA256(x))) of the stored bytes.
* This is commonly used in cryptocurrency addresses.
* @returns A Uint8Array containing the Hash160 value
*/
public toHash160Bytes(): Uint8Array {
return ripemd160.hash(this.toSHA256Bytes());
}
/**
* Computes the Hash160 (RIPEMD160(SHA256(x))) of the stored bytes and returns it as a hexadecimal string.
* @returns The Hash160 value as a hexadecimal string
*/
public toHash160Hex(): string {
return binToHex(this.toHash160Bytes());
}
/**
* Computes the Hash256 (SHA256(SHA256(x))) of the stored bytes.
* This is commonly used for computing block hashes in Bitcoin.
* @returns A Uint8Array containing the Hash256 value
*/
public toHash256Bytes(): Uint8Array {
return sha256.hash(this.toSHA256Bytes());
}
/**
* Computes the Hash256 (SHA256(SHA256(x))) of the stored bytes and returns it as a hexadecimal string.
* @returns The Hash256 value as a hexadecimal string
*/
public toHash256Hex(): string {
return binToHex(sha256.hash(this.toSHA256Bytes()));
}
}
+77 -85
View File
@@ -1,4 +1,6 @@
import { Bytes } from './bytes.js';
import { HDPublicNode } from './hd-public-node.js';
import { Mnemonic } from './mnemonic.js';
import { PrivateKey } from './private-key.js';
import {
@@ -8,7 +10,6 @@ import {
deriveHdPathRelative,
deriveHdPublicNode,
deriveHdPrivateNodeFromSeed,
deriveSeedFromBip39Mnemonic,
generateRandomBytes,
} from '@bitauth/libauth';
@@ -30,7 +31,7 @@ export class HDPrivateNode {
*
* @param node The HD Private Node.
*/
constructor(node: HdPrivateNodeValid) {
protected constructor(node: HdPrivateNodeValid) {
this.node = node;
}
@@ -43,27 +44,18 @@ export class HDPrivateNode {
*
* @returns The created HD Private Node.
*/
public static fromBytes(seed: Uint8Array): HDPrivateNode {
// Return a new HD Private Node from the given seed.
return this.fromSeed(seed);
}
public static fromSeed(seed: Uint8Array | string): HDPrivateNode {
// Cast from hex if a string was provided.
if (typeof seed === 'string') {
seed = Bytes.fromHex(seed).toBytes();
}
/**
* Creates a HD Private Node from a raw seed.
*
* @param seed The raw seed bytes.
*
* @throws {Error} If HD Private Node cannot be created.
*
* @returns The created HD Private Node.
*/
public static fromSeed(seed: Uint8Array): HDPrivateNode {
// If the seed is not 32 bytes, throw an error.
/*if (seed.length !== 32) {
// If the seed is not 64 bytes, throw an error.
if (seed.length !== 64) {
throw new Error(
`Failed to derive Private Node from seed: Seed must be 32 bytes (${seed.length} given)`
`Failed to derive Private Node from seed: Seed must be 64 bytes (${seed.length} given)`,
);
}*/
}
// Attempt to derive HD Private Node from the given seed.
const deriveResult = deriveHdPrivateNodeFromSeed(seed);
@@ -80,15 +72,15 @@ export class HDPrivateNode {
/**
* Creates a HD Private Node from the given mnemonic.
*
* @param mnemonic The mnemonic.
* @param phrase The mnemonic phrase as a string or array of words.
*
* @throws {Error} If HD Private Node cannot be created.
*
* @returns The created HD Private Node.
*/
public static fromMnemonic(mnemonic: string): HDPrivateNode {
public static fromMnemonic(phrase: string | Array<string>): HDPrivateNode {
// Derive the seed from the mnemonic.
const seed = deriveSeedFromBip39Mnemonic(mnemonic);
const seed = Mnemonic.from(phrase).toSeed();
// Return a new HDPrivateNode from the given seed.
return this.fromSeed(seed);
@@ -163,14 +155,74 @@ export class HDPrivateNode {
}
}
/**
* Returns the Private Key of this node (as a Uint8Array).
*
* @returns The Node's Private Key (as a Uint8Array).
*/
public toBytes(): Uint8Array {
// Encode the XPriv from our node info.
return this.node.privateKey;
}
/**
* Gets the Private Key entity for this node.
*
* @returns The Private Key Entity for this node.
*/
public privateKey(): PrivateKey {
public toPrivateKey(): PrivateKey {
// Return a Private Key Entity from the private key of our node.
return new PrivateKey(this.node.privateKey);
return PrivateKey.fromRaw(this.node.privateKey);
}
/**
* Converts this node to an XPriv Key for export.
*
* @param network {HdKeyNetwork} The network to encode for.
*
* @returns The XPriv Key.
*/
public toXPriv(network: HdKeyNetwork = 'mainnet'): string {
// Create our node info structure.
const nodeInfo: DecodedHdKey<HdPrivateNodeValid> = {
network: network,
node: this.node,
};
// Encode the XPriv from our node info.
return encodeHdPrivateKey(nodeInfo).hdPrivateKey;
}
/**
* Returns the XPriv string for this node.
*
* @returns The XPriv string for this node.
*/
public toString(): string {
// Return the Mainnet XPriv.
return this.toXPriv();
}
/**
* Returns the raw node data.
*
* @returns The raw node data.
*/
public toRaw(): HdPrivateNodeValid {
return this.node;
}
/**
* Derives a HD Public Node from this Private Node.
*
* @returns The derived HD Public Node
*/
public deriveHDPublicNode(): HDPublicNode {
// Derive a HD Public Node from this HD Private Node.
const publicNode = deriveHdPublicNode(this.node);
// Return a new HD Public Node entity from our derived Public Node.
return HDPublicNode.fromRaw(publicNode);
}
/**
@@ -216,64 +268,4 @@ export class HDPrivateNode {
// Return a new HD Private Node Entity derived from the given path.
return new HDPrivateNode(derivePathResult);
}
/**
* Derives a HD Public Node from this Private Node.
*
* @returns The derived HD Public Node
*/
public deriveHDPublicNode(): HDPublicNode {
// Derive a HD Public Node from this HD Private Node.
const publicNode = deriveHdPublicNode(this.node);
// Return a new HD Public Node entity from our derived Public Node.
return new HDPublicNode(publicNode);
}
/**
* Returns the Private Key of this node (as a Uint8Array).
*
* @returns The Node's Private Key (as a Uint8Array).
*/
public toBytes(): Uint8Array {
// Encode the XPriv from our node info.
return this.node.privateKey;
}
/**
* Converts this node to an XPriv Key for export.
*
* @param network {HdKeyNetwork} The network to encode for.
*
* @returns The XPriv Key.
*/
public toXPriv(network: HdKeyNetwork = 'mainnet'): string {
// Create our node info structure.
const nodeInfo: DecodedHdKey<HdPrivateNodeValid> = {
network: network,
node: this.node,
};
// Encode the XPriv from our node info.
return encodeHdPrivateKey(nodeInfo).hdPrivateKey;
}
/**
* Returns the XPriv string for this node.
*
* @returns The XPriv string for this node.
*/
public toString(): string {
// Return the Mainnet XPriv.
return this.toXPriv();
}
/**
* Returns the raw node data.
*
* @returns The raw node data.
*/
public toRaw(): HdPrivateNodeValid {
return this.node;
}
}
+48 -35
View File
@@ -24,7 +24,7 @@ export class HDPublicNode {
*
* @param node {HdPublicNode} The HD Public Node.
*/
constructor(node: HdPublicNodeValid) {
protected constructor(node: HdPublicNodeValid) {
this.node = node;
}
@@ -50,6 +50,14 @@ export class HDPublicNode {
return new HDPublicNode(decodeResult.node);
}
/**
* Creates a HDPublicNode instance from a raw object representation (LibAuth's HdPublicNodeValid).
*
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param obj - LibAuth Object of type HdPublicNodeValid
* @returns A new HDPublicNode instance
*/
public static fromRaw(node: HdPublicNodeValid) {
return new this(node);
}
@@ -68,9 +76,46 @@ export class HDPublicNode {
*
* @returns The Public Key Entity for this node.
*/
public publicKey(): PublicKey {
public toPublicKey(): PublicKey {
// Return a Public Key Entity from the public key of our node.
return new PublicKey(this.node.publicKey);
return PublicKey.fromRaw(this.node.publicKey);
}
/**
* Converts this node to an XPub Key for export.
*
* @param network The network to encode for.
*
* @returns The XPub Key.
*/
public toXPub(network: HdKeyNetwork = 'mainnet'): string {
// Create our node info structure.
const nodeInfo = {
network: network,
node: this.node,
} as DecodedHdKey<HdPublicNodeValid>;
// Encode the XPub from our node info.
return encodeHdPublicKey(nodeInfo).hdPublicKey;
}
/**
* Returns the XPub string for this node.
*
* @returns {string} The XPub string for this node.
*/
public toString(): string {
// Return the Mainnet XPub.
return this.toXPub();
}
/**
* Converts the HDPublicKey to its raw Libauth representation (HDPublicNodeValid).
*
* @returns A LibAuth HDPublicNodeValid object
*/
public toRaw(): HdPublicNodeValid {
return { ...this.node };
}
/**
@@ -94,36 +139,4 @@ export class HDPublicNode {
// Return a new HD Public Node Entity derived from the given path.
return new HDPublicNode(derivePathResult);
}
/**
* Converts this node to an XPub Key for export.
*
* @param network The network to encode for.
*
* @returns The XPub Key.
*/
public toXPub(network: HdKeyNetwork = 'mainnet'): string {
// Create our node info structure.
const nodeInfo = {
network: network,
node: this.node,
} as DecodedHdKey<HdPublicNodeValid>;
// Encode the XPub from our node info.
return encodeHdPublicKey(nodeInfo).hdPublicKey;
}
public toRaw(): HdPublicNodeValid {
return this.node;
}
/**
* Returns the XPub string for this node.
*
* @returns {string} The XPub string for this node.
*/
public toString(): string {
// Return the Mainnet XPub.
return this.toXPub();
}
}
-1
View File
@@ -2,7 +2,6 @@ export * from './address.js';
export * from './block-header.js';
export * from './bytes.js';
export * from './ext-json.js';
export * from './hasher.js';
export * from './hd-private-node.js';
export * from './hd-public-node.js';
export * from './mnemonic.js';
+34 -12
View File
@@ -1,6 +1,7 @@
import {
generateBip39MnemonicNonStandard,
bip39WordListEnglish,
deriveSeedFromBip39Mnemonic,
generateBip39MnemonicNonStandard,
} from '@bitauth/libauth';
export type MnemonicRaw = {
@@ -20,16 +21,19 @@ export class Mnemonic {
*
* @param phrase The complete phrase (mnemonic words + optional passphrase).
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
*
* @throws {Error} If the mnemonic is invalid.
*/
constructor(private mnemonic: MnemonicRaw) {}
protected constructor(private mnemonic: MnemonicRaw) {}
/**
* Instantiates a mnemonic from a string or array of words
*
* @param phraseOrWords The mnemonic phrase as a string or array of words
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
*
* @throws {Error} If mnemonic could not be generated.
*
* @returns Instance of Mnemonic.
*/
public static from(
@@ -41,18 +45,20 @@ export class Mnemonic {
return this.fromWords(phraseOrWords, wordList);
}
return this.fromString(phraseOrWords, wordList);
return this.fromPhrase(phraseOrWords, wordList);
}
/**
* Instantiates a mnemonic from a string
*
* @param phrase The mnemonic phrase as a string
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
*
* @throws {Error} If mnemonic could not be generated.
*
* @returns Instance of Mnemonic.
*/
public static fromString(
public static fromPhrase(
phrase: string,
wordList: Array<string> = bip39WordListEnglish,
) {
@@ -69,8 +75,10 @@ export class Mnemonic {
* Instantiates a mnemonic from an array of words.
*
* @param words Array of words (strings) that represent the mnemonic
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
*
* @throws {Error} If mnemonic could not be generated.
*
* @returns Instance of Mnemonic.
*/
public static fromWords(
@@ -133,6 +141,7 @@ export class Mnemonic {
*
* @param mnemonicRaw The raw menmonic data.
* @throws {Error} If mnemonic could not be generated.
*
* @returns Instance of Mnemonic.
*/
public static fromRaw(mnemonicRaw: MnemonicRaw) {
@@ -144,6 +153,7 @@ export class Mnemonic {
*
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
* @throws {Error} If mnemonic could not be generated.
*
* @returns Instance of Mnemonic.
*/
public static generateRandom(
@@ -173,6 +183,7 @@ export class Mnemonic {
*
* @param phraseOrWords The mnemonic phrase or words to validate.
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
*
* @returns boolean indicating if the phrase is valid.
*/
public static isValid(
@@ -192,6 +203,7 @@ export class Mnemonic {
*
* @param word Word to check.
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
*
* @returns boolean indicating if the word is valid.
*/
public static isValidWord(
@@ -202,21 +214,22 @@ export class Mnemonic {
}
/**
* Gets the passphrase if one exists.
* Returns the resulting seed for this mnemonic.
*
* @returns The passphrase or undefined if none exists.
* @returns The seed (for use with HDPrivateNodes).
*/
public getPassphrase(): string | undefined {
return this.mnemonic.passphrase;
public toSeed(): Uint8Array {
return deriveSeedFromBip39Mnemonic(this.toPhrase());
}
/**
* Returns the complete phrase as a string.
*
* @param includePassphrase Whether to include the passphrase in the output.
*
* @returns Complete phrase as a string.
*/
public toString(includePassphrase: boolean = true): string {
public toPhrase(includePassphrase: boolean = true): string {
// Join the menmonic words, separating them using a space character.
const mnemonicWords = this.mnemonic.words.join(' ');
@@ -252,4 +265,13 @@ export class Mnemonic {
public toRaw(): MnemonicRaw {
return { ...this.mnemonic };
}
/**
* Gets the passphrase if one exists.
*
* @returns The passphrase or undefined if none exists.
*/
public getPassphrase(): string | undefined {
return this.mnemonic.passphrase;
}
}
+87 -44
View File
@@ -32,7 +32,7 @@ export class PrivateKey {
*
* @param bytes {Uint8Array} The raw bytes (32) for the Private Key.
*/
constructor(bytes: Uint8Array) {
protected constructor(bytes: Uint8Array) {
// Ensure that the Private Key is valid.
if (!secp256k1.validatePrivateKey(bytes)) {
throw new Error(
@@ -43,6 +43,27 @@ export class PrivateKey {
this.bytes = bytes;
}
/**
* Instantiates a Private Key from either Bytes, Hex or WIF.
*
* @param privateKey The private key as either Bytes, Hex or WIF.
*
* @throws {Error} If the private key cannot be decoded.
*
* @returns The created Private Key Primitive.
*/
public static from(privateKey: Uint8Array | string) {
if (privateKey instanceof Uint8Array) {
return PrivateKey.fromBytes(privateKey);
}
if (PrivateKey.isWIF(privateKey)) {
return PrivateKey.fromWIF(privateKey);
}
return PrivateKey.fromHex(privateKey);
}
/**
* Create a Private Key Entity from the given bytes.
*
@@ -124,6 +145,19 @@ export class PrivateKey {
return new PrivateKey(decodeResult.privateKey);
}
/**
* Creates an instance from serialized data.
*
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param bytes - Serialized Primitive Data
*
* @returns A new instance of this primitive.
*/
public static fromRaw(bytes: Uint8Array) {
return new this(bytes);
}
/**
* Generate a random Private Key.
*
@@ -144,6 +178,57 @@ export class PrivateKey {
}
}
/**
* Convert the raw bytes of this Private Key to hexadecimal encoding.
*
* @returns {string} The raw bytes of the Private Key as a hexadecimal string.
*/
public toHex(): string {
// Return the hexadecimal encoded bytes of this Private Key.
return binToHex(this.bytes);
}
/**
* Convert this Private Key to a raw 32 byte representation.
*
* @returns {Uint8Array} The raw Private Key as a Uint8Array.
*/
public toBytes(): Uint8Array {
// Return the raw bytes for this Private Key.
return this.bytes;
}
/**
* Convert this Private Key to a WIF format.
*
* @param type {WalletImportFormatType} The type of WIF to create.
*
* @returns {string} The Private Key in WIF format.
*/
public toWif(type: WalletImportFormatType = 'mainnet'): string {
// Return the encoded Private Key WIF.
return encodePrivateKeyWif(this.bytes, type);
}
/**
* Returns the Private Key as a mainnet WIF.
*
* @returns {string} The Private Key as a mainnet WIF.
*/
public toString(): string {
// Return the encoded Mainnet Private Key WIF.
return this.toWif();
}
/**
* Converts this primitive to a serializable raw object representation.
*
* @returns Serialzied primitive data.
*/
toRaw() {
return this.bytes;
}
/**
* Derive the public key from this private key.
*
@@ -161,7 +246,7 @@ export class PrivateKey {
}
// Return the derived Public Key.
return new PublicKey(deriveResult);
return PublicKey.fromRaw(deriveResult);
}
/**
@@ -406,46 +491,4 @@ export class PrivateKey {
// Return the signature.
return signResult;
}
/**
* Convert the raw bytes of this Private Key to hexadecimal encoding.
*
* @returns {string} The raw bytes of the Private Key as a hexadecimal string.
*/
public toHex(): string {
// Return the hexadecimal encoded bytes of this Private Key.
return binToHex(this.bytes);
}
/**
* Convert this Private Key to a raw 32 byte representation.
*
* @returns {Uint8Array} The raw Private Key as a Uint8Array.
*/
public toBytes(): Uint8Array {
// Return the raw bytes for this Private Key.
return this.bytes;
}
/**
* Convert this Private Key to a WIF format.
*
* @param type {WalletImportFormatType} The type of WIF to create.
*
* @returns {string} The Private Key in WIF format.
*/
public toWif(type: WalletImportFormatType = 'mainnet'): string {
// Return the encoded Private Key WIF.
return encodePrivateKeyWif(this.bytes, type);
}
/**
* Returns the Private Key as a mainnet WIF.
*
* @returns {string} The Private Key as a mainnet WIF.
*/
public toString(): string {
// Return the encoded Mainnet Private Key WIF.
return this.toWif();
}
}
+72 -35
View File
@@ -22,15 +22,25 @@ export class PublicKey {
*
* @param bytes The raw bytes (33) for the Public Key.
*/
constructor(bytes: Uint8Array) {
// Ensure that exactly 33 Bytes are given.
if (!secp256k1.validatePublicKey(bytes)) {
throw new Error(`Invalid Public Key.`);
}
protected constructor(bytes: Uint8Array) {
this.bytes = bytes;
}
/**
* Instantiates a Public Key from either Public Key Hex or Public Key Bytes.
*
* @param publicKey The public key in either hex or bytes.
*
* @throws {Error} If the public key cannot be decoded.
*
* @returns The created Public Key Primitive.
*/
public static from(publicKey: Uint8Array | string) {
return publicKey instanceof Uint8Array
? PublicKey.fromBytes(publicKey)
: PublicKey.fromHex(publicKey);
}
/**
* Create a Public Key entity from the given hexadecimal string.
*
@@ -41,6 +51,11 @@ export class PublicKey {
* @returns The created Public Key entity.
*/
public static fromBytes(publicKeyBytes: Uint8Array): PublicKey {
// Ensure that exactly 33 Bytes are given.
if (!secp256k1.validatePublicKey(publicKeyBytes)) {
throw new Error(`Invalid Public Key.`);
}
return new PublicKey(publicKeyBytes);
}
@@ -68,6 +83,57 @@ export class PublicKey {
return new PublicKey(publicKey);
}
/**
* Creates an instance from serialized data.
*
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param bytes - Serialized Primitive Data
*
* @returns A new instance of this primitive.
*/
public static fromRaw(bytes: Uint8Array) {
return new this(bytes);
}
/**
* Encode the raw bytes of this Public Key to a hexadecimal representation.
*
* @returns The raw bytes Public Key encoded as Hexadecimal.
*/
public toHex(): string {
return binToHex(this.bytes);
}
/**
* Get the raw bytes of this Public Key.
*
* @returns The raw bytes of the Public Key.
*/
public toBytes(): Uint8Array {
// Return the raw bytes for this Public Key.
return this.bytes;
}
/**
* Return the hexadecimal representation of the raw bytes of the Public Key.
*
* @returns The raw bytes of the Public Key as hexadecimal.
*/
public toString(): string {
// Return the raw Public Key byes encoded as a hexadecimal string.
return this.toHex();
}
/**
* Converts this primitive to a serializable representation.
*
* @returns Serialzied primitive data.
*/
toRaw() {
return this.bytes;
}
/**
* Derive the Hash160 for this Public Key.
*
@@ -212,33 +278,4 @@ export class PublicKey {
return validity;
}
/**
* Encode the raw bytes of this Public Key to a hexadecimal representation.
*
* @returns The raw bytes Public Key encoded as Hexadecimal.
*/
public toHex(): string {
return binToHex(this.bytes);
}
/**
* Get the raw bytes of this Public Key.
*
* @returns The raw bytes of the Public Key.
*/
public toBytes(): Uint8Array {
// Return the raw bytes for this Public Key.
return this.bytes;
}
/**
* Return the hexadecimal representation of the raw bytes of the Public Key.
*
* @returns The raw bytes of the Public Key as hexadecimal.
*/
public toString(): string {
// Return the raw Public Key byes encoded as a hexadecimal string.
return this.toHex();
}
}
+3 -1
View File
@@ -1,3 +1,5 @@
export type BCHUnits = ['sats', 'bits', 'mBCH', 'BCH'];
/**
* Satoshis Primitive
*/
@@ -11,7 +13,7 @@ export class Satoshis {
*
* @param satoshis {number} The satoshi amount.
*/
constructor(satoshis: bigint | number) {
protected constructor(satoshis: bigint | number) {
// Set the satoshi amount.
this.satoshis = BigInt(satoshis);
}
+18 -44
View File
@@ -1,12 +1,9 @@
import {
assembleBytecodeBCH,
disassembleBytecodeBCH,
base58AddressToLockingBytecode,
cashAddressToLockingBytecode,
binToHex,
hexToBin,
isHex,
parseScript,
} from '@bitauth/libauth';
/**
@@ -20,14 +17,29 @@ export class Script {
*
* @param bytes {Uint8Array} The raw bytes of the Script.
*/
constructor(bytes: Uint8Array) {
protected constructor(bytes: Uint8Array) {
this.bytes = bytes;
}
/**
* Create a Script Entity from the given Assembly String.
* Instantiates a Script from either Bytes or Hex.
*
* @param asm {string} String of assembly code.
* @param script The script as either Bytes or Hex.
*
* @throws {Error} If the script cannot be decoded.
*
* @returns The created Script Primitive.
*/
public static from(script: Uint8Array | string) {
return script instanceof Uint8Array
? Script.fromBytes(script)
: Script.fromHex(script);
}
/**
* Create a Script Entity from bytes.
*
* @param bytes {string} Script Bytecode
*
* @throws {Error} If script cannot be decoded.
*
@@ -86,44 +98,6 @@ export class Script {
return new Script(scriptBin);
}
/**
* Create a Script Entity from the given CashAddr.
*
* @param cashAddr {string} The Address in CashAddr format.
*
* @throws {Error} If address cannot be decoded.
*
* @returns {Script} The created Script Entity.
*/
public static fromCashAddr(cashAddr: string): Script {
const decodeResult = cashAddressToLockingBytecode(cashAddr);
if (typeof decodeResult === 'string') {
throw new Error(decodeResult);
}
return new Script(decodeResult.bytecode);
}
/**
* Create a Script Entity from the given Legacy Address.
*
* @param legacyAddress {string} The Address in Legacy format.
*
* @throws {Error} If address cannot be decoded.
*
* @returns {Script} The created Script Entity.
*/
public static fromLegacyAddress(legacyAddress: string): Script {
const decodeResult = base58AddressToLockingBytecode(legacyAddress);
if (typeof decodeResult === 'string') {
throw new Error(decodeResult);
}
return new Script(decodeResult.bytecode);
}
/**
* Convert this script to a human-readable string of assembly.
*
+68 -3
View File
@@ -11,7 +11,35 @@ export class TransactionHash {
*
* @param bytes {Uint8Array} The Transaction Hash's bytes.
*/
constructor(bytes: Uint8Array) {
protected constructor(bytes: Uint8Array) {
this.bytes = bytes;
}
/**
* Instantiates a TransactionHash from either the Hash Hex or Hash Bytes.
*
* @param hash The Transaction Hash as either hex or bytes.
*
* @throws {Error} If the hash is invalid.
*
* @returns The created Public Key Primitive.
*/
public static from(hash: Uint8Array | string) {
return hash instanceof Uint8Array
? TransactionHash.fromBytes(hash)
: TransactionHash.fromHex(hash);
}
/**
* Instantiates TransactionHash from Hash Bytes.
*
* @param bytes The hash as bytes.
*
* @throws {Error} If hash is invalid.
*
* @returns {TransactionHash} Instance of TransactionHash.
*/
public static fromBytes(bytes: Uint8Array): TransactionHash {
// If bytes is not exactly 32, then this is an invalid transaction hash...
if (bytes.length !== 32) {
throw new Error(
@@ -19,7 +47,7 @@ export class TransactionHash {
);
}
this.bytes = bytes;
return new TransactionHash(bytes);
}
/**
@@ -38,7 +66,22 @@ export class TransactionHash {
const bytes = hexToBin(hex);
return new TransactionHash(bytes);
return this.fromBytes(bytes);
}
/**
* Instantiates a TransactionHash from either the Transaction Hex or Transaction Hash.
*
* @param hash The Transaction as either hex or bytes.
*
* @throws {Error} If the public key cannot be decoded.
*
* @returns The created Public Key Primitive.
*/
public static fromTransaction(transaction: Uint8Array | string) {
return transaction instanceof Uint8Array
? TransactionHash.fromTransactionBytes(transaction)
: TransactionHash.fromTransactionHex(transaction);
}
/**
@@ -75,6 +118,19 @@ export class TransactionHash {
return TransactionHash.fromTransactionBytes(bytes);
}
/**
* Creates an instance from serialized data.
*
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param bytes - Serialized Primitive Data
*
* @returns A new instance of this primitive.
*/
public static fromRaw(bytes: Uint8Array) {
return new this(bytes);
}
/**
* Returns transaction hash as a hex string.
*
@@ -92,4 +148,13 @@ export class TransactionHash {
public toBytes(): Uint8Array {
return this.bytes;
}
/**
* Converts this primitive to a serializable representation.
*
* @returns Serialzied primitive data.
*/
toRaw() {
return this.bytes;
}
}
+68 -16
View File
@@ -13,7 +13,7 @@ import type { TransactionBCH } from '@bitauth/libauth';
* Transaction Primitive.
*/
export class Transaction {
constructor(public transaction: TransactionBCH) {}
protected constructor(public transaction: TransactionBCH) {}
/**
* Instantiates a transaction from either:
@@ -28,19 +28,9 @@ export class Transaction {
* @returns The created Transaction Primitive.
*/
public static from(transaction: Uint8Array | string) {
// Handle string (hex) case
if (typeof transaction === 'string') {
return Transaction.fromHex(transaction);
}
// Handle Uint8Array case
if (transaction instanceof Uint8Array) {
return Transaction.fromBytes(transaction);
}
throw new TypeError(
'Invalid transaction input type. Expected Uint8Array, or hex string',
);
return transaction instanceof Uint8Array
? Transaction.fromBytes(transaction)
: Transaction.fromHex(transaction);
}
/**
@@ -90,7 +80,7 @@ export class Transaction {
/**
* Create a Transaction Primitive from LibAuth's TransactionBCH type.
*
* @remarks This method is UNSAFE and should only be used where input is trusted.
* @remarks This method is UNSAFE and MUST only be used where input is already verified or trusted.
*
* @param transaction The transaction object (as per LibAuth).
*
@@ -104,6 +94,7 @@ export class Transaction {
* Validates the structure of a transaction.
*
* @param transaction The transaction (as hex or bytes).
*
* @returns boolean indicating whether the transaction structure is valid.
*/
public static isValid(transaction: Uint8Array | string): boolean {
@@ -116,34 +107,67 @@ export class Transaction {
return true;
}
/**
* Serializes the transaction to a byte array.
* @returns The transaction serialized as a Uint8Array
*/
public toBytes(): Uint8Array {
const bytes = encodeTransaction(this.transaction);
return bytes;
}
/**
* Serializes the transaction to a byte array (represented as a hex string).
* @returns The transaction serialized in hex
*/
public toHex(): string {
const bytes = this.toBytes();
return binToHex(bytes);
}
/**
* Hashes the transaction and returns a TransactionHash primitive.
* @returns The transaction hash primitive.
*/
public toHash(): TransactionHash {
return TransactionHash.fromTransactionBytes(this.toBytes());
}
/**
* Hashes the transaction and returns the hash as hexadecimal.
* @returns The transaction hash hex.
*/
public toHashHex(): string {
return this.toHash().toHex();
}
/**
* Hashes the transaction and returns the hash as a Uint8Array.
* @returns The transaction hash bytes.
*/
public toHashBytes(): Uint8Array {
return this.toHash().toBytes();
}
/**
* Converts transaction to a raw object representation.
* @returns A TransactionBCH LibAuth object.
*/
public toRaw(): TransactionBCH {
return this.transaction;
return { ...this.transaction };
}
/**
* Checks whether this transaction is a Coinbase Transaction.
*
* @remarks UNTESTED
*
* @experimental
*
* @returns True if this is a Coinbase Transaction
*/
public isCoinbase(): boolean {
// A coinbase transaction MUST only have one input
if (this.getInputs().length !== 1) {
@@ -164,18 +188,46 @@ export class Transaction {
return isOutpointZero && isOutpointIndexMax;
}
/**
* Gets the version for this transaction.
*
* @experimental
*
* @returns The version of this transaction
*/
public getVersion() {
return this.transaction.version;
}
/**
* Gets the inputs in this transaction.
*
* @experimental
*
* @returns The inputs in this transaction
*/
public getInputs() {
return this.transaction.inputs;
}
/**
* Gets the outputs in this transaction.
*
* @experimental
*
* @returns The outputs in this transaction
*/
public getOutputs() {
return this.transaction.outputs;
}
/**
* Gets the locktime for this transaction.
*
* @experimental
*
* @returns The locktime of this transaction
*/
public getLocktime() {
return this.transaction.locktime;
}