169 lines
5.6 KiB
JavaScript
169 lines
5.6 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.decodeCid = exports.decodeManifestCid = exports.decodeFeedCid = exports.encodeManifestReference = exports.encodeFeedReference = exports.encodeReference = exports.ReferenceType = exports.REFERENCE_HEX_LENGTH = exports.SWARM_FEED_CODEC = exports.SWARM_MANIFEST_CODEC = exports.SWARM_NS_CODEC = exports.KECCAK_256_CODEC = void 0;
|
|
const multiformats_1 = require("multiformats");
|
|
const digest_1 = require("multiformats/hashes/digest");
|
|
// https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
exports.KECCAK_256_CODEC = 0x1b;
|
|
exports.SWARM_NS_CODEC = 0xe4;
|
|
exports.SWARM_MANIFEST_CODEC = 0xfa;
|
|
exports.SWARM_FEED_CODEC = 0xfb;
|
|
exports.REFERENCE_HEX_LENGTH = 64;
|
|
var ReferenceType;
|
|
(function (ReferenceType) {
|
|
ReferenceType["FEED"] = "feed";
|
|
ReferenceType["MANIFEST"] = "manifest";
|
|
})(ReferenceType = exports.ReferenceType || (exports.ReferenceType = {}));
|
|
/**
|
|
* Mapping for getting ReferenceType from given codec.
|
|
*/
|
|
const CODEC_TYPE_MAPPING = {
|
|
[exports.SWARM_FEED_CODEC]: ReferenceType.FEED,
|
|
[exports.SWARM_MANIFEST_CODEC]: ReferenceType.MANIFEST,
|
|
};
|
|
/**
|
|
* Encode Swarm hex-encoded Reference into CID that has appropriate codec set based on `type` parameter.
|
|
*
|
|
* @param ref
|
|
* @param type
|
|
*/
|
|
function encodeReference(ref, type) {
|
|
switch (type) {
|
|
case ReferenceType.FEED:
|
|
return _encodeReference(ref, exports.SWARM_FEED_CODEC);
|
|
case ReferenceType.MANIFEST:
|
|
return _encodeReference(ref, exports.SWARM_MANIFEST_CODEC);
|
|
default:
|
|
throw new Error('Unknown reference type.');
|
|
}
|
|
}
|
|
exports.encodeReference = encodeReference;
|
|
/**
|
|
* Encode Swarm hex-encoded Reference into CID and sets Feed codec.
|
|
* @param ref
|
|
*/
|
|
function encodeFeedReference(ref) {
|
|
return _encodeReference(ref, exports.SWARM_FEED_CODEC);
|
|
}
|
|
exports.encodeFeedReference = encodeFeedReference;
|
|
/**
|
|
* Encode Swarm hex-encoded Reference into CID and sets Manifest codec.
|
|
* @param ref
|
|
*/
|
|
function encodeManifestReference(ref) {
|
|
return _encodeReference(ref, exports.SWARM_MANIFEST_CODEC);
|
|
}
|
|
exports.encodeManifestReference = encodeManifestReference;
|
|
/**
|
|
* Function to decode Feed CID (both from string or CID instance) into hex encoded Swarm reference.
|
|
*
|
|
* @param cid
|
|
* @throws Error if the decoded codec did not matched Swarm Feed codec
|
|
*/
|
|
function decodeFeedCid(cid) {
|
|
const result = _decodeReference(cid);
|
|
if (result.type !== ReferenceType.FEED) {
|
|
throw new Error('CID did not have Swarm Feed codec!');
|
|
}
|
|
return result.reference;
|
|
}
|
|
exports.decodeFeedCid = decodeFeedCid;
|
|
/**
|
|
* Function to decode Manifest CID (both from string or CID instance) into hex encoded Swarm reference.
|
|
*
|
|
* @param cid
|
|
* @throws Error if the decoded codec did not matched Swarm Manifest codec
|
|
*/
|
|
function decodeManifestCid(cid) {
|
|
const result = _decodeReference(cid);
|
|
if (result.type !== ReferenceType.MANIFEST) {
|
|
throw new Error('CID did not have Swarm Manifest codec!');
|
|
}
|
|
return result.reference;
|
|
}
|
|
exports.decodeManifestCid = decodeManifestCid;
|
|
/**
|
|
* Decode CID or base encoded CID string into DecodeResult interface.
|
|
* Does not throw exception if the codec was not Swarm related. In that case `type` is undefined.
|
|
*
|
|
* @see DecodeResult
|
|
* @param cid
|
|
*/
|
|
function decodeCid(cid) {
|
|
return _decodeReference(cid);
|
|
}
|
|
exports.decodeCid = decodeCid;
|
|
function _decodeReference(cid) {
|
|
if (typeof cid === 'string') {
|
|
cid = multiformats_1.CID.parse(cid);
|
|
}
|
|
return {
|
|
reference: bytesToHex(cid.multihash.digest),
|
|
type: CODEC_TYPE_MAPPING[cid.code],
|
|
};
|
|
}
|
|
function _encodeReference(ref, codec) {
|
|
assertReference(ref);
|
|
const hashBytes = hexToBytes(ref);
|
|
return multiformats_1.CID.createV1(codec, (0, digest_1.create)(exports.KECCAK_256_CODEC, hashBytes));
|
|
}
|
|
/**
|
|
* Converts a hex string to Uint8Array
|
|
*
|
|
* @param hex string input without 0x prefix!
|
|
*/
|
|
function hexToBytes(hex) {
|
|
assertHexString(hex);
|
|
const bytes = new Uint8Array(hex.length / 2);
|
|
for (let i = 0; i < bytes.length; i++) {
|
|
const hexByte = hex.substr(i * 2, 2);
|
|
bytes[i] = parseInt(hexByte, 16);
|
|
}
|
|
return bytes;
|
|
}
|
|
/**
|
|
* Converts array of number or Uint8Array to HexString without prefix.
|
|
*
|
|
* @param bytes The input array
|
|
* @param len The length of the non prefixed HexString
|
|
*/
|
|
function bytesToHex(bytes, len) {
|
|
const hexByte = (n) => n.toString(16).padStart(2, '0');
|
|
const hex = Array.from(bytes, hexByte).join('');
|
|
if (len && hex.length !== len) {
|
|
throw new TypeError(`Resulting HexString does not have expected length ${len}: ${hex}`);
|
|
}
|
|
return hex;
|
|
}
|
|
/**
|
|
* Type guard for HexStrings.
|
|
* Requires no 0x prefix!
|
|
*
|
|
* @param s string input
|
|
* @param len expected length of the HexString
|
|
*/
|
|
function isHexString(s, len) {
|
|
return typeof s === 'string' && /^[0-9a-f]+$/i.test(s) && (!len || s.length === len);
|
|
}
|
|
/**
|
|
* Verifies if the provided input is a HexString.
|
|
*
|
|
* @param s string input
|
|
* @param len expected length of the HexString
|
|
* @param name optional name for the asserted value
|
|
* @returns HexString or throws error
|
|
*/
|
|
function assertHexString(s, len, name = 'value') {
|
|
if (!isHexString(s, len)) {
|
|
// Don't display length error if no length specified in order not to confuse user
|
|
const lengthMsg = len ? ` of length ${len}` : '';
|
|
throw new TypeError(`${name} not valid hex string${lengthMsg}: ${s}`);
|
|
}
|
|
}
|
|
function assertReference(ref) {
|
|
assertHexString(ref);
|
|
if (ref.length !== exports.REFERENCE_HEX_LENGTH) {
|
|
throw new TypeError(`Reference does not have expected length 64 characters. Encrypted references are not supported.`);
|
|
}
|
|
}
|