{
HoloHash,
HoloHashTypes,
AnyDhtHash,
AnyLinkableHash,
// HoloHash types
AgentPubKey,
EntryHash,
NetIdHash,
DhtOpHash,
HeaderHash,
WasmHash,
DnaHash,
ExternalHash,
// Error classes
Warning,
HoloHashError,
// HoloHashError types,
NoLeadingUError,
BadBase64Error,
BadSizeError,
BadPrefixError,
BadChecksumError,
// Other exports
logging,
base64,
bindNative,
}
Attempts to define HoloHash
on the native Object
properties. Returns the module exports so that
this can be called on the same line as require
.
Example
import { HoloHash, bindNative } from '@spartan-hc/holo-hash';
bindNative();
let hash = "uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU".toHoloHash();
A HoloHash
is always a 39-byte Uint8Array
. If no Holo Hash prefix is given, a "blank" prefix is
used (eg. hC--
).
- String inputs must contain the leading
u
; otherwise, theNoLeadingUError
is thrown - DHT address from input must match the calculated DHT address; otherwise, the
BadChecksumError
is thrown
Supported inputs are:
Uint8Array(39)
- full Holo Hash bytesUint8Array(36)
- hash digest + DHT addressUint8Array(32)
- hash digest- 53-char
string
- full Holo Hash string representation - 52-char
string
- base64 encoded (prefix + hash digest + DHT address) strict mode must be disabled - 48-char
string
- base64 encoded (hash digest + DHT address) - 43-char
string
- base64 encoded (hash digest)
Based on the given prefix, this will return an instance of the corresponding HoloHashType
instead
of the HoloHash
instance.
let hash = new HoloHash(new Uint8Array([
132, 33, 36, 130, 116, 237, 150, 68,
72, 116, 128, 83, 221, 230, 142, 102,
103, 244, 152, 130, 68, 40, 36, 61,
114, 177, 81, 125, 147, 240, 83, 37,
130, 223, 147, 135, 16, 31, 132
]));
hash.constructor.name;
// "EntryHash"
hash.toString();
// "uhCEkgnTtlkRIdIBT3eaOZmf0mIJEKCQ9crFRfZPwUyWC35OHEB-E"
Will be assigned the 'blank' prefix (uhC--
).
let hash = new HoloHash(new Uint8Array([
207, 39, 6, 42, 162, 2, 95, 176,
73, 215, 86, 158, 133, 121, 16, 209,
230, 217, 119, 208, 52, 155, 79, 31,
250, 159, 28, 212, 252, 178, 226, 227,
37, 53, 68, 20
]));
hash.constructor.name;
// "HoloHash"
hash.toString();
// "uhC--zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
Will be assigned the 'blank' prefix (uhC--
).
let hash = new HoloHash(new Uint8Array([
207, 39, 6, 42, 162, 2, 95, 176,
73, 215, 86, 158, 133, 121, 16, 209,
230, 217, 119, 208, 52, 155, 79, 31,
250, 159, 28, 212, 252, 178, 226, 227
]));
hash.constructor.name;
// "HoloHash"
hash.toString();
// "uhC--zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.constructor.name;
// "AgentPubKey"
By default, strict
mode is on and will throw the NoLeadingUError
. strict
mode must be
disabled to avoid throwing the error.
Warning: disabling
strict
mode will also disable the checksum error.
let hash = new HoloHash("hCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU", false );
hash.constructor.name;
// "AgentPubKey"
Same behavior as the 36-byte Uint8Array
input
let hash = new HoloHash("zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.constructor.name;
// "HoloHash"
hash.toString();
// "uhC--zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
Same behavior as the 32-byte Uint8Array
input
let hash = new HoloHash("zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uM");
hash.constructor.name;
// "HoloHash"
hash.toString();
// "uhC--zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
Will throw Error
because Holo Hash's should not be modified.
Example
Error: You should not be manually modifying HoloHash bytes
at AgentPubKey.set
Will throw Error
because an instance of HoloHash
must always be 39 bytes. Use
<HoloHash>.bytes()
to get Uint8Array
slices if needed.
Example
Error: HoloHash is not intended to by sliced; use <HoloHash>.bytes() to get Uint8Array slices
at AgentPubKey.slice
Works just like TypedArray.slice
except it always returns a Uint8Array
instead of the current
object's constructor class.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.slice(-4);
// Uint8Array(4) [ 37, 53, 68, 20 ]
Returns the first 3 bytes which represent the Holo Hast type.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.getPrefix();
// Uint8Array(3) [ 132, 32, 36 ]
Returns the URL-safe base64 representation of the Holo Hash prefix (includes the leading u
by
default).
with_leading_u
- whenfalse
, returns string without the leadingu
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.getPrefixB64();
// "uhCAk"
hash.getPrefixB64( false );
// "hCAk"
Returns the 32-byte hash digest without the prefix or DHT address bytes.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.getHash();
// Uint8Array(32) [
// 207, 39, 6, 42, 162, 2, 95, 176,
// 73, 215, 86, 158, 133, 121, 16, 209,
// 230, 217, 119, 208, 52, 155, 79, 31,
// 250, 159, 28, 212, 252, 178, 226, 227
// ]
By default, this will throw a Warning
because the string encoding of these 32 bytes on their own
might not match the full hash's string representation. See Base64 Encoding
Subtleties
When force === true
, it returns the URL-safe base64 representation of the 32-byte hash digest.
Example
let hash = new HoloHash("uhCEkgnTtlkRIdIBT3eaOZmf0mIJEKCQ9crFRfZPwUyWC35OHEB-E");
hash.getHashB64();
// [Warning( A base64 representation of the DHT Address MIGHT not match the base64 from the full hash string. )]
// at EntryHash.getHashB64
hash.getHashB64( true );
// "gnTtlkRIdIBT3eaOZmf0mIJEKCQ9crFRfZPwUyWC35M" (notice difference? '...35O' !== '...35M')
Returns the last 4 bytes which represent the DHT address.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.getDHTAddress();
// Uint8Array(4) [ 37, 53, 68, 20 ]
By default, this will throw a Warning
because the string encoding of these 4 bytes on their own
will not match the full hash's string representation. See Base64 Encoding
Subtleties
When force === true
, it returns the last URL-safe base64 representation of the last 4-byte DHT
address.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.getDHTAddressB64();
// [Warning( A base64 representation of the DHT Address MIGHT not match the base64 from the full hash string. )]
// at EntryHash.getHashB64
hash.getDHTAddressB64( true );
// "JTVEFA"
Returns the Uint32
value of the 4-byte DHT address.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.getDHTLocation();
// 624247828
Returns the URL-safe base64 value of the full 39-byte HoloHash
.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.toString();
// "uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
String(hash);
// "uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
Alias for <HoloHash>.bytes()
Returns the the same 36-byte hash + DHT as an instance of the given type with the new corresponding prefix.
Throws an Error
if type
does not match any of the Holo Hash Type class names.
Example
let agent = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
// AgentPubKey(39) [ 132, 32, 36, ... ]
let entry = hash.toType("EntryHash");
// EntryHash(39) [ 132, 33, 36, ... ]
String(entry)
// "uhCEkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU"
hash.toType("Invalid");
// Error: Invalid HoloHash type (BadClassName); must be one of: AgentPubKey,EntryHash,NetIdHash,DhtOpHash,HeaderHash,WasmHash,DnaHash
// at AgentPubKey.toType
Alias for <HoloHash>.toType(...)
Returns the constructor class of the current HoloHash instance.
Example
let hash = new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
hash.hashType();
// [class AgentPubKey extends AnyDhtHash] { PREFIX: [ 132, 32, 36 ] }
This error will occur when constructing from a full Holo Hash string
representation that is missing the leading
u
character.
Example
new HoloHash("hCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU");
// [NoLeadingUError( Holo Hash missing 'u' prefix: hCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUQU )]
// at new HoloHash
This error will occur when constructing from a string and it contains invalid base64 characters.
Example
new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUe?");
// [BadBase64Error( Failed to decode base64 input (hCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUe?) )]
// at new HoloHash
This error will occur when the given 3-byte prefix does not match any of the Holo Hash Type's prefixes.
Example
new HoloHash("uhC__zycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUeU");
// [BadPrefixError( Hash prefix did not match any HoloHash types: 132,47,255 )]
// at new HoloHash
This error will occur when the input length does not match one of the supported sizes.
Example
new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUeUaa");
// [BadSizeError( Invalid input byte length (40); expected length 39, 36, or 32 )]
// at new HoloHash
This error will occur when the input included a DHT address portion, but it does not match the calculated DHT address from the given hash digest.
Example
new HoloHash("uhCAkzycGKqICX7BJ11aehXkQ0ebZd9A0m08f-p8c1Pyy4uMlNUeU");
// [BadChecksumError( Given DHT address (37,53,71,148) does not match calculated address: 37,53,68,20 )]
// at new HoloHash
Since each base64 character only represents 6 bits, only byte arrays divisible by 3 will form a rounded base64 string. Furthermore, because base64 is encoded from left to right, counting 3-byte sets must start from the left side of any byte array.
Our Holo Hash prefix is the farthest left bytes, but it is divisible by 3; so when it is not present the following bytes will have the same base64 encoding.
However, the next section is our 32-byte hash digest which is not divisible by 3. This means that the farthest right base64 character will have 4 bits required by our 32-byte hash and 2 bits that are thrown away. Unless there are more bytes such as our DHT address. In that case, the 2 bits are used by the following bytes. Now there are 2 portions of encoded data that are sharing the same base64 character
In conclusion, this means:
- We cannot parse the DHT address from spliting the base64 string.
- There's no way to base64 encode the DHT address so that it matches the full encoding.
- An encoded hash digest could have several base64 characters that will result in the same bytes.