@ngraveio/ur-coin-identity
Version:
Provides BC UR type that uniquely identifies a crypto coin.
245 lines (240 loc) • 10.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CoinIdentity = exports.ComparisonMethod = exports.EllipticCurve = void 0;
const bc_ur_1 = require("@ngraveio/bc-ur");
/**
* Elliptic curve types defined by the IANA registry
*
* https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
* https://www.rfc-editor.org/rfc/rfc9053.html#name-elliptic-curve-keys
*
* P256=1 ; NIST P-256 also known as secp256r1
* P384=2 ; NIST P-384 also known as secp384r1
* P521=3 ; EC2 NIST P-521 also known as secp521r1
* X25519=4 ; X25519 for use w/ ECDH only
* X448=5 ; X448 for use w/ ECDH only
* Ed25519=6 ; Ed25519 for use w/ EdDSA only
* Ed448=7 ; Ed448 for use w/ EdDSA only
* secp256k1=8 ; SECG secp256k1 curve IESG
*
*/
var EllipticCurve;
(function (EllipticCurve) {
EllipticCurve[EllipticCurve["P256"] = 1] = "P256";
EllipticCurve[EllipticCurve["P384"] = 2] = "P384";
EllipticCurve[EllipticCurve["P521"] = 3] = "P521";
EllipticCurve[EllipticCurve["X25519"] = 4] = "X25519";
EllipticCurve[EllipticCurve["X448"] = 5] = "X448";
EllipticCurve[EllipticCurve["Ed25519"] = 6] = "Ed25519";
EllipticCurve[EllipticCurve["Ed448"] = 7] = "Ed448";
EllipticCurve[EllipticCurve["secp256k1"] = 8] = "secp256k1";
})(EllipticCurve || (exports.EllipticCurve = EllipticCurve = {}));
var ComparisonMethod;
(function (ComparisonMethod) {
ComparisonMethod["ExactMatch"] = "==";
ComparisonMethod["Parent"] = ">";
ComparisonMethod["Child"] = "<";
ComparisonMethod["NotEqual"] = "!=";
ComparisonMethod["LessThanOrEqual"] = "<=";
ComparisonMethod["GreaterThanOrEqual"] = ">=";
})(ComparisonMethod || (exports.ComparisonMethod = ComparisonMethod = {}));
const CoinIdentityBase = (0, bc_ur_1.registryItemFactory)({
tag: 41401,
URType: 'coin-identity',
keyMap: {
curve: 1,
type: 2,
subtype: 3,
},
CDDL: `
; Table should always be updated according to IANA registry
; https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
; https://www.rfc-editor.org/rfc/rfc9053.html#name-elliptic-curve-keys
P256=1 ; NIST P-256 also known as secp256r1
P384=2 ; NIST P-384 also known as secp384r1
P521=3 ; EC2 NIST P-521 also known as secp521r1
X25519=4 ; X25519 for use w/ ECDH only
X448=5 ; X448 for use w/ ECDH only
Ed25519=6 ; Ed25519 for use w/ EdDSA only
Ed448=7 ; Ed448 for use w/ EdDSA only
secp256k1=8 ; SECG secp256k1 curve IESG
elliptic_curve = P256 / P384 / P521 / X25519 / X448 / Ed25519 / Ed448 / secp256k1
; Subtypes specific to some coins (e.g. ChainId for EVM chains)
hex_string = #6.263(bstr) ; byte string is a hexadecimal string no need for decoding
sub_type_exp = uint32 / str / hex_string
coin-identity = {
curve: elliptic_curve,
type: uint31, ; values from [SLIP44] with high bit turned off,
? subtype: [ sub_type_exp + ] ; Compatible with the definition of several subtypes if necessary
}
curve = 1
type = 2
subtype = 3
`,
});
/** CDDL
*
* ; Table should always be updated according to IANA registry
* ; https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
* ; https://www.rfc-editor.org/rfc/rfc9053.html#name-elliptic-curve-keys
*
* P256=1 ; NIST P-256 also known as secp256r1
* P384=2 ; NIST P-384 also known as secp384r1
* P521=3 ; EC2 NIST P-521 also known as secp521r1
* X25519=4 ; X25519 for use w/ ECDH only
* X448=5 ; X448 for use w/ ECDH only
* Ed25519=6 ; Ed25519 for use w/ EdDSA only
* Ed448=7 ; Ed448 for use w/ EdDSA only
* secp256k1=8 ; SECG secp256k1 curve IESG
*
* elliptic_curve = P256 / P384 / P521 / X25519 / X448 / Ed25519 / Ed448 / secp256k1
*
* ; Subtypes specific to some coins (e.g. ChainId for EVM chains)
* hex_string = #6.263(bstr) ; byte string is a hexadecimal string no need for decoding
* sub_type_exp = uint32 / str / hex_string
*
* coin-identity = {
* curve: elliptic_curve,
* type: uint31, ; values from [SLIP44] with high bit turned off,
* ? subtype: [ sub_type_exp + ] ; Compatible with the definition of several subtypes if necessary
* }
*
* curve = 1
* type = 2
* subtype = 3
*/
class CoinIdentity extends CoinIdentityBase {
constructor(curve, type, subtype) {
super({ curve, type, subtype }, CoinIdentityBase.keyMap);
this.getCurve = () => this.data.curve;
this.getType = () => this.data.type;
this.getSubType = () => this.data.subtype || [];
/**
* Get the parent CoinIdentity of the current CoinIdentity
* @returns {CoinIdentity} a new instance of CoinIdentity for the parent if it exists or null if it does not.
*/
this.getParent = () => {
// If we dont have any subtypes, return null
if (!this.data.subtype?.length)
return null;
// Otherwise remove the last subtype and return a new CoinIdentity
const subtypes = this.data.subtype.slice(1, this.data.subtype.length);
return new CoinIdentity(this.data.curve, this.data.type, subtypes);
};
/**
* Create a url from ths CoinIdentity. The subtypes should be in the correct order.
* @returns {string} url representation of the CoinIdentity
*/
this.toURL = () => {
const curve = Object.values(EllipticCurve)[this.data.curve - 1];
const type = this.data.type;
const subtype = this.data.subtype;
const subtypes = subtype?.join('.');
if (subtypes?.length) {
return `bc-coin://${subtypes}.${curve}/${type}`;
}
return `bc-coin://${curve}/${type}`;
};
/**
* Compare the current id to a given id
* @param coinIdentity CoinIdentity to compare the current one with
* @param comparison comparison method to check
* @returns boolean indicating if the comparison is valid
*/
this.compare = (coinIdentity, comparison) => {
const url = this.toURL().replace('bc-coin://', '');
const urlToCompare = coinIdentity.toURL().replace('bc-coin://', '');
return CoinIdentity.compareCoinIds(url, urlToCompare, comparison);
};
this.data = { curve, type, subtype };
}
/**
* Static method to create an instance from CBOR data.
* It processes the raw CBOR data if needed and returns a new instance of the class.
*/
static fromCBORData(val, tagged) {
// Do some post processing data coming from the cbor decoder
const data = this.postCBOR(val);
const { curve, type, subtype } = data;
// Return an instance of the generated class
return new this(curve, type, subtype);
}
/**
* Create an Iterator that returns all the parents of this CoinIdentity
* @returns {Iterable<CoinIdentity>} An iterator for all the parent CoinIdentities of the current CoinIdentity
*/
getAllParents() {
let currentParent = this.getParent();
const parentIterator = {
[Symbol.iterator]() {
return {
next() {
if (currentParent) {
const returnParent = new CoinIdentity(currentParent.getCurve(), currentParent.getType(), currentParent.getSubType());
currentParent = currentParent.getParent();
return {
value: returnParent,
done: false,
};
}
return { value: undefined, done: true };
},
};
},
};
return parentIterator;
}
/**
* Compare a coin url, generated with '.toUrl()' method, with a different one
* @param coinUrl1 first coinIdentity as a url.
* @param coinUrl2 second coinIdentity as a url.
* @param comparison comparison method.
* @returns boolean indicating if the comparison is valid
*/
static compareCoinIds(coinUrl1, coinUrl2, comparison) {
const dict = CoinIdentity.compareCoinIdsDict(coinUrl1, coinUrl2);
return dict[comparison];
}
/**
* Creates a dictionary for all comparison methods for two given coin urls, generated with '.toUrl()'.
* @param coinUrl1 first coinIdentity as a url.
* @param coinUrl2 second coinIdentity as a url.
* @returns dictionary indicating which comparison methods are true | false.
*/
static compareCoinIdsDict(coinUrl1, coinUrl2) {
const url = coinUrl1.replace('bc-coin://', '');
const urlToCompare = coinUrl2.replace('bc-coin://', '');
const isEqual = url === urlToCompare;
const isChild = url.includes(urlToCompare);
const isParent = urlToCompare.includes(url);
const isNotEqual = url !== urlToCompare;
return {
[ComparisonMethod.ExactMatch]: isEqual,
[ComparisonMethod.Child]: isChild,
[ComparisonMethod.Parent]: isParent,
[ComparisonMethod.NotEqual]: isNotEqual,
[ComparisonMethod.LessThanOrEqual]: isEqual || isChild,
[ComparisonMethod.GreaterThanOrEqual]: isEqual || isParent,
};
}
}
exports.CoinIdentity = CoinIdentity;
/**
* Convert a url into a CoinIdentity
* @param url url representation of a CoinIdentity
* @returns {CoinIdentity} created from the passed url.
*/
CoinIdentity.fromUrl = (url) => {
const parts = url.split('://')[1].split('/');
const subtypeParts = parts[0].split('.');
if (subtypeParts.length > 1) {
const curve = subtypeParts[subtypeParts.length - 1];
const type = +parts[1];
const subTypes = subtypeParts.slice(0, subtypeParts.length - 1);
return new CoinIdentity(curve, type, subTypes);
}
const curve = parts[0];
const type = +parts[1];
return new CoinIdentity(curve, type);
};
//# sourceMappingURL=CoinIdentity.js.map