Skip to content

Commit

Permalink
refactor(ts-sdk): get rid of typescript-memoize dep
Browse files Browse the repository at this point in the history
  • Loading branch information
jjleng authored and banool committed Sep 15, 2022
1 parent f7bedc3 commit 1b1365e
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 22 deletions.
2 changes: 1 addition & 1 deletion ecosystem/typescript/sdk/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
testEnvironment: "node",
coveragePathIgnorePatterns: ["generated/*", "transaction_builder/aptos_types/*"],
coveragePathIgnorePatterns: ["generated/*", "transaction_builder/aptos_types/*", "utils/memoize-decorator.ts"],
testPathIgnorePatterns: ["dist/*"],
collectCoverage: true,
setupFiles: ["dotenv/config"],
Expand Down
3 changes: 1 addition & 2 deletions ecosystem/typescript/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
"ed25519-hd-key": "1.2.0",
"form-data": "4.0.0",
"js-sha3": "0.8.0",
"tweetnacl": "1.0.3",
"typescript-memoize": "1.1.0"
"tweetnacl": "1.0.3"
},
"devDependencies": {
"@types/jest": "28.1.8",
Expand Down
2 changes: 1 addition & 1 deletion ecosystem/typescript/sdk/src/aptos_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import nacl from "tweetnacl";
import sha3 from "js-sha3";
import { derivePath } from "ed25519-hd-key";
import * as bip39 from "@scure/bip39";
import { Memoize } from "typescript-memoize";
import { bytesToHex } from "./bytes_to_hex.js";
import { HexString, MaybeHexString } from "./hex_string";
import * as Gen from "./generated/index";
import { Memoize } from "./utils";

const { sha3_256: sha3Hash } = sha3;

Expand Down
2 changes: 1 addition & 1 deletion ecosystem/typescript/sdk/src/aptos_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import { AptosClient } from "./aptos_client";
import * as Gen from "./generated/index";
import { FAUCET_URL, NODE_URL } from "./util.test";
import { FaucetClient } from "./faucet_client";
import { AptosAccount } from "./aptos_account";
import {
Expand All @@ -14,6 +13,7 @@ import {
} from "./transaction_builder";
import { TokenClient } from "./token_client";
import { HexString } from "./hex_string";
import { FAUCET_URL, NODE_URL } from "./utils/test_helper.test";

const account = "0x1::account::Account";

Expand Down
3 changes: 1 addition & 2 deletions ecosystem/typescript/sdk/src/aptos_client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

import { Memoize } from "typescript-memoize";
import { HexString, MaybeHexString } from "./hex_string";
import { fixNodeUrl, sleep } from "./util";
import { fixNodeUrl, Memoize, sleep } from "./utils";
import { AptosAccount } from "./aptos_account";
import * as Gen from "./generated/index";
import {
Expand Down
2 changes: 1 addition & 1 deletion ecosystem/typescript/sdk/src/coin_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { AptosClient } from "./aptos_client";
import { FAUCET_URL, NODE_URL } from "./util.test";
import { FAUCET_URL, NODE_URL } from "./utils/test_helper.test";
import { FaucetClient } from "./faucet_client";
import { AptosAccount } from "./aptos_account";
import { CoinClient } from "./coin_client";
Expand Down
2 changes: 1 addition & 1 deletion ecosystem/typescript/sdk/src/faucet_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AptosAccount } from "./aptos_account";
import { HexString } from "./hex_string";
import * as Gen from "./generated/index";

import { NODE_URL, FAUCET_URL } from "./util.test";
import { NODE_URL, FAUCET_URL } from "./utils/test_helper.test";

const aptosCoin = "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>";

Expand Down
2 changes: 1 addition & 1 deletion ecosystem/typescript/sdk/src/token_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AptosAccount } from "./aptos_account";
import { AptosClient } from "./aptos_client";
import { TokenClient } from "./token_client";

import { NODE_URL, FAUCET_URL } from "./util.test";
import { FAUCET_URL, NODE_URL } from "./utils/test_helper.test";

test(
"full tutorial nft token flow",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

import sha3 from "js-sha3";
import { MemoizeExpiring } from "typescript-memoize";
import {
Ed25519PublicKey,
Ed25519Signature,
Expand Down Expand Up @@ -30,6 +29,7 @@ import { ArgumentABI, EntryFunctionABI, ScriptABI, TransactionScriptABI, TypeArg
import { HexString, MaybeHexString } from "../hex_string";
import { argToTransactionArgument, TypeTagParser, serializeArg } from "./builder_utils";
import * as Gen from "../generated/index";
import { MemoizeExpiring } from "../utils";

export { TypeTagParser } from "./builder_utils.js";

Expand Down
2 changes: 2 additions & 0 deletions ecosystem/typescript/sdk/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./misc";
export * from "./memoize-decorator";
148 changes: 148 additions & 0 deletions ecosystem/typescript/sdk/src/utils/memoize-decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/**
* Credits to https://github.com/darrylhodgins/typescript-memoize
*/

/* eslint-disable no-param-reassign */
/* eslint-disable no-restricted-syntax */

interface MemoizeArgs {
// ttl in milliseconds for cached items. After `ttlMs`, cached items are evicted automatically. If no `ttlMs`
// is provided, cached items won't get auto-evicted.
ttlMs?: number;
// produces the cache key based on `args`.
hashFunction?: boolean | ((...args: any[]) => any);
// cached items can be taged with `tags`. `tags` can be used to evict cached items
tags?: string[];
}

export function Memoize(args?: MemoizeArgs | MemoizeArgs["hashFunction"]) {
let hashFunction: MemoizeArgs["hashFunction"];
let ttlMs: MemoizeArgs["ttlMs"];
let tags: MemoizeArgs["tags"];

if (typeof args === "object") {
hashFunction = args.hashFunction;
ttlMs = args.ttlMs;
tags = args.tags;
} else {
hashFunction = args;
}

return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
if (descriptor.value != null) {
descriptor.value = getNewFunction(descriptor.value, hashFunction, ttlMs, tags);
} else if (descriptor.get != null) {
descriptor.get = getNewFunction(descriptor.get, hashFunction, ttlMs, tags);
} else {
throw new Error("Only put a Memoize() decorator on a method or get accessor.");
}
};
}

export function MemoizeExpiring(ttlMs: number, hashFunction?: MemoizeArgs["hashFunction"]) {
return Memoize({
ttlMs,
hashFunction,
});
}

const clearCacheTagsMap: Map<string, Map<any, any>[]> = new Map();

export function clear(tags: string[]): number {
const cleared: Set<Map<any, any>> = new Set();
for (const tag of tags) {
const maps = clearCacheTagsMap.get(tag);
if (maps) {
for (const mp of maps) {
if (!cleared.has(mp)) {
mp.clear();
cleared.add(mp);
}
}
}
}
return cleared.size;
}

function getNewFunction(
originalMethod: () => void,
hashFunction?: MemoizeArgs["hashFunction"],
ttlMs: number = 0,
tags?: MemoizeArgs["tags"],
) {
const propMapName = Symbol("__memoized_map__");

// The function returned here gets called instead of originalMethod.
// eslint-disable-next-line func-names
return function (...args: any[]) {
let returnedValue: any;

// Get or create map
// eslint-disable-next-line no-prototype-builtins
if (!this.hasOwnProperty(propMapName)) {
Object.defineProperty(this, propMapName, {
configurable: false,
enumerable: false,
writable: false,
value: new Map<any, any>(),
});
}
const myMap: Map<any, any> = this[propMapName];

if (Array.isArray(tags)) {
for (const tag of tags) {
if (clearCacheTagsMap.has(tag)) {
clearCacheTagsMap.get(tag).push(myMap);
} else {
clearCacheTagsMap.set(tag, [myMap]);
}
}
}

if (hashFunction || args.length > 0 || ttlMs > 0) {
let hashKey: any;

// If true is passed as first parameter, will automatically use every argument, passed to string
if (hashFunction === true) {
hashKey = args.map((a) => a.toString()).join("!");
} else if (hashFunction) {
hashKey = hashFunction.apply(this, args);
} else {
// eslint-disable-next-line prefer-destructuring
hashKey = args[0];
}

const timestampKey = `${hashKey}__timestamp`;
let isExpired: boolean = false;
if (ttlMs > 0) {
if (!myMap.has(timestampKey)) {
// "Expired" since it was never called before
isExpired = true;
} else {
const timestamp = myMap.get(timestampKey);
isExpired = Date.now() - timestamp > ttlMs;
}
}

if (myMap.has(hashKey) && !isExpired) {
returnedValue = myMap.get(hashKey);
} else {
returnedValue = originalMethod.apply(this, args);
myMap.set(hashKey, returnedValue);
if (ttlMs > 0) {
myMap.set(timestampKey, Date.now());
}
}
} else {
const hashKey = this;
if (myMap.has(hashKey)) {
returnedValue = myMap.get(hashKey);
} else {
returnedValue = originalMethod.apply(this, args);
myMap.set(hashKey, returnedValue);
}
}

return returnedValue;
};
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

import { AptosClient } from "./aptos_client";

export const NODE_URL = process.env.APTOS_NODE_URL;
export const FAUCET_URL = process.env.APTOS_FAUCET_URL;

test("noop", () => {
// All TS files are compiled by default into the npm package
// Adding this empty test allows us to:
// 1. Guarantee that this test library won't get compiled
// 2. Prevent jest from exploding when it finds a file with no tests in it
});
import { AptosClient } from "../aptos_client";

test("test fixNodeUrl", () => {
expect(new AptosClient("https://test.com").client.request.config.BASE).toBe("https://test.com/v1");
Expand Down
File renamed without changes.
8 changes: 8 additions & 0 deletions ecosystem/typescript/sdk/src/utils/test_helper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const NODE_URL = process.env.APTOS_NODE_URL;
export const FAUCET_URL = process.env.APTOS_FAUCET_URL;
test("noop", () => {
// All TS files are compiled by default into the npm package
// Adding this empty test allows us to:
// 1. Guarantee that this test library won't get compiled
// 2. Prevent jest from exploding when it finds a file with no tests in it
});

0 comments on commit 1b1365e

Please sign in to comment.