Skip to content

Commit

Permalink
Merge pull request #30 from iden3/feature/custom-registration
Browse files Browse the repository at this point in the history
Custom registration
  • Loading branch information
vmidyllic authored Dec 12, 2023
2 parents 7f7578a + 299f5ee commit 51f411b
Show file tree
Hide file tree
Showing 8 changed files with 378 additions and 67 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@iden3/js-iden3-core",
"version": "1.1.0",
"version": "1.2.0",
"description": "Low level API to create and manipulate iden3 Claims.",
"source": "./src/index.ts",
"typings": "dist/types/index.d.ts",
Expand Down
66 changes: 40 additions & 26 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,41 +42,55 @@ export const Constants = Object.freeze({
GENESIS_LENGTH: 27
});

export enum Blockchain {
Ethereum = 'eth',
Polygon = 'polygon',
ZkEVM = 'zkevm',
Unknown = 'unknown',
NoChain = '',
ReadOnly = 'readonly'
}
export const Blockchain: { [k: string]: string } = {
Ethereum: 'eth',
Polygon: 'polygon',
ZkEVM: 'zkevm',
Unknown: 'unknown',
NoChain: '',
ReadOnly: 'readonly'
};

export enum NetworkId {
Main = 'main',
Mumbai = 'mumbai',
Goerli = 'goerli',
Sepolia = 'sepolia',
Test = 'test',
Unknown = 'unknown',
NoNetwork = ''
}
export const NetworkId: { [k: string]: string } = {
Main: 'main',
Mumbai: 'mumbai',
Goerli: 'goerli',
Sepolia: 'sepolia',
Test: 'test',
Unknown: 'unknown',
NoNetwork: ''
};

export enum DidMethod {
Iden3 = 'iden3',
PolygonId = 'polygonid',
Other = ''
}
export const DidMethod: { [k: string]: string } = {
Iden3: 'iden3',
PolygonId: 'polygonid',
Other: ''
};

export const DidMethodByte: { [key: string]: number } = Object.freeze({
/**
* Object containing chain IDs for various blockchains and networks.
* @type { [key: string]: number }
*/
export const ChainIds: { [key: string]: number } = {
[`${Blockchain.Ethereum}:${NetworkId.Main}`]: 1,
[`${Blockchain.Ethereum}:${NetworkId.Goerli}`]: 5,
[`${Blockchain.Ethereum}:${NetworkId.Sepolia}`]: 11155111,
[`${Blockchain.Polygon}:${NetworkId.Main}`]: 137,
[`${Blockchain.Polygon}:${NetworkId.Mumbai}`]: 80001,
[`${Blockchain.ZkEVM}:${NetworkId.Main}`]: 1101,
[`${Blockchain.ZkEVM}:${NetworkId.Test}`]: 1442
};

export const DidMethodByte: { [key: string]: number } = {
[DidMethod.Iden3]: 0b00000001,
[DidMethod.PolygonId]: 0b00000010,
[DidMethod.Other]: 0b11111111
});
};

