From 5ab1e68f5583e660af088474ae953157a3cb12d7 Mon Sep 17 00:00:00 2001 From: Spring Chiu Date: Sat, 9 Dec 2023 17:21:48 +0800 Subject: [PATCH] feat: reconstruct with decodeObj2class if contains static schema and format --- .../test-status-deserialize-class.ava.js | 5 +- examples/src/status-deserialize-class.js | 156 +++++------------- .../near-sdk-js/lib/collections/lookup-map.js | 7 +- .../near-sdk-js/lib/collections/subtype.js | 5 +- .../lib/collections/unordered-map.js | 3 +- .../near-sdk-js/lib/collections/vector.js | 7 +- packages/near-sdk-js/lib/near-bindgen.js | 19 ++- packages/near-sdk-js/lib/utils.js | 21 ++- .../near-sdk-js/src/collections/lookup-map.ts | 22 ++- .../near-sdk-js/src/collections/subtype.ts | 88 +++++----- .../src/collections/unordered-map.ts | 16 +- .../near-sdk-js/src/collections/vector.ts | 26 +-- packages/near-sdk-js/src/near-bindgen.ts | 28 +++- packages/near-sdk-js/src/utils.ts | 61 ++++--- 14 files changed, 225 insertions(+), 239 deletions(-) diff --git a/examples/__tests__/test-status-deserialize-class.ava.js b/examples/__tests__/test-status-deserialize-class.ava.js index f4b9ed29e..ae595ab86 100644 --- a/examples/__tests__/test-status-deserialize-class.ava.js +++ b/examples/__tests__/test-status-deserialize-class.ava.js @@ -11,9 +11,10 @@ test.before(async (t) => { // Deploy the contract. const statusMessage = await root.devDeploy("./build/status-deserialize-class.wasm"); - await root.call(statusMessage, "init_messages", {}, {gas: new BN(200 * 10**12)}); - const result = await statusMessage.view("is_message_inited", {}); + await root.call(statusMessage, "init_contract", {}); + const result = await statusMessage.view("is_contract_inited", {}); t.is(result, true); + // Create test users const ali = await root.createSubAccount("ali"); const bob = await root.createSubAccount("bob"); diff --git a/examples/src/status-deserialize-class.js b/examples/src/status-deserialize-class.js index 5255368f5..0f3e25eb7 100644 --- a/examples/src/status-deserialize-class.js +++ b/examples/src/status-deserialize-class.js @@ -4,15 +4,10 @@ import { view, near, UnorderedMap, - serialize, - decode, - deserialize, - encode, LookupMap, Vector, - UnorderedSet, decodeObj2class + UnorderedSet, } from "near-sdk-js"; -import lodash from "lodash-es"; class Car { static schema = { @@ -29,8 +24,10 @@ class Car { } } -class InnerStatusDeserializeClass { +@NearBindgen({}) +export class StatusDeserializeClass { static schema = { + is_inited: "bool", records: {map: { key: 'string', value: 'string' }}, car: Car, messages: {array: {value: 'string'}}, @@ -45,6 +42,7 @@ class InnerStatusDeserializeClass { date: 'date' }; constructor() { + this.is_inited = false; this.records = {}; this.car = new Car(); this.messages = []; @@ -63,50 +61,33 @@ class InnerStatusDeserializeClass { this.big_num = 1n; this.date = new Date(); } -} - -@NearBindgen({}) -export class StatusDeserializeClass { - constructor() { - this.messages = ""; - } @call({}) - init_messages({ }) { - if (this.messages.length != 0) { + init_contract({ }) { + if (this.is_inited) { near.log(`message inited`); return; } - let account_id = near.signerAccountId(); - near.log(`${account_id} init_messages`); - let status = new InnerStatusDeserializeClass(); - let data = serialize(status) - this.messages = decode(data); + this.is_inited = true; } @view({}) - is_message_inited({}) { - near.log(`query is_message_inited`); - return this.messages.length != 0; + is_contract_inited({}) { + near.log(`query is_contract_inited`); + return this.is_inited; } @call({}) set_record({ message }) { let account_id = near.signerAccountId(); near.log(`${account_id} set_status with message ${message}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - inst.records[account_id] = message; - let data = serialize(inst) - this.messages = decode(data); + this.records[account_id] = message; } @view({}) get_record({ account_id }) { near.log(`get_record for account_id ${account_id}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.records[account_id] || null; + return this.records[account_id] || null; } @@ -114,140 +95,109 @@ export class StatusDeserializeClass { set_car_info({ name, speed }) { let account_id = near.signerAccountId(); near.log(`${account_id} set_car_info name ${name}, speed ${speed}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); let car = new Car(); car.name = name; car.speed = speed; - inst.car = car; - inst.user_car_map.set(account_id, car); - let data = serialize(inst) - this.messages = decode(data); + this.car = car; + this.user_car_map.set(account_id, car); } @view({}) get_car_info({ }) { near.log(`get_car_info`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.car.info(); + return this.car.info(); } @view({}) get_user_car_info({ account_id }) { near.log(`get_user_car_info for account_id ${account_id}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - let car = inst.user_car_map.get(account_id); + let car = this.user_car_map.get(account_id); if (car == null) { return null; } - return inst.user_car_map.get(account_id).info(); + return car.info(); } @call({}) push_message({ message }) { let account_id = near.signerAccountId(); near.log(`${account_id} push_message message ${message}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - inst.messages.push(message); - let data = serialize(inst) - this.messages = decode(data); + this.messages.push(message); } @view({}) get_messages({ }) { near.log(`get_messages`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.messages.join(','); + return this.messages.join(','); } @call({}) set_nested_efficient_recordes({ message, id }) { let account_id = near.signerAccountId(); near.log(`${account_id} set_nested_efficient_recordes with message ${message},id ${id}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - inst.efficient_recordes.set(account_id, message); - const nestedMap = inst.nested_efficient_recordes.get(id, { + this.efficient_recordes.set(account_id, message); + const nestedMap = this.nested_efficient_recordes.get(id, { defaultValue: new UnorderedMap("i_" + id + "_"), }); nestedMap.set(account_id, message); - inst.nested_efficient_recordes.set(id, nestedMap); + this.nested_efficient_recordes.set(id, nestedMap); - const nestedLookup = inst.nested_lookup_recordes.get(id, { + const nestedLookup = this.nested_lookup_recordes.get(id, { defaultValue: new LookupMap("li_" + id + "_"), }); nestedLookup.set(account_id, message); - inst.nested_lookup_recordes.set(id, nestedLookup); + this.nested_lookup_recordes.set(id, nestedLookup); // vector_nested_group: {vector: {value: { lookup_map: {value: 'string'}}}}, - const vecNestedLookup = inst.vector_nested_group.get(0, { + const vecNestedLookup = this.vector_nested_group.get(0, { defaultValue: new LookupMap("di_0_"), }); vecNestedLookup.set(account_id, message); - if (inst.vector_nested_group.isEmpty()) { - inst.vector_nested_group.push(vecNestedLookup); + if (this.vector_nested_group.isEmpty()) { + this.vector_nested_group.push(vecNestedLookup); } else { - inst.vector_nested_group.replace(0, vecNestedLookup); + this.vector_nested_group.replace(0, vecNestedLookup); } - const lookupNestVec = inst.lookup_nest_vec.get(account_id, { + const lookupNestVec = this.lookup_nest_vec.get(account_id, { defaultValue: new Vector("ei_" + account_id + "_"), }); lookupNestVec.push(message); - inst.lookup_nest_vec.set(account_id, lookupNestVec); - - inst.unordered_set.set(account_id); + this.lookup_nest_vec.set(account_id, lookupNestVec); - let data = serialize(inst) - this.messages = decode(data); + this.unordered_set.set(account_id); } @call({}) set_big_num_and_date({ bigint_num, new_date }) { let account_id = near.signerAccountId(); near.log(`${account_id} set_bigint_and_date bigint_num ${bigint_num}, new_date: ${new_date}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - inst.big_num = bigint_num; - inst.date = new_date; - let data = serialize(inst) - this.messages = decode(data); + this.big_num = bigint_num; + this.date = new_date; } @view({}) get_big_num({ }) { near.log(`get_big_num}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.big_num; + return this.big_num; } @view({}) get_date({ }) { near.log(`get_date`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.date; + return this.date; } @view({}) get_efficient_recordes({ account_id }) { near.log(`get_efficient_recordes for account_id ${account_id}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.efficient_recordes.get(account_id); + return this.efficient_recordes.get(account_id); } @view({}) get_nested_efficient_recordes({ account_id, id }) { near.log(`get_nested_efficient_recordes for account_id ${account_id}, id ${id}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.nested_efficient_recordes.get(id, { + return this.nested_efficient_recordes.get(id, { defaultValue: new UnorderedMap("i_" + id + "_"), }).get(account_id); } @@ -255,10 +205,7 @@ export class StatusDeserializeClass { @view({}) get_nested_lookup_recordes({ account_id, id }) { near.log(`get_nested_lookup_recordes for account_id ${account_id}, id ${id}`); - near.log(this.messages); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.nested_lookup_recordes.get(id, { + return this.nested_lookup_recordes.get(id, { defaultValue: new LookupMap("li_" + id + "_"), }).get(account_id); } @@ -266,49 +213,36 @@ export class StatusDeserializeClass { @view({}) get_vector_nested_group({ idx, account_id }) { near.log(`get_vector_nested_group for idx ${idx}, account_id ${account_id}`); - near.log(this.messages); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.vector_nested_group.get(idx).get(account_id); + return this.vector_nested_group.get(idx).get(account_id); } @view({}) get_lookup_nested_vec({ account_id, idx }) { near.log(`get_looup_nested_vec for account_id ${account_id}, idx ${idx}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.lookup_nest_vec.get(account_id).get(idx); + return this.lookup_nest_vec.get(account_id).get(idx); } @view({}) get_is_contains_user({ account_id }) { near.log(`get_is_contains_user for account_id ${account_id}`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.unordered_set.contains(account_id); + return this.unordered_set.contains(account_id); } @view({}) get_subtype_of_efficient_recordes({ }) { near.log(`get_subtype_of_efficient_recordes`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.efficient_recordes.subtype(); + return this.efficient_recordes.subtype(); } @view({}) get_subtype_of_nested_efficient_recordes({ }) { near.log(`get_subtype_of_nested_efficient_recordes`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.nested_efficient_recordes.subtype(); + return this.nested_efficient_recordes.subtype(); } @view({}) get_subtype_of_nested_lookup_recordes({ }) { near.log(`get_subtype_of_nested_lookup_recordes`); - let obj = deserialize(encode(this.messages)); - let inst = decodeObj2class(new InnerStatusDeserializeClass(), obj); - return inst.nested_lookup_recordes.subtype(); + return this.nested_lookup_recordes.subtype(); } } diff --git a/packages/near-sdk-js/lib/collections/lookup-map.js b/packages/near-sdk-js/lib/collections/lookup-map.js index f0ebb6ba7..5ffa5f96b 100644 --- a/packages/near-sdk-js/lib/collections/lookup-map.js +++ b/packages/near-sdk-js/lib/collections/lookup-map.js @@ -4,7 +4,7 @@ import { UnorderedMap } from "./unordered-map"; import { LookupSet } from "./lookup-set"; import { UnorderedSet } from "./unordered-set"; import { Vector } from "./vector"; -import { LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE } from "./subtype"; +import { LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE, } from "./subtype"; /** * A lookup map that stores data in NEAR storage. */ @@ -26,8 +26,7 @@ export class LookupMap { } /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype() { - } + subtype() { } /** * Get the data stored at the provided key. * @@ -40,7 +39,7 @@ export class LookupMap { if (options == undefined) { options = {}; } - if (((options.reconstructor == undefined)) && this.subtype() != undefined) { + if (options.reconstructor == undefined && this.subtype() != undefined) { // eslint-disable-next-line no-prototype-builtins if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/near-sdk-js/lib/collections/subtype.js b/packages/near-sdk-js/lib/collections/subtype.js index 504dc0523..56106f19a 100644 --- a/packages/near-sdk-js/lib/collections/subtype.js +++ b/packages/near-sdk-js/lib/collections/subtype.js @@ -11,13 +11,12 @@ export const VECTOR_SCHE = "vector"; export class SubType { /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype() { - } + subtype() { } set_reconstructor(options) { if (options == undefined) { options = {}; } - if (((options.reconstructor == undefined)) && this.subtype() != undefined) { + if (options.reconstructor == undefined && this.subtype() != undefined) { // eslint-disable-next-line no-prototype-builtins if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/near-sdk-js/lib/collections/unordered-map.js b/packages/near-sdk-js/lib/collections/unordered-map.js index 373b3db2a..19a57b77c 100644 --- a/packages/near-sdk-js/lib/collections/unordered-map.js +++ b/packages/near-sdk-js/lib/collections/unordered-map.js @@ -183,8 +183,7 @@ class UnorderedMapIterator { } /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype() { - } + subtype() { } next() { const key = this.keys.next(); if (key.done) { diff --git a/packages/near-sdk-js/lib/collections/vector.js b/packages/near-sdk-js/lib/collections/vector.js index dca47b1e9..f6f350554 100644 --- a/packages/near-sdk-js/lib/collections/vector.js +++ b/packages/near-sdk-js/lib/collections/vector.js @@ -4,7 +4,7 @@ import { UnorderedMap } from "./unordered-map"; import { LookupMap } from "./lookup-map"; import { LookupSet } from "./lookup-set"; import { UnorderedSet } from "./unordered-set"; -import { LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE } from "./subtype"; +import { LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE, } from "./subtype"; function indexToKey(prefix, index) { const data = new Uint32Array([index]); const array = new Uint8Array(data.buffer); @@ -32,13 +32,12 @@ export class Vector { } /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype() { - } + subtype() { } set_reconstructor(options) { if (options == undefined) { options = {}; } - if (((options.reconstructor == undefined)) && this.subtype() != undefined) { + if (options.reconstructor == undefined && this.subtype() != undefined) { // eslint-disable-next-line no-prototype-builtins if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/near-sdk-js/lib/near-bindgen.js b/packages/near-sdk-js/lib/near-bindgen.js index a7b4792f8..2cf8fc537 100644 --- a/packages/near-sdk-js/lib/near-bindgen.js +++ b/packages/near-sdk-js/lib/near-bindgen.js @@ -1,5 +1,5 @@ import * as near from "./api"; -import { deserialize, serialize, bytes, encode } from "./utils"; +import { deserialize, serialize, bytes, encode, decodeObj2class, } from "./utils"; /** * Tells the SDK to use this function as the migration function of the contract. * The migration function will ignore te existing state. @@ -101,13 +101,18 @@ export function NearBindgen({ requireInit = false, serializer = serialize, deser return deserializer(value); } static _reconstruct(classObject, plainObject) { - for (const item in classObject) { - const reconstructor = classObject[item].constructor?.reconstruct; - classObject[item] = reconstructor - ? reconstructor(plainObject[item]) - : plainObject[item]; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (classObject.constructor.schema === undefined) { + for (const item in classObject) { + const reconstructor = classObject[item].constructor?.reconstruct; + classObject[item] = reconstructor + ? reconstructor(plainObject[item]) + : plainObject[item]; + } + return classObject; } - return classObject; + return decodeObj2class(classObject, plainObject); } static _requireInit() { return requireInit; diff --git a/packages/near-sdk-js/lib/utils.js b/packages/near-sdk-js/lib/utils.js index 550da478c..958a8a770 100644 --- a/packages/near-sdk-js/lib/utils.js +++ b/packages/near-sdk-js/lib/utils.js @@ -1,4 +1,4 @@ -import { LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE } from "./collections"; +import { LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE, } from "./collections"; import { cloneDeep } from "lodash-es"; // make PromiseIndex a nominal typing var PromiseIndexBrand; @@ -66,7 +66,7 @@ export function getValueWithOptions(datatype, value, options = { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore for (const mkey in deserialized) { - if (datatype["map"]["value"] !== 'string') { + if (datatype["map"]["value"] !== "string") { deserialized[mkey] = decodeObj2class(new datatype["map"]["value"](), value[mkey]); } } @@ -77,7 +77,7 @@ export function getValueWithOptions(datatype, value, options = { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore for (const k in deserialized) { - if (datatype["array"]["value"] !== 'string') { + if (datatype["array"]["value"] !== "string") { new_vec.push(decodeObj2class(new datatype["array"]["value"](), value[k])); } } @@ -129,7 +129,8 @@ export function deserialize(valueToDeserialize) { }); } export function decodeObj2class(class_instance, obj) { - if (typeof obj != 'object' || class_instance.constructor.schema === undefined) { + if (typeof obj != "object" || + class_instance.constructor.schema === undefined) { return obj; } let key; @@ -137,14 +138,14 @@ export function decodeObj2class(class_instance, obj) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const value = obj[key]; - if (typeof value == 'object') { + if (typeof value == "object") { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const ty = class_instance.constructor.schema[key]; // eslint-disable-next-line no-prototype-builtins if (ty !== undefined && ty.hasOwnProperty("map")) { for (const mkey in value) { - if (ty["map"]["value"] === 'string') { + if (ty["map"]["value"] === "string") { class_instance[key][mkey] = value[mkey]; } else { @@ -155,7 +156,7 @@ export function decodeObj2class(class_instance, obj) { } else if (ty !== undefined && ty.hasOwnProperty("array")) { for (const k in value) { - if (ty["array"]["value"] === 'string') { + if (ty["array"]["value"] === "string") { class_instance[key].push(value[k]); } else { @@ -208,7 +209,8 @@ export function decodeObj2class(class_instance, obj) { } else { // normal class - class_instance[key].constructor.schema = class_instance.constructor.schema[key]; + class_instance[key].constructor.schema = + class_instance.constructor.schema[key]; class_instance[key] = decodeObj2class(class_instance[key], obj[key]); } } @@ -216,7 +218,8 @@ export function decodeObj2class(class_instance, obj) { const instance_tmp = cloneDeep(class_instance); class_instance = Object.assign(class_instance, obj); for (key in obj) { - if (typeof class_instance[key] == 'object' && !(class_instance[key] instanceof Date)) { + if (typeof class_instance[key] == "object" && + !(class_instance[key] instanceof Date)) { class_instance[key] = instance_tmp[key]; } } diff --git a/packages/near-sdk-js/src/collections/lookup-map.ts b/packages/near-sdk-js/src/collections/lookup-map.ts index 32fa6bbfa..0e9b7c825 100644 --- a/packages/near-sdk-js/src/collections/lookup-map.ts +++ b/packages/near-sdk-js/src/collections/lookup-map.ts @@ -5,11 +5,17 @@ import { serializeValueWithOptions, encode, } from "../utils"; -import {UnorderedMap} from "./unordered-map"; -import {LookupSet} from "./lookup-set"; -import {UnorderedSet} from "./unordered-set"; -import {Vector} from "./vector"; -import {LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE} from "./subtype"; +import { UnorderedMap } from "./unordered-map"; +import { LookupSet } from "./lookup-set"; +import { UnorderedSet } from "./unordered-set"; +import { Vector } from "./vector"; +import { + LOOKUP_MAP_SCHE, + LOOKUP_SET_SCHE, + UNORDERED_MAP_SCHE, + UNORDERED_SET_SCHE, + VECTOR_SCHE, +} from "./subtype"; /** * A lookup map that stores data in NEAR storage. @@ -32,9 +38,7 @@ export class LookupMap { /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype(): any { - - } + subtype(): any {} /** * Get the data stored at the provided key. @@ -51,7 +55,7 @@ export class LookupMap { if (options == undefined) { options = {}; } - if (((options.reconstructor == undefined)) && this.subtype() != undefined) { + if (options.reconstructor == undefined && this.subtype() != undefined) { // eslint-disable-next-line no-prototype-builtins if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/near-sdk-js/src/collections/subtype.ts b/packages/near-sdk-js/src/collections/subtype.ts index 7f93db704..741e35e22 100644 --- a/packages/near-sdk-js/src/collections/subtype.ts +++ b/packages/near-sdk-js/src/collections/subtype.ts @@ -1,9 +1,9 @@ -import {GetOptions} from "../types/collections"; -import {LookupMap} from "./lookup-map"; -import {LookupSet} from "./lookup-set"; -import {UnorderedSet} from "./unordered-set"; -import {Vector} from "./vector"; -import {UnorderedMap} from "./unordered-map"; +import { GetOptions } from "../types/collections"; +import { LookupMap } from "./lookup-map"; +import { LookupSet } from "./lookup-set"; +import { UnorderedSet } from "./unordered-set"; +import { Vector } from "./vector"; +import { UnorderedMap } from "./unordered-map"; export const LOOKUP_MAP_SCHE = "lookup_map"; export const LOOKUP_SET_SCHE = "lookup_set"; @@ -12,44 +12,44 @@ export const UNORDERED_SET_SCHE = "unordered_set"; export const VECTOR_SCHE = "vector"; export abstract class SubType { - /* eslint-disable @typescript-eslint/no-explicit-any */ - /* eslint-disable @typescript-eslint/no-empty-function */ - subtype(): any { + /* eslint-disable @typescript-eslint/no-explicit-any */ + /* eslint-disable @typescript-eslint/no-empty-function */ + subtype(): any {} + set_reconstructor( + options?: Omit, "serializer"> + ): Omit, "serializer"> { + if (options == undefined) { + options = {}; } - - set_reconstructor(options?: Omit, "serializer">): Omit, "serializer"> { - if (options == undefined) { - options = {}; - } - if (((options.reconstructor == undefined)) && this.subtype() != undefined) { - // eslint-disable-next-line no-prototype-builtins - if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = UnorderedMap.reconstruct; - // eslint-disable-next-line no-prototype-builtins - } else if (this.subtype().hasOwnProperty(LOOKUP_MAP_SCHE)) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = LookupMap.reconstruct; - // eslint-disable-next-line no-prototype-builtins - } else if (this.subtype().hasOwnProperty(LOOKUP_SET_SCHE)) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = LookupSet.reconstruct; - // eslint-disable-next-line no-prototype-builtins - } else if (this.subtype().hasOwnProperty(UNORDERED_SET_SCHE)) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = UnorderedSet.reconstruct; - // eslint-disable-next-line no-prototype-builtins - } else if (this.subtype().hasOwnProperty(VECTOR_SCHE)) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = Vector.reconstruct; - } - } - return options; + if (options.reconstructor == undefined && this.subtype() != undefined) { + // eslint-disable-next-line no-prototype-builtins + if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = UnorderedMap.reconstruct; + // eslint-disable-next-line no-prototype-builtins + } else if (this.subtype().hasOwnProperty(LOOKUP_MAP_SCHE)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = LookupMap.reconstruct; + // eslint-disable-next-line no-prototype-builtins + } else if (this.subtype().hasOwnProperty(LOOKUP_SET_SCHE)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = LookupSet.reconstruct; + // eslint-disable-next-line no-prototype-builtins + } else if (this.subtype().hasOwnProperty(UNORDERED_SET_SCHE)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = UnorderedSet.reconstruct; + // eslint-disable-next-line no-prototype-builtins + } else if (this.subtype().hasOwnProperty(VECTOR_SCHE)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = Vector.reconstruct; + } } -} \ No newline at end of file + return options; + } +} diff --git a/packages/near-sdk-js/src/collections/unordered-map.ts b/packages/near-sdk-js/src/collections/unordered-map.ts index ca0114556..b482164a5 100644 --- a/packages/near-sdk-js/src/collections/unordered-map.ts +++ b/packages/near-sdk-js/src/collections/unordered-map.ts @@ -10,7 +10,7 @@ import { import { Vector, VectorIterator } from "./vector"; import { LookupMap } from "./lookup-map"; import { GetOptions } from "../types/collections"; -import {SubType} from "./subtype"; +import { SubType } from "./subtype"; type ValueAndIndex = [value: string, index: number]; @@ -93,7 +93,7 @@ export class UnorderedMap extends SubType { const [oldValue, oldIndex] = valueAndIndex; this.values.set(key, [decode(serialized), oldIndex]); - return getValueWithOptions(this.subtype(),encode(oldValue), options); + return getValueWithOptions(this.subtype(), encode(oldValue), options); } /** @@ -127,7 +127,7 @@ export class UnorderedMap extends SubType { this.values.set(swappedKey, [swappedValueAndIndex[0], index]); } - return getValueWithOptions(this.subtype(),encode(value), options); + return getValueWithOptions(this.subtype(), encode(value), options); } /** @@ -254,9 +254,7 @@ class UnorderedMapIterator { /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype(): any { - - } + subtype(): any {} next(): { value: [string | null, DataType | null]; done: boolean } { const key = this.keys.next(); @@ -273,7 +271,11 @@ class UnorderedMapIterator { done: key.done, value: [ key.value, - getValueWithOptions(this.subtype(), encode(valueAndIndex[0]), this.options), + getValueWithOptions( + this.subtype(), + encode(valueAndIndex[0]), + this.options + ), ], }; } diff --git a/packages/near-sdk-js/src/collections/vector.ts b/packages/near-sdk-js/src/collections/vector.ts index 1459c9c5a..887d3ba2b 100644 --- a/packages/near-sdk-js/src/collections/vector.ts +++ b/packages/near-sdk-js/src/collections/vector.ts @@ -9,11 +9,17 @@ import { bytes, } from "../utils"; import { GetOptions } from "../types/collections"; -import {UnorderedMap} from "./unordered-map"; -import {LookupMap} from "./lookup-map"; -import {LookupSet} from "./lookup-set"; -import {UnorderedSet} from "./unordered-set"; -import {LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE} from "./subtype"; +import { UnorderedMap } from "./unordered-map"; +import { LookupMap } from "./lookup-map"; +import { LookupSet } from "./lookup-set"; +import { UnorderedSet } from "./unordered-set"; +import { + LOOKUP_MAP_SCHE, + LOOKUP_SET_SCHE, + UNORDERED_MAP_SCHE, + UNORDERED_SET_SCHE, + VECTOR_SCHE, +} from "./subtype"; function indexToKey(prefix: string, index: number): string { const data = new Uint32Array([index]); @@ -43,15 +49,15 @@ export class Vector { /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-empty-function */ - subtype(): any { - - } + subtype(): any {} - set_reconstructor(options?: Omit, "serializer">): Omit, "serializer"> { + set_reconstructor( + options?: Omit, "serializer"> + ): Omit, "serializer"> { if (options == undefined) { options = {}; } - if (((options.reconstructor == undefined)) && this.subtype() != undefined) { + if (options.reconstructor == undefined && this.subtype() != undefined) { // eslint-disable-next-line no-prototype-builtins if (this.subtype().hasOwnProperty(UNORDERED_MAP_SCHE)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/near-sdk-js/src/near-bindgen.ts b/packages/near-sdk-js/src/near-bindgen.ts index 614f62b90..df1e04a2f 100644 --- a/packages/near-sdk-js/src/near-bindgen.ts +++ b/packages/near-sdk-js/src/near-bindgen.ts @@ -1,5 +1,11 @@ import * as near from "./api"; -import { deserialize, serialize, bytes, encode } from "./utils"; +import { + deserialize, + serialize, + bytes, + encode, + decodeObj2class, +} from "./utils"; type EmptyParameterObject = Record; type AnyObject = Record; @@ -210,15 +216,21 @@ export function NearBindgen({ } static _reconstruct(classObject: object, plainObject: AnyObject): object { - for (const item in classObject) { - const reconstructor = classObject[item].constructor?.reconstruct; - - classObject[item] = reconstructor - ? reconstructor(plainObject[item]) - : plainObject[item]; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (classObject.constructor.schema === undefined) { + for (const item in classObject) { + const reconstructor = classObject[item].constructor?.reconstruct; + + classObject[item] = reconstructor + ? reconstructor(plainObject[item]) + : plainObject[item]; + } + + return classObject; } - return classObject; + return decodeObj2class(classObject, plainObject); } static _requireInit(): boolean { diff --git a/packages/near-sdk-js/src/utils.ts b/packages/near-sdk-js/src/utils.ts index ef0853e55..68d03ba48 100644 --- a/packages/near-sdk-js/src/utils.ts +++ b/packages/near-sdk-js/src/utils.ts @@ -1,6 +1,12 @@ import { GetOptions } from "./types/collections"; -import {LOOKUP_MAP_SCHE, LOOKUP_SET_SCHE, UNORDERED_MAP_SCHE, UNORDERED_SET_SCHE, VECTOR_SCHE} from "./collections"; -import {cloneDeep} from "lodash-es"; +import { + LOOKUP_MAP_SCHE, + LOOKUP_SET_SCHE, + UNORDERED_MAP_SCHE, + UNORDERED_SET_SCHE, + VECTOR_SCHE, +} from "./collections"; +import { cloneDeep } from "lodash-es"; // import lodash from 'lodash'; export interface Env { @@ -108,8 +114,11 @@ export function getValueWithOptions( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore for (const mkey in deserialized) { - if (datatype["map"]["value"] !=='string') { - deserialized[mkey] = decodeObj2class(new datatype["map"]["value"](), value[mkey]); + if (datatype["map"]["value"] !== "string") { + deserialized[mkey] = decodeObj2class( + new datatype["map"]["value"](), + value[mkey] + ); } } // eslint-disable-next-line no-prototype-builtins @@ -118,8 +127,10 @@ export function getValueWithOptions( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore for (const k in deserialized) { - if (datatype["array"]["value"] !=='string') { - new_vec.push(decodeObj2class(new datatype["array"]["value"](), value[k])); + if (datatype["array"]["value"] !== "string") { + new_vec.push( + decodeObj2class(new datatype["array"]["value"](), value[k]) + ); } } deserialized = new_vec; @@ -187,7 +198,10 @@ export function deserialize(valueToDeserialize: Uint8Array): unknown { } export function decodeObj2class(class_instance, obj) { - if (typeof obj != 'object' || class_instance.constructor.schema === undefined) { + if ( + typeof obj != "object" || + class_instance.constructor.schema === undefined + ) { return obj; } let key; @@ -195,26 +209,31 @@ export function decodeObj2class(class_instance, obj) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const value = obj[key]; - if (typeof value == 'object') { + if (typeof value == "object") { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const ty = class_instance.constructor.schema[key]; // eslint-disable-next-line no-prototype-builtins if (ty !== undefined && ty.hasOwnProperty("map")) { for (const mkey in value) { - if (ty["map"]["value"]==='string') { + if (ty["map"]["value"] === "string") { class_instance[key][mkey] = value[mkey]; } else { - class_instance[key][mkey] = decodeObj2class(new ty["map"]["value"](), value[mkey]); + class_instance[key][mkey] = decodeObj2class( + new ty["map"]["value"](), + value[mkey] + ); } } // eslint-disable-next-line no-prototype-builtins } else if (ty !== undefined && ty.hasOwnProperty("array")) { for (const k in value) { - if (ty["array"]["value"]==='string') { + if (ty["array"]["value"] === "string") { class_instance[key].push(value[k]); } else { - class_instance[key].push(decodeObj2class(new ty["array"]["value"](), value[k])); + class_instance[key].push( + decodeObj2class(new ty["array"]["value"](), value[k]) + ); } } // eslint-disable-next-line no-prototype-builtins @@ -224,7 +243,7 @@ export function decodeObj2class(class_instance, obj) { const subtype_value = ty[UNORDERED_MAP_SCHE]["value"]; class_instance[key].subtype = function () { return subtype_value; - } + }; // eslint-disable-next-line no-prototype-builtins } else if (ty !== undefined && ty.hasOwnProperty(VECTOR_SCHE)) { class_instance[key].length = obj[key].length; @@ -232,7 +251,7 @@ export function decodeObj2class(class_instance, obj) { const subtype_value = ty[VECTOR_SCHE]["value"]; class_instance[key].subtype = function () { return subtype_value; - } + }; // eslint-disable-next-line no-prototype-builtins } else if (ty !== undefined && ty.hasOwnProperty(UNORDERED_SET_SCHE)) { class_instance[key]._elements.length = obj[key]._elements.length; @@ -240,24 +259,25 @@ export function decodeObj2class(class_instance, obj) { const subtype_value = ty[UNORDERED_SET_SCHE]["value"]; class_instance[key].subtype = function () { return subtype_value; - } + }; // eslint-disable-next-line no-prototype-builtins } else if (ty !== undefined && ty.hasOwnProperty(LOOKUP_MAP_SCHE)) { class_instance[key].constructor.schema = ty; const subtype_value = ty[LOOKUP_MAP_SCHE]["value"]; class_instance[key].subtype = function () { return subtype_value; - } + }; // eslint-disable-next-line no-prototype-builtins } else if (ty !== undefined && ty.hasOwnProperty(LOOKUP_SET_SCHE)) { class_instance[key].constructor.schema = ty; const subtype_value = ty[LOOKUP_SET_SCHE]["value"]; class_instance[key].subtype = function () { return subtype_value; - } + }; } else { // normal class - class_instance[key].constructor.schema = class_instance.constructor.schema[key]; + class_instance[key].constructor.schema = + class_instance.constructor.schema[key]; class_instance[key] = decodeObj2class(class_instance[key], obj[key]); } } @@ -265,7 +285,10 @@ export function decodeObj2class(class_instance, obj) { const instance_tmp = cloneDeep(class_instance); class_instance = Object.assign(class_instance, obj); for (key in obj) { - if (typeof class_instance[key] == 'object' && !(class_instance[key] instanceof Date)) { + if ( + typeof class_instance[key] == "object" && + !(class_instance[key] instanceof Date) + ) { class_instance[key] = instance_tmp[key]; } }