Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1114 class revision #1175

Merged
merged 3 commits into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/diagrams/architecture/vcdm.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ classDiagram
class Quantity {
+Quantity of(bigint|number exp)$
}
class Revision {
+boolean isValid(number|string value)$
+Revision of(bigint|number|string|Uint8Array|Hex value)$
}
class Sha256 {
+Sha256 of(bigint|number|string|Uint8Array|Hex exp)$
}
Expand Down Expand Up @@ -62,6 +66,7 @@ classDiagram
HexUInt <|-- Quantity
HexUInt <|-- Sha256
String <|-- Txt
Txt <|-- Revision
VeChainDataModel <|.. Hex
VeChainDataModel <|.. Txt
```
1 change: 0 additions & 1 deletion packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ export * from './data';
export * from './hdnode';
export * from './transaction';
export * from './units';
export * from './revision';
1 change: 0 additions & 1 deletion packages/core/src/utils/revision/index.ts

This file was deleted.

42 changes: 0 additions & 42 deletions packages/core/src/utils/revision/revision.ts

This file was deleted.

8 changes: 4 additions & 4 deletions packages/core/src/vcdm/Hex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Hex implements VeChainDataModel<Hex> {
*
* @type {RegExp}
*/
protected static readonly REGEX_PREFIX: RegExp = /^-?0x/i;
protected static readonly REGEX_HEX_PREFIX: RegExp = /^-?0x/i;

/**
* Returns the hexadecimal digits expressing this absolute value, sign and `0x` prefix omitted.
Expand Down Expand Up @@ -249,7 +249,7 @@ class Hex implements VeChainDataModel<Hex> {
* @return {boolean} - True if the string is a valid hexadecimal number prefixed with '0x', otherwise false.
*/
public static isValid0x(exp: string): boolean {
return Hex.REGEX_PREFIX.test(exp) && Hex.isValid(exp);
return Hex.REGEX_HEX_PREFIX.test(exp) && Hex.isValid(exp);
}

/**
Expand Down Expand Up @@ -292,14 +292,14 @@ class Hex implements VeChainDataModel<Hex> {
if (exp.startsWith('-')) {
return new Hex(
this.NEGATIVE,
this.REGEX_PREFIX.test(exp)
this.REGEX_HEX_PREFIX.test(exp)
? exp.slice(3)
: exp.slice(1)
);
}
return new Hex(
this.POSITIVE,
this.REGEX_PREFIX.test(exp) ? exp.slice(2) : exp
this.REGEX_HEX_PREFIX.test(exp) ? exp.slice(2) : exp
);
}
// noinspection ExceptionCaughtLocallyJS
Expand Down
43 changes: 40 additions & 3 deletions packages/core/src/vcdm/HexUInt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,43 @@ import { InvalidDataType } from '@vechain/sdk-errors';
* @extends HexInt
*/
class HexUInt extends HexInt {
/**
* Regular expression for matching hexadecimal strings.
* An empty input is represented as a empty digits.
*
* @type {RegExp}
*/
private static readonly REGEX_HEXUINT: RegExp = /^(0x)?[0-9a-f]*$/i;

/**
* Regular expression pattern to match a prefix indicating hexadecimal number.
*
* @type {RegExp}
*/
protected static readonly REGEX_HEXUINT_PREFIX: RegExp = /^0x/i;

/**
* Checks if the given string expression is a valid unsigned hexadecimal value.
*
* @param {string} exp - The string representation of a hexadecimal value.
*
* @return {boolean} - True if the expression is a valid unsigned hexadecimal value, case-insensitive,
* optionally prefixed with `0x`; false otherwise.
*/
public static isValid(exp: string): boolean {
return HexUInt.REGEX_HEXUINT.test(exp);
}

/**
* Determines whether the given string is a valid unsigned hexadecimal number prefixed with '0x'.
*
* @param {string} exp - The string to be evaluated.
* @return {boolean} - True if the string is a valid unsigned hexadecimal number prefixed with '0x', otherwise false.
*/
public static isValid0x(exp: string): boolean {
return HexUInt.REGEX_HEX_PREFIX.test(exp) && Hex.isValid(exp);
}

/**
* Create a HexUInt instance from a bigint, number, string, Uint8Array, or {@link HexInt}.
*
Expand All @@ -30,9 +67,9 @@ class HexUInt extends HexInt {
exp: bigint | number | string | Uint8Array | HexInt
): HexUInt {
try {
const hxi = HexInt.of(exp);
if (hxi.sign >= Hex.POSITIVE) {
return new HexUInt(hxi.sign, hxi.digits);
const hint = HexInt.of(exp);
if (hint.sign >= Hex.POSITIVE) {
return new HexUInt(hint.sign, hint.digits);
}
throw new InvalidDataType(
'HexUInt.of',
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/vcdm/Quantity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ class Quantity extends HexUInt {
*/
public static of(exp: bigint | number): Quantity {
try {
const hxu = HexUInt.of(exp);
const huint = HexUInt.of(exp);
let cue = 0;
while (cue < hxu.digits.length && hxu.digits.at(cue) === '0') {
while (cue < huint.digits.length && huint.digits.at(cue) === '0') {
cue++;
}
return new Quantity(
hxu.sign,
cue === hxu.digits.length ? '0' : hxu.digits.slice(cue)
huint.sign,
cue === huint.digits.length ? '0' : huint.digits.slice(cue)
);
} catch (e) {
throw new InvalidDataType(
Expand Down
94 changes: 94 additions & 0 deletions packages/core/src/vcdm/Revision.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Txt } from './Txt';
import { Hex } from './Hex';
import { InvalidDataType } from '@vechain/sdk-errors';
import { HexUInt } from './HexUInt';

/**
* Represents a revision for a Thor transaction or block.
*
* @remark The string representation of the revision is always expressed as a number in base 10.
*
* @extends Txt
*/
class Revision extends Txt {
/**
lucanicoladebiasi marked this conversation as resolved.
Show resolved Hide resolved
* Regular expression pattern for revision strings.
* Revision strings can be one of the following:
* - "best": indicating the best revision
* - "finalized": indicating a finalized revision
* - A positive numeric string indicating a specific revision
*
* @type {RegExp}
*/
private static readonly REGEX_DECIMAL_REVISION = /^(best|finalized|\d+)$/;

/**
* Determines if the given value is valid.
* This is true if the given value is
* - "best" string or {@link Txt}: indicating the best revision;
* - "finalized" string or {@link Txt}: indicating a finalized revision;
* - a positive number;
* - a positive numeric decimal or `0x` prefixed hexadecimal string indicating a specific revision,
*
* @param {bigint | number | string | Hex | Txt} value - The value to be validated.
* @returns {boolean} - Returns `true` if the value is valid, `false` otherwise.
*/
public static isValid(value: number | string): boolean {
if (typeof value === 'number') {
return Number.isInteger(value) && value >= 0;
}
return (
HexUInt.isValid0x(value) ||
Revision.REGEX_DECIMAL_REVISION.test(value)
);
}

/**
* Creates a new Revision object from the given value.
*
* @param {bigint | number | string | Uint8Array | Hex } value - The value to create the Revision from:
* * {@link Hex} must be positive;
* * {@link Uint8Array} is decoded as a string: see {@link Txt.of}.
*
* @returns {Revision} - The created Revision object.
*
* @throws {InvalidDataType} if the given value is not a valid revision: see {@link isValid}.
*
* @remark The string representation of the revision is always expressed as a number in base 10.
* @remark The {@link Uint8Array} value is decoded as a string content: see {@link Txt.of}.
*/
public static of(value: bigint | number | string | Uint8Array | Hex): Txt {
try {
let txt: string;
if (value instanceof Hex) {
txt = value.bi.toString();
} else if (value instanceof Uint8Array) {
txt = Txt.of(value).toString();
} else {
txt = `${value}`;
}
if (Revision.isValid(txt)) {
return new Revision(txt);
}
throw new InvalidDataType('Revision.of', 'not a revision', {
value: `${value}`
});
} catch (e) {
throw new InvalidDataType('Revision.of', 'not a revision', {
value: `${value}`,
e
});
}
}
}

// TODO: Backwards compatibility, remove when it is matured enough

Check warning on line 85 in packages/core/src/vcdm/Revision.ts

View workflow job for this annotation

GitHub Actions / install-build / Build & Lint

Unexpected 'todo' comment: 'TODO: Backwards compatibility, remove...'

const revisionUtils = {
isRevisionAccount: (revision: string | number): boolean =>
Revision.isValid(revision),
isRevisionBlock: (revision: string | number): boolean =>
Revision.isValid(revision)
};

export { Revision, revisionUtils };
4 changes: 2 additions & 2 deletions packages/core/src/vcdm/ThorId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ThorId extends Hex {
* @experimental
*/
public static isValid(exp: string): boolean {
return Hex.isValid(exp) && Hex.REGEX_PREFIX.test(exp)
return Hex.isValid(exp) && Hex.REGEX_HEX_PREFIX.test(exp)
? exp.length === ThorId.DIGITS + 2
: exp.length === ThorId.DIGITS;
}
Expand All @@ -54,7 +54,7 @@ class ThorId extends Hex {
* @experimental
*/
public static isValid0x(exp: string): boolean {
return Hex.REGEX_PREFIX.test(exp) && ThorId.isValid(exp);
return Hex.REGEX_HEX_PREFIX.test(exp) && ThorId.isValid(exp);
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/vcdm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './Hex';
export * from './HexInt';
export * from './HexUInt';
export * from './Quantity';
export * from './Revision';
export * from './ThorId';
export * from './Txt';
export * from './VeChainDataModel';
6 changes: 3 additions & 3 deletions packages/core/tests/utils/revision/revision.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, test } from '@jest/globals';
import { accountRevisions, blockRevisions } from './fixture';
import { revisionUtils } from '../../../src';
import { Revision } from '../../../src';

/**
* Unit tests for the blockUtils module.
Expand All @@ -13,7 +13,7 @@ describe('blockUtils', () => {
*/
test('isBlockRevision', () => {
blockRevisions.forEach(({ revision, expected }) => {
expect(revisionUtils.isRevisionBlock(revision)).toBe(expected);
expect(Revision.isValid(revision)).toBe(expected);
});
});

Expand All @@ -22,7 +22,7 @@ describe('blockUtils', () => {
*/
test('isAccountRevision', () => {
accountRevisions.forEach(({ revision, expected }) => {
expect(revisionUtils.isRevisionAccount(revision)).toBe(expected);
expect(Revision.isValid(revision)).toBe(expected);
});
});
});
2 changes: 1 addition & 1 deletion packages/core/tests/vcdm/Quantity.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { InvalidDataType } from '@vechain/sdk-errors';
import { Hex, Quantity } from '../../src';

/**
* Test HexInt class.
* Test Quantity class.
* @group unit/vcdm
*/
describe('Quantity class tests', () => {
Expand Down
Loading
Loading