near / near-sdk-as

Tools for building NEAR smart contracts in AssemblyScript
https://near.github.io/near-sdk-as/
Other
115 stars 43 forks source link

nearBindgen does not support child classes #695

Open tituszban opened 2 years ago

tituszban commented 2 years ago

As detailed on [StackOverflow](https://stackoverflow.com/questions/70916471/does-persistentvector-not-support-child-classes) @nearBindgen doesn't seem to support child classes.

To Reproduce

 // index.ts

import 

 { PersistentVector } 

 from "near-sdk-as";

@nearBindgen
 class Base {
 constructor(
 public value1: u64
 ) { }
 }

@nearBindgen
 class Child extends Base {
 constructor(
 value1: u64,
 public value2: u64
 ) 

 { super(value1); } 

}

@nearBindgen
 export class Contract {
 private pers: PersistentVector<Base> = new PersistentVector<Base>("vec");

 add(value1: u64, value2: u64): Child 

 { const c = new Child(value1, value2); this.pers.pushBack(c); return c; } 

 get(): Array<Base> {
 const res: Array<Base> = [];

 for (let i = 0; i < this.pers.length; i++) 

 { res.push(this.pers[i]); } 

 return res;
 }
 }

// index.unit.spec.ts

import 

 { Contract } 

 from "../assembly/index";

let cont: Contract

beforeEach(() => 

 { cont = new Contract(); } 

)

describe("Contract", () => {

 it("add returns correct value", () => 

 { const result = cont.add(7, 3); expect(result.value1).toBe(7); expect(result.value2).toBe(3); } 

);

 it("get after add returns 1 correct value", () => 

 { cont.add(7, 3); const results = cont.get(); expect(results).toHaveLength(1); const result = results[0]; expect(result.value1).toBe(7); } 

);
 })

It throws the following error:

 <span class="error">[Describe]</span>: Contract

 <span class="error">[Success]</span>: ✔ add returns correct value
 <span class="error">[Fail]</span>: ✖ get after add returns 1 correct value
 <span class="error">[Actual]</span>: 0 as u64
 <span class="error">[Expected]</span>: 7 as u64
 <span class="error">[Stack]</span>: RuntimeError: unreachable
 at node_modules/@as-pect/assembly/assembly/internal/assert/assert (wasm://wasm/00023e6a:wasm-function<span class="error">[52]</span>:0xde9)
 at node_modules/@as-pect/assembly/assembly/internal/Expectation/Expectation<u64>#toBe (wasm://wasm/00023e6a:wasm-function<span class="error">[138]</span>:0x2d9c)
 at start:src/minimal/__tests__/index.unit.spec~anonymous|1~anonymous|1 (wasm://wasm/00023e6a:wasm-function<span class="error">[176]</span>:0x466a)
 at node_modules/@as-pect/assembly/assembly/internal/call/__call (wasm://wasm/00023e6a:wasm-function<span class="error">[179]</span>:0x4690)

 <span class="error">[File]</span>: src/minimal/__tests__/index.unit.spec.ts
 <span class="error">[Groups]</span>: 2 pass, 2 total
 <span class="error">[Result]</span>: ✖ FAIL
 <span class="error">[Snapshot]</span>: 0 total, 0 added, 0 removed, 0 different
 <span class="error">[Summary]</span>: 1 pass, 1 fail, 2 total
 <span class="error">[Time]</span>: 2.333ms

Expected behavior @nearBindgen supports complex inheritence

Desktop (please complete the following information):

willemneal commented 2 years ago

Yeah this would have been addressed in a stalled update that used serial-as, which handles this properly. You can use it instead of @nearBindgen to handle your serialization. Except you would need to change the type of the PersistentVector's generic to Uint8Array and then manually serialize and de-serialize.

tituszban commented 2 years ago

Alright. I have made it work by creating an intermediary serialiseable class. But regardless it's not great that this is not clear. I've raise a PR here, so that at least the docs reflect this limitation: https://github.com/near/docs/pull/983