From 1ddf1af75da5cc8a0469d30705167124c957d47e Mon Sep 17 00:00:00 2001 From: BotchM Date: Mon, 25 Oct 2021 15:05:32 +0200 Subject: [PATCH 01/10] add kya interface to cap-js --- package.json | 1 + src/config.ts | 6 +-- src/declarations/cap/index.d.ts | 1 - src/index.ts | 90 +++++++++++++-------------------- src/kyasshu/index.ts | 64 +++++++++++++++++++++++ src/kyasshu/types.ts | 15 ++++++ 6 files changed, 118 insertions(+), 59 deletions(-) create mode 100644 src/kyasshu/index.ts create mode 100644 src/kyasshu/types.ts diff --git a/package.json b/package.json index e81f3de..d5f2f61 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@dfinity/agent": "^0.10.1", "@dfinity/candid": "^0.10.1", "@dfinity/principal": "^0.10.1", + "axios": "^0.23.0", "cross-fetch": "^3.1.4" }, "devDependencies": { diff --git a/src/config.ts b/src/config.ts index 71482bd..fb1715e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,8 +1,8 @@ export default {}; // To edit or maintain -export const DFX_JSON_HISTORY_ROUTER_KEY_NAME = 'ic-history-router' -const IC_HISTORY_ROUTER_CANISTER_ID_MAINNET = 'rrkah-fqaaa-aaaaa-aaaaq-cai'; +export const DFX_JSON_HISTORY_ROUTER_KEY_NAME = "ic-history-router"; +const IC_HISTORY_ROUTER_CANISTER_ID_MAINNET = "rrkah-fqaaa-aaaaa-aaaaq-cai"; // The CanisterInfo is exported to the application // As such, might require maintenance of `mainnet` canister id @@ -11,4 +11,4 @@ export const CanisterInfo = { mainnet: IC_HISTORY_ROUTER_CANISTER_ID_MAINNET, local: IC_HISTORY_ROUTER_CANISTER_ID_MAINNET, }, -} \ No newline at end of file +}; diff --git a/src/declarations/cap/index.d.ts b/src/declarations/cap/index.d.ts index 3f96a06..36bedea 100644 --- a/src/declarations/cap/index.d.ts +++ b/src/declarations/cap/index.d.ts @@ -14,7 +14,6 @@ export { Witness, } from "./root"; - export { default as Router, GetIndexCanistersResponse, diff --git a/src/index.ts b/src/index.ts index 7a37227..f28438e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,32 +43,27 @@ export { GetUserRootBucketsResponse, } from "./declarations/cap"; -import { - CanisterInfo, - DFX_JSON_HISTORY_ROUTER_KEY_NAME, -} from './config'; +import { CanisterInfo, DFX_JSON_HISTORY_ROUTER_KEY_NAME } from "./config"; export { CanisterInfo }; export const Hosts = { - mainnet: 'https://ic0.app', - local: 'http://localhost:8000', + mainnet: "https://ic0.app", + local: "http://localhost:8000", }; -type IdlFactory = ({ IDL }: { IDL: any; }) => any; +type IdlFactory = ({ IDL }: { IDL: any }) => any; export interface ActorParams { - host: string, - canisterId: string, - idlFactory: IdlFactory, + host: string; + canisterId: string; + idlFactory: IdlFactory; } -export class CapBase { +export class CapBase { public actor: ActorSubclass; - constructor( - actor: ActorSubclass, - ) { + constructor(actor: ActorSubclass) { this.actor = actor; } @@ -77,9 +72,9 @@ export class CapBase { canisterId, idlFactory, }: { - host: string, - canisterId: string, - idlFactory: IdlFactory, + host: string; + canisterId: string; + idlFactory: IdlFactory; }): Promise> { const agent = new HttpAgent({ host, @@ -90,7 +85,9 @@ export class CapBase { try { agent.fetchRootKey(); } catch (err) { - console.warn('Oops! Unable to fetch root key, is the local replica running?'); + console.warn( + "Oops! Unable to fetch root key, is the local replica running?" + ); console.error(err); } } @@ -101,11 +98,7 @@ export class CapBase { }); } - public static inititalise ({ - host, - canisterId, - idlFactory, - }: ActorParams) { + public static inititalise({ host, canisterId, idlFactory }: ActorParams) { return (async () => { const actor = await CapBase.createActor({ host, @@ -118,13 +111,13 @@ export class CapBase { } } -export class CapRouter extends CapBase <_ROUTER_SERVICE>{ +export class CapRouter extends CapBase<_ROUTER_SERVICE> { public static init({ host = Hosts.mainnet, canisterId = CanisterInfo[DFX_JSON_HISTORY_ROUTER_KEY_NAME].mainnet, }: { - host?: string, - canisterId?: string, + host?: string; + canisterId?: string; }) { return (async () => { const actor = await CapBase.inititalise<_ROUTER_SERVICE>({ @@ -133,26 +126,22 @@ export class CapRouter extends CapBase <_ROUTER_SERVICE>{ idlFactory: routerFactory, }); - const cap = new CapRouter( - actor, - ); + const cap = new CapRouter(actor); return cap; })(); } - // TODO: Isn't it best to use the Actor directly? no point on this method wrappers public async get_index_canisters({ witness = false, }: { - witness?: boolean, + witness?: boolean; }): Promise { return this.actor.get_index_canisters({ witness, - }) + }); } - // TODO: Isn't it best to use the Actor directly? no point on this method wrappers public async get_token_contract_root_bucket({ tokenId, witness = false, @@ -166,13 +155,12 @@ export class CapRouter extends CapBase <_ROUTER_SERVICE>{ }); } - // TODO: Isn't it best to use the Actor directly? no point on this method wrappers public async get_user_root_buckets({ user, witness = false, }: { - user: Principal, - witness?: boolean, + user: Principal; + witness?: boolean; }): Promise { return this.actor.get_user_root_buckets({ user, @@ -180,27 +168,25 @@ export class CapRouter extends CapBase <_ROUTER_SERVICE>{ }); } - // TODO: Isn't it best to use the Actor directly? no point on this method wrappers public async insert_new_users( contractId: Principal, - users: Principal[], + users: Principal[] ): Promise { return this.actor.insert_new_users(contractId, users); } - // TODO: Isn't it best to use the Actor directly? no point on this method wrappers public async install_bucket_code(canisterId: Principal) { return this.actor.install_bucket_code(canisterId); } } -export class CapRoot extends CapBase <_ROOT_SERVICE>{ +export class CapRoot extends CapBase<_ROOT_SERVICE> { public static init({ host = Hosts.mainnet, canisterId, }: { - host?: string, - canisterId: string, + host?: string; + canisterId: string; }) { return (async () => { const actor = await CapBase.inititalise<_ROOT_SERVICE>({ @@ -209,18 +195,15 @@ export class CapRoot extends CapBase <_ROOT_SERVICE>{ idlFactory: rootFactory, }); - const cap = new CapRoot( - actor, - ); + const cap = new CapRoot(actor); return cap; })(); } - // TODO: Best to use the Actor direclty, no point on this method wrappers public async get_transaction( id: bigint, - witness = false, + witness = false ): Promise { return this.actor.get_transaction({ id, @@ -228,7 +211,6 @@ export class CapRoot extends CapBase <_ROOT_SERVICE>{ }); } - // TODO: Best to use the Actor direclty, no point on this method wrappers public async get_transactions({ witness = false, page, @@ -242,24 +224,22 @@ export class CapRoot extends CapBase <_ROOT_SERVICE>{ }); } - // TODO: Best to use the Actor direclty, no point on this method wrappers public async get_user_transactions({ page, user, witness = false, }: { - page?: number, - user: Principal, - witness?: boolean, + page?: number; + user: Principal; + witness?: boolean; }): Promise { return this.actor.get_user_transactions({ page: page ? [page] : [], user, witness, - }) + }); } - // TODO: Best to use the Actor direclty, no point on this method wrappers public async insert({ to, fee, @@ -277,6 +257,6 @@ export class CapRoot extends CapBase <_ROOT_SERVICE>{ operation, caller, amount, - }) + }); } } diff --git a/src/kyasshu/index.ts b/src/kyasshu/index.ts new file mode 100644 index 0000000..dd1b55d --- /dev/null +++ b/src/kyasshu/index.ts @@ -0,0 +1,64 @@ +import { KyaApi, RequestArgs } from "./types"; +import { EventEmitter } from "events"; +import axios, { AxiosResponse, AxiosRequestConfig } from "axios"; + +export type KyaOptions = { url: string }; + +export class KyaRestApi extends EventEmitter implements KyaApi { + public url: string; + + constructor(protected options: string | KyaOptions) { + super(); + if (typeof options === "string") { + this.url = options; + } else { + this.url = options.url; + } + } + + public async connect(): Promise { + this.emit("connected"); + } + + public async disconnect(): Promise { + this.emit("disconnected"); + } + + private get headers() { + return { + "Content-Type": "application/json", + // when authenticating to kya api + // ...(this.token ? { 'Authorization': `Bearer ${this.token}` } : {}) + }; + } + + public async request(req: RequestArgs): Promise { + const options: AxiosRequestConfig = { + method: "get", + url: this.url, + headers: this.headers, + ...req.params, + }; + + let resp: AxiosResponse; + + try { + resp = await axios(options); + } catch (error) { + throw new Error((error as Error).message); + } + + if (resp.statusText !== "OK") { + throw new Error(`status: ${resp.status}, ${resp.statusText}`); + } + + return resp.data; + } + + public on( + event: "connected" | "disconnected", + listener: (...args: any[]) => void + ): this { + return super.on(event, listener); + } +} diff --git a/src/kyasshu/types.ts b/src/kyasshu/types.ts new file mode 100644 index 0000000..107a8b3 --- /dev/null +++ b/src/kyasshu/types.ts @@ -0,0 +1,15 @@ +export interface RequestArgs { + readonly method: string; + readonly params?: readonly unknown[]; +} + +export interface KyaApi { + url: string; + disconnect(): Promise; + connect(): Promise; + request(req: RequestArgs): Promise; + on( + event: "connected" | "disconnected", + listener: (...args: any[]) => void + ): this; +} From 42ebf55d383a038f2c9bfde5a65f4aa3e4136356 Mon Sep 17 00:00:00 2001 From: BotchM Date: Mon, 25 Oct 2021 17:28:49 +0200 Subject: [PATCH 02/10] add kya url, create kyasshu class --- src/config.ts | 3 +++ src/index.ts | 6 +++++- src/kyasshu/index.ts | 5 +++-- src/kyasshu/types.ts | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/config.ts b/src/config.ts index fb1715e..350c5c9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,8 @@ export default {}; +//kyasshu +export const KYA_URL = "http://localhost:3000/dev/cap"; + // To edit or maintain export const DFX_JSON_HISTORY_ROUTER_KEY_NAME = "ic-history-router"; const IC_HISTORY_ROUTER_CANISTER_ID_MAINNET = "rrkah-fqaaa-aaaaa-aaaaq-cai"; diff --git a/src/index.ts b/src/index.ts index f28438e..ae064a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import { HttpAgentOptions, } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; +import { KyaRestApi } from './kyasshu'; import _ROUTER_SERVICE from "./declarations/cap/router"; import _ROOT_SERVICE from "./declarations/cap/root"; @@ -43,7 +44,7 @@ export { GetUserRootBucketsResponse, } from "./declarations/cap"; -import { CanisterInfo, DFX_JSON_HISTORY_ROUTER_KEY_NAME } from "./config"; +import { CanisterInfo, DFX_JSON_HISTORY_ROUTER_KEY_NAME, KYA_URL } from "./config"; export { CanisterInfo }; @@ -63,8 +64,11 @@ export interface ActorParams { export class CapBase { public actor: ActorSubclass; + public cache: KyaRestApi; + constructor(actor: ActorSubclass) { this.actor = actor; + this.cache = new KyaRestApi({ url: KYA_URL }); } private static async createActor({ diff --git a/src/kyasshu/index.ts b/src/kyasshu/index.ts index dd1b55d..dedf620 100644 --- a/src/kyasshu/index.ts +++ b/src/kyasshu/index.ts @@ -33,11 +33,12 @@ export class KyaRestApi extends EventEmitter implements KyaApi { } public async request(req: RequestArgs): Promise { + const params = new URLSearchParams(req.params); const options: AxiosRequestConfig = { method: "get", - url: this.url, + url: `${this.url}/${req.path}`, headers: this.headers, - ...req.params, + ...params && ({ params: params.toString() }) }; let resp: AxiosResponse; diff --git a/src/kyasshu/types.ts b/src/kyasshu/types.ts index 107a8b3..12bdd5a 100644 --- a/src/kyasshu/types.ts +++ b/src/kyasshu/types.ts @@ -1,5 +1,5 @@ export interface RequestArgs { - readonly method: string; + readonly path: string; readonly params?: readonly unknown[]; } From a7b1ef2d025391af7a304941e0fa9097e5a1f3a2 Mon Sep 17 00:00:00 2001 From: BotchM Date: Thu, 28 Oct 2021 13:06:58 +0200 Subject: [PATCH 03/10] kya urls, get all user txns --- src/config.ts | 11 +++++++++-- src/index.ts | 37 +++++++++++++++++++++++++++++-------- src/kyasshu/index.ts | 6 +++--- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/config.ts b/src/config.ts index 350c5c9..86c7fd3 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,14 @@ export default {}; -//kyasshu -export const KYA_URL = "http://localhost:3000/dev/cap"; +//kyasshu +export const KyaUrl = (stage: string = "prod") => { + const resp: { [key: string]: string } = { + prod: "https://kyasshu-prod.fleek.co", + dev: "https://kyasshu-dev.fleek.co", + }; + + return resp[stage]; +}; // To edit or maintain export const DFX_JSON_HISTORY_ROUTER_KEY_NAME = "ic-history-router"; diff --git a/src/index.ts b/src/index.ts index ae064a1..a08d2b5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ import { HttpAgentOptions, } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; -import { KyaRestApi } from './kyasshu'; +import { KyaConnector } from "./kyasshu"; import _ROUTER_SERVICE from "./declarations/cap/router"; import _ROOT_SERVICE from "./declarations/cap/root"; @@ -44,7 +44,11 @@ export { GetUserRootBucketsResponse, } from "./declarations/cap"; -import { CanisterInfo, DFX_JSON_HISTORY_ROUTER_KEY_NAME, KYA_URL } from "./config"; +import { + CanisterInfo, + KyaUrl, + DFX_JSON_HISTORY_ROUTER_KEY_NAME, +} from "./config"; export { CanisterInfo }; @@ -64,11 +68,13 @@ export interface ActorParams { export class CapBase { public actor: ActorSubclass; - public cache: KyaRestApi; + public cache: KyaConnector | undefined; - constructor(actor: ActorSubclass) { + constructor(actor: ActorSubclass, cache?: KyaConnector) { this.actor = actor; - this.cache = new KyaRestApi({ url: KYA_URL }); + if (cache) { + this.cache = cache; + } } private static async createActor({ @@ -84,7 +90,6 @@ export class CapBase { host, fetch, } as unknown as HttpAgentOptions); - if (process.env.NODE_ENV !== "production") { try { agent.fetchRootKey(); @@ -130,7 +135,8 @@ export class CapRouter extends CapBase<_ROUTER_SERVICE> { idlFactory: routerFactory, }); - const cap = new CapRouter(actor); + const cache = new KyaConnector(KyaUrl("dev")); + const cap = new CapRouter(actor, cache); return cap; })(); @@ -199,7 +205,9 @@ export class CapRoot extends CapBase<_ROOT_SERVICE> { idlFactory: rootFactory, }); - const cap = new CapRoot(actor); + // ToDo cache flag + const cache = new KyaConnector(KyaUrl("dev")); + const cap = new CapRoot(actor, cache); return cap; })(); @@ -263,4 +271,17 @@ export class CapRoot extends CapBase<_ROOT_SERVICE> { amount, }); } + + public async get_all_user_transactions({ + user, + LastEvaluatedKey, + }: { + user: Principal; + LastEvaluatedKey?: number; + }): Promise { + return this.cache?.request({ + path: `cap/user/txns/${user.toString()}`, + params: [LastEvaluatedKey], + }); + } } diff --git a/src/kyasshu/index.ts b/src/kyasshu/index.ts index dedf620..d24ab84 100644 --- a/src/kyasshu/index.ts +++ b/src/kyasshu/index.ts @@ -4,7 +4,7 @@ import axios, { AxiosResponse, AxiosRequestConfig } from "axios"; export type KyaOptions = { url: string }; -export class KyaRestApi extends EventEmitter implements KyaApi { +export class KyaConnector extends EventEmitter implements KyaApi { public url: string; constructor(protected options: string | KyaOptions) { @@ -33,12 +33,12 @@ export class KyaRestApi extends EventEmitter implements KyaApi { } public async request(req: RequestArgs): Promise { - const params = new URLSearchParams(req.params); + const params = req.params; const options: AxiosRequestConfig = { method: "get", url: `${this.url}/${req.path}`, headers: this.headers, - ...params && ({ params: params.toString() }) + ...(params && { params: Object.assign({}, ...params) }), }; let resp: AxiosResponse; From 479ea15b461ec36d14569b443e7d6427957236e3 Mon Sep 17 00:00:00 2001 From: BotchM Date: Thu, 28 Oct 2021 16:51:42 +0200 Subject: [PATCH 04/10] get all user txns docs --- README.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/README.md b/README.md index 990e0c4..28f1263 100644 --- a/README.md +++ b/README.md @@ -455,6 +455,53 @@ console.log(userTxns); ### `capRoot.time([options])` > ToDo +### Kyasshu Layer + +### `capRoot.get_all_user_transactions(userId, LastEvaluatedKey)` +> Return all of the user transactions for `userId`, if `LastEvaluatedKey` is returned, you must provide it in subsequent calls to query the rest of the data. + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| userId | [principal](#principal) | The user Id of the requested transactions | +| LastEvaluatedKey | [string?](#string?) | The optional `LastEvaluatedKey`, If LastEvaluatedKey is empty, then the "last page" of results has been processed and there is no more data to be retrieved. If LastEvaluatedKey is not empty, it does not necessarily mean that there is more data in the result set. The only way to know when you have reached the end of the result set is when LastEvaluatedKey is empty. | + +#### Returns + +| Type | Description | +| ---- | ----------- | +| `GetTransactionsResponseBorrowed` | An object returning an array of `data` as well as the page queried. If witness = `true` the certified response will be appended to the response | + +#### Example + +```JavaScript +const userTxns = await capRoot.get_all_user_transactions({ + userId: "avesb-mgo2l-ds25i-g7kd4-3he5l-z7ary-3biiq-sojiw-xjgbk-ich5l-mae", +}); + +// or +const userTxns = await capRoot.get_all_user_transactions({ + userId: "avesb-mgo2l-ds25i-g7kd4-3he5l-z7ary-3biiq-sojiw-xjgbk-ich5l-mae", + LastEvaluatedKey: {}, +}); + +console.log(transaction); +``` +```bash +{ + Items?: { + [key: string]: Event; + }[] | undefined; + LastEvaluatedKey?: { + [key: string]: any; + } | undefined; +} +``` + +#### Notes +- Unstable endpoint + ### API - ToDo From 4bfb12a9945f6a87d6b5cfdcd7ad1db337aff0bf Mon Sep 17 00:00:00 2001 From: BotchM Date: Fri, 29 Oct 2021 11:06:25 +0200 Subject: [PATCH 05/10] CapCache class --- README.md | 15 +++++++++------ src/config.ts | 1 + src/index.ts | 37 +++++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 28f1263..69e1cf4 100644 --- a/README.md +++ b/README.md @@ -476,17 +476,20 @@ console.log(userTxns); #### Example ```JavaScript -const userTxns = await capRoot.get_all_user_transactions({ - userId: "avesb-mgo2l-ds25i-g7kd4-3he5l-z7ary-3biiq-sojiw-xjgbk-ich5l-mae", +const capCache = new CapCache(); + +const userTxns = await capCache.get_all_user_transactions({ + user: Principal.from("zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae"), }); // or -const userTxns = await capRoot.get_all_user_transactions({ - userId: "avesb-mgo2l-ds25i-g7kd4-3he5l-z7ary-3biiq-sojiw-xjgbk-ich5l-mae", - LastEvaluatedKey: {}, + +const userTxns = await capCache.get_all_user_transactions({ + user: Principal.from("zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae"), + LastEvaluatedKey, }); -console.log(transaction); +console.log(userTxns); ``` ```bash { diff --git a/src/config.ts b/src/config.ts index 86c7fd3..32ceec0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,6 +5,7 @@ export const KyaUrl = (stage: string = "prod") => { const resp: { [key: string]: string } = { prod: "https://kyasshu-prod.fleek.co", dev: "https://kyasshu-dev.fleek.co", + local: "http://localhost:3000/dev", }; return resp[stage]; diff --git a/src/index.ts b/src/index.ts index 0a8c958..980d64b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,8 +6,8 @@ import { HttpAgentOptions, } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; -import { KyaConnector } from "./kyasshu"; +import { KyaConnector } from "./kyasshu"; import _ROUTER_SERVICE from "./declarations/cap/router"; import _ROOT_SERVICE from "./declarations/cap/root"; import { routerFactory } from "./declarations/cap/router.did.js"; @@ -78,7 +78,7 @@ export class CapBase { } } - private static async createActor({ + private static createActor({ host, canisterId, idlFactory, @@ -86,7 +86,7 @@ export class CapBase { host: string; canisterId: string; idlFactory: IdlFactory; - }): Promise> { + }): ActorSubclass { const agent = new HttpAgent({ host, fetch, @@ -109,8 +109,8 @@ export class CapBase { } public static inititalise({ host, canisterId, idlFactory }: ActorParams) { - return (async () => { - const actor = await CapBase.createActor({ + return (() => { + const actor = CapBase.createActor({ host, canisterId, idlFactory, @@ -129,15 +129,14 @@ export class CapRouter extends CapBase<_ROUTER_SERVICE> { host?: string; canisterId?: string; }) { - return (async () => { - const actor = await CapBase.inititalise<_ROUTER_SERVICE>({ + return (() => { + const actor = CapBase.inititalise<_ROUTER_SERVICE>({ host, canisterId, idlFactory: routerFactory, }); - const cache = new KyaConnector(KyaUrl("dev")); - const cap = new CapRouter(actor, cache); + const cap = new CapRouter(actor); return cap; })(); @@ -199,8 +198,8 @@ export class CapRoot extends CapBase<_ROOT_SERVICE> { host?: string; canisterId: string; }) { - return (async () => { - const actor = await CapBase.inititalise<_ROOT_SERVICE>({ + return (() => { + const actor = CapBase.inititalise<_ROOT_SERVICE>({ host, canisterId, idlFactory: rootFactory, @@ -266,13 +265,27 @@ export class CapRoot extends CapBase<_ROOT_SERVICE> { caller, }); } +} + +export class CapCache extends CapBase<_ROOT_SERVICE> { + constructor(cacheStage?: string) { + const actor = CapBase.inititalise<_ROOT_SERVICE>({ + host: Hosts.mainnet, + canisterId: CanisterInfo[DFX_JSON_HISTORY_ROUTER_KEY_NAME].mainnet, + idlFactory: rootFactory, + }); + + const cache = new KyaConnector(KyaUrl(cacheStage)); + + super(actor, cache); + } public async get_all_user_transactions({ user, LastEvaluatedKey, }: { user: Principal; - LastEvaluatedKey?: number; + LastEvaluatedKey?: unknown; }): Promise { return this.cache?.request({ path: `cap/user/txns/${user.toString()}`, From ae12a551f142f7ff13283780630082cb66f24416 Mon Sep 17 00:00:00 2001 From: BotchM Date: Fri, 29 Oct 2021 11:36:06 +0200 Subject: [PATCH 06/10] setup cap-js tests --- jest.config.js | 10 ++++++++++ package.json | 1 + tests/cap.test.ts | 2 ++ tests/kyasshu.test.ts | 2 ++ 4 files changed, 15 insertions(+) create mode 100644 jest.config.js create mode 100644 tests/cap.test.ts create mode 100644 tests/kyasshu.test.ts diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..40a880e --- /dev/null +++ b/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + roots: [ + '/tests/', + ], + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ["/tests/**/*.(spec|test).ts"], + setupFiles: ["/tests/setup-tests.ts"], + testTimeout: 30000, +}; \ No newline at end of file diff --git a/package.json b/package.json index e81f3de..67d97eb 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "cross-fetch": "^3.1.4" }, "devDependencies": { + "@types/jest": "^27.0.2", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", "eslint": "^7.32.0", diff --git a/tests/cap.test.ts b/tests/cap.test.ts new file mode 100644 index 0000000..33c413c --- /dev/null +++ b/tests/cap.test.ts @@ -0,0 +1,2 @@ +describe('Cap', () => { +}); \ No newline at end of file diff --git a/tests/kyasshu.test.ts b/tests/kyasshu.test.ts new file mode 100644 index 0000000..7a4483b --- /dev/null +++ b/tests/kyasshu.test.ts @@ -0,0 +1,2 @@ +describe('Kyasshu Integration', () => { +}); \ No newline at end of file From 9d195afafefd171d42e4661e2fd36618362f6f4a Mon Sep 17 00:00:00 2001 From: BotchM Date: Fri, 29 Oct 2021 13:46:39 +0200 Subject: [PATCH 07/10] add capCahe, and kya integration tests --- src/config.ts | 4 +- src/index.ts | 3 +- src/types.ts | 1 + tests/cap.test.ts | 2 - tests/integration/cap.test.ts | 88 +++++++++++++++++++++++++++++++ tests/integration/kyasshu.test.ts | 38 +++++++++++++ tests/kyasshu.test.ts | 2 - tests/unit/cap.test.ts | 0 tests/unit/kyasshu.test.ts | 0 tsconfig.json | 4 +- 10 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 src/types.ts delete mode 100644 tests/cap.test.ts create mode 100644 tests/integration/cap.test.ts create mode 100644 tests/integration/kyasshu.test.ts delete mode 100644 tests/kyasshu.test.ts create mode 100644 tests/unit/cap.test.ts create mode 100644 tests/unit/kyasshu.test.ts diff --git a/src/config.ts b/src/config.ts index 32ceec0..2a518f6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,9 @@ +import { KyaStage } from "./types"; + export default {}; //kyasshu -export const KyaUrl = (stage: string = "prod") => { +export const KyaUrl = (stage: KyaStage = "prod") => { const resp: { [key: string]: string } = { prod: "https://kyasshu-prod.fleek.co", dev: "https://kyasshu-dev.fleek.co", diff --git a/src/index.ts b/src/index.ts index 980d64b..ff1e034 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,7 @@ import { KyaUrl, DFX_JSON_HISTORY_ROUTER_KEY_NAME, } from "./config"; +import { KyaStage } from "./types"; export { CanisterInfo }; @@ -268,7 +269,7 @@ export class CapRoot extends CapBase<_ROOT_SERVICE> { } export class CapCache extends CapBase<_ROOT_SERVICE> { - constructor(cacheStage?: string) { + constructor(cacheStage?: KyaStage) { const actor = CapBase.inititalise<_ROOT_SERVICE>({ host: Hosts.mainnet, canisterId: CanisterInfo[DFX_JSON_HISTORY_ROUTER_KEY_NAME].mainnet, diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..24e9f3c --- /dev/null +++ b/src/types.ts @@ -0,0 +1 @@ +export type KyaStage = "prod" | "dev" | "local"; diff --git a/tests/cap.test.ts b/tests/cap.test.ts deleted file mode 100644 index 33c413c..0000000 --- a/tests/cap.test.ts +++ /dev/null @@ -1,2 +0,0 @@ -describe('Cap', () => { -}); \ No newline at end of file diff --git a/tests/integration/cap.test.ts b/tests/integration/cap.test.ts new file mode 100644 index 0000000..a0e6e3c --- /dev/null +++ b/tests/integration/cap.test.ts @@ -0,0 +1,88 @@ +import { Principal } from "@dfinity/principal"; +import { CapCache, CapRoot, CapRouter } from "../../src"; + +const getCapRouterInstance = async ({ + canisterId, + host, +}: { + canisterId: string; + host: string; +}) => + CapRouter.init({ + host, + canisterId, + }); + +const getCapRootInstance = async ({ + canisterId, + host, +}: { + canisterId: string; + host: string; +}) => + CapRoot.init({ + host, + canisterId, + }); + +describe("Cap Integration", () => { + let capRouter: CapRouter; + + beforeAll(async () => { + capRouter = await getCapRouterInstance({ + canisterId: "ryjl3-tyaaa-aaaaa-aaaba-cai", + host: "http://localhost:8000", + }); + }); + + describe("Cap Router", () => { + test("some test", async () => {}); + }); + + describe("Cap Root", () => { + let capRoot: CapRoot; + + beforeAll(async () => { + capRoot = await getCapRootInstance({ + canisterId: "ryjl3-tyaaa-aaaaa-aaaba-cai", + host: "http://localhost:8000", + }); + }); + + test("some test", async () => {}); + }); + + describe("Cap Cache", () => { + describe("dev", () => { + let capCache: CapCache; + + beforeAll(async () => { + capCache = new CapCache("dev"); + }); + + test("get_all_user_transactions", async () => { + const result = await capCache.get_all_user_transactions({ + user: Principal.from( + "zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae" + ), + }); + }); + }); + + describe("prod", () => { + let capCache: CapCache; + + beforeAll(async () => { + capCache = new CapCache(); + }); + + test("get_all_user_transactions", async () => { + const result = await capCache.get_all_user_transactions({ + user: Principal.from( + "zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae" + ), + }); + }); + }); + }); +}); diff --git a/tests/integration/kyasshu.test.ts b/tests/integration/kyasshu.test.ts new file mode 100644 index 0000000..2ea04bd --- /dev/null +++ b/tests/integration/kyasshu.test.ts @@ -0,0 +1,38 @@ +import { KyaUrl } from "../../src/config"; +import { KyaConnector } from "../../src/kyasshu"; + +describe("Kyasshu Integration", () => { + describe("dev", () => { + let kya: KyaConnector; + + beforeAll(async () => { + kya = new KyaConnector(KyaUrl("dev")); + }); + + test("request", async () => { + const LastEvaluatedKey = { data: "dafsd" }; + + const result = await kya.request({ + path: `cap/user/txns/zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae`, + params: [LastEvaluatedKey], + }); + }); + }); + + describe("prod", () => { + let kya: KyaConnector; + + beforeAll(async () => { + kya = new KyaConnector(KyaUrl("prod")); + }); + + test("request", async () => { + const LastEvaluatedKey = { data: "dafsd" }; + + const result = await kya.request({ + path: `cap/user/txns/zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae`, + params: [LastEvaluatedKey], + }); + }); + }); +}); diff --git a/tests/kyasshu.test.ts b/tests/kyasshu.test.ts deleted file mode 100644 index 7a4483b..0000000 --- a/tests/kyasshu.test.ts +++ /dev/null @@ -1,2 +0,0 @@ -describe('Kyasshu Integration', () => { -}); \ No newline at end of file diff --git a/tests/unit/cap.test.ts b/tests/unit/cap.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/kyasshu.test.ts b/tests/unit/kyasshu.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json index f0b7e4e..ec9e2d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -72,6 +72,8 @@ "include": ["src/**/*"], "exclude": [ "node_modules", - ".vscode/**/*" + ".vscode/**/*", + "dist", + "tests", ] } From 8ebdba88065ee9feee35bc0d9d46918d1664537b Mon Sep 17 00:00:00 2001 From: BotchM Date: Fri, 29 Oct 2021 13:48:38 +0200 Subject: [PATCH 08/10] format tests --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 2459bcc..de47169 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "lint": "eslint src --ext ts", "lint:fix": "eslint src --fix --ext ts && prettier --write \"./src/**/*.{ts,tsx,js,jsx}\"", "format": "prettier --write \"./src/**/*.{ts,tsx,js,jsx}\"", + "format:tests": "prettier --write \"./tests/**/*.{ts,tsx,js,jsx}\"", "format:check": "prettier --check \"./src/**/*.{ts,tsx,js,jsx}\"" }, "husky": { From 5c1aba4c076d2d468e1676e60c0fe95cd0236c73 Mon Sep 17 00:00:00 2001 From: BotchM Date: Mon, 1 Nov 2021 14:22:09 +0200 Subject: [PATCH 09/10] remove async createActor dependency --- README.md | 2 +- src/index.ts | 83 ++++++++++++++++++++++------------------------------ 2 files changed, 36 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 17f4eb4..3bc3256 100644 --- a/README.md +++ b/README.md @@ -481,7 +481,7 @@ console.log(userTxns); ### Kyasshu Layer -### `capRoot.get_all_user_transactions(userId, LastEvaluatedKey)` +### `capCache.get_all_user_transactions(userId, LastEvaluatedKey)` > Return all of the user transactions for `userId`, if `LastEvaluatedKey` is returned, you must provide it in subsequent calls to query the rest of the data. #### Parameters diff --git a/src/index.ts b/src/index.ts index b8f85ce..970889c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -66,15 +66,16 @@ export interface ActorParams { idlFactory: IdlFactory; } -type CreateActorFromTokenParams = { - tokenId: string; - router: CapRouter; -} | -{ - tokenId: string; - routerHost?: string; - routerCanisterId?: string; -} +type CreateActorFromTokenParams = + | { + tokenId: string; + router: CapRouter; + } + | { + tokenId: string; + routerHost?: string; + routerCanisterId?: string; + }; interface CreateActorFromRootParams { canisterId: string; @@ -107,11 +108,11 @@ export class CapBase { } } - private static async createActor({ + private static createActor({ host, idlFactory, ...args - }: CreateActorParams): Promise> { + }: CreateActorParams): ActorSubclass { const agent = new HttpAgent({ host, fetch, @@ -134,17 +135,9 @@ export class CapBase { }); } - const router = "router" in args ? args.router : await CapRouter.init({ host: args.routerHost, canisterId: args.routerCanisterId }); - - const { canister } = await router.get_token_contract_root_bucket({ - tokenId: Principal.fromText(args.tokenId), - }); - - if (!canister?.[0]) throw Error(`Token ${args.tokenId} not in cap`); - return Actor.createActor(idlFactory, { agent, - canisterId: canister[0], + canisterId: args.tokenId, }); } @@ -153,15 +146,13 @@ export class CapBase { idlFactory, ...args }: CreateActorParams) { - return (async () => { - const actor = await CapBase.createActor({ - host, - idlFactory, - ...args, - }); + const actor = CapBase.createActor({ + host, + idlFactory, + ...args, + }); - return actor; - })(); + return actor; } } @@ -173,17 +164,15 @@ export class CapRouter extends CapBase<_ROUTER_SERVICE> { host?: string; canisterId?: string; }) { - return (async () => { - const actor = await CapBase.inititalise<_ROUTER_SERVICE>({ - host, - canisterId, - idlFactory: routerFactory, - }); + const actor = CapBase.inititalise<_ROUTER_SERVICE>({ + host, + canisterId, + idlFactory: routerFactory, + }); - const cap = new CapRouter(actor); + const cap = new CapRouter(actor); - return cap; - })(); + return cap; } public async get_index_canisters({ @@ -236,19 +225,17 @@ export class CapRouter extends CapBase<_ROUTER_SERVICE> { export class CapRoot extends CapBase<_ROOT_SERVICE> { public static init({ host = Hosts.mainnet, ...args }: InitRootParams) { - return (async () => { - const actor = await CapBase.inititalise<_ROOT_SERVICE>({ - host, - idlFactory: rootFactory, - ...args, - }); + const actor = CapBase.inititalise<_ROOT_SERVICE>({ + host, + idlFactory: rootFactory, + ...args, + }); - // ToDo cache flag - const cache = new KyaConnector(KyaUrl("dev")); - const cap = new CapRoot(actor, cache); + // ToDo cache flag + const cache = new KyaConnector(KyaUrl("dev")); + const cap = new CapRoot(actor, cache); - return cap; - })(); + return cap; } public async get_transaction( From 02aa67924ac885dcc95ab3ab5237365997fdca67 Mon Sep 17 00:00:00 2001 From: BotchM Date: Mon, 1 Nov 2021 19:38:39 +0200 Subject: [PATCH 10/10] enclose cache params in object --- README.md | 12 +++++++----- scripts/commands.md | 4 +++- src/index.ts | 4 +++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3bc3256..d421277 100644 --- a/README.md +++ b/README.md @@ -502,15 +502,13 @@ console.log(userTxns); ```JavaScript const capCache = new CapCache(); -const userTxns = await capCache.get_all_user_transactions({ +let userTxns = await capCache.get_all_user_transactions({ user: Principal.from("zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae"), }); -// or - -const userTxns = await capCache.get_all_user_transactions({ +userTxns = await capCache.get_all_user_transactions({ user: Principal.from("zxt4e-ian3w-g4ll2-3n5mz-lfqkc-eyj7k-yg6jl-rsbud-f6sft-zdfq3-pae"), - LastEvaluatedKey, + LastEvaluatedKey: userTxns.LastEvaluatedKey, }); console.log(userTxns); @@ -533,6 +531,10 @@ console.log(userTxns); - ToDo +## Local Development + +- ToDo + ## Roadmap - Cache every endpoitn with Kyasshu diff --git a/scripts/commands.md b/scripts/commands.md index 24d7749..e8a1045 100644 --- a/scripts/commands.md +++ b/scripts/commands.md @@ -50,4 +50,6 @@ dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get_next_canisters "(record {witne dfx canister call ic-history-router print_out "()" # Contract root buckets -dfx canister call ic-history-router get_token_contract_root_bucket "(record { canister=(principal \"avesb-mgo2l-ds25i-g7kd4-3he5l-z7ary-3biiq-sojiw-xjgbk-ich5l-mae\"); witness=(false:bool)})" \ No newline at end of file +dfx canister call ic-history-router get_token_contract_root_bucket "(record { canister=(principal \"avesb-mgo2l-ds25i-g7kd4-3he5l-z7ary-3biiq-sojiw-xjgbk-ich5l-mae\"); witness=(false:bool)})" + +dfx canister --network ic call o3aoo-taaaa-aaaad-qayza-cai get_transactions "(record {page=(0:nat32); witness=(false:bool)})" diff --git a/src/index.ts b/src/index.ts index 970889c..7acf78d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -314,7 +314,9 @@ export class CapCache extends CapBase<_ROOT_SERVICE> { }): Promise { return this.cache?.request({ path: `cap/user/txns/${user.toString()}`, - params: [LastEvaluatedKey], + params: [{ + LastEvaluatedKey + }], }); } }