Skip to content

Commit

Permalink
Add a package unfetch
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelKim20 committed Sep 13, 2023
1 parent da6cea0 commit b007d72
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "del-osx",
"name": "del-sdk",
"version": "1.0.0",
"description": "JS SDK for links e-mail and wallet addresses",
"repository": "https://github.com/bosagora/del-sdk",
Expand Down
3 changes: 2 additions & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@
"@ethersproject/wallet": "^5.7.0",
"del-osx-lib": "^1.0.6",
"del-sdk-common": "^1.0.0",
"dotenv": "^16.3.1"
"dotenv": "^16.3.1",
"unfetch": "^5.0.0"
},
"jest": {
"testEnvironment": "../../test-environment.js",
Expand Down
9 changes: 9 additions & 0 deletions packages/client/src/client-common/interfaces/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,12 @@ export type SupportedNetworks = typeof SupportedNetworksArray[number];
export type NetworkDeployment = {
LinkCollection: string;
};

export type GenericRecord = Record<string, string | number | boolean | null | undefined>;

export interface IHttpConfig {
/** IPFS Cluster URL */
url: URL;
/** Additional headers to be included with requests */
headers?: Record<string, string>;
}
45 changes: 45 additions & 0 deletions packages/client/src/client-common/interfaces/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import fetch, { UnfetchResponse } from "unfetch";
import { GenericRecord, IHttpConfig } from "./common";
import { InvalidResponseError } from "../../utils/errors";

export namespace Network {
/**
* Performs a request and returns a JSON object with the response
*/

export async function get(config: IHttpConfig, path: string, data?: GenericRecord) {
const { url, headers } = config;
const endpoint: URL = new URL(path, url);
for (const [key, value] of Object.entries(data ?? {})) {
if (value != null) {
endpoint.searchParams.set(key, String(value));
}
}
const response: UnfetchResponse = await fetch(endpoint.href, {
method: "GET",
headers
});
if (!response.ok) {
throw new InvalidResponseError(response);
}
return response.json();
}

export async function post(config: IHttpConfig, path: string, data?: any) {
const { url, headers } = config;
const endpoint: URL = new URL(path, url);
const response: UnfetchResponse = await fetch(endpoint.href, {
method: "POST",
headers: {
"Content-Type": "application/json",
...headers
},
body: JSON.stringify(data)
});

if (!response.ok) {
throw new InvalidResponseError(response);
}
return response.json();
}
}
8 changes: 8 additions & 0 deletions packages/client/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface IClientMethods extends IClientCore {
toAddress: (email: string) => Promise<string>;
toEmail: (wallet: string) => Promise<string>;
nonceOf: (wallet: string) => Promise<BigNumber>;
getValidators: () => Promise<ValidatorInfoValue[]>;
}

export interface IClient {
Expand All @@ -29,6 +30,13 @@ export type NonceOfParams = {
wallet: string;
};

export type ValidatorInfoValue = {
address: string;
index: number;
endpoint: string;
status: number;
};

export type AddRequestValue =
| { key: AddRequestSteps.ADDING; txHash: string }
| {
Expand Down
22 changes: 21 additions & 1 deletion packages/client/src/internal/client/methods.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LinkCollection__factory } from "del-osx-lib";
import { NoProviderError, NoSignerError } from "del-sdk-common";

import { AddRequestSteps, AddRequestValue, IClientMethods } from "../../interfaces";
import { AddRequestSteps, AddRequestValue, IClientMethods, ValidatorInfoValue } from "../../interfaces";

import { ClientCore, Context } from "../../client-common";
import { ContractUtils } from "../../utils/ContractUtils";
Expand Down Expand Up @@ -120,4 +120,24 @@ export class ClientMethods extends ClientCore implements IClientMethods {
if (await contract.isAvailable(id)) return id;
}
}

public async getValidators(): Promise<ValidatorInfoValue[]> {
const signer = this.web3.getConnectedSigner();
if (!signer) {
throw new NoSignerError();
} else if (!signer.provider) {
throw new NoProviderError();
}

const contract = LinkCollection__factory.connect(this.web3.getLinkCollectionAddress(), signer);
const validators = await contract.getValidators()
return validators.map(m => {
return {
address: m.validator,
index: m.index.toNumber(),
endpoint: m.endpoint,
status: m.status
}
})
}
}
57 changes: 57 additions & 0 deletions packages/client/src/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { UnfetchResponse } from "unfetch";

export class InvalidEmailParamError extends Error {
constructor() {
super("The param does not email");
}
}

