Skip to content

Commit

Permalink
feat: add sismo api in sdk class (#9)
Browse files Browse the repository at this point in the history
* feat: add sismo api in sdk class

* feat: fetch group on sismo api directly from zk connect

* feat: create sdk from an url instead of an env

* fix: remove typo

---------

Co-authored-by: Dev <[email protected]>
  • Loading branch information
yum0e and gabin54 authored Mar 14, 2023
1 parent f22f448 commit 1588632
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 44 deletions.
2 changes: 2 additions & 0 deletions packages/zk-connect-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"author": "[email protected]",
"license": "MIT",
"dependencies": {
"@apollo/client": "^3.7.10",
"graphql": "^16.6.0",
"@ethersproject/bignumber": "5.7.0"
},
"lint-staged": {
Expand Down
19 changes: 19 additions & 0 deletions packages/zk-connect-client/src/api/api-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ApolloClient, InMemoryCache, QueryOptions } from "@apollo/client";

export class ApiFetcher {
private _url: string;
private _client: ApolloClient<any>;

constructor(sismoApiUrl: string) {
this._url = sismoApiUrl;
this._client = new ApolloClient({
uri: this._url,
cache: new InMemoryCache(),
});
}

public async getWithQuery<T>(opts: QueryOptions) {
const res = await this._client.query<T>(opts);
return res.data;
}
}
2 changes: 2 additions & 0 deletions packages/zk-connect-client/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./api-fetcher";
export * from "./types";
5 changes: 5 additions & 0 deletions packages/zk-connect-client/src/api/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const sismoApiUrls: Record<string, string> = {
staging: "https://api.staging.zikies.io",
testnets: "https://api.testnets.sismo.io",
prod: "https://api.sismo.io",
};
2 changes: 2 additions & 0 deletions packages/zk-connect-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from "./zk-connect";
export * from "./types";
export * from "./constants";
export * from "./common-types";
export * from "./sdk";
export * from "./api";
3 changes: 3 additions & 0 deletions packages/zk-connect-client/src/sdk/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./queries";
export * from "./sdk";
export * from "./types";
33 changes: 33 additions & 0 deletions packages/zk-connect-client/src/sdk/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { gql } from "@apollo/client";

export const getGroupFromIdQuery = gql`
query getGroup($id: ID!) {
group(id: $id) {
id
name
description
specs
generationFrequency
snapshots {
timestamp
dataUrl
}
}
}
`;

export const getGroupFromNameQuery = gql`
query getGroup($name: String!) {
group(name: $name) {
id
name
description
specs
generationFrequency
snapshots {
timestamp
dataUrl
}
}
}
`;
49 changes: 49 additions & 0 deletions packages/zk-connect-client/src/sdk/sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ApiFetcher, sismoApiUrls } from "../api";
import { getGroupFromIdQuery, getGroupFromNameQuery } from "./queries";
import { FetchedData, GetGroupQueryOutput, GroupParams } from "./types";

export class Sdk {
private _apiFetcher: ApiFetcher;

constructor(sismoApiUrl?: string) {
this._apiFetcher = new ApiFetcher(sismoApiUrl ?? sismoApiUrls.prod);
}

public async getGroup({ id, name, timestamp }: GroupParams) {
if (!id && !name) {
throw new Error(
"Either id or name must be provided for the group. You can view all groups at https://factory.sismo.io/groups-explorer."
);
}

const group: GetGroupQueryOutput = id
? (
await this._apiFetcher.getWithQuery<{ group: GetGroupQueryOutput }>({
query: getGroupFromIdQuery,
variables: { id },
})
).group
: (
await this._apiFetcher.getWithQuery<{ group: GetGroupQueryOutput }>({
query: getGroupFromNameQuery,
variables: { name },
})
).group;

let dataUrl: string;
if (timestamp) {
const snapshot = group.snapshots.filter(
(s: { timestamp: string }) => s.timestamp === timestamp
)[0];
({ dataUrl } = snapshot);
if (!snapshot) {
({ dataUrl } = group.snapshots[0]);
}
} else {
({ dataUrl } = group.snapshots[0]);
}

const data: FetchedData = await fetch(dataUrl).then((res) => res.json());
return { ...group, data } as GetGroupQueryOutput & { data: FetchedData };
}
}
15 changes: 15 additions & 0 deletions packages/zk-connect-client/src/sdk/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type GroupParams = { id?: string; name?: string; timestamp?: string };
export type FetchedData = Record<string, number>;

// queries types
export type GetGroupQueryOutput = {
id: string;
name: string;
description: string;
specs: string;
generationFrequency: string;
snapshots: {
timestamp: string;
dataUrl: string;
}[];
};
11 changes: 2 additions & 9 deletions packages/zk-connect-client/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { BigNumberish } from '@ethersproject/bignumber';
import { DataRequest, DataRequestType } from "./common-types";

export type ZkConnectParams = {
appId: string;
opts?: {
isDevMode?: boolean;
vaultAppBaseUrl?: string;
};
};
import { DataRequestType } from "./common-types";