// DIDMethodNetwork is map for did methods and their blockchain networks
export const DidMethodNetwork: {
[k: string]: { [k: string]: number };
} = Object.freeze({
} = {
[DidMethod.Iden3]: {
[`${Blockchain.ReadOnly}:${NetworkId.NoNetwork}`]: 0b00000000,
[`${Blockchain.Polygon}:${NetworkId.Main}`]: 0b00010000 | 0b00000001,
Expand All @@ -100,4 +114,4 @@ export const DidMethodNetwork: {
[DidMethod.Other]: {
[`${Blockchain.Unknown}:${NetworkId.Unknown}`]: 0b11111111
}
});
};
33 changes: 8 additions & 25 deletions src/did/did-helper.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
import {
Blockchain,
Constants,
DidMethodByte,
DidMethodNetwork,
DidMethod,
NetworkId
} from '../constants';
import { Constants, DidMethodByte, DidMethodNetwork } from '../constants';

// DIDNetworkFlag is a structure to represent DID blockchain and network id
export class DIDNetworkFlag {
constructor(public readonly blockchain: Blockchain, public readonly networkId: NetworkId) {}
constructor(public readonly blockchain: string, public readonly networkId: string) {}

toString(): string {
return `${this.blockchain}:${this.networkId}`;
}

static fromString(s: string): DIDNetworkFlag {
const [blockchain, networkId] = s.split(':');
return new DIDNetworkFlag(
blockchain.replace('_', '') as Blockchain,
networkId.replace('_', '') as NetworkId
);
return new DIDNetworkFlag(blockchain.replace('_', ''), networkId.replace('_', ''));
}
}

// BuildDIDType builds bytes type from chain and network
export function buildDIDType(
method: DidMethod,
blockchain: Blockchain,
network: NetworkId
): Uint8Array {
export function buildDIDType(method: string, blockchain: string, network: string): Uint8Array {
const fb = DidMethodByte[method];
if (!fb) {
throw Constants.ERRORS.UNSUPPORTED_DID_METHOD;
Expand All @@ -53,7 +39,7 @@ export function buildDIDType(
}

// FindNetworkIDForDIDMethodByValue finds network by byte value
export function findNetworkIDForDIDMethodByValue(method: DidMethod, byteNumber: number): NetworkId {
export function findNetworkIDForDIDMethodByValue(method: string, byteNumber: number): string {
const methodMap = DidMethodNetwork[method];
if (!methodMap) {
throw Constants.ERRORS.UNSUPPORTED_DID_METHOD;
Expand All @@ -67,10 +53,7 @@ export function findNetworkIDForDIDMethodByValue(method: DidMethod, byteNumber:
}

// findBlockchainForDIDMethodByValue finds blockchain type by byte value
export function findBlockchainForDIDMethodByValue(
method: DidMethod,
byteNumber: number
): Blockchain {
export function findBlockchainForDIDMethodByValue(method: string, byteNumber: number): string {
const methodMap = DidMethodNetwork[method];
if (!methodMap) {
throw new Error(
Expand All @@ -86,10 +69,10 @@ export function findBlockchainForDIDMethodByValue(
}

// findDIDMethodByValue finds did method by its byte value
export function findDIDMethodByValue(byteNumber: number): DidMethod {
export function findDIDMethodByValue(byteNumber: number): string {
for (const [key, value] of Object.entries(DidMethodByte)) {
if (value === byteNumber) {
return key as DidMethod;
return key;
}
}
throw Constants.ERRORS.UNSUPPORTED_DID_METHOD;
Expand Down
20 changes: 10 additions & 10 deletions src/did/did.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ export class DID {
}

static decodePartsFromId(id: Id): {
method: DidMethod;
blockchain: Blockchain;
networkId: NetworkId;
method: string;
blockchain: string;
networkId: string;
} {
const method = findDIDMethodByValue(id.bytes[0]);
const blockchain = findBlockchainForDIDMethodByValue(method, id.bytes[1]);
Expand All @@ -119,22 +119,22 @@ export class DID {
return { method, blockchain, networkId };
}

static networkIdFromId(id: Id): NetworkId {
static networkIdFromId(id: Id): string {
return DID.throwIfDIDUnsupported(id).networkId;
}

static methodFromId(id: Id): DidMethod {
static methodFromId(id: Id): string {
return DID.throwIfDIDUnsupported(id).method;
}

static blockchainFromId(id: Id): Blockchain {
static blockchainFromId(id: Id): string {
return DID.throwIfDIDUnsupported(id).blockchain;
}

private static throwIfDIDUnsupported(id: Id): {
method: DidMethod;
blockchain: Blockchain;
networkId: NetworkId;
method: string;
blockchain: string;
networkId: string;
} {
const { method, blockchain, networkId } = DID.decodePartsFromId(id);

Expand Down Expand Up @@ -191,7 +191,7 @@ export class DID {
return id;
}

static isUnsupported(method: DidMethod, blockchain: Blockchain, networkId: NetworkId): boolean {
static isUnsupported(method: string, blockchain: string, networkId: string): boolean {
return (
method == DidMethod.Other &&
blockchain == Blockchain.Unknown &&
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './elemBytes';
export * from './id';
export * from './schemaHash';
export * from './utils';
export * from './registration';
157 changes: 157 additions & 0 deletions src/registration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import {
Blockchain,
ChainIds,
DidMethod,
DidMethodByte,
DidMethodNetwork,
NetworkId
} from './constants';
import { DID } from './did';

export const registerBlockchain = (blockchain: string): void => {
Blockchain[blockchain] = blockchain;
};

export const registerNetwork = (network: string): void => {
NetworkId[network] = network;
};

export const registerDidMethod = (method: string, byte: number): void => {
const existingByte = DidMethodByte[method];
if (typeof DidMethodByte[method] === 'number' && existingByte !== byte) {
throw new Error(
`DID method '${method}' already registered with byte '${existingByte.toString(2)}'`
);
}
const max = DidMethodByte[DidMethod.Other];

if (byte >= max) {
throw new Error(
`Can't register DID method byte: current '${byte.toString(2)}', maximum byte allowed: '${(
max - 1
).toString(2)}'`
);
}

DidMethod[method] = method;
DidMethodByte[method] = byte;
};

/**
* Register chain ID for a blockchain and network.
*
* @param {string} blockchain
* @param {string} network
* @param {number} [chainId]
* @returns {void}
*/
export const registerChainId = (blockchain: string, network: string, chainId: number): void => {
const key = `${blockchain}:${network}`;

if (typeof ChainIds[key] === 'number' && ChainIds[key] !== chainId) {
throw new Error(
`chainId '${blockchain}:${network}' already registered with value '${ChainIds[key]}'`
);
}

ChainIds[key] = chainId;
};

/**
* Get chain ID by a blockchain and network.
*
* @param {string} blockchain
* @param {string} [network]
* @returns {number}
*/
export const getChainId = (blockchain: string, network?: string): number => {
if (network) {
blockchain += `:${network}`;
}
const chainId = ChainIds[blockchain];
if (!chainId) {
throw new Error(`chainId not found for ${blockchain}`);
}
return chainId;
};

/**
* ChainIDfromDID returns chain name from w3c.DID
*
* @param {DID} did
* @returns {number}
*/
export const chainIDfromDID = (did: DID): number => {
const id = DID.idFromDID(did);

const blockchain = DID.blockchainFromId(id);

const networkId = DID.networkIdFromId(id);

const chainId = ChainIds[`${blockchain}:${networkId}`];
if (typeof chainId !== 'number') {
throw new Error(`chainId not found for ${blockchain}:${networkId}`);
}

return chainId;
};

/**
* Register a DID method with a byte value.
* https://docs.iden3.io/getting-started/identity/identity-types/#regular-identity
* @param {{
* method: DidMethodName; DID method name
* methodByte?: number; put DID method byte value in case you want to register new DID method
* blockchain: BlockchainName; blockchain name
* network: NetworkName; network name
* networkFlag: number; network flag
* chainId?: number; put chain ID in case you need to use it
* }} {
* method,
* methodByte,
* blockchain,
* network,
* chainId,
* networkFlag
* }
*/
export const registerDidMethodNetwork = ({
method,
methodByte,
blockchain,
network,
chainId,
networkFlag
}: {
method: string;
methodByte?: number;
blockchain: string;
network: string;
networkFlag: number;
chainId?: number;
}): void => {
registerBlockchain(blockchain);
registerNetwork(network);
if (typeof methodByte === 'number') {
registerDidMethod(method, methodByte);
}

if (!DidMethodNetwork[method]) {
DidMethodNetwork[method] = {};
}

if (typeof chainId === 'number') {
registerChainId(blockchain, network, chainId);
}

const key = `${blockchain}:${network}`;
const existedFlag = DidMethodNetwork[method][key];
if (typeof existedFlag === 'number' && existedFlag !== networkFlag) {
throw new Error(
`DID method network '${method}' with blockchain '${blockchain}' and network '${network}' already registered with another flag '${existedFlag.toString(
2
)}'`
);
}
DidMethodNetwork[method][key] = networkFlag;
};
Loading

0 comments on commit 51f411b

Please sign in to comment.