diff --git a/src/base/index.ts b/src/base/index.ts index c3af042..f34d2d0 100644 --- a/src/base/index.ts +++ b/src/base/index.ts @@ -1,6 +1,26 @@ -import { PersonaAnalysisConfig, RequestInit } from '../types'; +import { + PersonaAnalysisConfig, + RequestInit, + ResponseError as ResponseErrorType, + ResponseErrorTitle, + ResponseErrorStatus, +} from '../types'; import { isWalletAddressValid, areWalletAddressesValid } from '../utils'; +export class ResponseError implements ResponseErrorType { + type: string; + title: ResponseErrorTitle; + status: ResponseErrorStatus; + description?: string; + + constructor(responseError: ResponseErrorType) { + this.type = responseError.type; + this.title = responseError.title; + this.status = responseError.status; + this.description = responseError.description; + } +} + export abstract class Base { private apiKey: string; private baseUrl: string; @@ -10,7 +30,31 @@ export abstract class Base { this.baseUrl = config.baseUrl || 'https://api.persona.staging.cookie3.co'; } - protected async request(endpoint: string, options: RequestInit): Promise { + private handleError(error: Error): ResponseErrorType { + try { + const { type, title, status, description }: ResponseErrorType = JSON.parse(error.message); + + return new ResponseError({ + type, + title, + status, + description, + }); + } catch (e) { + // If the error message is not a valid JSON string, return a default error object + return new ResponseError({ + type: 'https://httpstatuses.com/500', + title: 'Internal Server Error', + status: 500, + description: 'An internal server error occurred', + }); + } + } + + protected async request( + endpoint: string, + options: RequestInit, + ): Promise { const url = `${this.baseUrl}${endpoint}`; const body = JSON.parse(options.body); const walletAddress = body.walletAddress; @@ -25,16 +69,32 @@ export abstract class Base { headers, }; - const validateWalletAddresses = Promise.resolve( - !!walletAddress ? isWalletAddressValid(walletAddress) : areWalletAddressesValid(body), - ); - - const areValid = await validateWalletAddresses; - return areValid - ? fetch(url, config) - .then((response) => response.text()) - .then((result) => result as T) - .catch((error) => error) - : 'incorrect wallet address, please ensure that any wallet address you provide is correct'; + const validateWalletAddresses = !!walletAddress + ? isWalletAddressValid(walletAddress) + : areWalletAddressesValid(body); + + const areWalletsValid = validateWalletAddresses; + + if (!areWalletsValid) { + return new ResponseError({ + type: 'https://httpstatuses.com/422', + title: 'Unprocessable Entity', + status: 422, + description: + 'incorrect wallet address, please ensure that any wallet address you provide is correct', + }); + } + + try { + const response = await fetch(url, config); + + if (response.status === 401) { + throw new Error(JSON.stringify(await response.json())); + } + + return response.json() as T; + } catch (error: any) { + return this.handleError(error); + } } } diff --git a/src/index.ts b/src/index.ts index c5f8899..e4d33c0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,11 @@ -import PersonaAnalysis from './personaAnalysis'; +import { PersonaAnalysis } from './personaAnalysis'; +import { ResponseError } from './base'; +import { isWalletAddressValid, areWalletAddressesValid, isResponseError } from './utils'; -export default PersonaAnalysis; +export { + PersonaAnalysis, + ResponseError, + isWalletAddressValid, + areWalletAddressesValid, + isResponseError, +}; diff --git a/src/personaAnalysis/index.ts b/src/personaAnalysis/index.ts index 016b59f..f2d9ffe 100644 --- a/src/personaAnalysis/index.ts +++ b/src/personaAnalysis/index.ts @@ -1,8 +1,8 @@ import { Base } from '../base'; import { PersonaAnalysisStatus, HttpMethod, WalletsForPersona, ResponseError } from '../types'; -export default class PersonaAnalysis extends Base { - // Returns information if provided wallet address meet rules for given persona +export class PersonaAnalysis extends Base { + //Returns information if provided wallet address meet rules for given persona isPersonaMatched( walletAddress: string, personaId: string, @@ -12,7 +12,7 @@ export default class PersonaAnalysis extends Base { body: JSON.stringify({ walletAddress, personaId }), }); } - // Returns wallets that meet the rules in all personas attached to account + //Returns wallets that meet the rules in all personas attached to account filterMatchedPersonas(walletAddresses: string[]): Promise { return this.request('/personaAnalysis/personaArray', { method: HttpMethod.POST, diff --git a/src/types.ts b/src/types.ts index 0bfd541..548c73d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -40,13 +40,18 @@ interface WalletsForPersona { walletsForPersona: PersonaWallet[]; } -type ResponseErrorTitle = 'Unauthorized' | 'Too Many Requests'; -type ResponseErrorStatus = 401 | 429; +type ResponseErrorTitle = + | 'Unauthorized' + | 'Too Many Requests' + | 'Unprocessable Entity' + | 'Internal Server Error'; +type ResponseErrorStatus = 401 | 422 | 429 | 500; interface ResponseError { type: string; title: ResponseErrorTitle; status: ResponseErrorStatus; + description?: string; } export type { @@ -55,6 +60,8 @@ export type { PersonaAnalysisStatus, WalletsForPersona, ResponseError, + ResponseErrorTitle, + ResponseErrorStatus, }; export { HttpMethod }; diff --git a/src/utils/index.ts b/src/utils/index.ts index 5cc6f35..6e0b21b 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,10 @@ +import { ResponseError } from '../base'; +import { + ResponseError as ResponseErrorType, + PersonaAnalysisStatus, + WalletsForPersona, +} from '../types'; + export const isWalletAddressValid = (walletAddress: string) => { const regex = new RegExp(/^0x[a-fA-F0-9]{40}$/); @@ -6,3 +13,7 @@ export const isWalletAddressValid = (walletAddress: string) => { export const areWalletAddressesValid = (walletAddresses: string[]) => !walletAddresses.find((walletAddress) => !isWalletAddressValid(walletAddress)); + +export const isResponseError = ( + response: ResponseErrorType | PersonaAnalysisStatus | WalletsForPersona, +): response is ResponseError => response instanceof ResponseError; diff --git a/tsconfig.json b/tsconfig.json index b607595..f96e7da 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,8 @@ "outDir": "./dist", "baseUrl": "./", "incremental": true, - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "moduleResolution": "node" }, "include": ["src/**/*"], "exclude": ["node_modules"]