export type RequestParams = {
dataRequest?: DataRequestType;
Expand All @@ -22,4 +14,5 @@ export type ZkConnectClientConfig = {
devAddresses?: string[] | Record<string, Number | BigNumberish> // Will insert this addresses in data groups
},
vaultAppBaseUrl?: string
sismoApiUrl?: string
}
65 changes: 32 additions & 33 deletions packages/zk-connect-client/src/zk-connect.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,67 @@
import { RequestParams, ZkConnectClientConfig } from "./types";
import { ZkConnectResponse } from "./common-types";

import { Sdk, GroupParams } from "./sdk";
import { DEV_VAULT_APP_BASE_URL, PROD_VAULT_APP_BASE_URL, VERSION } from "./constants";
import { BigNumberish } from "@ethersproject/bignumber";

export const ZkConnect = (config: ZkConnectClientConfig): ZkConnectClient => {
return new ZkConnectClient(config);
}
};

export class ZkConnectClient {
private _appId: string;
private _vaultAppBaseUrl: string;
private _devModeEnabled: boolean;
private _devAddresses: Record<string, Number | BigNumberish> | null;
private _sdk: Sdk;

constructor({ appId, devMode, vaultAppBaseUrl }: ZkConnectClientConfig) {
constructor({ appId, devMode, vaultAppBaseUrl, sismoApiUrl }: ZkConnectClientConfig) {
this._appId = appId;
this._devModeEnabled = devMode?.enabled ?? false;
this._vaultAppBaseUrl = vaultAppBaseUrl ?? (this._devModeEnabled ? DEV_VAULT_APP_BASE_URL : PROD_VAULT_APP_BASE_URL);
this._vaultAppBaseUrl =
vaultAppBaseUrl ?? (this._devModeEnabled ? DEV_VAULT_APP_BASE_URL : PROD_VAULT_APP_BASE_URL);
if (this._devModeEnabled) {
console.warn(
"zkConnect launch in DevMode! Never use this mode in production!"
);
console.warn("zkConnect launch in DevMode! Never use this mode in production!");
}
if (devMode?.devAddresses) {
console.warn(
`These Eligibles addresses will be used in data groups. Never use this in production!`
);
if(Array.isArray(devMode.devAddresses)) {
if (Array.isArray(devMode.devAddresses)) {
this._devAddresses = devMode.devAddresses.reduce((acc, address) => {
acc[address] = 1;
return acc;
}, {});
} else if (typeof devMode.devAddresses === 'object') {
} else if (typeof devMode.devAddresses === "object") {
this._devAddresses = devMode.devAddresses;
} else {
throw new Error(`devAddresses must be of type Record<string, Number | BigNumberish>`);
}
}
this._sdk = new Sdk(sismoApiUrl);
}

public request = ({
dataRequest,
namespace,
callbackPath,
}: RequestParams = {}) => {
if (!window)
throw new Error(`requestProof is not available outside of a browser`);
public request = ({ dataRequest, namespace, callbackPath }: RequestParams = {}) => {
if (!window) throw new Error(`requestProof is not available outside of a browser`);

let url = `${this._vaultAppBaseUrl}/connect?version=${VERSION}&appId=${this._appId}`;

if (dataRequest) {
const statementRequestsWithDevAddresses = dataRequest.statementRequests.map((statementRequest) => {
if (this._devAddresses) {
console.info(
`Eligible group data for groupId ${statementRequest.groupId} is overridden with:`,
this._devAddresses
);
statementRequest.extraData = {
...statementRequest.extraData,
devAddresses: this._devAddresses,
};
const statementRequestsWithDevAddresses = dataRequest.statementRequests.map(
(statementRequest) => {
if (this._devAddresses) {
console.info(
`Eligible group data for groupId ${statementRequest.groupId} is overridden with:`,
this._devAddresses
);
statementRequest.extraData = {
...statementRequest.extraData,
devAddresses: this._devAddresses,
};
}
return statementRequest;
}
return statementRequest;
});
);
url += `&dataRequest=${JSON.stringify({
...dataRequest,
statementRequests: statementRequestsWithDevAddresses,
Expand All @@ -79,14 +77,15 @@ export class ZkConnectClient {
};

public getResponse = (): ZkConnectResponse | null => {
if (!window)
throw new Error(`getResponse is not available outside of a browser`);
if (!window) throw new Error(`getResponse is not available outside of a browser`);
const url = new URL(window.location.href);
if (url.searchParams.has("zkConnectResponse")) {
return JSON.parse(
url.searchParams.get("zkConnectResponse") as string
) as ZkConnectResponse;
return JSON.parse(url.searchParams.get("zkConnectResponse") as string) as ZkConnectResponse;
}
return null;
};

public async getGroup({ id, name, timestamp }: GroupParams) {
return this._sdk.getGroup({ id, name, timestamp });
}
}
Loading

0 comments on commit 1588632

Please sign in to comment.