Skip to content

Commit

Permalink
Merge pull request #118 from ElrondNetwork/development
Browse files Browse the repository at this point in the history
Merge Development into Main
  • Loading branch information
andreibancioiu authored Feb 8, 2022
2 parents c1006b6 + e4923eb commit 4b1e7ee
Show file tree
Hide file tree
Showing 10 changed files with 404 additions and 107 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how

## [Unreleased]

## [9.0.2]
- [Fix recursivity issue when mapping types](https://github.com/ElrondNetwork/elrond-sdk-erdjs/pull/114).
- Bump version, since previously published `8.0.2-alpha.1` version is picked as `latest` version by npmjs.

## [9.0.1]
- [Add globals polyfill for Buffer](https://github.com/ElrondNetwork/elrond-sdk-erdjs/pull/112)

Expand Down
2 changes: 1 addition & 1 deletion 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": "@elrondnetwork/erdjs",
"version": "9.0.1",
"version": "9.0.2",
"description": "Smart Contracts interaction framework",
"main": "out/index.js",
"types": "out/index.d.js",
Expand Down
4 changes: 2 additions & 2 deletions src/smartcontracts/abi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ErrInvariantFailed } from "../errors";
import { loadAbiRegistry } from "../testutils";
import { guardValueIsSet } from "../utils";
import { guardValueIsSetWithMessage } from "../utils";
import { ContractFunction } from "./function";
import { AbiRegistry, EndpointDefinition } from "./typesystem";
import { ContractInterface } from "./typesystem/contractInterface";
Expand Down Expand Up @@ -33,7 +33,7 @@ export class SmartContractAbi {
name = name.name;
}
let result = this.getAllEndpoints().find(item => item.name === name);
guardValueIsSet("result", result);
guardValueIsSetWithMessage(`endpoint [${name}] not found`, result);
return result!;
}

Expand Down
43 changes: 38 additions & 5 deletions src/smartcontracts/codec/binary.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assert } from "chai";
import { BinaryCodec, BinaryCodecConstraints } from "./binary";
import { AddressType, AddressValue, BigIntType, BigUIntType, BigUIntValue, BooleanType, BooleanValue, I16Type, I32Type, I64Type, I8Type, NumericalType, NumericalValue, Struct, Field, StructType, TypedValue, U16Type, U32Type, U32Value, U64Type, U64Value, U8Type, U8Value, List, ListType, EnumType, EnumVariantDefinition, EnumValue, ArrayVec, ArrayVecType, U16Value } from "../typesystem";
import { AddressType, AddressValue, BigIntType, BigUIntType, BigUIntValue, BooleanType, BooleanValue, I16Type, I32Type, I64Type, I8Type, NumericalType, NumericalValue, Struct, Field, StructType, TypedValue, U16Type, U32Type, U32Value, U64Type, U64Value, U8Type, U8Value, List, ListType, EnumType, EnumVariantDefinition, EnumValue, ArrayVec, ArrayVecType, U16Value, TokenIdentifierType, TokenIdentifierValue } from "../typesystem";
import { discardSuperfluousBytesInTwosComplement, discardSuperfluousZeroBytes, isMsbOne } from "./utils";
import { Address } from "../../address";
import { Balance } from "../../balance";
Expand Down Expand Up @@ -112,7 +112,7 @@ describe("test binary codec (advanced)", () => {
assert.deepEqual(decodedTopLevel, list);
});

