Skip to content

Commit

Permalink
feat-issue-239: test lookup set
Browse files Browse the repository at this point in the history
  • Loading branch information
fospring committed Oct 29, 2023
1 parent cbc1417 commit 5f1c6b1
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 26 deletions.
16 changes: 16 additions & 0 deletions examples/__tests__/test-nested-collections.ava.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,19 @@ test("sets then gets nested nested collection", async (t) => {
"dog"
);
});

test("Ali add_lk_sets then get_lk_set", async (t) => {
const { ali, nestedCollections } = t.context.accounts;
await ali.call(nestedCollections, "add_lk_set", { id: "1" });
await ali.call(nestedCollections, "add_lk_set", { id: "2" });

t.is(
await nestedCollections.view("get_lk_set", { id: "1", accountId: ali.accountId }),
true
);

t.is(
await nestedCollections.view("get_lk_set", { id: "2", accountId: ali.accountId }),
true
);
});
44 changes: 28 additions & 16 deletions examples/src/nested-collections.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import { NearBindgen, near, call, view, UnorderedMap } from "near-sdk-js";
import {NearBindgen, near, call, view, UnorderedMap, LookupMap, LookupSet, UnorderedSet, Vector} from "near-sdk-js";

@NearBindgen({})
export class Contract {
outerMap: UnorderedMap<UnorderedMap<string>>;
groups: UnorderedMap<UnorderedMap<UnorderedMap<string>>>;
outerLkpSet: UnorderedMap<LookupSet<string>>;
outerSet: UnorderedMap<UnorderedSet<string>>;
outerVec: UnorderedMap<Vector<string>>;

constructor() {
this.outerMap = new UnorderedMap("o");
this.groups = new UnorderedMap("gs");
this.outerLkpSet = new UnorderedMap("ols");
this.outerSet = new UnorderedMap("os");
this.outerVec = new UnorderedMap("ov");
}

// Using some type-awared format instead of standard JSON.stringify
@call({})
add({ id, text }: { id: string; text: string }) {
// But car.run() doesn't work, because SDK only know how to deserialize it as a plain object, not a Car instance.
// This problem is particularly painful when class is nested, for example collection class instance LookupMap containing Car class instance. Currently SDK mitigate this problem by requires user to manually reconstruct the JS object to an instance of the original class.
const innerMap = this.outerMap.get(id, {
// reconstructor: UnorderedMap.reconstruct,
defaultValue: new UnorderedMap<string>("i_" + id + "_"),
});
innerMap.set(near.signerAccountId(), text);
Expand All @@ -25,9 +27,7 @@ export class Contract {

@view({})
get({ id, accountId }: { id: string; accountId: string }) {
const innerMap = this.outerMap.get(id, {
reconstructor: UnorderedMap.reconstruct,
});
const innerMap = this.outerMap.get(id);
if (innerMap === null) {
return null;
}
Expand All @@ -45,11 +45,9 @@ export class Contract {
text: string;
}) {
const groupMap = this.groups.get(group, {
// reconstructor: UnorderedMap.reconstruct,
defaultValue: new UnorderedMap<UnorderedMap<string>>("g_" + group + "_"),
});
const innerMap = groupMap.get(id, {
// reconstructor: UnorderedMap.reconstruct,
defaultValue: new UnorderedMap<string>("gi_" + group + "_" + id + "_"),
});
innerMap.set(near.signerAccountId(), text);
Expand All @@ -67,18 +65,32 @@ export class Contract {
id: string;
accountId: string;
}) {
const groupMap = this.groups.get(group, {
// reconstructor: UnorderedMap.reconstruct,
});
const groupMap = this.groups.get(group);
if (groupMap === null) {
return null;
}
const innerMap = groupMap.get(id, {
// reconstructor: UnorderedMap.reconstruct,
});
const innerMap = groupMap.get(id);
if (innerMap === null) {
return null;
}
return innerMap.get(accountId);
}

@call({})
add_lk_set({ id }: { id: string }) {
const innerSet = this.outerLkpSet.get(id, {
defaultValue: new LookupSet<string>("i_" + id + "_"),
});
innerSet.set(near.signerAccountId());
this.outerLkpSet.set(id, innerSet);
}

@view({})
get_lk_set({ id, accountId }: { id: string; accountId: string }) {
const innerMap = this.outerLkpSet.get(id);
if (innerMap === null) {
return null;
}
return innerMap.contains(accountId);
}
}
2 changes: 1 addition & 1 deletion packages/near-sdk-js/lib/collections/lookup-map.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/near-sdk-js/lib/near-bindgen.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions packages/near-sdk-js/lib/utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/near-sdk-js/src/collections/lookup-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class LookupMap<DataType> {
const storageKey = this.keyPrefix + key;
const value = near.storageReadRaw(encode(storageKey));

return getValueWithOptions(value, options);
return getValueWithOptions(value, options, true);
}

/**
Expand Down
1 change: 0 additions & 1 deletion packages/near-sdk-js/src/collections/unordered-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { LookupMap } from "./lookup-map";
import { GetOptions } from "../types/collections";

type ValueAndIndex = [value: string, index: number];

/**
* An unordered map that stores data in NEAR storage.
*/
Expand Down
1 change: 0 additions & 1 deletion packages/near-sdk-js/src/near-bindgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ export function NearBindgen({
return new target();
}

/// 如何return Class而不是json
static _getState(): unknown | null {
const rawState = near.storageReadRaw(bytes("STATE"));
return rawState ? this._deserialize(rawState) : null;
Expand Down
17 changes: 14 additions & 3 deletions packages/near-sdk-js/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GetOptions } from "./types/collections";
import {UnorderedMap} from "./collections";
import { LookupSet, UnorderedMap } from "./collections";
import { log } from "./api";

export interface Env {
uint8array_to_latin1_string(a: Uint8Array): string;
Expand Down Expand Up @@ -75,7 +76,7 @@ export function getValueWithOptions<DataType>(
options: Omit<GetOptions<DataType>, "serializer"> = {
deserializer: deserialize,
},
check_reconstruct?: boolean,
check_reconstruct?: boolean
): DataType | null {
if (value === null) {
return options?.defaultValue ?? null;
Expand All @@ -90,10 +91,20 @@ export function getValueWithOptions<DataType>(
if (options?.reconstructor) {
return options.reconstructor(deserialized);
} else if (check_reconstruct) {
if (deserialized["prefix"] && deserialized["_keys"] && deserialized["values"]) {
log("deserialized=", deserialized);
if (
deserialized["prefix"] &&
deserialized["_keys"] &&
deserialized["values"]
) {
const f: unknown = UnorderedMap.reconstruct;
// @ts-ignore
return f(deserialized) as DataType;
} else if (deserialized["keyPrefix"]) {
log("decode LookupSet");
const f: unknown = LookupSet.reconstruct;
// @ts-ignore
return f(deserialized) as DataType;
}
}

Expand Down

0 comments on commit 5f1c6b1

Please sign in to comment.