Skip to content

Commit

Permalink
Merge pull request #165 from ElrondNetwork/classnames-10-beta
Browse files Browse the repository at this point in the history
erdjs v10 (beta): Hardcode class names for classes within erdjs' typesystem.
  • Loading branch information
andreibancioiu authored Mar 25, 2022
2 parents 5d27b02 + bd82b74 commit 012f3ea
Show file tree
Hide file tree
Showing 25 changed files with 435 additions and 78 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
.PHONY: clean browser-tests

browser-tests: out-browser-tests/erdjs-tests-unit.js out-browser-tests/erdjs-tests-localnet.js out-browser-tests/erdjs-tests-devnet.js out-browser-tests/erdjs-tests-testnet.js out-browser-tests/erdjs-tests-mainnet.js
browser-tests: out-browser-tests/erdjs-tests-unit.js out-browser-tests/erdjs-tests-unit-min.js out-browser-tests/erdjs-tests-localnet.js out-browser-tests/erdjs-tests-devnet.js out-browser-tests/erdjs-tests-testnet.js out-browser-tests/erdjs-tests-mainnet.js

out-browser-tests/erdjs-tests-unit.js: out-tests
npx browserify $(shell find out-tests -type f -name '*.js' ! -name '*.net.spec.*') --require buffer/:buffer -o out-browser-tests/erdjs-tests-unit.js --standalone erdjs-tests -p esmify

out-browser-tests/erdjs-tests-unit-min.js: out-tests
npx browserify $(shell find out-tests -type f -name '*.js' ! -name '*.net.spec.*') --require buffer/:buffer -o out-browser-tests/erdjs-tests-unit-min.js --standalone erdjs-tests -p esmify -p tinyify

out-browser-tests/erdjs-tests-localnet.js: out-tests
npx browserify $(shell find out-tests -type f -name '*.js' ! -name '*.spec.*') $(shell find out-tests -type f -name '*.local.net.spec.js') --require buffer/:buffer -o out-browser-tests/erdjs-tests-localnet.js --standalone erdjs-tests -p esmify

Expand Down
5 changes: 5 additions & 0 deletions browser-tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
Unit tests
</button>
</li>
<li class="list-group-item">
<button class="btn btn-link" onclick="runTests('/out-browser-tests/erdjs-tests-unit-min.js')">
Unit tests (minified code)
</button>
</li>
<li class="list-group-item">
<button class="btn btn-link" onclick="runTests('/out-browser-tests/erdjs-tests-localnet.js')">
Integration tests - local testnet
Expand Down
10 changes: 0 additions & 10 deletions src/reflection.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
export function hasJavascriptConstructor(obj: Object, javascriptConstructorName: string): boolean {
return obj.constructor.name == javascriptConstructorName;
}

export function getJavascriptConstructorsNamesInHierarchy(obj: Object, filter: (prototype: any) => boolean): string[] {
let prototypes = getJavascriptPrototypesInHierarchy(obj, filter);
let constructorNames = prototypes.map(prototype => prototype.constructor.name);
return constructorNames;
}