it("benchmark: should work well with large lists", async function() {
it("benchmark: should work well with large lists", async function () {
let numItems = 2 ** 12;
let codec = new BinaryCodec(new BinaryCodecConstraints({
maxListLength: numItems,
Expand All @@ -133,7 +133,7 @@ describe("test binary codec (advanced)", () => {
assert.equal(buffer.length, 4 + numItems * 4);

console.time("decoding");
let [decodedList, decodedLength] = codec.decodeNested<List>(buffer, new ListType(new U32Type()));
let [decodedList, decodedLength] = codec.decodeNested<List>(buffer, new ListType(new U32Type()));
console.timeEnd("decoding");
assert.equal(decodedLength, buffer.length);
assert.deepEqual(decodedList, list);
Expand Down Expand Up @@ -214,6 +214,39 @@ describe("test binary codec (advanced)", () => {
});
});

it("should encode / decode structs containing a TokenIdentifier", async () => {
let codec = new BinaryCodec();
let paymentType = new StructType(
"Payment",
[
new FieldDefinition("token_identifier", "", new TokenIdentifierType()),
new FieldDefinition("nonce", "", new U64Type()),
new FieldDefinition("amount", "", new BigUIntType()),
]
);

let paymentStruct = new Struct(paymentType, [
new Field(new TokenIdentifierValue(Buffer.from("TEST-1234")), "token_identifier"),
new Field(new U64Value(new BigNumber(42)), "nonce"),
new Field(new BigUIntValue(new BigNumber("123450000000000000000")), "amount")
]);

let encodedExpected = serialized("[00000009|544553542d31323334] [000000000000002a] [00000009|06b13680ef11f90000]");
let encoded = codec.encodeNested(paymentStruct);
assert.deepEqual(encoded, encodedExpected);

let [decoded, decodedLength] = codec.decodeNested(encodedExpected, paymentType);
assert.equal(decodedLength, encodedExpected.length);
assert.deepEqual(decoded, paymentStruct);

let decodedPayment = decoded.valueOf();
assert.deepEqual(decodedPayment, {
token_identifier: Buffer.from("TEST-1234"),
nonce: new BigNumber(42),
amount: new BigNumber("123450000000000000000"),
});
});

it("should encode / decode enums", async () => {
let codec = new BinaryCodec();
let enumType = new EnumType("Colour", [
Expand Down Expand Up @@ -263,8 +296,8 @@ describe("test binary codec (advanced)", () => {
]);

let enumType = new EnumType("Colour", [
orangeVariant,
blueVariant
orangeVariant,
blueVariant
]);

let orange = new EnumValue(enumType, orangeVariant, [
Expand Down
4 changes: 2 additions & 2 deletions src/smartcontracts/typesystem/contractInterface.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { guardValueIsSet } from "../../utils";
import { guardValueIsSetWithMessage } from "../../utils";
import { EndpointDefinition } from "./endpoint";

const NamePlaceholder = "?";
Expand Down Expand Up @@ -32,7 +32,7 @@ export class ContractInterface {

getEndpoint(name: string): EndpointDefinition {
let result = this.endpoints.find(e => e.name == name);
guardValueIsSet("result", result);
guardValueIsSetWithMessage(`endpoint [${name}] not found`, result);
return result!;
}
}
Expand Down
88 changes: 45 additions & 43 deletions src/smartcontracts/typesystem/typeMapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,59 +10,61 @@ import { OptionalType } from "./algebraic";
import { CompositeType } from "./composite";
import { ListType, OptionType } from "./generic";
import { TupleType } from "./tuple";
import { TokenIdentifierType } from "..";

type TypeConstructor = new (...typeParameters: Type[]) => Type;

describe("test mapper", () => {
let parser = new TypeExpressionParser();
let mapper = new TypeMapper();
let parser = new TypeExpressionParser();
let mapper = new TypeMapper();

it("should map primitive types", () => {
testMapping("u8", U8Type);
testMapping("u16", U16Type);
testMapping("u32", U32Type);
testMapping("u64", U64Type);
testMapping("BigUint", BigUIntType);
});
it("should map primitive types", () => {
testMapping("u8", U8Type);
testMapping("u16", U16Type);
testMapping("u32", U32Type);
testMapping("u64", U64Type);
testMapping("BigUint", BigUIntType);
testMapping("TokenIdentifier", TokenIdentifierType);
});

it("should map generic types", () => {
testMapping("Option<u64>", OptionType, [new U64Type()]);
testMapping("List<u64>", ListType, [new U64Type()]);
});
it("should map generic types", () => {
testMapping("Option<u64>", OptionType, [new U64Type()]);
testMapping("List<u64>", ListType, [new U64Type()]);
});

it("should map variadic types", () => {
testMapping("VarArgs<u32>", VariadicType, [new U32Type()]);
testMapping("VarArgs<bytes>", VariadicType, [new BytesType()]);
testMapping("MultiResultVec<u32>", VariadicType, [new U32Type()]);
testMapping("MultiResultVec<Address>", VariadicType, [new AddressType()]);
});
it("should map variadic types", () => {
testMapping("VarArgs<u32>", VariadicType, [new U32Type()]);
testMapping("VarArgs<bytes>", VariadicType, [new BytesType()]);
testMapping("MultiResultVec<u32>", VariadicType, [new U32Type()]);
testMapping("MultiResultVec<Address>", VariadicType, [new AddressType()]);
});

it("should map complex generic, composite, variadic types", () => {
testMapping("MultiResultVec<MultiResult<i32,bytes,>>", VariadicType, [
new CompositeType(new I32Type(), new BytesType()),
]);
testMapping("VarArgs<MultiArg<i32,bytes,>>", VariadicType, [new CompositeType(new I32Type(), new BytesType())]);
testMapping("OptionalResult<Address>", OptionalType, [new AddressType()]);
});
it("should map complex generic, composite, variadic types", () => {
testMapping("MultiResultVec<MultiResult<i32,bytes,>>", VariadicType, [
new CompositeType(new I32Type(), new BytesType()),
]);
testMapping("VarArgs<MultiArg<i32,bytes,>>", VariadicType, [new CompositeType(new I32Type(), new BytesType())]);
testMapping("OptionalResult<Address>", OptionalType, [new AddressType()]);
});

it("should map tuples", () => {
testMapping("tuple2<u32,bytes>", TupleType, [new U32Type(), new BytesType()]);
testMapping("tuple2<Address,BigUint>", TupleType, [new AddressType(), new BigUIntType()]);
testMapping("tuple3<u32, bytes, u64>", TupleType, [new U32Type(), new BytesType(), new U64Type()]);
//TODO: Rewrite serializer to map more complex objects
it("should map tuples", () => {
testMapping("tuple2<u32,bytes>", TupleType, [new U32Type(), new BytesType()]);
testMapping("tuple2<Address,BigUint>", TupleType, [new AddressType(), new BigUIntType()]);
testMapping("tuple3<u32, bytes, u64>", TupleType, [new U32Type(), new BytesType(), new U64Type()]);
//TODO: Rewrite serializer to map more complex objects

// After improvement enable the following test
// testMapping("tuple2<tuple3<u32, bytes, u64>, Address>", TupleType, [
// new TupleType(new Type("tuple3", [new U32Type(), new BytesType(), new U64Type()])),
// new AddressType(),
// ]);
});
// After improvement enable the following test
// testMapping("tuple2<tuple3<u32, bytes, u64>, Address>", TupleType, [
// new TupleType(new Type("tuple3", [new U32Type(), new BytesType(), new U64Type()])),
// new AddressType(),
// ]);
});

function testMapping(expression: string, constructor: TypeConstructor, typeParameters: Type[] = []) {
let type = parser.parse(expression);
let mappedType = mapper.mapType(type);
function testMapping(expression: string, constructor: TypeConstructor, typeParameters: Type[] = []) {
let type = parser.parse(expression);
let mappedType = mapper.mapType(type);

assert.instanceOf(mappedType, constructor);
assert.deepEqual(mappedType, new constructor(...typeParameters));
}
assert.instanceOf(mappedType, constructor);
assert.deepEqual(mappedType, new constructor(...typeParameters));
}
});
12 changes: 10 additions & 2 deletions src/smartcontracts/typesystem/typeMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class TypeMapper {
}
}

mapType(type: Type): Type {
mapRecursiveType(type: Type): Type | null {
let isGeneric = type.isGenericType();

if (type instanceof EnumType) {
Expand All @@ -114,13 +114,21 @@ export class TypeMapper {
// This will call mapType() recursively, for all the type parameters.
return this.mapGenericType(type);
}
return null;
}

mapType(type: Type): Type {
let mappedType = this.mapRecursiveType(type);
if (mappedType !== null) {
return mappedType;
}

let knownClosedType = this.closedTypesMap.get(type.getName());
if (!knownClosedType) {
throw new errors.ErrTypingSystem(`Cannot map the type "${type.getName()}" to a known type`);
}

return knownClosedType;
return this.mapRecursiveType(knownClosedType) ?? knownClosedType;
}

feedCustomType(type: Type): void {
Expand Down
47 changes: 45 additions & 2 deletions src/smartcontracts/wrapper/esdt.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Address, ContractWrapper, createBalanceBuilder, Egld, Token, SystemWrapper, TokenType, setupInteractiveWithProvider } from "../..";
import { isOnBrowserTests, MockProvider, setupUnitTestWatcherTimeouts, TestWallet } from "../../testutils";
import { assert } from "chai";
import { ArgSerializer } from "..";
import BigNumber from "bignumber.js";

describe("test ESDT transfers via the smart contract wrapper", async function () {
let dummyAddress = new Address("erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3");
Expand All @@ -18,7 +20,7 @@ describe("test ESDT transfers via the smart contract wrapper", async function ()
market.address(dummyAddress).sender(alice).gas(500_000);
});

it("calling ", async function () {
it("formats the call arguments with an NFT transfer", async function () {
setupUnitTestWatcherTimeouts();

let minBid = 100;
Expand All @@ -45,7 +47,48 @@ describe("test ESDT transfers via the smart contract wrapper", async function ()
"544553542d31323334",
"1388"
]);
});
})

it("binary codec encodes / decodes the result of getAllAuctions", async function () {
let definitions = market.getSmartContract().getAbi().getEndpoint("getAllAuctions").output;
let data = "AAAAAAAAABAAAAALVEVTVC1mZWVkNjAAAAAAAAAAAQAAAAEBAQAAAARFR0xEAAAAAAAAAAAAAAAIDeC2s6dkAAABAAAACIrHIwSJ6AAAAAAAAGH5jkwAAAAAYfmYSHcAUz3KJ/38F1qkbu0H68K6R6XlPs1xLnqrL6ipWMb5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgPoAAAAAgnE";
let serializer = new ArgSerializer();

const values = serializer.buffersToValues([Buffer.from(data, 'base64')], definitions);

assert.equal(values.length, 1);
const value = values[0].valueOf();

const expected = Array.from([{
field0: new BigNumber(16),
field1: {
auction_type: {
fields: [],
name: "Nft"
},
auctioned_token: {
nonce: new BigNumber(1),
token_type: Buffer.from("TEST-feed60"),
},
creator_royalties_percentage: new BigNumber(2500),
current_bid: new BigNumber(0),
current_winner: new Address("0000000000000000000000000000000000000000000000000000000000000000"),
deadline: new BigNumber(1643747400),
marketplace_cut_percentage: new BigNumber(1000),
max_bid: new BigNumber("10000000000000000000"),
min_bid: new BigNumber("1000000000000000000"),
nr_auctioned_tokens: new BigNumber(1),
original_owner: new Address("erd1wuq9x0w2yl7lc96653hw6pltc2ay0f098mxhztn64vh6322ccmussa83g9"),
payment_token: {
nonce: new BigNumber(0),
token_type: Buffer.from("EGLD")
},
start_time: new BigNumber(1643744844)
}
}]);

assert.deepEqual(value, expected);
})
});

function callBuffersToStrings(values: Buffer[]): string[] {
Expand Down
Loading

0 comments on commit 4b1e7ee

Please sign in to comment.