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

fix!: refactor bindgen and update node versions #581

Closed
wants to merge 13 commits into from
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
platform: [ubuntu-latest, macos-latest]
nodeversion: ['12.x', '13.x', '14.x', '15.x']
nodeversion: ['14.x', '15.x', '16.x']
steps:
- uses: actions/checkout@v2
- name: Use Node.js v"${{ matrix.nodeversion }}""
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -28,3 +28,4 @@ build/
sim-ffi/sim-ffi/target/

sim-ffi/sim-ffi/index.node
sim-ffi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could remove the previous two file patterns here

25 changes: 13 additions & 12 deletions bindgen/assembly/__tests__/model.ts
@@ -1,8 +1,9 @@
// @nearfile out
import { u128 } from "near-sdk-core";

@nearBindgen
export class FooBar {
foo: i32 = 0;
foo: i32 = 42;
bar: u32 = 1;
u64Val: u64 = 4294967297;
u64_zero: u64;
Expand All @@ -13,26 +14,26 @@ export class FooBar {
f64_zero: f64;
flag: bool;
baz: string = "123";
uint8array: Uint8Array;
arr: Array<Array<string>>;
u32Arr: u32[];
i32Arr: i32[];
u128Val: u128;
uint8arrays: Array<Uint8Array>;
uint8array: Uint8Array = new Uint8Array(0);
arr: Array<Array<string>> | null;
u32Arr: u32[] = [];
i32Arr: i32[] = [];
u128Val: u128 | null;
uint8arrays: Array<Uint8Array> = [];
// TODO: Fix u64 arrays
u64Arr: u64[];
u64Arr: u64[] = [];
}

@nearBindgen
export class Nullables {
str: string;
u128: u128;
uint8Array: Uint8Array;
str: string | null;
u128: u128 | null;
uint8Array: Uint8Array | null;
}

@nearBindgen
export class ContainerClass {
foobar: FooBar;
foobar: FooBar | null;
}

@nearBindgen
Expand Down
66 changes: 37 additions & 29 deletions bindgen/assembly/__tests__/test.ts
@@ -1,14 +1,15 @@
// @nearfile out
import * as main from "./main";
import { base64, logging, u128 } from "near-sdk-as";
import { base64, logging, u128, JSON, util } from "near-sdk-as";
import {
FooBar,
Nullables,
ContainerClass,
AnotherContainerClass,
} from "./model";

function roundtrip<T>(obj: T): T {
return decode<T>(encode<T>(obj));
function roundTrip<T>(obj: T): T {
return JSON.parse<T>(JSON.stringify<T>(obj));
}

function isNull<T>(t: T): bool {
Expand All @@ -24,8 +25,16 @@ function equalFloat(f: f64, f1: f64): boolean {
return Math.abs(f - f1) < SMALL_FLOAT;
}

function decodeJSON<T>(encoded: Uint8Array): T {
const str = util.bytesToString(encoded)!;
return JSON.parse<T>(str);
}

function encodeJSON<T>(t: T): Uint8Array {
return util.stringToBytes(JSON.stringify<T>(t));
}

export function runTest(): void {
logging.log("starting test");
const original = new FooBar();
original.u32Arr = [42, 11];
original.foo = 321;
Expand All @@ -39,15 +48,11 @@ export function runTest(): void {
original.uint8arrays[0] = base64.decode("aGVsbG8sIHdvcmxkIQ==");
original.uint8arrays[1] = base64.decode("aGVsbG8sIHdvcmxkIQ==");
original.u64Arr = [10000000000, 100000000000];
// @ts-ignore
logging.log("Before: " + original.toJSON());
// @ts-ignore
const encoded = original.encode();
// @ts-ignore
let decoded: FooBar = decode<FooBar>(encoded);
logging.log("After: " + decoded.toJSON());
let decodedStatic: FooBar = FooBar.decode(encoded);
assert(decoded.toJSON() == decodedStatic.toJSON());

const encoded = encodeJSON(original);
let decoded: FooBar = decodeJSON<FooBar>(encoded);
let decodedStatic: FooBar = decodeJSON<FooBar>(encoded);
assert(JSON.stringify(decoded) == JSON.stringify(decodedStatic));
assert(original.foo == decoded.foo);
assert(original.bar == decoded.bar);
assert(
Expand All @@ -57,53 +62,56 @@ export function runTest(): void {
base64.encode(original.uint8arrays[0]) ==
base64.encode(decoded.uint8arrays[0])
);
assert(original.arr[0][0] == "Hello");
assert(original.arr![0][0] == "Hello");
assert(original.u64Arr[0] == decoded.u64Arr[0]);
assert(original.u64_zero == decoded.u64_zero);

const nullable = new Nullables();
logging.log(String.UTF8.decode(nullable.encode().buffer));
// @ts-ignore
const nullable2 = decode<Nullables>(nullable.encode());

const nullable2 = roundTrip(nullable);
assert(nullable2.str == null);
logging.log(isNull(nullable2.u128).toString());
assert(
isNull(nullable2.uint8Array),
"expected nullable2.uint8Array to be null"
);

const foobar2 = new FooBar();
foobar2.arr = [];
const foobar2_ = decode<FooBar>(foobar2.encode());
assert(foobar2_.arr.length == foobar2.arr.length);
const foobar2_ = roundTrip(foobar2);
assert(foobar2_.arr!.length == foobar2.arr!.length);

// Handle arrays without field;
const arr: u64[] = [123456789];
const encodedArr: Uint8Array = encode<u64[]>(arr);
const arr2: u64[] = decode<u64[]>(encodedArr);
const arr2: u64[] = decodeJSON<u64[]>(encodedArr);
assert(arr[0] == arr2[0]);
assert(original.f32 == decoded.f32);
assert(original.f64 == decoded.f64);
assert(original.f32_zero == decoded.f32_zero);
assert(original.f64_zero == decoded.f64_zero);

assert(roundtrip<f32>(3.4) == 3.4);
assert(roundTrip<f32>(3.4) == 3.4);

assert(roundtrip<u64[]>([]).length == 0);
assert(roundtrip<i32>(42) == 42);
assert(roundtrip<i64>(42) == 42);
assert(roundTrip<u64[]>([]).length == 0);
assert(roundTrip<i32>(42) == 42);
assert(roundTrip<i64>(42) == 42);
const str = roundTrip<string>("hello world");
assert(
roundtrip<string>("hello world") == "hello world",
'expected "hello world"'
str == "hello world",
'expected "hello world" + got '+ str
);
assert(roundtrip<u128>(new u128(42, 42)).lo == 42);
assert(roundTrip<u128>(new u128(42, 42)).lo == 42);

logging.log("Test Passed");
}

function _convertFoobars(foobars: Array<FooBar>): Array<ContainerClass> {
return foobars.map<ContainerClass>((foobar) => ({ foobar }));
}

export function convertFoobars(foobars: Array<FooBar>): Array<ContainerClass> {
// @ts-ignore will be converted when parsed
return main.convertFoobars(foobars);
return _convertFoobars(foobars);
}

export function getStringArrayLength(arr: string[]): i32 {
Expand Down
2 changes: 2 additions & 0 deletions bindgen/assembly/as_types.d.ts
@@ -0,0 +1,2 @@
/// <reference types="near-sdk-as/assembly/as_types" />
declare function ExternalContract<T extends { new (...args: any[]): {} }>(constructor: T): T & any;