export function getJavascriptPrototypesInHierarchy(obj: Object, filter: (prototype: any) => boolean): Object[] {
let prototypes: Object[] = [];
let prototype: any = Object.getPrototypeOf(obj);
Expand Down
12 changes: 6 additions & 6 deletions src/smartcontracts/argSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,18 @@ export class ArgSerializer {
function readValue(type: Type): TypedValue {
// TODO: Use matchers.

if (type.hasJavascriptConstructor(OptionalType.name)) {
if (type.hasExactClass(OptionalType.ClassName)) {
let typedValue = readValue(type.getFirstTypeParameter());
return new OptionalValue(type, typedValue);
} else if (type.hasJavascriptConstructor(VariadicType.name)) {
} else if (type.hasExactClass(VariadicType.ClassName)) {
let typedValues = [];

while (!hasReachedTheEnd()) {
typedValues.push(readValue(type.getFirstTypeParameter()));
}

return new VariadicValue(type, typedValues);
} else if (type.hasJavascriptConstructor(CompositeType.name)) {
} else if (type.hasExactClass(CompositeType.ClassName)) {
let typedValues = [];

for (const typeParameter of type.getTypeParameters()) {
Expand Down Expand Up @@ -132,17 +132,17 @@ export class ArgSerializer {
function handleValue(value: TypedValue): void {
// TODO: Use matchers.

if (value.hasJavascriptConstructor(OptionalValue.name)) {
if (value.hasExactClass(OptionalValue.ClassName)) {
let valueAsOptional = <OptionalValue>value;
if (valueAsOptional.isSet()) {
handleValue(valueAsOptional.getTypedValue());
}
} else if (value.hasJavascriptConstructor(VariadicValue.name)) {
} else if (value.hasExactClass(VariadicValue.ClassName)) {
let valueAsVariadic = <VariadicValue>value;
for (const item of valueAsVariadic.getItems()) {
handleValue(item);
}
} else if (value.hasJavascriptConstructor(CompositeValue.name)) {
} else if (value.hasExactClass(CompositeValue.ClassName)) {
let valueAsComposite = <CompositeValue>value;
for (const item of valueAsComposite.getItems()) {
handleValue(item);
Expand Down
4 changes: 2 additions & 2 deletions src/smartcontracts/typesystem/abiRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,15 @@ export class AbiRegistry {
return names.map((name) => this.getInterface(name));
}
getStruct(name: string): StructType {
let result = this.customTypes.find((e) => e.getName() == name && e.hasJavascriptConstructor(StructType.name));
let result = this.customTypes.find((e) => e.getName() == name && e.hasExactClass(StructType.ClassName));
guardValueIsSetWithMessage(`struct [${name}] not found`, result);
return <StructType>result!;
}
getStructs(names: string[]): StructType[] {
return names.map((name) => this.getStruct(name));
}
getEnum(name: string): EnumType {
let result = this.customTypes.find((e) => e.getName() == name && e.hasJavascriptConstructor(EnumType.name));
let result = this.customTypes.find((e) => e.getName() == name && e.hasExactClass(EnumType.ClassName));
guardValueIsSetWithMessage(`enum [${name}] not found`, result);
return <EnumType>result!;
}
Expand Down
11 changes: 11 additions & 0 deletions src/smartcontracts/typesystem/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,33 @@ import { Address } from "../../address";
import { PrimitiveType, PrimitiveValue } from "./types";

export class AddressType extends PrimitiveType {
static ClassName = "AddressType";

constructor() {
super("Address");
}

getClassName(): string {
return AddressType.ClassName;
}
}

/**
* An address fed to or fetched from a Smart Contract contract, as an immutable abstraction.
*/
export class AddressValue extends PrimitiveValue {
static ClassName = "AddressValue";
private readonly value: Address;

constructor(value: Address) {
super(new AddressType());
this.value = value;
}

getClassName(): string {
return AddressValue.ClassName;
}

/**
* Returns whether two objects have the same value.
*
Expand Down
15 changes: 13 additions & 2 deletions src/smartcontracts/typesystem/algebraic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,29 @@ import { NullType, Type, TypeCardinality, TypedValue } from "./types";
* An optional is an algebraic type. It holds zero or one values.
*/
export class OptionalType extends Type {
static ClassName = "OptionalType";

constructor(typeParameter: Type) {
super("Optional", [typeParameter], TypeCardinality.variable(1));
}

getClassName(): string {
return OptionalType.ClassName;
}

isAssignableFrom(type: Type): boolean {
if (!(type.hasJavascriptConstructor(OptionalType.name))) {
if (!(type.hasExactClass(OptionalType.ClassName))) {
return false;
}

let invariantTypeParameters = this.getFirstTypeParameter().equals(type.getFirstTypeParameter());
let fakeCovarianceToNull = type.getFirstTypeParameter().hasJavascriptConstructor(NullType.name);
let fakeCovarianceToNull = type.getFirstTypeParameter().hasExactClass(NullType.ClassName);
return invariantTypeParameters || fakeCovarianceToNull;
}
}

export class OptionalValue extends TypedValue {
static ClassName = "OptionalValue";
private readonly value: TypedValue | null;

constructor(type: OptionalType, value: TypedValue | null = null) {
Expand All @@ -31,6 +38,10 @@ export class OptionalValue extends TypedValue {
this.value = value;
}

getClassName(): string {
return OptionalValue.ClassName;
}

/**
* Creates an OptionalValue, as not provided (missing).
*/
Expand Down
11 changes: 11 additions & 0 deletions src/smartcontracts/typesystem/boolean.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import { PrimitiveType, PrimitiveValue } from "./types";

export class BooleanType extends PrimitiveType {
static ClassName = "BooleanType";

constructor() {
super("bool");
}

getClassName(): string {
return BooleanType.ClassName;
}
}

/**
* A boolean value fed to or fetched from a Smart Contract contract, as an immutable abstraction.
*/
export class BooleanValue extends PrimitiveValue {
static ClassName = "BooleanValue";
private readonly value: boolean;

constructor(value: boolean) {
super(new BooleanType());
this.value = value;
}

getClassName(): string {
return BooleanValue.ClassName;
}

/**
* Returns whether two objects have the same value.
*
Expand Down
12 changes: 11 additions & 1 deletion src/smartcontracts/typesystem/bytes.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
import * as errors from "../../errors";
import { PrimitiveType, PrimitiveValue } from "./types";

export class BytesType extends PrimitiveType {
static ClassName = "BytesType";

constructor() {
super("bytes");
}

getClassName(): string {
return BytesType.ClassName;
}
}

export class BytesValue extends PrimitiveValue {
static ClassName = "BytesValue";
private readonly value: Buffer;

constructor(value: Buffer) {
super(new BytesType());
this.value = value;
}

getClassName(): string {
return BytesValue.ClassName;
}

/**
* Creates a BytesValue from a utf-8 string.
*/
Expand Down
11 changes: 11 additions & 0 deletions src/smartcontracts/typesystem/composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ import { guardLength } from "../../utils";
import { Type, TypeCardinality, TypedValue } from "./types";

export class CompositeType extends Type {
static ClassName = "CompositeType";

constructor(...typeParameters: Type[]) {
super("Composite", typeParameters, TypeCardinality.variable(typeParameters.length));
}

getClassName(): string {
return CompositeType.ClassName;
}
}

export class CompositeValue extends TypedValue {
static ClassName = "CompositeValue";
private readonly items: TypedValue[];

constructor(type: CompositeType, items: TypedValue[]) {
Expand All @@ -20,6 +27,10 @@ export class CompositeValue extends TypedValue {
this.items = items;
}

getClassName(): string {
return CompositeValue.ClassName;
}

static fromItems(...items: TypedValue[]): CompositeValue {
let typeParameters = items.map(value => value.getType());
let type = new CompositeType(...typeParameters);
Expand Down
10 changes: 10 additions & 0 deletions src/smartcontracts/typesystem/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ import { CustomType, TypedValue } from "./types";
const SimpleEnumMaxDiscriminant = 256;

export class EnumType extends CustomType {
static ClassName = "EnumType";
readonly variants: EnumVariantDefinition[] = [];

constructor(name: string, variants: EnumVariantDefinition[]) {
super(name);
this.variants = variants;
}

getClassName(): string {
return EnumType.ClassName;
}

static fromJSON(json: { name: string; variants: any[] }): EnumType {
let variants = (json.variants || []).map((variant) => EnumVariantDefinition.fromJSON(variant));
return new EnumType(json.name, variants);
Expand Down Expand Up @@ -58,6 +63,7 @@ export class EnumVariantDefinition {
}

export class EnumValue extends TypedValue {
static ClassName = "EnumValue";
readonly name: string;
readonly discriminant: number;
private readonly fields: Field[] = [];
Expand All @@ -74,6 +80,10 @@ export class EnumValue extends TypedValue {
Fields.checkTyping(this.fields, definitions);
}

getClassName(): string {
return EnumValue.ClassName;
}

/**
* Utility (named constructor) to create a simple (i.e. without fields) enum value.
*/
Expand Down
26 changes: 24 additions & 2 deletions src/smartcontracts/typesystem/generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,43 @@ import { Type, TypedValue, NullType, TypePlaceholder } from "./types";

// TODO: Move to a new file, "genericOption.ts"
export class OptionType extends Type {
static ClassName = "OptionType";

constructor(typeParameter: Type) {
super("Option", [typeParameter]);
}

getClassName(): string {
return OptionType.ClassName;
}

isAssignableFrom(type: Type): boolean {
if (!(type.hasJavascriptConstructor(OptionType.name))) {
if (!(type.hasExactClass(OptionType.ClassName))) {
return false;
}

let invariantTypeParameters = this.getFirstTypeParameter().equals(type.getFirstTypeParameter());
let fakeCovarianceToNull = type.getFirstTypeParameter().hasJavascriptConstructor(NullType.name);
let fakeCovarianceToNull = type.getFirstTypeParameter().hasExactClass(NullType.ClassName);
return invariantTypeParameters || fakeCovarianceToNull;
}
}

// TODO: Move to a new file, "genericList.ts"
export class ListType extends Type {
static ClassName = "ListType";

constructor(typeParameter: Type) {
super("List", [typeParameter]);
}

getClassName(): string {
return ListType.ClassName;
}
}

// TODO: Move to a new file, "genericOption.ts"
export class OptionValue extends TypedValue {
static ClassName = "OptionValue";
private readonly value: TypedValue | null;

constructor(type: OptionType, value: TypedValue | null = null) {
Expand All @@ -38,6 +51,10 @@ export class OptionValue extends TypedValue {
this.value = value;
}

getClassName(): string {
return OptionValue.ClassName;
}

/**
* Creates an OptionValue, as a missing option argument.
*/
Expand Down Expand Up @@ -80,6 +97,7 @@ export class OptionValue extends TypedValue {
// TODO: Rename to ListValue, for consistency (though the term is slighly unfortunate).
// Question for review: or not?
export class List extends TypedValue {
static ClassName = "List";
private readonly backingCollection: CollectionOfTypedValues;

/**
Expand All @@ -95,6 +113,10 @@ export class List extends TypedValue {
this.backingCollection = new CollectionOfTypedValues(items);
}

getClassName(): string {
return List.ClassName;
}

static fromItems(items: TypedValue[]): List {
if (items.length == 0) {
return new List(new TypePlaceholder(), []);
Expand Down
Loading

0 comments on commit 012f3ea

Please sign in to comment.