export class MismatchApproveAddressError extends Error {
constructor() {
super("Customer and approver mismatch");
}
}

export class UnregisteredEmailError extends Error {
constructor() {
super("Unregistered email error");
}
}
export class InsufficientBalanceError extends Error {
constructor() {
super("Insufficient balance error");
}
}

export class NoHttpModuleError extends Error {
constructor() {
super("A Http Module is needed");
}
}
export class ClientError extends Error {
public response: UnfetchResponse;
constructor(res: UnfetchResponse) {
super(res.statusText);
this.name = "ClientError";
this.response = res;
}
}

export class InvalidResponseError extends ClientError {
constructor(res: UnfetchResponse) {
super(res);
this.message = "Invalid response";
}
}
export class MissingBodyeError extends ClientError {
constructor(res: UnfetchResponse) {
super(res);
this.message = "Missing response body";
}
}
export class BodyParseError extends ClientError {
constructor(res: UnfetchResponse) {
super(res);
this.message = "Error parsing body";
}
}
111 changes: 111 additions & 0 deletions packages/client/src/utils/network/ErrorTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* Contains definition for error types
*
* Copyright:
* Copyright (c) 2022 BOSAGORA Foundation All rights reserved.
*
* License:
* MIT License. See LICENSE for details.
*/

/**
* The class used when a network error occurs
*/
export class NetworkError extends Error {
/**
* The status code
*/
public status: number;

/**
* The status text
*/
public statusText: string;

/**
* The message of response
*/
public statusMessage: string;

/**
* Constructor
* @param status The status code
* @param statusText The status text
* @param statusMessage The message of response
*/
constructor(status: number, statusText: string, statusMessage: string) {
super(statusText);
this.name = "NetworkError";
this.status = status;
this.statusText = statusText;
this.statusMessage = statusMessage;
}
}

/**
* When status code is 404
*/
export class NotFoundError extends NetworkError {
/**
* Constructor
* @param status The status code
* @param statusText The status text
* @param statusMessage The message of response
*/
constructor(status: number, statusText: string, statusMessage: string) {
super(status, statusText, statusMessage);
this.name = "NotFoundError";
}
}

/**
* When status code is 400
*/
export class BadRequestError extends NetworkError {
/**
* Constructor
* @param status The status code
* @param statusText The status text
* @param statusMessage The message of response
*/
constructor(status: number, statusText: string, statusMessage: string) {
super(status, statusText, statusMessage);
this.name = "BadRequestError";
}
}

/**
* It is a function that handles errors that occur during communication
* with a server for easy use.
* @param error This is why the error occurred
* @returns The instance of Error
*/
export function handleNetworkError(error: any): Error {
if (
error.response !== undefined &&
error.response.status !== undefined &&
error.response.statusText !== undefined
) {
let statusMessage: string;
if (error.response.data !== undefined) {
if (typeof error.response.data === "string") statusMessage = error.response.data;
else if (typeof error.response.data === "object" && error.response.data.statusMessage !== undefined)
statusMessage = error.response.data.statusMessage;
else if (typeof error.response.data === "object" && error.response.data.errorMessage !== undefined)
statusMessage = error.response.data.errorMessage;
else statusMessage = error.response.data.toString();
} else statusMessage = "";

switch (error.response.status) {
case 400:
return new BadRequestError(error.response.status, error.response.statusText, statusMessage);
case 404:
return new NotFoundError(error.response.status, error.response.statusText, statusMessage);
default:
return new NetworkError(error.response.status, error.response.statusText, statusMessage);
}
} else {
if (error.message !== undefined) return new Error(error.message);
else return new Error("An unknown error has occurred.");
}
}
5 changes: 5 additions & 0 deletions packages/client/test/methods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ describe("SDK Client", () => {
await expect(await client.methods.toAddress(emailHash)).toEqual(address);
await expect(await client.methods.toEmail(address)).toEqual(emailHash);
});

it("getValidators", async () => {
const infos = await client.methods.getValidators();
console.log(infos);
});
});
});
});
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9038,6 +9038,11 @@ unbox-primitive@^1.0.2:
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"

unfetch@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-5.0.0.tgz#8a5b6e5779ebe4dde0049f7d7a81d4a1af99d142"
integrity sha512-3xM2c89siXg0nHvlmYsQ2zkLASvVMBisZm5lF3gFDqfF2xonNStDJyMpvaOBe0a1Edxmqrf2E0HBdmy9QyZaeg==

unicode-canonical-property-names-ecmascript@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
Expand Down

0 comments on commit b007d72

Please sign in to comment.