Merge branch 'primitive_amendments' into 'development'
Amend Primitives/Tooling See merge request GeneralProtocols/xo/stack!17
This commit is contained in:
@@ -129,7 +129,6 @@ export default defineConfig({
|
|||||||
link: '/tools/primitives#block-header',
|
link: '/tools/primitives#block-header',
|
||||||
},
|
},
|
||||||
{ text: 'Bytes', link: '/tools/primitives#bytes' },
|
{ text: 'Bytes', link: '/tools/primitives#bytes' },
|
||||||
{ text: 'Hasher', link: '/tools/primitives#hasher' },
|
|
||||||
{
|
{
|
||||||
text: 'HD Private Node',
|
text: 'HD Private Node',
|
||||||
link: '/tools/primitives#hd-private-node',
|
link: '/tools/primitives#hd-private-node',
|
||||||
@@ -164,18 +163,35 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
text: 'Stack',
|
text: 'Stack',
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
items: [
|
items: [
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
text: 'Blockchain',
|
text: 'Blockchain',
|
||||||
items: [{ text: 'Blockchain Electrum' }],
|
link: '/tools/stack/blockchain',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Electrum',
|
||||||
|
link: '/tools/stack/blockchain#encryption',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
{
|
||||||
|
text: 'Utils',
|
||||||
|
link: '/tools/stack/utils',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Encrypter',
|
||||||
|
link: '/tools/stack/utils#encrypter',
|
||||||
|
},
|
||||||
|
{ text: 'Hasher', link: '/tools/stack/utils#hasher' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ body {
|
|||||||
.vp-doc h4 {
|
.vp-doc h4 {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
|
color: var(--primary);
|
||||||
|
padding-top: 3em;
|
||||||
|
border-top: 1px solid var(--vp-c-text-1);
|
||||||
|
margin-top: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.VPSidebarItem .text {
|
.VPSidebarItem .text {
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import {
|
|||||||
Bytes,
|
Bytes,
|
||||||
encodeExtendedJson,
|
encodeExtendedJson,
|
||||||
decodeExtendedJson,
|
decodeExtendedJson,
|
||||||
Hasher,
|
// Encrypter,
|
||||||
|
// Hasher,
|
||||||
HDPrivateNode,
|
HDPrivateNode,
|
||||||
HDPublicNode,
|
HDPublicNode,
|
||||||
Mnemonic,
|
Mnemonic,
|
||||||
@@ -116,10 +117,10 @@ export const address = {
|
|||||||
export const blockHeader = {
|
export const blockHeader = {
|
||||||
from: [
|
from: [
|
||||||
{
|
{
|
||||||
label: 'From Hex',
|
label: 'From',
|
||||||
inputs: ['UTF-8'],
|
inputs: ['Hex'],
|
||||||
models: [''],
|
models: [''],
|
||||||
callback: (args: [string]) => BlockHeader.fromHex(...args),
|
callback: (args: [string]) => BlockHeader.from(...args),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
to: [
|
to: [
|
||||||
@@ -193,67 +194,30 @@ export const bytes = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hasher = {
|
|
||||||
from: [
|
|
||||||
{
|
|
||||||
label: 'From Hex',
|
|
||||||
inputs: ['Hex'],
|
|
||||||
models: [''],
|
|
||||||
callback: (args: [string]) => Hasher.fromHex(...args),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'From Base64',
|
|
||||||
inputs: ['Base64'],
|
|
||||||
models: [''],
|
|
||||||
callback: (args: [string]) => Hasher.fromBase64(...args),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'From UTF-8',
|
|
||||||
inputs: ['UTF-8'],
|
|
||||||
models: [''],
|
|
||||||
callback: (args: [string]) => Hasher.fromUTF8(...args),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
to: [
|
|
||||||
{
|
|
||||||
label: 'To Sha256 Hex',
|
|
||||||
callback: (hasher: Hasher) => hasher.toSHA256Hex(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'To RipeMD160 Hex',
|
|
||||||
callback: (hasher: Hasher) => hasher.toRIPEMD160Hex(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'To Hash160 Hex',
|
|
||||||
callback: (hasher: Hasher) => hasher.toHash160Hex(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'To Hash256 Hex',
|
|
||||||
callback: (hasher: Hasher) => hasher.toHash256Hex(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const hdPrivateNode = {
|
export const hdPrivateNode = {
|
||||||
from: [
|
from: [
|
||||||
{
|
{
|
||||||
label: 'Generate Random',
|
label: 'Generate Random',
|
||||||
inputs: ['Derivation Path'],
|
|
||||||
models: ["m/44'/145'/0'/0/1"],
|
|
||||||
callback: () => HDPrivateNode.generateRandom(),
|
callback: () => HDPrivateNode.generateRandom(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'From Mnemonic',
|
label: 'From Mnemonic Phrase',
|
||||||
inputs: ['Mnemonic', 'Derivation Path'],
|
inputs: ['Mnemonic'],
|
||||||
models: ['', "m/44'/145'/0'/0/1"],
|
models: [''],
|
||||||
callback: (args: [string]) => HDPrivateNode.fromMnemonic(...args),
|
callback: (args: [string]) => HDPrivateNode.fromMnemonic(...args),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'From XPriv Key',
|
label: 'From XPriv Key',
|
||||||
inputs: ['XPriv Key', 'Derivation Path'],
|
inputs: ['XPriv Key'],
|
||||||
models: ['', "m/44'/145'/0'/0/1"],
|
models: [''],
|
||||||
callback: (args: [string]) => HDPrivateNode.fromXPriv(...args),
|
callback: (args: [string]) => HDPrivateNode.fromXPriv(...args),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'From Seed',
|
||||||
|
inputs: ['Seed (Hex)'],
|
||||||
|
models: [''],
|
||||||
|
callback: (args: [string]) => HDPrivateNode.fromSeed(...args),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'From Raw',
|
label: 'From Raw',
|
||||||
inputs: ['Raw (LibAuth Format/ExtJSON Encoded)'],
|
inputs: ['Raw (LibAuth Format/ExtJSON Encoded)'],
|
||||||
@@ -283,6 +247,18 @@ export const hdPrivateNode = {
|
|||||||
hdPrivateNode.deriveHDPublicNode().toXPub(),
|
hdPrivateNode.deriveHDPublicNode().toXPub(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
methods: [
|
||||||
|
{
|
||||||
|
label: 'Derive Path',
|
||||||
|
inputs: ['BIP32 Path'],
|
||||||
|
models: ["m/44'/145'/0'/0/0"],
|
||||||
|
callback: (hdPrivateNode: HDPrivateNode, args: [string]) =>
|
||||||
|
hdPrivateNode
|
||||||
|
.derivePath(...args)
|
||||||
|
.toPrivateKey()
|
||||||
|
.toWif(),
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hdPublicNode = {
|
export const hdPublicNode = {
|
||||||
@@ -317,30 +293,50 @@ export const hdPublicNode = {
|
|||||||
encodeExtendedJson(hdPublicNode.toRaw(), 2),
|
encodeExtendedJson(hdPublicNode.toRaw(), 2),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
methods: [
|
||||||
|
{
|
||||||
|
label: 'Derive Path',
|
||||||
|
inputs: ['BIP32 Public Key Path'],
|
||||||
|
models: ['M/0/0'],
|
||||||
|
callback: (hdPublicNode: HDPublicNode, args: [string]) =>
|
||||||
|
hdPublicNode
|
||||||
|
.derivePath(...args)
|
||||||
|
.toPublicKey()
|
||||||
|
.deriveAddress()
|
||||||
|
.toCashAddr(),
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mnemonic = {
|
export const mnemonic = {
|
||||||
from: [
|
from: [
|
||||||
{
|
{
|
||||||
label: 'Generate Random',
|
label: 'Generate Random',
|
||||||
callback: () => Mnemonic.generateRandom(),
|
inputs: ['Passphrase (Optional)'],
|
||||||
|
models: [undefined],
|
||||||
|
callback: (args: [string?]) => Mnemonic.generateRandom(...args),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'From String',
|
label: 'From Phrase',
|
||||||
inputs: ['String'],
|
inputs: ['Mnemonic Phrase'],
|
||||||
models: [''],
|
models: [''],
|
||||||
callback: (args: [string]) => Mnemonic.fromString(...args),
|
callback: (args: [string]) => Mnemonic.fromPhrase(...args),
|
||||||
extendedInput: true,
|
extendedInput: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
to: [
|
to: [
|
||||||
{
|
{
|
||||||
label: 'To String (without passphrase)',
|
label: 'To Seed',
|
||||||
callback: (mnemonic: Mnemonic) => mnemonic.toString(false),
|
callback: (mnemonic: Mnemonic) =>
|
||||||
|
Bytes.fromBytes(mnemonic.toSeed()).toHex(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'To String (with passphrase)',
|
label: 'To Phrase (without passphrase)',
|
||||||
callback: (mnemonic: Mnemonic) => mnemonic.toString(true),
|
callback: (mnemonic: Mnemonic) => mnemonic.toPhrase(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'To Phrase (with passphrase)',
|
||||||
|
callback: (mnemonic: Mnemonic) => mnemonic.toPhrase(true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Words',
|
label: 'Words',
|
||||||
@@ -361,16 +357,10 @@ export const privateKey = {
|
|||||||
callback: () => PrivateKey.generateRandom(),
|
callback: () => PrivateKey.generateRandom(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'From Hex',
|
label: 'From Hex or WIF',
|
||||||
inputs: ['Hex'],
|
inputs: ['Hex or WIF'],
|
||||||
models: [''],
|
models: [''],
|
||||||
callback: (args: [string]) => PrivateKey.fromHex(...args),
|
callback: (args: [string]) => PrivateKey.from(...args),
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'From WIF',
|
|
||||||
inputs: ['WIF'],
|
|
||||||
models: [''],
|
|
||||||
callback: (args: [string]) => PrivateKey.fromWIF(...args),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
to: [
|
to: [
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {
|
|||||||
address,
|
address,
|
||||||
blockHeader,
|
blockHeader,
|
||||||
bytes,
|
bytes,
|
||||||
hasher,
|
|
||||||
hdPrivateNode,
|
hdPrivateNode,
|
||||||
hdPublicNode,
|
hdPublicNode,
|
||||||
mnemonic,
|
mnemonic,
|
||||||
@@ -58,18 +57,6 @@ import {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Hasher
|
|
||||||
|
|
||||||
<div class="tool">
|
|
||||||
<p>A utility tool for computing various cryptographic hashes commonly used in Bitcoin Cash.</p>
|
|
||||||
|
|
||||||
<PrimitiveToolVue
|
|
||||||
:fromFunctions="hasher.from"
|
|
||||||
:toFunctions="hasher.to"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## HD Private Node
|
## HD Private Node
|
||||||
|
|
||||||
<div class="tool">
|
<div class="tool">
|
||||||
@@ -78,6 +65,7 @@ import {
|
|||||||
<PrimitiveToolVue
|
<PrimitiveToolVue
|
||||||
:fromFunctions="hdPrivateNode.from"
|
:fromFunctions="hdPrivateNode.from"
|
||||||
:toFunctions="hdPrivateNode.to"
|
:toFunctions="hdPrivateNode.to"
|
||||||
|
:methods="hdPrivateNode.methods"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -90,6 +78,7 @@ import {
|
|||||||
<PrimitiveToolVue
|
<PrimitiveToolVue
|
||||||
:fromFunctions="hdPublicNode.from"
|
:fromFunctions="hdPublicNode.from"
|
||||||
:toFunctions="hdPublicNode.to"
|
:toFunctions="hdPublicNode.to"
|
||||||
|
:methods="hdPublicNode.methods"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import { Bytes } from '@xocash/primitives';
|
import { Bytes } from '@xocash/primitives';
|
||||||
|
import { Encrypter, Hasher } from '@xocash/stack';
|
||||||
|
|
||||||
import { Encryption } from '@xocash/stack';
|
export const encrypter = {
|
||||||
|
|
||||||
export const encryption = {
|
|
||||||
from: [
|
from: [
|
||||||
{
|
{
|
||||||
label: 'From Passphrase',
|
label: 'From Passphrase',
|
||||||
inputs: ['Passphrase'],
|
inputs: ['Passphrase'],
|
||||||
models: [''],
|
models: [''],
|
||||||
callback: (args: [string]) => Encryption.fromPassphrase(...args),
|
callback: (args: [string]) => Encrypter.fromPassphrase(...args),
|
||||||
extendedInput: true,
|
extendedInput: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -18,17 +17,58 @@ export const encryption = {
|
|||||||
label: 'Encrypt',
|
label: 'Encrypt',
|
||||||
inputs: ['UTF8'],
|
inputs: ['UTF8'],
|
||||||
models: ['Your text here'],
|
models: ['Your text here'],
|
||||||
callback: async (encryption: Encryption, args: [string]) =>
|
callback: async (encrypter: Encrypter, args: [string]) =>
|
||||||
Bytes.fromBytes(await encryption.encrypt(...args)).toHex(),
|
Bytes.fromBytes(await encrypter.encrypt(...args)).toHex(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Decrypt',
|
label: 'Decrypt',
|
||||||
inputs: ['Hex'],
|
inputs: ['Hex'],
|
||||||
models: ['Encrypted Data (hex)'],
|
models: ['Encrypted Data (hex)'],
|
||||||
callback: async (encryption: Encryption, args: [string]) =>
|
callback: async (encrypter: Encrypter, args: [string]) =>
|
||||||
Bytes.fromBytes(
|
Bytes.fromBytes(
|
||||||
await encryption.decrypt(Bytes.fromHex(...args).toBytes()),
|
await encrypter.decrypt(Bytes.fromHex(...args).toBytes()),
|
||||||
).toUtf8(),
|
).toUtf8(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const hasher = {
|
||||||
|
from: [
|
||||||
|
{
|
||||||
|
label: 'From Hex',
|
||||||
|
inputs: ['Hex'],
|
||||||
|
models: [''],
|
||||||
|
callback: (args: [string]) => Hasher.fromHex(...args),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'From Base64',
|
||||||
|
inputs: ['Base64'],
|
||||||
|
models: [''],
|
||||||
|
callback: (args: [string]) => Hasher.fromBase64(...args),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'From UTF-8',
|
||||||
|
inputs: ['UTF-8'],
|
||||||
|
models: [''],
|
||||||
|
callback: (args: [string]) => Hasher.fromUTF8(...args),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
label: 'To Sha256 Hex',
|
||||||
|
callback: (hasher: Hasher) => hasher.toSHA256Hex(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'To RipeMD160 Hex',
|
||||||
|
callback: (hasher: Hasher) => hasher.toRIPEMD160Hex(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'To Hash160 Hex',
|
||||||
|
callback: (hasher: Hasher) => hasher.toHash160Hex(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'To Hash256 Hex',
|
||||||
|
callback: (hasher: Hasher) => hasher.toHash256Hex(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import PrimitiveToolVue, { type FromFunction, type ToFunction } from '@theme/com
|
|||||||
|
|
||||||
// Import our tool functions
|
// Import our tool functions
|
||||||
import {
|
import {
|
||||||
encryption
|
encrypter,
|
||||||
|
hasher,
|
||||||
} from './utils-functions.ts'
|
} from './utils-functions.ts'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -11,15 +12,27 @@ import {
|
|||||||
|
|
||||||
# Utils
|
# Utils
|
||||||
|
|
||||||
## Encryption
|
## Encrypter
|
||||||
|
|
||||||
<div class="tool">
|
<div class="tool">
|
||||||
<p>A Utility tool for converting between different address formats.</p>
|
<p>A Utility tool for encrypting data using AES-GCM.</p>
|
||||||
|
<p>Additional parameters (Salt, Key Length, IV, etc) are available via the API.</p>
|
||||||
|
|
||||||
<PrimitiveToolVue
|
<PrimitiveToolVue
|
||||||
:fromFunctions="encryption.from"
|
:fromFunctions="encrypter.from"
|
||||||
:toFunctions="encryption.to"
|
:toFunctions="encrypter.to"
|
||||||
:methods="encryption.methods"
|
:methods="encrypter.methods"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Hasher
|
||||||
|
|
||||||
|
<div class="tool">
|
||||||
|
<p>A utility tool for computing various cryptographic hashes commonly used in Bitcoin Cash.</p>
|
||||||
|
|
||||||
|
<PrimitiveToolVue
|
||||||
|
:fromFunctions="hasher.from"
|
||||||
|
:toFunctions="hasher.to"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
**NOTE: This package is EXTREMELY UNSTABLE and WILL BREAK frequently. DO NOT USE.**
|
**NOTE: This package is EXTREMELY UNSTABLE and WILL BREAK frequently. DO NOT USE.**
|
||||||
|
|
||||||
A collection of useful BCH Primitives.
|
A collection of immutable primitives for use with BCH.
|
||||||
|
|||||||
@@ -18,13 +18,20 @@ import type { KnownAddressTypeContents } from '@bitauth/libauth';
|
|||||||
|
|
||||||
export type AddressType = 'P2PK' | 'P2PKH' | 'P2SH20' | 'P2SH32';
|
export type AddressType = 'P2PK' | 'P2PKH' | 'P2SH20' | 'P2SH32';
|
||||||
|
|
||||||
|
export const DEFAULT_ADDRESS_PREFIXES = [
|
||||||
|
'',
|
||||||
|
'bitcoincash',
|
||||||
|
'bchtest',
|
||||||
|
'bchreg',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address Entity.
|
* Address Entity.
|
||||||
*/
|
*/
|
||||||
export class Address {
|
export class Address {
|
||||||
public readonly addressContents: KnownAddressTypeContents;
|
public readonly addressContents: KnownAddressTypeContents;
|
||||||
|
|
||||||
constructor(addressContents: KnownAddressTypeContents) {
|
protected constructor(addressContents: KnownAddressTypeContents) {
|
||||||
this.addressContents = addressContents;
|
this.addressContents = addressContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,13 +44,16 @@ export class Address {
|
|||||||
*
|
*
|
||||||
* @returns {Address} Instance of 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.
|
// Attempt to decode as a Cash Address.
|
||||||
try {
|
try {
|
||||||
return Address.fromCashAddr(address);
|
return this.fromCashAddr(address, tryPrefixes);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
// And if that fails, attempt to decode as a Base58 Address.
|
// 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(
|
public static fromCashAddr(
|
||||||
cashAddr: string,
|
cashAddr: string,
|
||||||
tryPrefixes: Array<string> = ['', 'bitcoincash', 'bchtest', 'bchreg'],
|
tryPrefixes: Array<string> = DEFAULT_ADDRESS_PREFIXES,
|
||||||
): Address {
|
): Address {
|
||||||
// Try all prefixes (including empty string) until we find a valid decode
|
// Try all prefixes (including empty string) until we find a valid decode
|
||||||
const decodeResult = tryPrefixes
|
const decodeResult = tryPrefixes
|
||||||
@@ -158,7 +168,7 @@ export class Address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return a new instance of 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);
|
const contractBytecode = hexToBin(hex);
|
||||||
|
|
||||||
// Return a new instance of address.
|
// 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})`);
|
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);
|
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);
|
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) {
|
public static fromRaw(addressContents: KnownAddressTypeContents) {
|
||||||
return new this(addressContents);
|
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 {
|
try {
|
||||||
Address.from(address);
|
Address.from(address, tryPrefixes);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -284,6 +312,13 @@ export class Address {
|
|||||||
return true;
|
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 {
|
public static isValidLegacy(address: string): boolean {
|
||||||
try {
|
try {
|
||||||
Address.fromLegacy(address);
|
Address.fromLegacy(address);
|
||||||
@@ -294,9 +329,19 @@ export class Address {
|
|||||||
return true;
|
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 {
|
try {
|
||||||
Address.fromCashAddr(address);
|
Address.fromCashAddr(address, tryPrefixes);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -467,6 +512,11 @@ export class Address {
|
|||||||
return lockscriptAsm;
|
return lockscriptAsm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the address to its raw LibAuth representation (KnownAddressTypeContents).
|
||||||
|
*
|
||||||
|
* @returns A LibAuth KnownAddressTypeContents object.
|
||||||
|
*/
|
||||||
public toRaw() {
|
public toRaw() {
|
||||||
return { ...this.addressContents };
|
return { ...this.addressContents };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export class BlockHeader {
|
|||||||
* @param bits - Compact representation of the target threshold
|
* @param bits - Compact representation of the target threshold
|
||||||
* @param nonce - Value modified during mining to make the block hash valid
|
* @param nonce - Value modified during mining to make the block hash valid
|
||||||
*/
|
*/
|
||||||
constructor(
|
protected constructor(
|
||||||
private readonly version: number,
|
private readonly version: number,
|
||||||
private readonly previousBlockHash: Uint8Array,
|
private readonly previousBlockHash: Uint8Array,
|
||||||
private readonly merkleRoot: Uint8Array,
|
private readonly merkleRoot: Uint8Array,
|
||||||
@@ -33,6 +33,24 @@ export class BlockHeader {
|
|||||||
private readonly nonce: number,
|
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.
|
* Creates a BlockHeader instance from a byte array.
|
||||||
* @param bytes - 80-byte array containing the serialized block header
|
* @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.
|
* 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
|
* @param obj - Object containing the block header fields
|
||||||
* @returns A new BlockHeader instance
|
* @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.
|
* Serializes the block header to a byte array.
|
||||||
* @returns 80-byte array containing the serialized block header
|
* @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
|
* @returns Object containing the block header fields
|
||||||
*/
|
*/
|
||||||
toRaw(): BlockHeaderRaw {
|
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
|
// Getters
|
||||||
getVersion(): number {
|
getVersion(): number {
|
||||||
return this.version;
|
return this.version;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export class Bytes {
|
|||||||
*
|
*
|
||||||
* @param bytes {Uint8Array} The bytes to use.
|
* @param bytes {Uint8Array} The bytes to use.
|
||||||
*/
|
*/
|
||||||
constructor(bytes: Uint8Array) {
|
protected constructor(bytes: Uint8Array) {
|
||||||
this.bytes = bytes;
|
this.bytes = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
* TODO: These are intended as temporary stand-ins until this functionality has been implemented directly in LibAuth.
|
||||||
// See: https://github.com/bitauth/libauth/pull/108
|
* 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';
|
import { binToHex, hexToBin } from '@bitauth/libauth';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { Bytes } from './bytes.js';
|
||||||
import { HDPublicNode } from './hd-public-node.js';
|
import { HDPublicNode } from './hd-public-node.js';
|
||||||
|
import { Mnemonic } from './mnemonic.js';
|
||||||
import { PrivateKey } from './private-key.js';
|
import { PrivateKey } from './private-key.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -8,7 +10,6 @@ import {
|
|||||||
deriveHdPathRelative,
|
deriveHdPathRelative,
|
||||||
deriveHdPublicNode,
|
deriveHdPublicNode,
|
||||||
deriveHdPrivateNodeFromSeed,
|
deriveHdPrivateNodeFromSeed,
|
||||||
deriveSeedFromBip39Mnemonic,
|
|
||||||
generateRandomBytes,
|
generateRandomBytes,
|
||||||
} from '@bitauth/libauth';
|
} from '@bitauth/libauth';
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ export class HDPrivateNode {
|
|||||||
*
|
*
|
||||||
* @param node The HD Private Node.
|
* @param node The HD Private Node.
|
||||||
*/
|
*/
|
||||||
constructor(node: HdPrivateNodeValid) {
|
protected constructor(node: HdPrivateNodeValid) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,27 +44,18 @@ export class HDPrivateNode {
|
|||||||
*
|
*
|
||||||
* @returns The created HD Private Node.
|
* @returns The created HD Private Node.
|
||||||
*/
|
*/
|
||||||
public static fromBytes(seed: Uint8Array): HDPrivateNode {
|
public static fromSeed(seed: Uint8Array | string): HDPrivateNode {
|
||||||
// Return a new HD Private Node from the given seed.
|
// Cast from hex if a string was provided.
|
||||||
return this.fromSeed(seed);
|
if (typeof seed === 'string') {
|
||||||
|
seed = Bytes.fromHex(seed).toBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// If the seed is not 64 bytes, throw an error.
|
||||||
* Creates a HD Private Node from a raw seed.
|
if (seed.length !== 64) {
|
||||||
*
|
|
||||||
* @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) {
|
|
||||||
throw new Error(
|
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.
|
// Attempt to derive HD Private Node from the given seed.
|
||||||
const deriveResult = deriveHdPrivateNodeFromSeed(seed);
|
const deriveResult = deriveHdPrivateNodeFromSeed(seed);
|
||||||
@@ -80,15 +72,15 @@ export class HDPrivateNode {
|
|||||||
/**
|
/**
|
||||||
* Creates a HD Private Node from the given mnemonic.
|
* 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.
|
* @throws {Error} If HD Private Node cannot be created.
|
||||||
*
|
*
|
||||||
* @returns The created HD Private Node.
|
* @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.
|
// 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 a new HDPrivateNode from the given seed.
|
||||||
return this.fromSeed(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.
|
* Gets the Private Key entity for this node.
|
||||||
*
|
*
|
||||||
* @returns 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 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 a new HD Private Node Entity derived from the given path.
|
||||||
return new HDPrivateNode(derivePathResult);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export class HDPublicNode {
|
|||||||
*
|
*
|
||||||
* @param node {HdPublicNode} The HD Public Node.
|
* @param node {HdPublicNode} The HD Public Node.
|
||||||
*/
|
*/
|
||||||
constructor(node: HdPublicNodeValid) {
|
protected constructor(node: HdPublicNodeValid) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +50,14 @@ export class HDPublicNode {
|
|||||||
return new HDPublicNode(decodeResult.node);
|
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) {
|
public static fromRaw(node: HdPublicNodeValid) {
|
||||||
return new this(node);
|
return new this(node);
|
||||||
}
|
}
|
||||||
@@ -68,9 +76,46 @@ export class HDPublicNode {
|
|||||||
*
|
*
|
||||||
* @returns The Public Key Entity for this node.
|
* @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 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 a new HD Public Node Entity derived from the given path.
|
||||||
return new HDPublicNode(derivePathResult);
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ export * from './address.js';
|
|||||||
export * from './block-header.js';
|
export * from './block-header.js';
|
||||||
export * from './bytes.js';
|
export * from './bytes.js';
|
||||||
export * from './ext-json.js';
|
export * from './ext-json.js';
|
||||||
export * from './hasher.js';
|
|
||||||
export * from './hd-private-node.js';
|
export * from './hd-private-node.js';
|
||||||
export * from './hd-public-node.js';
|
export * from './hd-public-node.js';
|
||||||
export * from './mnemonic.js';
|
export * from './mnemonic.js';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
generateBip39MnemonicNonStandard,
|
|
||||||
bip39WordListEnglish,
|
bip39WordListEnglish,
|
||||||
|
deriveSeedFromBip39Mnemonic,
|
||||||
|
generateBip39MnemonicNonStandard,
|
||||||
} from '@bitauth/libauth';
|
} from '@bitauth/libauth';
|
||||||
|
|
||||||
export type MnemonicRaw = {
|
export type MnemonicRaw = {
|
||||||
@@ -20,16 +21,19 @@ export class Mnemonic {
|
|||||||
*
|
*
|
||||||
* @param phrase The complete phrase (mnemonic words + optional passphrase).
|
* @param phrase The complete phrase (mnemonic words + optional passphrase).
|
||||||
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
|
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
|
||||||
|
*
|
||||||
* @throws {Error} If the mnemonic is invalid.
|
* @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
|
* Instantiates a mnemonic from a string or array of words
|
||||||
*
|
*
|
||||||
* @param phraseOrWords The mnemonic phrase as 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.
|
* @throws {Error} If mnemonic could not be generated.
|
||||||
|
*
|
||||||
* @returns Instance of Mnemonic.
|
* @returns Instance of Mnemonic.
|
||||||
*/
|
*/
|
||||||
public static from(
|
public static from(
|
||||||
@@ -41,18 +45,20 @@ export class Mnemonic {
|
|||||||
return this.fromWords(phraseOrWords, wordList);
|
return this.fromWords(phraseOrWords, wordList);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.fromString(phraseOrWords, wordList);
|
return this.fromPhrase(phraseOrWords, wordList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a mnemonic from a string
|
* Instantiates a mnemonic from a string
|
||||||
*
|
*
|
||||||
* @param phrase The mnemonic phrase as 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.
|
* @throws {Error} If mnemonic could not be generated.
|
||||||
|
*
|
||||||
* @returns Instance of Mnemonic.
|
* @returns Instance of Mnemonic.
|
||||||
*/
|
*/
|
||||||
public static fromString(
|
public static fromPhrase(
|
||||||
phrase: string,
|
phrase: string,
|
||||||
wordList: Array<string> = bip39WordListEnglish,
|
wordList: Array<string> = bip39WordListEnglish,
|
||||||
) {
|
) {
|
||||||
@@ -69,8 +75,10 @@ export class Mnemonic {
|
|||||||
* Instantiates a mnemonic from an array of words.
|
* Instantiates a mnemonic from an array of words.
|
||||||
*
|
*
|
||||||
* @param words Array of words (strings) that represent the mnemonic
|
* @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.
|
* @throws {Error} If mnemonic could not be generated.
|
||||||
|
*
|
||||||
* @returns Instance of Mnemonic.
|
* @returns Instance of Mnemonic.
|
||||||
*/
|
*/
|
||||||
public static fromWords(
|
public static fromWords(
|
||||||
@@ -133,6 +141,7 @@ export class Mnemonic {
|
|||||||
*
|
*
|
||||||
* @param mnemonicRaw The raw menmonic data.
|
* @param mnemonicRaw The raw menmonic data.
|
||||||
* @throws {Error} If mnemonic could not be generated.
|
* @throws {Error} If mnemonic could not be generated.
|
||||||
|
*
|
||||||
* @returns Instance of Mnemonic.
|
* @returns Instance of Mnemonic.
|
||||||
*/
|
*/
|
||||||
public static fromRaw(mnemonicRaw: MnemonicRaw) {
|
public static fromRaw(mnemonicRaw: MnemonicRaw) {
|
||||||
@@ -144,6 +153,7 @@ export class Mnemonic {
|
|||||||
*
|
*
|
||||||
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
|
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
|
||||||
* @throws {Error} If mnemonic could not be generated.
|
* @throws {Error} If mnemonic could not be generated.
|
||||||
|
*
|
||||||
* @returns Instance of Mnemonic.
|
* @returns Instance of Mnemonic.
|
||||||
*/
|
*/
|
||||||
public static generateRandom(
|
public static generateRandom(
|
||||||
@@ -173,6 +183,7 @@ export class Mnemonic {
|
|||||||
*
|
*
|
||||||
* @param phraseOrWords The mnemonic phrase or words to validate.
|
* @param phraseOrWords The mnemonic phrase or words to validate.
|
||||||
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
|
* @param wordList Optional wordlist (defaults to English BIP-39 wordlist).
|
||||||
|
*
|
||||||
* @returns boolean indicating if the phrase is valid.
|
* @returns boolean indicating if the phrase is valid.
|
||||||
*/
|
*/
|
||||||
public static isValid(
|
public static isValid(
|
||||||
@@ -192,6 +203,7 @@ export class Mnemonic {
|
|||||||
*
|
*
|
||||||
* @param word Word to check.
|
* @param word Word to check.
|
||||||
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
|
* @param dictionary Optional wordlist (defaults to English BIP-39 wordlist).
|
||||||
|
*
|
||||||
* @returns boolean indicating if the word is valid.
|
* @returns boolean indicating if the word is valid.
|
||||||
*/
|
*/
|
||||||
public static isValidWord(
|
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 {
|
public toSeed(): Uint8Array {
|
||||||
return this.mnemonic.passphrase;
|
return deriveSeedFromBip39Mnemonic(this.toPhrase());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the complete phrase as a string.
|
* Returns the complete phrase as a string.
|
||||||
*
|
*
|
||||||
* @param includePassphrase Whether to include the passphrase in the output.
|
* @param includePassphrase Whether to include the passphrase in the output.
|
||||||
|
*
|
||||||
* @returns Complete phrase as a string.
|
* @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.
|
// Join the menmonic words, separating them using a space character.
|
||||||
const mnemonicWords = this.mnemonic.words.join(' ');
|
const mnemonicWords = this.mnemonic.words.join(' ');
|
||||||
|
|
||||||
@@ -252,4 +265,13 @@ export class Mnemonic {
|
|||||||
public toRaw(): MnemonicRaw {
|
public toRaw(): MnemonicRaw {
|
||||||
return { ...this.mnemonic };
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export class PrivateKey {
|
|||||||
*
|
*
|
||||||
* @param bytes {Uint8Array} The raw bytes (32) for the Private Key.
|
* @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.
|
// Ensure that the Private Key is valid.
|
||||||
if (!secp256k1.validatePrivateKey(bytes)) {
|
if (!secp256k1.validatePrivateKey(bytes)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -43,6 +43,27 @@ export class PrivateKey {
|
|||||||
this.bytes = bytes;
|
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.
|
* Create a Private Key Entity from the given bytes.
|
||||||
*
|
*
|
||||||
@@ -124,6 +145,19 @@ export class PrivateKey {
|
|||||||
return new PrivateKey(decodeResult.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.
|
* 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.
|
* Derive the public key from this private key.
|
||||||
*
|
*
|
||||||
@@ -161,7 +246,7 @@ export class PrivateKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the derived Public Key.
|
// Return the derived Public Key.
|
||||||
return new PublicKey(deriveResult);
|
return PublicKey.fromRaw(deriveResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -406,46 +491,4 @@ export class PrivateKey {
|
|||||||
// Return the signature.
|
// Return the signature.
|
||||||
return signResult;
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,23 @@ export class PublicKey {
|
|||||||
*
|
*
|
||||||
* @param bytes The raw bytes (33) for the Public Key.
|
* @param bytes The raw bytes (33) for the Public Key.
|
||||||
*/
|
*/
|
||||||
constructor(bytes: Uint8Array) {
|
protected constructor(bytes: Uint8Array) {
|
||||||
// Ensure that exactly 33 Bytes are given.
|
this.bytes = bytes;
|
||||||
if (!secp256k1.validatePublicKey(bytes)) {
|
|
||||||
throw new Error(`Invalid Public Key.`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +51,11 @@ export class PublicKey {
|
|||||||
* @returns The created Public Key entity.
|
* @returns The created Public Key entity.
|
||||||
*/
|
*/
|
||||||
public static fromBytes(publicKeyBytes: Uint8Array): PublicKey {
|
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);
|
return new PublicKey(publicKeyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +83,57 @@ export class PublicKey {
|
|||||||
return new PublicKey(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.
|
* Derive the Hash160 for this Public Key.
|
||||||
*
|
*
|
||||||
@@ -212,33 +278,4 @@ export class PublicKey {
|
|||||||
|
|
||||||
return validity;
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
export type BCHUnits = ['sats', 'bits', 'mBCH', 'BCH'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Satoshis Primitive
|
* Satoshis Primitive
|
||||||
*/
|
*/
|
||||||
@@ -11,7 +13,7 @@ export class Satoshis {
|
|||||||
*
|
*
|
||||||
* @param satoshis {number} The satoshi amount.
|
* @param satoshis {number} The satoshi amount.
|
||||||
*/
|
*/
|
||||||
constructor(satoshis: bigint | number) {
|
protected constructor(satoshis: bigint | number) {
|
||||||
// Set the satoshi amount.
|
// Set the satoshi amount.
|
||||||
this.satoshis = BigInt(satoshis);
|
this.satoshis = BigInt(satoshis);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
assembleBytecodeBCH,
|
assembleBytecodeBCH,
|
||||||
disassembleBytecodeBCH,
|
disassembleBytecodeBCH,
|
||||||
base58AddressToLockingBytecode,
|
|
||||||
cashAddressToLockingBytecode,
|
|
||||||
binToHex,
|
binToHex,
|
||||||
hexToBin,
|
hexToBin,
|
||||||
isHex,
|
isHex,
|
||||||
parseScript,
|
|
||||||
} from '@bitauth/libauth';
|
} from '@bitauth/libauth';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,14 +17,29 @@ export class Script {
|
|||||||
*
|
*
|
||||||
* @param bytes {Uint8Array} The raw bytes of the Script.
|
* @param bytes {Uint8Array} The raw bytes of the Script.
|
||||||
*/
|
*/
|
||||||
constructor(bytes: Uint8Array) {
|
protected constructor(bytes: Uint8Array) {
|
||||||
this.bytes = bytes;
|
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.
|
* @throws {Error} If script cannot be decoded.
|
||||||
*
|
*
|
||||||
@@ -86,44 +98,6 @@ export class Script {
|
|||||||
return new Script(scriptBin);
|
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.
|
* Convert this script to a human-readable string of assembly.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,7 +11,35 @@ export class TransactionHash {
|
|||||||
*
|
*
|
||||||
* @param bytes {Uint8Array} The Transaction Hash's bytes.
|
* @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 is not exactly 32, then this is an invalid transaction hash...
|
||||||
if (bytes.length !== 32) {
|
if (bytes.length !== 32) {
|
||||||
throw new Error(
|
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);
|
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);
|
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.
|
* Returns transaction hash as a hex string.
|
||||||
*
|
*
|
||||||
@@ -92,4 +148,13 @@ export class TransactionHash {
|
|||||||
public toBytes(): Uint8Array {
|
public toBytes(): Uint8Array {
|
||||||
return this.bytes;
|
return this.bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this primitive to a serializable representation.
|
||||||
|
*
|
||||||
|
* @returns Serialzied primitive data.
|
||||||
|
*/
|
||||||
|
toRaw() {
|
||||||
|
return this.bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type { TransactionBCH } from '@bitauth/libauth';
|
|||||||
* Transaction Primitive.
|
* Transaction Primitive.
|
||||||
*/
|
*/
|
||||||
export class Transaction {
|
export class Transaction {
|
||||||
constructor(public transaction: TransactionBCH) {}
|
protected constructor(public transaction: TransactionBCH) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a transaction from either:
|
* Instantiates a transaction from either:
|
||||||
@@ -28,19 +28,9 @@ export class Transaction {
|
|||||||
* @returns The created Transaction Primitive.
|
* @returns The created Transaction Primitive.
|
||||||
*/
|
*/
|
||||||
public static from(transaction: Uint8Array | string) {
|
public static from(transaction: Uint8Array | string) {
|
||||||
// Handle string (hex) case
|
return transaction instanceof Uint8Array
|
||||||
if (typeof transaction === 'string') {
|
? Transaction.fromBytes(transaction)
|
||||||
return Transaction.fromHex(transaction);
|
: 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',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +80,7 @@ export class Transaction {
|
|||||||
/**
|
/**
|
||||||
* Create a Transaction Primitive from LibAuth's TransactionBCH type.
|
* 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).
|
* @param transaction The transaction object (as per LibAuth).
|
||||||
*
|
*
|
||||||
@@ -104,6 +94,7 @@ export class Transaction {
|
|||||||
* Validates the structure of a transaction.
|
* Validates the structure of a transaction.
|
||||||
*
|
*
|
||||||
* @param transaction The transaction (as hex or bytes).
|
* @param transaction The transaction (as hex or bytes).
|
||||||
|
*
|
||||||
* @returns boolean indicating whether the transaction structure is valid.
|
* @returns boolean indicating whether the transaction structure is valid.
|
||||||
*/
|
*/
|
||||||
public static isValid(transaction: Uint8Array | string): boolean {
|
public static isValid(transaction: Uint8Array | string): boolean {
|
||||||
@@ -116,34 +107,67 @@ export class Transaction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the transaction to a byte array.
|
||||||
|
* @returns The transaction serialized as a Uint8Array
|
||||||
|
*/
|
||||||
public toBytes(): Uint8Array {
|
public toBytes(): Uint8Array {
|
||||||
const bytes = encodeTransaction(this.transaction);
|
const bytes = encodeTransaction(this.transaction);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the transaction to a byte array (represented as a hex string).
|
||||||
|
* @returns The transaction serialized in hex
|
||||||
|
*/
|
||||||
public toHex(): string {
|
public toHex(): string {
|
||||||
const bytes = this.toBytes();
|
const bytes = this.toBytes();
|
||||||
|
|
||||||
return binToHex(bytes);
|
return binToHex(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the transaction and returns a TransactionHash primitive.
|
||||||
|
* @returns The transaction hash primitive.
|
||||||
|
*/
|
||||||
public toHash(): TransactionHash {
|
public toHash(): TransactionHash {
|
||||||
return TransactionHash.fromTransactionBytes(this.toBytes());
|
return TransactionHash.fromTransactionBytes(this.toBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the transaction and returns the hash as hexadecimal.
|
||||||
|
* @returns The transaction hash hex.
|
||||||
|
*/
|
||||||
public toHashHex(): string {
|
public toHashHex(): string {
|
||||||
return this.toHash().toHex();
|
return this.toHash().toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashes the transaction and returns the hash as a Uint8Array.
|
||||||
|
* @returns The transaction hash bytes.
|
||||||
|
*/
|
||||||
public toHashBytes(): Uint8Array {
|
public toHashBytes(): Uint8Array {
|
||||||
return this.toHash().toBytes();
|
return this.toHash().toBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts transaction to a raw object representation.
|
||||||
|
* @returns A TransactionBCH LibAuth object.
|
||||||
|
*/
|
||||||
public toRaw(): TransactionBCH {
|
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 {
|
public isCoinbase(): boolean {
|
||||||
// A coinbase transaction MUST only have one input
|
// A coinbase transaction MUST only have one input
|
||||||
if (this.getInputs().length !== 1) {
|
if (this.getInputs().length !== 1) {
|
||||||
@@ -164,18 +188,46 @@ export class Transaction {
|
|||||||
return isOutpointZero && isOutpointIndexMax;
|
return isOutpointZero && isOutpointIndexMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the version for this transaction.
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*
|
||||||
|
* @returns The version of this transaction
|
||||||
|
*/
|
||||||
public getVersion() {
|
public getVersion() {
|
||||||
return this.transaction.version;
|
return this.transaction.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the inputs in this transaction.
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*
|
||||||
|
* @returns The inputs in this transaction
|
||||||
|
*/
|
||||||
public getInputs() {
|
public getInputs() {
|
||||||
return this.transaction.inputs;
|
return this.transaction.inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the outputs in this transaction.
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*
|
||||||
|
* @returns The outputs in this transaction
|
||||||
|
*/
|
||||||
public getOutputs() {
|
public getOutputs() {
|
||||||
return this.transaction.outputs;
|
return this.transaction.outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the locktime for this transaction.
|
||||||
|
*
|
||||||
|
* @experimental
|
||||||
|
*
|
||||||
|
* @returns The locktime of this transaction
|
||||||
|
*/
|
||||||
public getLocktime() {
|
public getLocktime() {
|
||||||
return this.transaction.locktime;
|
return this.transaction.locktime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { Bytes } from '~/src/bytes';
|
||||||
import { Mnemonic, MnemonicRaw } from '~/src/mnemonic';
|
import { Mnemonic, MnemonicRaw } from '~/src/mnemonic';
|
||||||
|
|
||||||
describe('Success cases', () => {
|
describe('Success cases', () => {
|
||||||
// Simple array of cases
|
// Simple array of cases
|
||||||
const testCases: Array<{
|
const testCases: Array<{
|
||||||
fromString: string;
|
fromPhrase: string;
|
||||||
fromWords: Array<string>;
|
fromWords: Array<string>;
|
||||||
passphrase?: string;
|
passphrase?: string;
|
||||||
raw: MnemonicRaw;
|
raw: MnemonicRaw;
|
||||||
toString: string;
|
toSeed: Uint8Array;
|
||||||
toStringWithoutPassphrase: string;
|
toPhrase: string;
|
||||||
|
toPhraseWithoutPassphrase: string;
|
||||||
toWords: Array<string>;
|
toWords: Array<string>;
|
||||||
toWordsWithoutPassphrase: Array<string>;
|
toWordsWithoutPassphrase: Array<string>;
|
||||||
}> = [
|
}> = [
|
||||||
// No pass-phrase
|
// No pass-phrase
|
||||||
{
|
{
|
||||||
fromString:
|
fromPhrase:
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
||||||
fromWords: [
|
fromWords: [
|
||||||
'goose',
|
'goose',
|
||||||
@@ -47,9 +49,12 @@ describe('Success cases', () => {
|
|||||||
'exhaust',
|
'exhaust',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
toString:
|
toSeed: Bytes.fromHex(
|
||||||
|
'7066f43a742829f0edce7d8e3c31651df320f13913995a6500f4e515db372b35202227f923ff181defc35cea02f8468df39f8fa9d97a202d252e61562e4bbfb5',
|
||||||
|
).toBytes(),
|
||||||
|
toPhrase:
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
||||||
toStringWithoutPassphrase:
|
toPhraseWithoutPassphrase:
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
||||||
toWords: [
|
toWords: [
|
||||||
'goose',
|
'goose',
|
||||||
@@ -82,7 +87,7 @@ describe('Success cases', () => {
|
|||||||
},
|
},
|
||||||
// Passphrase
|
// Passphrase
|
||||||
{
|
{
|
||||||
fromString:
|
fromPhrase:
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust GeneralProtocols!',
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust GeneralProtocols!',
|
||||||
fromWords: [
|
fromWords: [
|
||||||
'goose',
|
'goose',
|
||||||
@@ -117,9 +122,12 @@ describe('Success cases', () => {
|
|||||||
],
|
],
|
||||||
passphrase: 'GeneralProtocols!',
|
passphrase: 'GeneralProtocols!',
|
||||||
},
|
},
|
||||||
toString:
|
toSeed: Bytes.fromHex(
|
||||||
|
'2f706756ab2083f7ce07c0c0fcde8f14f062da5de839f42763262b25e0d871f03dd2b561d55eaacc471c94da656ee7b0007fb48a64e31ec91a1a2ba706b46b89',
|
||||||
|
).toBytes(),
|
||||||
|
toPhrase:
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust GeneralProtocols!',
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust GeneralProtocols!',
|
||||||
toStringWithoutPassphrase:
|
toPhraseWithoutPassphrase:
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
'goose just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
||||||
toWords: [
|
toWords: [
|
||||||
'goose',
|
'goose',
|
||||||
@@ -153,44 +161,46 @@ describe('Success cases', () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
it.each(testCases)(
|
it.each(testCases)('from(string)', ({ fromPhrase: phrase, raw }) => {
|
||||||
'from(string)',
|
|
||||||
({ fromString: phrase, raw: expected }) => {
|
|
||||||
const mnemonic = Mnemonic.from(phrase);
|
const mnemonic = Mnemonic.from(phrase);
|
||||||
expect(mnemonic.toRaw()).toStrictEqual(expected);
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
it.each(testCases)('from(words)', ({ fromWords, raw: expected }) => {
|
it.each(testCases)('from(words)', ({ fromWords, raw }) => {
|
||||||
const mnemonic = Mnemonic.from(fromWords);
|
const mnemonic = Mnemonic.from(fromWords);
|
||||||
expect(mnemonic.toRaw()).toStrictEqual(expected);
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(testCases)('fromString', ({ fromString, raw: expected }) => {
|
it.each(testCases)('fromPhrase', ({ fromPhrase, raw }) => {
|
||||||
const mnemonic = Mnemonic.fromString(fromString);
|
const mnemonic = Mnemonic.fromPhrase(fromPhrase);
|
||||||
expect(mnemonic.toRaw()).toStrictEqual(expected);
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(testCases)('fromWords', ({ fromWords, raw: expected }) => {
|
it.each(testCases)('fromWords', ({ fromWords, raw }) => {
|
||||||
const mnemonic = Mnemonic.fromWords(fromWords);
|
const mnemonic = Mnemonic.fromWords(fromWords);
|
||||||
expect(mnemonic.toRaw()).toStrictEqual(expected);
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(testCases)('fromWords', ({ fromWords, raw: expected }) => {
|
it.each(testCases)('fromWords', ({ fromWords, raw }) => {
|
||||||
const mnemonic = Mnemonic.fromWords(fromWords);
|
const mnemonic = Mnemonic.fromWords(fromWords);
|
||||||
expect(mnemonic.toRaw()).toStrictEqual(expected);
|
expect(mnemonic.toRaw()).toStrictEqual(raw);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(testCases)('toString', ({ toString, raw }) => {
|
it.each(testCases)('toSeed', ({ toSeed, raw }) => {
|
||||||
const mnemonic = Mnemonic.fromRaw(raw);
|
const mnemonic = Mnemonic.fromRaw(raw);
|
||||||
expect(mnemonic.toString()).toStrictEqual(toString);
|
expect(mnemonic.toSeed()).toStrictEqual(toSeed);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(testCases)('toPhrase', ({ toPhrase, raw }) => {
|
||||||
|
const mnemonic = Mnemonic.fromRaw(raw);
|
||||||
|
expect(mnemonic.toPhrase()).toStrictEqual(toPhrase);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each(testCases)(
|
it.each(testCases)(
|
||||||
'toString(withoutPassphrase)',
|
'toPhrase(withoutPassphrase)',
|
||||||
({ toStringWithoutPassphrase, raw }) => {
|
({ toPhraseWithoutPassphrase, raw }) => {
|
||||||
const mnemonic = Mnemonic.fromRaw(raw);
|
const mnemonic = Mnemonic.fromRaw(raw);
|
||||||
expect(mnemonic.toString(false)).toStrictEqual(toStringWithoutPassphrase);
|
expect(mnemonic.toPhrase(false)).toStrictEqual(toPhraseWithoutPassphrase);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -254,10 +264,10 @@ describe('Validations', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Fail cases', () => {
|
describe('Fail cases', () => {
|
||||||
it('fromString should fail if invalid number of words', () => {
|
it('fromPhrase should fail if invalid number of words', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
// 11 words.
|
// 11 words.
|
||||||
Mnemonic.fromString(
|
Mnemonic.fromPhrase(
|
||||||
'goose just fan kidney barrel album wave crowd movie flame cousin',
|
'goose just fan kidney barrel album wave crowd movie flame cousin',
|
||||||
);
|
);
|
||||||
}).toThrow();
|
}).toThrow();
|
||||||
@@ -289,10 +299,10 @@ describe('Fail cases', () => {
|
|||||||
}).toThrow();
|
}).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fromString should fail if word not in dictionary', () => {
|
it('fromPhrase should fail if word not in dictionary', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
// Invalid word "fnord".
|
// Invalid word "fnord".
|
||||||
Mnemonic.fromString(
|
Mnemonic.fromPhrase(
|
||||||
'fnord just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
'fnord just fan kidney barrel album wave crowd movie flame cousin exhaust',
|
||||||
);
|
);
|
||||||
}).toThrow();
|
}).toThrow();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Encryption, EventEmitter } from '../utils';
|
import { Encrypter, EventEmitter } from '../utils';
|
||||||
|
|
||||||
export type StorageOpts = {
|
export type StorageOpts = {
|
||||||
syncInMemory?: boolean;
|
syncInMemory?: boolean;
|
||||||
encryption?: Encryption;
|
encryption?: Encrypter;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StoreEvents = {
|
export type StoreEvents = {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { BaseStorage, BaseStore, StorageOpts } from './base-store.js';
|
import { BaseStorage, BaseStore, StorageOpts } from './base-store.js';
|
||||||
import { StoreInMemorySynced } from './store-inmemory-synced.js';
|
import { StoreInMemorySynced } from './store-inmemory-synced.js';
|
||||||
|
|
||||||
import { Encryption } from '../utils';
|
import { Encrypter } from '../utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
encodeExtendedJsonObject,
|
encodeExtendedJsonObject,
|
||||||
@@ -113,7 +113,7 @@ export class StoreIndexedDB extends BaseStore {
|
|||||||
constructor(
|
constructor(
|
||||||
public db: IDBPDatabase,
|
public db: IDBPDatabase,
|
||||||
public storeName: string,
|
public storeName: string,
|
||||||
public encryption?: Encryption,
|
public encryption?: Encrypter,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ export class StoreIndexedDB extends BaseStore {
|
|||||||
static async create(
|
static async create(
|
||||||
db: IDBPDatabase,
|
db: IDBPDatabase,
|
||||||
storeName: string,
|
storeName: string,
|
||||||
encryption?: Encryption,
|
encryption?: Encrypter,
|
||||||
) {
|
) {
|
||||||
return new this(db, storeName, encryption);
|
return new this(db, storeName, encryption);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { utf8ToBin } from '@bitauth/libauth';
|
|||||||
export const DEFAULT_XO_SALT =
|
export const DEFAULT_XO_SALT =
|
||||||
'cash.xo.default_salt_for_encryption_aabbccddeeff00112233445566778899';
|
'cash.xo.default_salt_for_encryption_aabbccddeeff00112233445566778899';
|
||||||
|
|
||||||
export type EncryptionOpts = {
|
export type EncrypterOpts = {
|
||||||
algorithm: string;
|
algorithm: string;
|
||||||
keyLength: number;
|
keyLength: number;
|
||||||
salt: Uint8Array;
|
salt: Uint8Array;
|
||||||
@@ -17,13 +17,13 @@ export type EncryptionOpts = {
|
|||||||
iterations: number;
|
iterations: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Encryption {
|
export class Encrypter {
|
||||||
constructor(
|
constructor(
|
||||||
private key: CryptoKey,
|
private key: CryptoKey,
|
||||||
public opts: EncryptionOpts,
|
public opts: EncrypterOpts,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static async fromBytes(key: Uint8Array, opts: Partial<EncryptionOpts> = {}) {
|
static async fromBytes(key: Uint8Array, opts: Partial<EncrypterOpts> = {}) {
|
||||||
// Merge the provided options into our default options.
|
// Merge the provided options into our default options.
|
||||||
const encryptionOpts = {
|
const encryptionOpts = {
|
||||||
algorithm: 'AES-GCM',
|
algorithm: 'AES-GCM',
|
||||||
@@ -60,12 +60,12 @@ export class Encryption {
|
|||||||
['encrypt', 'decrypt'],
|
['encrypt', 'decrypt'],
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Encryption(derivedKey, encryptionOpts);
|
return new Encrypter(derivedKey, encryptionOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async fromPassphrase(
|
static async fromPassphrase(
|
||||||
passphrase: string,
|
passphrase: string,
|
||||||
opts: Partial<EncryptionOpts> = {},
|
opts: Partial<EncrypterOpts> = {},
|
||||||
) {
|
) {
|
||||||
const key = utf8ToBin(passphrase);
|
const key = utf8ToBin(passphrase);
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './encryption.js';
|
export * from './encrypter.js';
|
||||||
export * from './event-emitter.js';
|
export * from './event-emitter.js';
|
||||||
export * from './ext-error.js';
|
export * from './ext-error.js';
|
||||||
|
export * from './hasher.js';
|
||||||
export * from './memoizer.js';
|
export * from './memoizer.js';
|
||||||
export * from './misc.js';
|
export * from './misc.js';
|
||||||
export * from './uuid.js';
|
export * from './uuid.js';
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ export class WalletHD<
|
|||||||
// Derive the private key at the given path.
|
// Derive the private key at the given path.
|
||||||
const privateKeyHex = await this.cache.getOrSet(derivationPath, () => {
|
const privateKeyHex = await this.cache.getOrSet(derivationPath, () => {
|
||||||
const childNode = this.hdPrivateNode.derivePath(derivationPath);
|
const childNode = this.hdPrivateNode.derivePath(derivationPath);
|
||||||
return childNode.privateKey().toHex();
|
return childNode.toPrivateKey().toHex();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a child P2PKH wallet for this Private Key.
|
// Create a child P2PKH wallet for this Private Key.
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
|
||||||
import { Encryption } from '~/src/utils/encryption';
|
import { Encrypter } from '~/src/utils/encrypter';
|
||||||
import { binToUtf8, utf8ToBin } from '@bitauth/libauth';
|
import { binToUtf8, utf8ToBin } from '@bitauth/libauth';
|
||||||
|
|
||||||
describe('Encryption', () => {
|
describe('Encrypter', () => {
|
||||||
let encryption: Encryption;
|
let encryption: Encrypter;
|
||||||
const testKey = 'test-secret-key-123';
|
const testKey = 'test-secret-key-123';
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
encryption = await Encryption.fromPassphrase(testKey);
|
encryption = await Encrypter.fromPassphrase(testKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('constructor', () => {
|
describe('constructor', () => {
|
||||||
it('should create instance with string key', async () => {
|
it('should create instance with string key', async () => {
|
||||||
const enc = await Encryption.fromPassphrase('test-key');
|
const enc = await Encrypter.fromPassphrase('test-key');
|
||||||
expect(enc).toBeInstanceOf(Encryption);
|
expect(enc).toBeInstanceOf(Encrypter);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create instance with Uint8Array key', async () => {
|
it('should create instance with Uint8Array key', async () => {
|
||||||
const enc = await Encryption.fromBytes(utf8ToBin('test-key'));
|
const enc = await Encrypter.fromBytes(utf8ToBin('test-key'));
|
||||||
expect(enc).toBeInstanceOf(Encryption);
|
expect(enc).toBeInstanceOf(Encrypter);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,8 +77,8 @@ describe('Encryption', () => {
|
|||||||
|
|
||||||
describe('cross-instance encryption', () => {
|
describe('cross-instance encryption', () => {
|
||||||
it('should decrypt data encrypted with different instance using same key', async () => {
|
it('should decrypt data encrypted with different instance using same key', async () => {
|
||||||
const enc1 = await Encryption.fromPassphrase(testKey);
|
const enc1 = await Encrypter.fromPassphrase(testKey);
|
||||||
const enc2 = await Encryption.fromPassphrase(testKey);
|
const enc2 = await Encrypter.fromPassphrase(testKey);
|
||||||
|
|
||||||
const originalData = 'Hello, World!';
|
const originalData = 'Hello, World!';
|
||||||
const encrypted = await enc1.encrypt(originalData);
|
const encrypted = await enc1.encrypt(originalData);
|
||||||
|
|||||||
Reference in New Issue
Block a user